mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +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 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 );
|
||||
}
|
||||
|
@ -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
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user