diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 19cf900..92a01dc 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -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 ); diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index 526dd25..3103e84 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -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; diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 0b2e7cf..895887a 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -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 ); diff --git a/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java index e1844ed..487dcb9 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java @@ -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 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 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 );