duplicate the this on stack before a virtual method call invoke

This commit is contained in:
Volker Berlin 2019-06-09 21:09:05 +02:00
parent 1ee77584d9
commit 90126b16da
5 changed files with 35 additions and 8 deletions

View File

@ -1018,8 +1018,13 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
protected void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx ) throws IOException { protected void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx, int tempVarIdx ) throws IOException {
callIndirect = true; callIndirect = true;
// duplicate this on the stack
writeLocal( VariableOperator.tee, tempVarIdx );
writeLocal( VariableOperator.get, tempVarIdx );
codeStream.writeOpCode( STRUCT_GET ); codeStream.writeOpCode( STRUCT_GET );
codeStream.writeValueType( type ); codeStream.writeValueType( type );
codeStream.writeVaruint32( 0 ); // vtable is ever on position 0 codeStream.writeVaruint32( 0 ); // vtable is ever on position 0

View File

@ -244,10 +244,12 @@ public abstract class ModuleWriter implements Closeable {
* the base type that should be called * the base type that should be called
* @param virtualFunctionIdx * @param virtualFunctionIdx
* the index of the virtual method in the object. If the value < 0 a direct call should be used. * the index of the virtual method in the object. If the value < 0 a direct call should be used.
* @param tempVarIdx
* the index of a temporary variable of type "type" to duplicate "this"
* @throws IOException * @throws IOException
* if any I/O error occur * if any I/O error occur
*/ */
protected abstract void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx ) throws IOException; protected abstract void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx, int tempVarIdx ) throws IOException;
/** /**
* Write a block/branch code * Write a block/branch code

View File

@ -30,23 +30,36 @@ import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
*/ */
class WasmCallIndirectInstruction extends WasmCallInstruction { class WasmCallIndirectInstruction extends WasmCallInstruction {
private int virtualFunctionIdx = -1; private int virtualFunctionIdx = -1;
private StructType type; private final StructType type;
private final int tempVar;
private final LocaleVariableManager localVariables;
/** /**
* Create an instance of a function call instruction * Create an instance of a function call instruction
* *
* @param name * @param name
* the function name that should be called * the function name that should be called
* @param type
* the type with the virtual method/function
* @param tempVar
* the slot of a temporary variable of type "type" to duplicate "this"
* @param localVariables
* the manager for local variables to translate the Java slot of the temporary variable into wasm local
* position
* @param javaCodePos * @param javaCodePos
* the code position/offset in the Java method * the code position/offset in the Java method
* @param lineNumber * @param lineNumber
* the line number in the Java source code * the line number in the Java source code
*/ */
WasmCallIndirectInstruction( FunctionName name, @Nonnull StructType type, int javaCodePos, int lineNumber ) { WasmCallIndirectInstruction( FunctionName name, @Nonnull StructType type, int tempVar, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) {
super( name, javaCodePos, lineNumber ); super( name, javaCodePos, lineNumber );
this.type = type; this.type = type;
this.tempVar = tempVar;
this.localVariables = localVariables;
} }
/** /**
@ -74,7 +87,8 @@ class WasmCallIndirectInstruction extends WasmCallInstruction {
if( virtualFunctionIdx < 0 || true ) { if( virtualFunctionIdx < 0 || true ) {
super.writeTo( writer ); super.writeTo( writer );
} else { } else {
writer.writeVirtualFunctionCall( getFunctionName(), type, virtualFunctionIdx ); int tempVarIdx = localVariables.get( tempVar, getCodePosition() );
writer.writeVirtualFunctionCall( getFunctionName(), type, virtualFunctionIdx, tempVarIdx );
} }
} }

View File

@ -285,7 +285,8 @@ public abstract class WasmCodeBuilder {
*/ */
protected void addCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber ) { protected void addCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
StructType type = types.valueOf( name.className ); StructType type = types.valueOf( name.className );
instructions.add( new WasmCallIndirectInstruction( name, type, javaCodePos, lineNumber ) ); int tempVar = localVariables.getTempVariable( type, javaCodePos, javaCodePos + 1 );
instructions.add( new WasmCallIndirectInstruction( name, type, tempVar, localVariables, javaCodePos, lineNumber ) );
} }
/** /**

View File

@ -580,8 +580,13 @@ public class TextModuleWriter extends ModuleWriter {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
protected void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx ) throws IOException { protected void writeVirtualFunctionCall( FunctionName name, AnyType type, int virtualFunctionIdx, int tempVarIdx ) throws IOException {
callIndirect = true; callIndirect = true;
// duplicate this on the stack
writeLocal( VariableOperator.tee, tempVarIdx );
writeLocal( VariableOperator.get, tempVarIdx );
newline( methodOutput ); newline( methodOutput );
methodOutput.append( "struct.get " ).append( normalizeName( type.toString() ) ).append( " 0 ;;vtable" ); // vtable is ever on position 0 methodOutput.append( "struct.get " ).append( normalizeName( type.toString() ) ).append( " 0 ;;vtable" ); // vtable is ever on position 0
newline( methodOutput ); newline( methodOutput );