diff --git a/src/de/inetsoftware/jwebassembly/module/LocaleVariableManager.java b/src/de/inetsoftware/jwebassembly/module/LocaleVariableManager.java index 13c139b..0684d86 100644 --- a/src/de/inetsoftware/jwebassembly/module/LocaleVariableManager.java +++ b/src/de/inetsoftware/jwebassembly/module/LocaleVariableManager.java @@ -359,6 +359,20 @@ class LocaleVariableManager { return var.idx; } + /** + * Expand code range for which the variable is valid + * + * @param slot + * the memory/slot index of the local variable + * @param javaCodePos + * the new end code position in the Java method + */ + void expandUse( int slot, int javaCodePos ) { + Variable var = variables[slot]; + //TODO does we need to check for overlap with other slots? + var.endPos = Math.max( var.endPos, javaCodePos ); + } + /** * Get the WebAssembly variable index of the given Java Slot. * diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 6c5e58d..6dabb17 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -316,23 +316,28 @@ public abstract class WasmCodeBuilder { protected void addDupInstruction( int javaCodePos, int lineNumber ) { WasmInstruction instr = findInstructionThatPushValue( 1, javaCodePos ); AnyType type = instr.getPushValueType(); - int varIndex = -1; + int slot = -1; // if it is a GET to a local variable then we can use it if( instr.getType() == Type.Local ) { WasmLocalInstruction local1 = (WasmLocalInstruction)instr; - if( local1.getOperator() == VariableOperator.get ) { - varIndex = local1.getIndex(); + switch( local1.getOperator() ) { + case get: + case tee: + slot = local1.getSlot(); + break; + default: } } //alternate we need to create a new locale variable - if( varIndex < 0 ) { - varIndex = getTempVariable( type, javaCodePos, javaCodePos + 1 ); - instructions.add( new WasmLoadStoreInstruction( VariableOperator.tee, varIndex, localVariables, javaCodePos, lineNumber ) ); - instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, varIndex, localVariables, javaCodePos, lineNumber ) ); + if( slot < 0 ) { + slot = getTempVariable( type, javaCodePos, javaCodePos + 1 ); + instructions.add( new WasmLoadStoreInstruction( VariableOperator.tee, 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 // new SyntheticFunctionName( "dup" + storeType, "local.get 0 local.get 0 return", storeType, null, storeType, storeType ), codePos, lineNumber ) } else { - instructions.add( new WasmLocalInstruction( VariableOperator.get, varIndex, localVariables, javaCodePos, lineNumber ) ); + instructions.add( new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) ); + localVariables.expandUse( slot, javaCodePos ); } } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmLocalInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmLocalInstruction.java index df4c51f..e2fb3bf 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmLocalInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmLocalInstruction.java @@ -90,6 +90,16 @@ class WasmLocalInstruction extends WasmInstruction { this.op = op; } + /** + * Get the slot of the locals + * + * @return the Java slot for the variable + */ + @Nonnegative + int getSlot() { + return idx; + } + /** * Get the number of the locals *