From e30deb315d45ee72e17aee747e42d4cc7fdd3947 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Fri, 8 May 2020 22:24:57 +0200 Subject: [PATCH] write itable into the memory; implement interface instruction; WIP --- .../jwebassembly/module/TypeManager.java | 34 +++++++++++++++---- .../module/WasmCallInterfaceInstruction.java | 11 +++--- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index 855c693..f87277a 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -24,6 +24,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.function.ToIntFunction; @@ -315,6 +316,7 @@ public class TypeManager { + " local.set 3" // set $table + " br 0 " // + "end " // + + "unreachable" // should never reach , valueOf( "java/lang/Object" ), ValueType.i32, ValueType.i32, null, ValueType.i32 ); // THIS, classIndex, virtualfunctionIndex, returns functionIndex } @@ -400,6 +402,8 @@ public class TypeManager { private Set instanceOFs; + private Map> interfaceMethods; + /** * The offset to the vtable in the data section. */ @@ -448,8 +452,9 @@ public class TypeManager { methods = new ArrayList<>(); instanceOFs = new LinkedHashSet<>(); // remembers the order from bottom to top class. instanceOFs.add( this ); - HashSet allNeededFields = new HashSet<>(); + interfaceMethods = new LinkedHashMap<>(); if( classIndex >= PRIMITIVE_CLASSES.length ) { + HashSet allNeededFields = new HashSet<>(); listStructFields( name, functions, types, classFileLoader, allNeededFields ); } } @@ -578,17 +583,25 @@ public class TypeManager { for( ConstantClass interClass : classFile.getInterfaces() ) { String interName = interClass.getName(); StructType type = types.structTypes.get( interName ); - if( type != null ) { - // add all interfaces to the instanceof set - instanceOFs.add( type ); + if( type == null ) { + continue; } + // add all used interfaces to the instanceof set + instanceOFs.add( type ); + + List iMethods = interfaceMethods.get( type ); ClassFile interClassFile = classFileLoader.get( interName ); for( MethodInfo interMethod : interClassFile.getMethods() ) { FunctionName funcName = new FunctionName( interMethod ); if( functions.isUsed( funcName ) ) { MethodInfo method = classFile.getMethod( funcName.methodName, funcName.signature ); if( method != null ) { - functions.markAsNeeded( new FunctionName( method ) ); + FunctionName methodName = new FunctionName( method ); + functions.markAsNeeded( methodName ); + if( iMethods == null ) { + interfaceMethods.put( type, iMethods = new ArrayList<>() ); + } + iMethods.add( methodName ); } } } @@ -701,7 +714,16 @@ public class TypeManager { // header position TYPE_DESCRIPTION_INTERFACE_OFFSET header.writeInt32( data.size() + VTABLE_FIRST_FUNCTION_INDEX * 4 ); // offset of interface calls - //TODO interface calls + for( Entry> entry : interfaceMethods.entrySet() ) { + data.writeInt32( entry.getKey().getClassIndex() ); + List iMethods = entry.getValue(); + int nextClassPosition = data.size() + 4 * (1 + iMethods.size()); + data.writeInt32( nextClassPosition ); + for( FunctionName funcName : iMethods ) { + int functIdx = getFunctionsID.applyAsInt( funcName ); + data.writeInt32( functIdx ); + } + } data.writeInt32( 0 ); // no more interface in itable // header position TYPE_DESCRIPTION_INSTANCEOF_OFFSET diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCallInterfaceInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmCallInterfaceInstruction.java index 0d7283d..b8ef834 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCallInterfaceInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCallInterfaceInstruction.java @@ -23,6 +23,7 @@ import javax.annotation.Nonnull; import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.module.TypeManager.StructType; import de.inetsoftware.jwebassembly.wasm.ValueType; +import de.inetsoftware.jwebassembly.wasm.VariableOperator; /** * WasmInstruction for a function call. @@ -76,13 +77,15 @@ class WasmCallInterfaceInstruction extends WasmCallIndirectInstruction { FunctionName name = getFunctionName(); StructType type = getThisType(); int classIndex = type.getClassIndex(); + int interfaceFunctionIdx = options.functions.getFunctionIndex( name ); - //writer.writeLocal( VariableOperator.get, tempVarIdx ); // duplicate this on the stack + // duplicate this on the stack + writer.writeLocal( VariableOperator.get, getVariableIndexOfThis() ); writer.writeConst( classIndex, ValueType.i32 ); - //writer.writeConst( functionIndex, ValueType.i32 ); - //writer.writeFunctionCall( callInterface ); // parameters: this, classIndex, functionIndex + writer.writeConst( interfaceFunctionIdx * 4, ValueType.i32 ); + writer.writeFunctionCall( options.getCallInterface(), null ); // parameters: this, classIndex, functionIndex - //writer.writeVirtualFunctionCall( name, type ); + writer.writeVirtualFunctionCall( name, type ); throw new WasmException( "Interface calls are not supported.", getLineNumber() ); } }