diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index eb9948c..d31416c 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -1018,7 +1018,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod * {@inheritDoc} */ @Override - protected void writeStructOperator( StructOperator op, AnyType type, String fieldName ) throws IOException { + protected void writeStructOperator( StructOperator op, AnyType type, NamedStorageType fieldName ) throws IOException { int opCode; switch(op) { case NEW: diff --git a/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java b/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java index bccbda3..7106515 100644 --- a/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java +++ b/src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java @@ -59,10 +59,10 @@ class StructTypeEntry extends TypeEntry { stream.writeVaruint32( this.fields.size() ); for( NamedStorageType field : this.fields ) { stream.writeVarint( 1 ); // 0 - immutable; 1 - mutable - if( field.type.getCode() > 0 ) { + if( field.getType().getCode() > 0 ) { stream.writeValueType( ValueType.ref_type ); } - stream.writeValueType( field.type ); + stream.writeValueType( field.getType() ); } } @@ -73,13 +73,11 @@ class StructTypeEntry extends TypeEntry { * the name of the field * @return the index */ - int getFieldIdx( @Nonnull String fieldName ) { - for( int i = 0; i < fields.size(); i++ ) { - NamedStorageType field = fields.get( i ); - if( field.name.equals( fieldName ) ) { - return i; - } - } + int getFieldIdx( @Nonnull NamedStorageType fieldName ) { + int idx = fields.indexOf( fieldName ); + if( idx >= 0 ) { + return idx; + } throw new WasmException( fieldName + " not found", -1 ); } diff --git a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java index e956c14..ea38bfd 100644 --- a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java @@ -28,6 +28,7 @@ import de.inetsoftware.classparser.ConstantRef; import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ArrayOperator; +import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; @@ -567,11 +568,11 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder { break; case 180: // getfield ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() ); - addStructInstruction( StructOperator.GET, ref.getClassName(), ref.getName(), codePos, lineNumber ); + addStructInstruction( StructOperator.GET, ref.getClassName(), new NamedStorageType( ref ), codePos, lineNumber ); break; case 181: // putfield ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() ); - addStructInstruction( StructOperator.SET, ref.getClassName(), ref.getName(), codePos, lineNumber ); + addStructInstruction( StructOperator.SET, ref.getClassName(), new NamedStorageType( ref ), codePos, lineNumber ); break; case 182: // invokevirtual case 183: // invokespecial, invoke a constructor diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 245aa06..55b053b 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -35,6 +35,7 @@ import javax.annotation.Nonnull; import de.inetsoftware.classparser.ClassFile; import de.inetsoftware.classparser.Code; +import de.inetsoftware.classparser.ConstantClass; import de.inetsoftware.classparser.FieldInfo; import de.inetsoftware.classparser.MethodInfo; import de.inetsoftware.jwebassembly.JWebAssembly; @@ -44,7 +45,6 @@ import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; -import de.inetsoftware.jwebassembly.wasm.ValueTypeParser; import de.inetsoftware.jwebassembly.watparser.WatParser; /** @@ -225,26 +225,47 @@ public class ModuleGenerator { */ private void writeStructType( StructType type ) throws IOException { String className = type.getName(); + List list = new ArrayList<>(); + listStructFields( className, list ); + + int id = writer.writeStruct( className, list ); + types.useType( type, id, list ); + for( NamedStorageType namedType : list ) { + if( namedType.getType().getCode() == Integer.MAX_VALUE ) { + writeStructType( (StructType)namedType.getType() ); + } + } + } + + /** + * List the non static fields of the class and its superclasses. + * + * @param className + * the className + * @param list + * the container for the fields + * @throws IOException + * if any I/O error occur + */ + private void listStructFields( String className, List list ) throws IOException { InputStream stream = libraries.getResourceAsStream( className + ".class" ); if( stream == null ) { throw new WasmException( "Missing class: " + className, -1 ); } ClassFile classFile = new ClassFile( stream ); - List list = new ArrayList<>(); + + ConstantClass superClass = classFile.getSuperClass(); + if( superClass != null ) { + String superClassName = superClass.getName(); + listStructFields( superClassName, list ); + } + FieldInfo[] fields = classFile.getFields(); for( FieldInfo field : fields ) { if( field.isStatic() ) { continue; } - AnyType fieldtype = new ValueTypeParser( field.getType(), types ).next(); - list.add( new NamedStorageType( fieldtype, field.getName() ) ); - } - int id = writer.writeStruct( className, list ); - types.useType( type, id, list ); - for( NamedStorageType namedType : list ) { - if( namedType.type.getCode() == Integer.MAX_VALUE ) { - writeStructType( (StructType)namedType.type ); - } + list.add( new NamedStorageType( className, field ) ); } } @@ -392,8 +413,8 @@ public class ModuleGenerator { if( instr.getOperator() == StructOperator.NEW_DEFAULT ) { List list = instr.getStructType().getFields(); for( NamedStorageType storageType : list ) { - if( storageType.type.getCode() < 0 ) { - ValueType type = (ValueType)storageType.type; + if( storageType.getType().getCode() < 0 ) { + ValueType type = (ValueType)storageType.getType(); switch( type ) { case i32: case i64: @@ -405,6 +426,9 @@ public class ModuleGenerator { case i16: writer.writeConst( 0, ValueType.i32 ); break; + case anyref: + writer.writeStructOperator( StructOperator.NULL, null, null ); + break; default: throw new WasmException( "Not supported storage type: " + type, instruction.getLineNumber() ); } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java index 683cf5c..ac59a0d 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleWriter.java @@ -23,10 +23,10 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import de.inetsoftware.classparser.Member; +import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NumericOperator; -import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.VariableOperator; @@ -251,5 +251,5 @@ public abstract class ModuleWriter implements Closeable { * @throws IOException * if any I/O error occur */ - protected abstract void writeStructOperator( StructOperator op, AnyType type, String fieldName ) throws IOException; + protected abstract void writeStructOperator( StructOperator op, AnyType type, NamedStorageType fieldName ) throws IOException; } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 4ce9049..cdbe6a6 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -27,6 +27,7 @@ import de.inetsoftware.classparser.Member; import de.inetsoftware.jwebassembly.module.WasmInstruction.Type; import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ArrayOperator; +import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; @@ -318,7 +319,7 @@ public abstract class WasmCodeBuilder { * @param lineNumber * the line number in the Java source code */ - protected void addStructInstruction( StructOperator op, @Nullable String typeName, @Nullable String fieldName, int javaCodePos, int lineNumber ) { + protected void addStructInstruction( StructOperator op, @Nullable String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) { instructions.add( new WasmStructInstruction( op, typeName == null ? null : types.valueOf( typeName ), fieldName, javaCodePos, lineNumber ) ); } } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java index 3bff572..bbe146d 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmStructInstruction.java @@ -24,6 +24,7 @@ import javax.annotation.Nullable; import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.module.TypeManager.StructType; import de.inetsoftware.jwebassembly.wasm.AnyType; +import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; @@ -35,11 +36,11 @@ import de.inetsoftware.jwebassembly.wasm.ValueType; */ class WasmStructInstruction extends WasmInstruction { - private final StructOperator op; + private final StructOperator op; - private final StructType type; + private final StructType type; - private final String fieldName; + private final NamedStorageType fieldName; /** * Create an instance of numeric operation. @@ -55,7 +56,7 @@ class WasmStructInstruction extends WasmInstruction { * @param lineNumber * the line number in the Java source code */ - WasmStructInstruction( @Nullable StructOperator op, @Nullable StructType type, @Nullable String fieldName, int javaCodePos, int lineNumber ) { + WasmStructInstruction( @Nullable StructOperator op, @Nullable StructType type, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) { super( javaCodePos, lineNumber ); this.op = op; this.type = type; diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index bbd7d82..e4cd66a 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -29,10 +29,10 @@ import de.inetsoftware.jwebassembly.JWebAssembly; import de.inetsoftware.jwebassembly.module.FunctionName; import de.inetsoftware.jwebassembly.module.ModuleWriter; import de.inetsoftware.jwebassembly.module.ValueTypeConvertion; +import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.NamedStorageType; import de.inetsoftware.jwebassembly.wasm.NumericOperator; -import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.VariableOperator; @@ -108,11 +108,11 @@ public class TextModuleWriter extends ModuleWriter { for( NamedStorageType field : fields ) { newline( output ); output.append( "(field" ); - if( debugNames && field.name != null ) { - output.append( " $" ).append( field.name ); + if( debugNames && field.getUniqueName() != null ) { + output.append( " $" ).append( normalizeName( field.getUniqueName() ) ); } output.append( " (mut " ); - AnyType type = field.type; + AnyType type = field.getType(); if( type.getCode() < 0 ) { output.append( type.toString() ); } else { @@ -545,7 +545,7 @@ public class TextModuleWriter extends ModuleWriter { * {@inheritDoc} */ @Override - protected void writeStructOperator( StructOperator op, AnyType type, String fieldName ) throws IOException { + protected void writeStructOperator( StructOperator op, AnyType type, NamedStorageType fieldName ) throws IOException { String operation; switch( op ) { case NEW: @@ -571,7 +571,7 @@ public class TextModuleWriter extends ModuleWriter { methodOutput.append( ' ' ).append( normalizeName( type.toString() ) ); } if( fieldName != null ) { - methodOutput.append( " $" ).append( fieldName ); + methodOutput.append( " $" ).append( normalizeName( fieldName.getUniqueName() ) ); } } } diff --git a/src/de/inetsoftware/jwebassembly/wasm/NamedStorageType.java b/src/de/inetsoftware/jwebassembly/wasm/NamedStorageType.java index d9cfc01..4153dbe 100644 --- a/src/de/inetsoftware/jwebassembly/wasm/NamedStorageType.java +++ b/src/de/inetsoftware/jwebassembly/wasm/NamedStorageType.java @@ -15,6 +15,9 @@ */ package de.inetsoftware.jwebassembly.wasm; +import de.inetsoftware.classparser.ConstantRef; +import de.inetsoftware.classparser.FieldInfo; + /** * A ValueType with a name for debug information. * @@ -22,17 +25,87 @@ package de.inetsoftware.jwebassembly.wasm; */ public class NamedStorageType { - public final AnyType type; + private final AnyType type; - public final String name; + private final String name; /** * Create a new instance - * @param type the type - * @param name the name + * + * @param className + * the parent className of the field + * @param field + * the FieldInfo */ - public NamedStorageType( AnyType type, String name ) { - this.type = type; + public NamedStorageType( String className, FieldInfo field ) { + this( field.getType(), className + '.' + field.getName() ); + } + + /** + * Create a new instance + * + * @param ref + * the reference + */ + public NamedStorageType( ConstantRef ref ) { + this( ref.getType(), ref.getClassName() + '.' + ref.getName() ); + } + + /** + * Create a new instance + * + * @param type + * the type + * @param name + * the name + */ + private NamedStorageType( String type, String name ) { + this.type = new ValueTypeParser( type ).next(); this.name = name; } + + /** + * Get the type. + * + * @return the type + */ + public AnyType getType() { + return type; + } + + /** + * Get the global unique name of the field. See + * https://github.com/lars-t-hansen/moz-gc-experiments/blob/master/version2.md#struct-and-ref-types + * + * @return the name + */ + public String getUniqueName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals( Object obj ) { + if( this == obj ) { + return true; + } + if( obj == null ) { + return false; + } + if( getClass() != obj.getClass() ) { + return false; + } + NamedStorageType other = (NamedStorageType)obj; + return name.equals( other.name ); + } }