mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Handle DUP2 as two dup if used for non 64 bit values
This commit is contained in:
parent
534cd19c0f
commit
6520370e02
@ -310,7 +310,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
break;
|
break;
|
||||||
case 89: // dup: duplicate the value on top of the stack
|
case 89: // dup: duplicate the value on top of the stack
|
||||||
case 92: // dup2
|
case 92: // dup2
|
||||||
addDupInstruction( codePos, lineNumber );
|
addDupInstruction( op == 92, codePos, lineNumber );
|
||||||
break;
|
break;
|
||||||
case 90: // dup_x1
|
case 90: // dup_x1
|
||||||
case 93: // dup2_x1
|
case 93: // dup2_x1
|
||||||
|
@ -20,6 +20,8 @@ import java.util.ArrayDeque;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import de.inetsoftware.jwebassembly.WasmException;
|
import de.inetsoftware.jwebassembly.WasmException;
|
||||||
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
||||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||||
@ -42,6 +44,7 @@ class StackInspector {
|
|||||||
* the current code position, important to follow jumps in the code
|
* the current code position, important to follow jumps in the code
|
||||||
* @return details of the stack position
|
* @return details of the stack position
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
static StackValue findInstructionThatPushValue( List<WasmInstruction> instructions, int count, int javaCodePos ) {
|
static StackValue findInstructionThatPushValue( List<WasmInstruction> instructions, int count, int javaCodePos ) {
|
||||||
// because there can be jumps (GOTO) we can analyze the stack only forward. If we iterate backward we will not see that we are in a jump.
|
// because there can be jumps (GOTO) we can analyze the stack only forward. If we iterate backward we will not see that we are in a jump.
|
||||||
ArrayDeque<StackValue> stack = new ArrayDeque<>();
|
ArrayDeque<StackValue> stack = new ArrayDeque<>();
|
||||||
|
@ -218,6 +218,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
* current code position for which the stack is inspected
|
* current code position for which the stack is inspected
|
||||||
* @return the instruction
|
* @return the instruction
|
||||||
*/
|
*/
|
||||||
|
@Nonnull
|
||||||
private WasmInstruction findInstructionThatPushValue( int count, int javaCodePos ) {
|
private WasmInstruction findInstructionThatPushValue( int count, int javaCodePos ) {
|
||||||
return StackInspector.findInstructionThatPushValue( instructions, count, javaCodePos ).instr;
|
return StackInspector.findInstructionThatPushValue( instructions, count, javaCodePos ).instr;
|
||||||
}
|
}
|
||||||
@ -332,36 +333,62 @@ public abstract class WasmCodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a WasmDupInstruction.
|
* Get a possible slot from the instruction
|
||||||
*
|
*
|
||||||
* @param javaCodePos
|
* @param instr
|
||||||
* the code position/offset in the Java method
|
* the instruction
|
||||||
* @param lineNumber
|
* @return the slot or -1 if there no slot
|
||||||
* the line number in the Java source code
|
|
||||||
*/
|
*/
|
||||||
protected void addDupInstruction( int javaCodePos, int lineNumber ) {
|
private static int getPossibleSlot( @Nonnull WasmInstruction instr ) {
|
||||||
WasmInstruction instr = findInstructionThatPushValue( 1, javaCodePos );
|
|
||||||
AnyType type = instr.getPushValueType();
|
|
||||||
int slot = -1;
|
|
||||||
// if it is a GET to a local variable then we can use it
|
// if it is a GET to a local variable then we can use it
|
||||||
if( instr.getType() == Type.Local ) {
|
if( instr.getType() == Type.Local ) {
|
||||||
WasmLocalInstruction local1 = (WasmLocalInstruction)instr;
|
WasmLocalInstruction local1 = (WasmLocalInstruction)instr;
|
||||||
switch( local1.getOperator() ) {
|
switch( local1.getOperator() ) {
|
||||||
case get:
|
case get:
|
||||||
case tee:
|
case tee:
|
||||||
slot = local1.getSlot();
|
return local1.getSlot();
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a WasmDupInstruction.
|
||||||
|
*
|
||||||
|
* @param dup2
|
||||||
|
* call from dup2 instruction
|
||||||
|
* @param javaCodePos
|
||||||
|
* the code position/offset in the Java method
|
||||||
|
* @param lineNumber
|
||||||
|
* the line number in the Java source code
|
||||||
|
*/
|
||||||
|
protected void addDupInstruction( boolean dup2, int javaCodePos, int lineNumber ) {
|
||||||
|
WasmInstruction instr = findInstructionThatPushValue( 1, javaCodePos );
|
||||||
|
AnyType type = instr.getPushValueType();
|
||||||
|
int slot = getPossibleSlot( instr );
|
||||||
|
|
||||||
|
// occur with:
|
||||||
|
// int[] data = new int[x];
|
||||||
|
// data[i] |= any;
|
||||||
|
instr = dup2 && type != ValueType.i64 && type != ValueType.f64 ? //
|
||||||
|
findInstructionThatPushValue( 2, javaCodePos ) : null;
|
||||||
|
|
||||||
//alternate we need to create a new locale variable
|
//alternate we need to create a new locale variable
|
||||||
if( slot < 0 ) {
|
if( slot < 0 ) {
|
||||||
|
if( instr != null ) {
|
||||||
|
throw new WasmException( "DUP2 for two slots without variables", lineNumber );
|
||||||
|
}
|
||||||
slot = getTempVariable( type, javaCodePos, javaCodePos + 1 );
|
slot = getTempVariable( type, javaCodePos, javaCodePos + 1 );
|
||||||
instructions.add( new WasmLoadStoreInstruction( VariableOperator.tee, slot, localVariables, javaCodePos, lineNumber ) );
|
instructions.add( new WasmLoadStoreInstruction( VariableOperator.tee, slot, localVariables, javaCodePos, lineNumber ) );
|
||||||
instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) );
|
instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) );
|
||||||
// an alternative solution can be a function call with multiple return values but this seems to be slower
|
// 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 )
|
// new SyntheticFunctionName( "dup" + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber )
|
||||||
} else {
|
} else {
|
||||||
|
if( instr != null ) {
|
||||||
|
int slot2 = getPossibleSlot( instr );
|
||||||
|
instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot2, localVariables, javaCodePos, lineNumber ) );
|
||||||
|
}
|
||||||
instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) );
|
instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) );
|
||||||
localVariables.expandUse( slot, javaCodePos );
|
localVariables.expandUse( slot, javaCodePos );
|
||||||
}
|
}
|
||||||
@ -861,7 +888,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
break;
|
break;
|
||||||
case NEW_DEFAULT:
|
case NEW_DEFAULT:
|
||||||
if( options.useGC() ) {
|
if( options.useGC() ) {
|
||||||
addDupInstruction( javaCodePos, lineNumber );
|
addDupInstruction( false, javaCodePos, lineNumber );
|
||||||
addConstInstruction( structInst.getStructType().getVTable(), javaCodePos, lineNumber );
|
addConstInstruction( structInst.getStructType().getVTable(), javaCodePos, lineNumber );
|
||||||
instructions.add( new WasmStructInstruction( StructOperator.SET, typeName, new NamedStorageType( ValueType.i32, "", TypeManager.FIELD_VTABLE ), javaCodePos, lineNumber, types ) );
|
instructions.add( new WasmStructInstruction( StructOperator.SET, typeName, new NamedStorageType( ValueType.i32, "", TypeManager.FIELD_VTABLE ), javaCodePos, lineNumber, types ) );
|
||||||
break;
|
break;
|
||||||
@ -920,7 +947,7 @@ public abstract class WasmCodeBuilder {
|
|||||||
int pos = instructions.size();
|
int pos = instructions.size();
|
||||||
addStructInstruction( StructOperator.NEW_DEFAULT, lambdaTypeName, null, javaCodePos, lineNumber );
|
addStructInstruction( StructOperator.NEW_DEFAULT, lambdaTypeName, null, javaCodePos, lineNumber );
|
||||||
if( !options.useGC() ) {
|
if( !options.useGC() ) {
|
||||||
addDupInstruction( javaCodePos, lineNumber );
|
addDupInstruction( false, javaCodePos, lineNumber );
|
||||||
}
|
}
|
||||||
int slot = ((WasmLocalInstruction)findInstructionThatPushValue( 1, javaCodePos )).getSlot();
|
int slot = ((WasmLocalInstruction)findInstructionThatPushValue( 1, javaCodePos )).getSlot();
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ public class ArrayOperations extends AbstractBaseTest {
|
|||||||
addParam( list, script, "loopObject" );
|
addParam( list, script, "loopObject" );
|
||||||
addParam( list, script, "copyBack2Front" );
|
addParam( list, script, "copyBack2Front" );
|
||||||
addParam( list, script, "copyFront2Back" );
|
addParam( list, script, "copyFront2Back" );
|
||||||
|
addParam( list, script, "dup2" );
|
||||||
addParam( list, script, "dup_x2" );
|
addParam( list, script, "dup_x2" );
|
||||||
addParam( list, script, "byteArrayClassName" );
|
addParam( list, script, "byteArrayClassName" );
|
||||||
addParam( list, script, "shortArrayClassName" );
|
addParam( list, script, "shortArrayClassName" );
|
||||||
@ -212,6 +213,18 @@ public class ArrayOperations extends AbstractBaseTest {
|
|||||||
return crc.getValue();
|
return crc.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int dup2() {
|
||||||
|
int[] data = {1,2,3};
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < data.length; i++ ) {
|
||||||
|
data[i] |= 13; // use dup2 to duplicate the array and the index
|
||||||
|
sum += data[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int dup_x2() {
|
static int dup_x2() {
|
||||||
Object[] data = {null,null,null};
|
Object[] data = {null,null,null};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user