Use a Placeholder Instruction for Java DUP opertions.

This commit is contained in:
Volker Berlin 2019-11-16 19:17:22 +01:00
parent 8649438fa9
commit 10b754e3e3
4 changed files with 117 additions and 16 deletions

View File

@ -282,14 +282,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
break;
case 89: // dup: duplicate the value on top of the stack
case 92: // dup2
// save it in a temporary variable and load it 2 times; optimize will change it to TEE
storeType = findValueTypeFromStack( 1 );
int idx = getTempVariable( storeType, codePos, codePos + 1 );
addLoadStoreInstruction( storeType, false, idx, codePos, lineNumber );
addLoadStoreInstruction( storeType, true, idx, codePos, lineNumber );
addLoadStoreInstruction( storeType, true, idx, codePos, lineNumber );
// addCallInstruction( new SyntheticFunctionName( "dup"
// + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber );
addDupInstruction( codePos, lineNumber );
break;
case 90: // dup_x1
case 91: // dup_x2
@ -415,7 +408,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
addNumericInstruction( NumericOperator.xor, ValueType.i64, codePos, lineNumber );
break;
case 132: // iinc
idx = byteCode.readUnsignedIndex( wide );
int idx = byteCode.readUnsignedIndex( wide );
addLoadStoreInstruction( ValueType.i32, true, idx, codePos, lineNumber );
addConstInstruction( (int)(wide ? byteCode.readShort() : byteCode.readByte()), ValueType.i32, codePos, lineNumber );
addNumericInstruction( NumericOperator.add, ValueType.i32, codePos, lineNumber );

View File

@ -246,7 +246,6 @@ public abstract class WasmCodeBuilder {
* @param lineNumber
* the line number in the Java source code
*/
@Nonnull
protected void addLoadStoreInstruction( AnyType valueType, boolean load, @Nonnegative int javaIdx, int javaCodePos, int lineNumber ) {
localVariables.use( valueType, javaIdx, javaCodePos );
instructions.add( new WasmLoadStoreInstruction( load, javaIdx, localVariables, javaCodePos, lineNumber ) );
@ -264,7 +263,6 @@ public abstract class WasmCodeBuilder {
* @param lineNumber
* the line number in the Java source code
*/
@Nonnull
protected void addLocalInstruction( VariableOperator op, @Nonnegative int wasmIdx, int javaCodePos, int lineNumber ) {
switch( op ) {
case set:
@ -275,6 +273,22 @@ public abstract class WasmCodeBuilder {
instructions.add( new WasmLocalInstruction( op, wasmIdx, javaCodePos, lineNumber ) );
}
/**
* Create a WasmDupInstruction.
*
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
protected void addDupInstruction( int javaCodePos, int lineNumber ) {
AnyType type = findValueTypeFromStack( 1 );
int idx = getTempVariable( type, javaCodePos, javaCodePos + 1 );
instructions.add( new WasmDupInstruction( idx, type, localVariables, javaCodePos, lineNumber ) );
// an alternative solution can be a function call with multiple return values but this seems to be slower
// new SyntheticFunctionName( "dup" + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber )
}
/**
* Add a global instruction
*
@ -409,10 +423,11 @@ public abstract class WasmCodeBuilder {
if( instr.getType() == Type.Struct ) {
WasmStructInstruction struct = (WasmStructInstruction)instr;
if( struct.getOperator() == StructOperator.NEW_DEFAULT ) {
instructions.remove( i ); // NEW_DEFAULT
instructions.remove( i ); // SET temp from a dup of the instance reference
instructions.remove( i ); // GET temp from a dup of the instance reference
instructions.remove( i ); // GET temp from a dup of the instance reference
instructions.set( i, new WasmNopInstruction( struct.getCodePosition(), struct.getLineNumber() ) ); // replace NEW_DEFAULT with Nop, Nop because the code position can be needed for the branch manager
instr = instructions.get( ++i );
if( instr.getType() == Type.Dup ) {
instructions.remove( i ); // dup of the instance reference if it is later assign, missing if the object after the constructor is never assign
}
break;
}
}

View File

@ -0,0 +1,93 @@
/*
Copyright 2019 Volker Berlin (i-net software)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package de.inetsoftware.jwebassembly.module;
import java.io.IOException;
import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
/**
* WasmInstruction that emulate the Java dup instruction which duplicate the value on the stack.
*
* @author Volker Berlin
*
*/
class WasmDupInstruction extends WasmInstruction {
private int idx;
private AnyType type;
private LocaleVariableManager localVariables;
/**
* Create an instance of a dup instruction
*
* @param idx
* the memory/slot idx of the temp variable
* @param type
* the type of the duplicate value
* @param localVariables
* the manager for local variables
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
WasmDupInstruction( int idx, AnyType type, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) {
super( javaCodePos, lineNumber );
this.idx = idx;
this.type = type;
this.localVariables = localVariables;
}
/**
* {@inheritDoc}
*/
@Override
Type getType() {
return Type.Dup;
}
/**
* {@inheritDoc}
*/
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
// save it in a temporary variable and load it 2 times;
int index = localVariables.get( idx, getCodePosition() );
writer.writeLocal( VariableOperator.tee, index );
writer.writeLocal( VariableOperator.get, index );
}
/**
* {@inheritDoc}
*/
AnyType getPushValueType() {
return type;
}
/**
* {@inheritDoc}
*/
@Override
int getPopCount() {
return 0;
}
}

View File

@ -35,7 +35,7 @@ abstract class WasmInstruction {
* Type of instruction to faster differ as with instanceof.
*/
static enum Type {
Const, Convert, Local, Global, Table, Block, Numeric, Nop, Call, CallIndirect, Array, Struct, DupThis;
Const, Convert, Local, Global, Table, Block, Numeric, Nop, Call, CallIndirect, Array, Struct, Dup, DupThis;
}
private int javaCodePos;