mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Fix SWITCH start position detection and replace erroneous ValueStackManager
This commit is contained in:
parent
ae39ccb302
commit
fcaa15d22d
@ -53,8 +53,6 @@ public class ModuleGenerator {
|
|||||||
|
|
||||||
private BranchManger branchManager = new BranchManger( instructions );
|
private BranchManger branchManager = new BranchManger( instructions );
|
||||||
|
|
||||||
private ValueStackManger stackManager = new ValueStackManger();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new generator.
|
* Create a new generator.
|
||||||
*
|
*
|
||||||
@ -162,7 +160,6 @@ public class ModuleGenerator {
|
|||||||
writeMethodSignature( method );
|
writeMethodSignature( method );
|
||||||
|
|
||||||
localVariables.reset();
|
localVariables.reset();
|
||||||
stackManager.reset();
|
|
||||||
branchManager.reset();
|
branchManager.reset();
|
||||||
|
|
||||||
byteCode = code.getByteCode();
|
byteCode = code.getByteCode();
|
||||||
@ -300,40 +297,32 @@ public class ModuleGenerator {
|
|||||||
case 6: // iconst_3
|
case 6: // iconst_3
|
||||||
case 7: // iconst_4
|
case 7: // iconst_4
|
||||||
case 8: // iconst_5
|
case 8: // iconst_5
|
||||||
stackManager.add( ValueType.i32, codePos );
|
|
||||||
instr = new WasmConstInstruction( Integer.valueOf( op - 3 ), ValueType.i32, codePos );
|
instr = new WasmConstInstruction( Integer.valueOf( op - 3 ), ValueType.i32, codePos );
|
||||||
break;
|
break;
|
||||||
case 9: // lconst_0
|
case 9: // lconst_0
|
||||||
case 10: // lconst_1
|
case 10: // lconst_1
|
||||||
stackManager.add( ValueType.i64, codePos );
|
|
||||||
instr = new WasmConstInstruction( Long.valueOf( op - 9 ), ValueType.i64, codePos );
|
instr = new WasmConstInstruction( Long.valueOf( op - 9 ), ValueType.i64, codePos );
|
||||||
break;
|
break;
|
||||||
case 11: // fconst_0
|
case 11: // fconst_0
|
||||||
case 12: // fconst_1
|
case 12: // fconst_1
|
||||||
case 13: // fconst_2
|
case 13: // fconst_2
|
||||||
stackManager.add( ValueType.f32, codePos );
|
|
||||||
instr = new WasmConstInstruction( Float.valueOf( op - 11 ), ValueType.f32, codePos );
|
instr = new WasmConstInstruction( Float.valueOf( op - 11 ), ValueType.f32, codePos );
|
||||||
break;
|
break;
|
||||||
case 14: // dconst_0
|
case 14: // dconst_0
|
||||||
case 15: // dconst_1
|
case 15: // dconst_1
|
||||||
stackManager.add( ValueType.f64, codePos );
|
|
||||||
instr = new WasmConstInstruction( Double.valueOf( op - 14 ), ValueType.f64, codePos );
|
instr = new WasmConstInstruction( Double.valueOf( op - 14 ), ValueType.f64, codePos );
|
||||||
break;
|
break;
|
||||||
case 16: // bipush
|
case 16: // bipush
|
||||||
stackManager.add( ValueType.i32, codePos );
|
|
||||||
instr = new WasmConstInstruction( Integer.valueOf( byteCode.readByte() ), ValueType.i32, codePos );
|
instr = new WasmConstInstruction( Integer.valueOf( byteCode.readByte() ), ValueType.i32, codePos );
|
||||||
break;
|
break;
|
||||||
case 17: // sipush
|
case 17: // sipush
|
||||||
stackManager.add( ValueType.i32, codePos );
|
|
||||||
instr = new WasmConstInstruction( Integer.valueOf( byteCode.readShort() ), ValueType.i32, codePos );
|
instr = new WasmConstInstruction( Integer.valueOf( byteCode.readShort() ), ValueType.i32, codePos );
|
||||||
break;
|
break;
|
||||||
case 18: // ldc
|
case 18: // ldc
|
||||||
stackManager.add( null, codePos );
|
|
||||||
instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedByte() ), codePos );
|
instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedByte() ), codePos );
|
||||||
break;
|
break;
|
||||||
case 19: // ldc_w
|
case 19: // ldc_w
|
||||||
case 20: // ldc2_w
|
case 20: // ldc2_w
|
||||||
stackManager.add( null, codePos );
|
|
||||||
instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedShort() ), codePos );
|
instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedShort() ), codePos );
|
||||||
break;
|
break;
|
||||||
case 21: // iload
|
case 21: // iload
|
||||||
@ -436,7 +425,6 @@ public class ModuleGenerator {
|
|||||||
//TODO case 86: // sastore
|
//TODO case 86: // sastore
|
||||||
case 87: // pop
|
case 87: // pop
|
||||||
case 88: // pop2
|
case 88: // pop2
|
||||||
stackManager.remove();
|
|
||||||
instr = new WasmBlockInstruction( WasmBlockOperator.DROP, null, codePos );
|
instr = new WasmBlockInstruction( WasmBlockOperator.DROP, null, codePos );
|
||||||
break;
|
break;
|
||||||
case 89: // dup: duplicate the value on top of the stack
|
case 89: // dup: duplicate the value on top of the stack
|
||||||
@ -706,11 +694,6 @@ public class ModuleGenerator {
|
|||||||
case 184: // invokestatic
|
case 184: // invokestatic
|
||||||
idx = byteCode.readUnsignedShort();
|
idx = byteCode.readUnsignedShort();
|
||||||
ConstantRef method = (ConstantRef)constantPool.get( idx );
|
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 );
|
instr = new WasmCallInstruction( method, codePos );
|
||||||
break;
|
break;
|
||||||
//TODO case 185: // invokeinterface
|
//TODO case 185: // invokeinterface
|
||||||
@ -762,12 +745,13 @@ public class ModuleGenerator {
|
|||||||
byteCode.skip( 4 - padding );
|
byteCode.skip( 4 - padding );
|
||||||
}
|
}
|
||||||
startPosition--;
|
startPosition--;
|
||||||
|
int switchValuestartPosition = findPreviousPushCodePosition();
|
||||||
|
|
||||||
int defaultPosition = startPosition + byteCode.readInt();
|
int defaultPosition = startPosition + byteCode.readInt();
|
||||||
int[] keys;
|
int[] keys;
|
||||||
int[] positions;
|
int[] positions;
|
||||||
if( isLookupSwitch ) { // lookupswitch
|
if( isLookupSwitch ) { // lookupswitch
|
||||||
localVariables.useTempI32();
|
localVariables.useTempI32(); //TODO
|
||||||
int count = byteCode.readInt();
|
int count = byteCode.readInt();
|
||||||
keys = new int[count];
|
keys = new int[count];
|
||||||
positions = new int[count];
|
positions = new int[count];
|
||||||
@ -821,10 +805,31 @@ public class ModuleGenerator {
|
|||||||
instructions.add( new WasmNumericInstruction( NumericOperator.sub, ValueType.i32, codePos ) );
|
instructions.add( new WasmNumericInstruction( NumericOperator.sub, ValueType.i32, codePos ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int switchValuestartPosition = stackManager.getCodePosition( 0 );
|
|
||||||
branchManager.addSwitchOperator( switchValuestartPosition, 0, lineNumber, keys, positions, defaultPosition );
|
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.
|
* Find the next higher value.
|
||||||
*
|
*
|
||||||
@ -861,7 +866,6 @@ public class ModuleGenerator {
|
|||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private WasmLoadStoreInstruction loadStore( ValueType valueType, boolean load, @Nonnegative int idx, int codePos ) {
|
private WasmLoadStoreInstruction loadStore( ValueType valueType, boolean load, @Nonnegative int idx, int codePos ) {
|
||||||
stackManager.add( valueType, codePos );
|
|
||||||
localVariables.use( valueType, idx );
|
localVariables.use( valueType, idx );
|
||||||
return new WasmLoadStoreInstruction( load, idx, localVariables, codePos );
|
return new WasmLoadStoreInstruction( load, idx, localVariables, codePos );
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -193,12 +193,12 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int switchDirect() {
|
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 ) {
|
private static int tableSwitch( int a ) {
|
||||||
int b;
|
int b;
|
||||||
switch(a){
|
switch( 1 + a - 1 ){
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
b = 2;
|
b = 2;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user