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 { public void prepareFinish() throws IOException {
int functCount; int functCount;
int typeCount = 0;
do { do {
scanFunctions(); 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(); scanForClinit();
if( typeCount < types.size() ) { types.scanTypeHierarchy( classFileLoader ); // scan the type hierarchy can find new functions
types.scanTypeHierarchy( classFileLoader ); // scan the type hierarchy can find new functions
typeCount = types.size();
}
} while( functCount < functions.size() ); } while( functCount < functions.size() );
// write only the needed imports to the output // write only the needed imports to the output
@ -322,11 +318,8 @@ public class ModuleGenerator {
writeMethodSignature( name, FunctionType.Abstract, null ); writeMethodSignature( name, FunctionType.Abstract, null );
} }
// scan again if there are new types // scan again if there are new types or new needed fields
if( typeCount < types.size() ) { types.scanTypeHierarchy( classFileLoader );
types.scanTypeHierarchy( classFileLoader );
typeCount = types.size();
}
JWebAssembly.LOGGER.fine( "scan finish" ); JWebAssembly.LOGGER.fine( "scan finish" );
types.prepareFinish( writer, classFileLoader ); 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.LittleEndianOutputStream;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.ValueTypeParser;
/** /**
* Manage the written and to write types (classes) * Manage the written and to write types (classes)
@ -226,7 +227,11 @@ public class TypeManager {
if( type == null ) { if( type == null ) {
checkStructTypesState( name ); 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 ); structTypes.put( name, type );
} }
return type; return type;

View File

@ -796,21 +796,9 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code * the line number in the Java source code
*/ */
protected void addStructInstruction( StructOperator op, @Nonnull String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) { 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 ); WasmStructInstruction structInst = new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types );
instructions.add( structInst ); instructions.add( structInst );
if( !options.useGC() ) { if( !options.useGC() || op == StructOperator.CAST || op == StructOperator.INSTANCEOF ) {
SyntheticFunctionName name = structInst.createNonGcFunction(); SyntheticFunctionName name = structInst.createNonGcFunction();
if( name != null ) { if( name != null ) {
functions.markAsNeeded( name ); functions.markAsNeeded( name );

View File

@ -117,6 +117,12 @@ class WasmStructInstruction extends WasmInstruction {
fieldType = fieldName.getType(); fieldType = fieldName.getType();
functionName = new JavaScriptSyntheticFunctionName( "NonGC", "get_" + validJsName( fieldType ), () -> "(a,i) => a[i]", ValueType.externref, ValueType.i32, null, fieldType ); functionName = new JavaScriptSyntheticFunctionName( "NonGC", "get_" + validJsName( fieldType ), () -> "(a,i) => a[i]", ValueType.externref, ValueType.i32, null, fieldType );
break; break;
case INSTANCEOF:
functionName = options.getInstanceOf();
break;
case CAST:
functionName = options.getCast();
break;
default: default:
} }
return functionName; return functionName;
@ -162,33 +168,40 @@ class WasmStructInstruction extends WasmInstruction {
*/ */
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
int idx = -1; int idx = -1;
if( type != null && fieldName != null ) { switch( op ) {
// 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. case GET:
List<NamedStorageType> fields = type.getFields(); case SET:
boolean classNameMatched = type.getName().equals( fieldName.geClassName() ); // 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.
for( int i = fields.size()-1; i >= 0; i-- ) { List<NamedStorageType> fields = type.getFields();
NamedStorageType field = fields.get( i ); boolean classNameMatched = type.getName().equals( fieldName.geClassName() );
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-- ) { for( int i = fields.size()-1; i >= 0; i-- ) {
NamedStorageType field = fields.get( 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; idx = i;
break; 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( functionName != null ) { // nonGC
if( fieldName != null ) { if( idx >= 0 ) {
writer.writeConst( idx, ValueType.i32 ); writer.writeConst( idx, ValueType.i32 );
} }
writer.writeFunctionCall( functionName, null ); writer.writeFunctionCall( functionName, null );