From fcaa15d22dab050594171a40668386ef5047e2f7 Mon Sep 17 00:00:00 2001 From: Volker Date: Sat, 11 Aug 2018 18:12:40 +0200 Subject: [PATCH] Fix SWITCH start position detection and replace erroneous ValueStackManager --- .../jwebassembly/module/ModuleGenerator.java | 44 +++---- .../jwebassembly/module/ValueStackManger.java | 110 ------------------ .../runtime/ControlFlowOperators.java | 4 +- 3 files changed, 26 insertions(+), 132 deletions(-) delete mode 100644 src/de/inetsoftware/jwebassembly/module/ValueStackManger.java diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index f15cd41..9680e8c 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -53,8 +53,6 @@ public class ModuleGenerator { private BranchManger branchManager = new BranchManger( instructions ); - private ValueStackManger stackManager = new ValueStackManger(); - /** * Create a new generator. * @@ -162,7 +160,6 @@ public class ModuleGenerator { writeMethodSignature( method ); localVariables.reset(); - stackManager.reset(); branchManager.reset(); byteCode = code.getByteCode(); @@ -300,40 +297,32 @@ public class ModuleGenerator { case 6: // iconst_3 case 7: // iconst_4 case 8: // iconst_5 - stackManager.add( ValueType.i32, codePos ); instr = new WasmConstInstruction( Integer.valueOf( op - 3 ), ValueType.i32, codePos ); break; case 9: // lconst_0 case 10: // lconst_1 - stackManager.add( ValueType.i64, codePos ); instr = new WasmConstInstruction( Long.valueOf( op - 9 ), ValueType.i64, codePos ); break; case 11: // fconst_0 case 12: // fconst_1 case 13: // fconst_2 - stackManager.add( ValueType.f32, codePos ); instr = new WasmConstInstruction( Float.valueOf( op - 11 ), ValueType.f32, codePos ); break; case 14: // dconst_0 case 15: // dconst_1 - stackManager.add( ValueType.f64, codePos ); instr = new WasmConstInstruction( Double.valueOf( op - 14 ), ValueType.f64, codePos ); break; case 16: // bipush - stackManager.add( ValueType.i32, codePos ); instr = new WasmConstInstruction( Integer.valueOf( byteCode.readByte() ), ValueType.i32, codePos ); break; case 17: // sipush - stackManager.add( ValueType.i32, codePos ); instr = new WasmConstInstruction( Integer.valueOf( byteCode.readShort() ), ValueType.i32, codePos ); break; case 18: // ldc - stackManager.add( null, codePos ); instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedByte() ), codePos ); break; case 19: // ldc_w case 20: // ldc2_w - stackManager.add( null, codePos ); instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedShort() ), codePos ); break; case 21: // iload @@ -436,7 +425,6 @@ public class ModuleGenerator { //TODO case 86: // sastore case 87: // pop case 88: // pop2 - stackManager.remove(); instr = new WasmBlockInstruction( WasmBlockOperator.DROP, null, codePos ); break; case 89: // dup: duplicate the value on top of the stack @@ -706,11 +694,6 @@ public class ModuleGenerator { case 184: // invokestatic idx = byteCode.readUnsignedShort(); ConstantRef method = (ConstantRef)constantPool.get( idx ); - String signature = method.getType(); - type = getValueType( signature, signature.indexOf( ')' ) + 1 ); - if( type != null ) { - stackManager.add( type, codePos ); - } instr = new WasmCallInstruction( method, codePos ); break; //TODO case 185: // invokeinterface @@ -762,12 +745,13 @@ public class ModuleGenerator { byteCode.skip( 4 - padding ); } startPosition--; + int switchValuestartPosition = findPreviousPushCodePosition(); int defaultPosition = startPosition + byteCode.readInt(); int[] keys; int[] positions; if( isLookupSwitch ) { // lookupswitch - localVariables.useTempI32(); + localVariables.useTempI32(); //TODO int count = byteCode.readInt(); keys = new int[count]; positions = new int[count]; @@ -821,10 +805,31 @@ public class ModuleGenerator { instructions.add( new WasmNumericInstruction( NumericOperator.sub, ValueType.i32, codePos ) ); } } - int switchValuestartPosition = stackManager.getCodePosition( 0 ); branchManager.addSwitchOperator( switchValuestartPosition, 0, lineNumber, keys, positions, defaultPosition ); } + /** + * We need one value from the stack inside of a block. We need to find the code position on which the block can + * start. If this a function call or numeric expression this can be complex to find the right point. + * + * @return the code position + */ + private int findPreviousPushCodePosition() { + int valueCount = 0; + for( int i = instructions.size() - 1; i >= 0; i-- ) { + WasmInstruction instr = instructions.get( i ); + ValueType valueType = instr.getPushValueType(); + if( valueType != null ) { + valueCount++; + } + valueCount -= instr.getPopCount(); + if( valueCount == 1 ) { + return instr.getCodePosition(); + } + } + throw new WasmException( "Switch start position not found", sourceFile, -1 ); // should never occur + } + /** * Find the next higher value. * @@ -861,7 +866,6 @@ public class ModuleGenerator { */ @Nonnull private WasmLoadStoreInstruction loadStore( ValueType valueType, boolean load, @Nonnegative int idx, int codePos ) { - stackManager.add( valueType, codePos ); localVariables.use( valueType, idx ); return new WasmLoadStoreInstruction( load, idx, localVariables, codePos ); } diff --git a/src/de/inetsoftware/jwebassembly/module/ValueStackManger.java b/src/de/inetsoftware/jwebassembly/module/ValueStackManger.java deleted file mode 100644 index 74c02b2..0000000 --- a/src/de/inetsoftware/jwebassembly/module/ValueStackManger.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright 2018 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.util.Arrays; - -/** - * This manager monitor the value stack of a method - * - * @author Volker Berlin - * - */ -class ValueStackManger { - - private StackElement[] elements; - - private int size; - - /** - * Create a new instance. - */ - ValueStackManger() { - // initialize with a initial capacity that should be enough for the most methods - elements = new StackElement[8]; - for( int i = 0; i < elements.length; i++ ) { - elements[i] = new StackElement(); - } - } - - /** - * Reset the manager to an initial state - */ - void reset() { - size = 0; - } - - /** - * Add an value to the stack. - * - * @param valueType - * the type of the value on the stack - * @param codePosition - * the code position on which this value was push to the stack - */ - void add( ValueType valueType, int codePosition ) { - ensureCapacity(); - StackElement el = elements[size++]; - el.valueType = valueType; - el.codePosition = codePosition; - } - - /** - * Remove the the last value from the stack - */ - void remove() { - size--; - } - - /** - * Get the code position on which the value on the stack was define. - * - * @param deep the position in the stack, 0 means the last position - * @return the code position - */ - int getCodePosition( int deep ) { - return elements[size - deep - 1].codePosition; - } - - /** - * Get the value type of the last value on the stack. - * - * @return the value type - */ - ValueType getLastValueType() { - return elements[size - 1].valueType; - } - - /** - * Ensure that there is enough capacity. - */ - private void ensureCapacity() { - if( size == elements.length ) { - elements = Arrays.copyOf( elements, size + 1 ); - elements[size] = new StackElement(); - } - } - - /** - * The state of a single stack position. - */ - private static class StackElement { - private ValueType valueType; - - private int codePosition; - } -} diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index 3e23d7d..4f05828 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -193,12 +193,12 @@ public class ControlFlowOperators extends AbstractBaseTest { @Export static int switchDirect() { - return tableSwitch(10) + (tableSwitch( 9 ) * 10) + + (tableSwitch( -1 ) * 100) + (lookupSwitch(Integer.MAX_VALUE) * 1000) + (lookupSwitch(0) * 10000 ); + return tableSwitch(10) + (tableSwitch( 9 ) * 10) + (tableSwitch( -1 ) * 100) + (lookupSwitch(Integer.MAX_VALUE) * 1000) + (lookupSwitch(0) * 10000 ); } private static int tableSwitch( int a ) { int b; - switch(a){ + switch( 1 + a - 1 ){ case 8: case 9: b = 2;