fix findValueTypeFromStack after a CAST

This commit is contained in:
Volker Berlin 2020-08-08 23:20:09 +02:00
parent cd1d034b5c
commit 3e9a8b1460
4 changed files with 43 additions and 44 deletions

View File

@ -275,15 +275,11 @@ public class ModuleGenerator {
*/
public void prepareFinish() throws IOException {
int functCount;
int typeCount = 0;
do {
scanFunctions();
functCount = functions.size(); // scan the functions can find new needed types
functCount = functions.size(); // scan the functions can find new needed types or only new needed fields in the known types
scanForClinit();
if( typeCount < types.size() ) {
types.scanTypeHierarchy( classFileLoader ); // scan the type hierarchy can find new functions
typeCount = types.size();
}
types.scanTypeHierarchy( classFileLoader ); // scan the type hierarchy can find new functions
} while( functCount < functions.size() );
// write only the needed imports to the output
@ -322,11 +318,8 @@ public class ModuleGenerator {
writeMethodSignature( name, FunctionType.Abstract, null );
}
// scan again if there are new types
if( typeCount < types.size() ) {
types.scanTypeHierarchy( classFileLoader );
typeCount = types.size();
}
// scan again if there are new types or new needed fields
types.scanTypeHierarchy( classFileLoader );
JWebAssembly.LOGGER.fine( "scan finish" );
types.prepareFinish( writer, classFileLoader );

View File

@ -42,6 +42,7 @@ import de.inetsoftware.jwebassembly.wasm.ArrayType;
import de.inetsoftware.jwebassembly.wasm.LittleEndianOutputStream;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.ValueTypeParser;
/**
* Manage the written and to write types (classes)
@ -226,7 +227,11 @@ public class TypeManager {
if( type == null ) {
checkStructTypesState( name );
type = new StructType( name, structTypes.size() );
if( name.startsWith( "[" ) ) {
type = (StructType)new ValueTypeParser( name, options.types ).next();
} else {
type = new StructType( name, structTypes.size() );
}
structTypes.put( name, type );
}
return type;

View File

@ -796,21 +796,9 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addStructInstruction( StructOperator op, @Nonnull String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) {
switch( op ) {
case INSTANCEOF:
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
FunctionName name = options.getInstanceOf();
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
return;
case CAST:
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
name = options.getCast();
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
return;
}
WasmStructInstruction structInst = new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types );
instructions.add( structInst );
if( !options.useGC() ) {
if( !options.useGC() || op == StructOperator.CAST || op == StructOperator.INSTANCEOF ) {
SyntheticFunctionName name = structInst.createNonGcFunction();
if( name != null ) {
functions.markAsNeeded( name );

View File

@ -117,6 +117,12 @@ class WasmStructInstruction extends WasmInstruction {
fieldType = fieldName.getType();
functionName = new JavaScriptSyntheticFunctionName( "NonGC", "get_" + validJsName( fieldType ), () -> "(a,i) => a[i]", ValueType.externref, ValueType.i32, null, fieldType );
break;
case INSTANCEOF:
functionName = options.getInstanceOf();
break;
case CAST:
functionName = options.getCast();
break;
default:
}
return functionName;
@ -162,33 +168,40 @@ class WasmStructInstruction extends WasmInstruction {
*/
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
int idx = -1;
if( type != null && fieldName != null ) {
// The fieldName of the struct operation does not contain the class name in which the field was declared. It contains the class name of the variable. This can be the class or a subclass.
List<NamedStorageType> fields = type.getFields();
boolean classNameMatched = type.getName().equals( fieldName.geClassName() );
for( int i = fields.size()-1; i >= 0; i-- ) {
NamedStorageType field = fields.get( i );
if( !classNameMatched && field.geClassName().equals( fieldName.geClassName() ) ) {
classNameMatched = true;
}
if( classNameMatched && field.getName().equals( fieldName.getName() ) ) {
idx = i;
break;
}
}
if( !classNameMatched ) {
// special case, the type self does not add a needed field, that we search in all fields
switch( op ) {
case GET:
case SET:
// The fieldName of the struct operation does not contain the class name in which the field was declared. It contains the class name of the variable. This can be the class or a subclass.
List<NamedStorageType> fields = type.getFields();
boolean classNameMatched = type.getName().equals( fieldName.geClassName() );
for( int i = fields.size()-1; i >= 0; i-- ) {
NamedStorageType field = fields.get( i );
if( field.getName().equals( fieldName.getName() ) ) {
if( !classNameMatched && field.geClassName().equals( fieldName.geClassName() ) ) {
classNameMatched = true;
}
if( classNameMatched && field.getName().equals( fieldName.getName() ) ) {
idx = i;
break;
}
}
}
if( !classNameMatched ) {
// special case, the type self does not add a needed field, that we search in all fields
for( int i = fields.size()-1; i >= 0; i-- ) {
NamedStorageType field = fields.get( i );
if( field.getName().equals( fieldName.getName() ) ) {
idx = i;
break;
}
}
}
break;
case INSTANCEOF:
case CAST:
idx = type.getClassIndex();
break;
}
if( functionName != null ) { // nonGC
if( fieldName != null ) {
if( idx >= 0 ) {
writer.writeConst( idx, ValueType.i32 );
}
writer.writeFunctionCall( functionName, null );