mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
fix loop detection for nested loops
This commit is contained in:
parent
7823db2708
commit
f52c41ae14
@ -203,9 +203,18 @@ class BranchManager {
|
||||
// if a condition form outside of the loop point inside the loop then it must be conditional return and a jump to the loop condition.
|
||||
for( int n = b - 1; n >= 0; n-- ) {
|
||||
ParsedBlock prevBlock = parsedOperations.get( n );
|
||||
if( prevBlock.op == JavaBlockOperator.IF && prevBlock.startPosition < start && prevBlock.endPosition > start
|
||||
&& prevBlock.endPosition < parsedBlock.startPosition ) {
|
||||
prevBlock.endPosition = start;
|
||||
switch( prevBlock.op ) {
|
||||
case IF:
|
||||
if( prevBlock.startPosition < start && prevBlock.endPosition > start && prevBlock.endPosition < parsedBlock.startPosition ) {
|
||||
prevBlock.endPosition = start;
|
||||
}
|
||||
break;
|
||||
case LOOP:
|
||||
if( start == prevBlock.nextPosition ) {
|
||||
loop.startPosition = prevBlock.startPosition;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -543,31 +552,16 @@ class BranchManager {
|
||||
}
|
||||
|
||||
if( branch == null ) {
|
||||
if( startBlock.endPosition > parent.endPos ) {
|
||||
// we jump outside the parent. This is like a conditional break.
|
||||
//TODO should be BR_IF
|
||||
branch = new BranchNode( startPos - 1, startPos, WasmBlockOperator.IF, WasmBlockOperator.END, ValueType.empty );
|
||||
parent.add( branch );
|
||||
breakOperations.add( new BreakBlock( branch, startPos, startBlock.endPosition ) );
|
||||
return;
|
||||
}
|
||||
branch = new BranchNode( startPos - 1, endPos, WasmBlockOperator.IF, WasmBlockOperator.END, ValueType.empty );
|
||||
parent.add( branch );
|
||||
if( startBlock.endPosition > parent.endPos ) {
|
||||
int count = 0;
|
||||
for( int j = 0; j < instructions.size(); j++ ) {
|
||||
WasmInstruction instr = instructions.get( j );
|
||||
int pos = instr.getCodePosition();
|
||||
if( pos < startPos ) {
|
||||
continue;
|
||||
}
|
||||
if( pos >= endPos ) {
|
||||
break;
|
||||
}
|
||||
if( instr.getType() == Type.Jump ) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if( count == 0 ) {
|
||||
// we jump outside the parent and there are no instructions. This is like a conditional break
|
||||
//TODO should be BR_IF
|
||||
breakOperations.add( new BreakBlock( branch, endPos, startBlock.endPosition ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
startBlock.negateCompare();
|
||||
|
||||
@ -1062,21 +1056,22 @@ class BranchManager {
|
||||
* @param parsedOperations
|
||||
* the not consumed operations in the parent branch
|
||||
*/
|
||||
private void calculateGoto ( BranchNode parent, ParsedBlock gotoBlock, List<ParsedBlock> parsedOperations ) {
|
||||
private void calculateGoto ( @Nonnull BranchNode parent, @Nonnull ParsedBlock gotoBlock, List<ParsedBlock> parsedOperations ) {
|
||||
int jump = gotoBlock.endPosition; // jump position of the GOTO
|
||||
int start = gotoBlock.startPosition;
|
||||
if( start > jump ) {
|
||||
// back jump to a previous position like in loops
|
||||
int deep = 0;
|
||||
while( parent != null ) {
|
||||
if( parent.startOp == WasmBlockOperator.LOOP && parent.startPos == jump ) {
|
||||
BranchNode node = parent;
|
||||
do {
|
||||
if( node.startOp == WasmBlockOperator.LOOP && node.startPos == jump ) {
|
||||
// the loop instruction itself doesn’t result in an iteration, instead a br 0 instruction causes the loop to repeat
|
||||
parent.add( new BranchNode( start, start, WasmBlockOperator.BR, null, deep ) ); // continue to the start of the loop
|
||||
return;
|
||||
}
|
||||
parent = parent.parent;
|
||||
node = node.parent;
|
||||
deep++;
|
||||
}
|
||||
} while( node != null );
|
||||
throw new WasmException( "GOTO code without target loop/block. Jump from " + start + " to " + jump, gotoBlock.lineNumber );
|
||||
} else {
|
||||
if( gotoBlock.nextPosition == jump ) {
|
||||
@ -1384,6 +1379,12 @@ class BranchManager {
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
if( parent != null && parent.startOp == WasmBlockOperator.LOOP ) {
|
||||
// a break in a LOOP is only a continue, we need to break to the outer block
|
||||
deep++;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
if( parent != null && parent.elseEndPos > gotoEndPos ) {
|
||||
|
||||
// check if we break into an ELSE block which is possible in Java with a GOTO, occur with concatenated conditional operators
|
||||
|
@ -25,6 +25,7 @@ import de.inetsoftware.jwebassembly.ScriptEngine;
|
||||
import de.inetsoftware.jwebassembly.WasmRule;
|
||||
import de.inetsoftware.jwebassembly.api.annotation.Export;
|
||||
|
||||
@SuppressWarnings( { "javadoc", "null", "rawtypes", "cast", "boxing", "unused" } )
|
||||
public class ControlFlowOperators extends AbstractBaseTest {
|
||||
|
||||
@ClassRule
|
||||
@ -55,6 +56,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
||||
addParam( list, script, "whileLoopInElse_13" );
|
||||
addParam( list, script, "whileLoopInElseAfterReturn" );
|
||||
addParam( list, script, "whileLoopAfterIfWithReturn" );
|
||||
addParam( list, script, "whileLoopInsideLoop" );
|
||||
addParam( list, script, "forLoop" );
|
||||
addParam( list, script, "conditionalOperator" );
|
||||
addParam( list, script, "conditionalOperator2" );
|
||||
@ -414,6 +416,26 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Export
|
||||
public static int whileLoopInsideLoop() {
|
||||
int i = 15;
|
||||
|
||||
MAIN: while( true ) {
|
||||
while( i >= 9 ) {
|
||||
i--;
|
||||
}
|
||||
int start = i;
|
||||
|
||||
while( i > start ) {
|
||||
if( true ) {
|
||||
i--;
|
||||
continue MAIN;
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
@Export
|
||||
static int forLoop() {
|
||||
int a = 0;
|
||||
|
@ -29,10 +29,10 @@ import org.junit.runners.Parameterized.Parameters;
|
||||
import de.inetsoftware.jwebassembly.ScriptEngine;
|
||||
import de.inetsoftware.jwebassembly.WasmRule;
|
||||
import de.inetsoftware.jwebassembly.api.annotation.Export;
|
||||
import de.inetsoftware.jwebassembly.runtime.StructsGC.Abc2;
|
||||
import de.inetsoftware.jwebassembly.web.DOMString;
|
||||
import de.inetsoftware.jwebassembly.web.JSObject;
|
||||
|
||||
@SuppressWarnings( { "javadoc", "null", "rawtypes", "cast", "boxing" } )
|
||||
public class StructsNonGC extends AbstractBaseTest {
|
||||
|
||||
@ClassRule
|
||||
@ -76,12 +76,11 @@ public class StructsNonGC extends AbstractBaseTest {
|
||||
addParam( list, script, "lambda1" );
|
||||
addParam( list, script, "lambda2" );
|
||||
addParam( list, script, "lambda3" );
|
||||
// TODO too many classes are loaded that are currently not yet compilable
|
||||
// addParam( list, script, "simpleName_Object" );
|
||||
// addParam( list, script, "simpleName_Anonymous" );
|
||||
// addParam( list, script, "simpleName_Array" );
|
||||
// addParam( list, script, "simpleName_InnerClass" );
|
||||
// addParam( list, script, "simpleName_LocalClass" );
|
||||
addParam( list, script, "simpleName_Object" );
|
||||
addParam( list, script, "simpleName_Anonymous" );
|
||||
addParam( list, script, "simpleName_Array" );
|
||||
addParam( list, script, "simpleName_InnerClass" );
|
||||
addParam( list, script, "simpleName_LocalClass" );
|
||||
addParam( list, script, "isPrimitive_int" );
|
||||
addParam( list, script, "isPrimitive_Object" );
|
||||
}
|
||||
@ -251,42 +250,41 @@ public class StructsNonGC extends AbstractBaseTest {
|
||||
return JSObject.domString( clazz.getName() );
|
||||
}
|
||||
|
||||
// TODO too many classes are loaded that are currently not yet compilable
|
||||
// @Export
|
||||
// static DOMString simpleName_Object() {
|
||||
// Object obj = new Object();
|
||||
// Class clazz = obj.getClass();
|
||||
// return JSObject.domString( clazz.getSimpleName() );
|
||||
// }
|
||||
//
|
||||
// @Export
|
||||
// static DOMString simpleName_Anonymous() {
|
||||
// Object obj = new Object() {};
|
||||
// Class clazz = obj.getClass();
|
||||
// return JSObject.domString( clazz.getSimpleName() );
|
||||
// }
|
||||
//
|
||||
// @Export
|
||||
// static DOMString simpleName_Array() {
|
||||
// Object obj = new Object[0];
|
||||
// Class clazz = obj.getClass();
|
||||
// return JSObject.domString( clazz.getSimpleName() );
|
||||
// }
|
||||
//
|
||||
// @Export
|
||||
// static DOMString simpleName_InnerClass() {
|
||||
// Class clazz = TestClass.class;
|
||||
// return JSObject.domString( clazz.getSimpleName() );
|
||||
// }
|
||||
//
|
||||
// @Export
|
||||
// static DOMString simpleName_LocalClass() {
|
||||
// class Foobar {}
|
||||
// Object obj = new Foobar();
|
||||
// Class clazz = obj.getClass();
|
||||
// return JSObject.domString( clazz.getSimpleName() );
|
||||
// }
|
||||
//
|
||||
@Export
|
||||
static DOMString simpleName_Object() {
|
||||
Object obj = new Object();
|
||||
Class clazz = obj.getClass();
|
||||
return JSObject.domString( clazz.getSimpleName() );
|
||||
}
|
||||
|
||||
@Export
|
||||
static DOMString simpleName_Anonymous() {
|
||||
Object obj = new Object() {};
|
||||
Class clazz = obj.getClass();
|
||||
return JSObject.domString( clazz.getSimpleName() );
|
||||
}
|
||||
|
||||
@Export
|
||||
static DOMString simpleName_Array() {
|
||||
Object obj = new Object[0];
|
||||
Class clazz = obj.getClass();
|
||||
return JSObject.domString( clazz.getSimpleName() );
|
||||
}
|
||||
|
||||
@Export
|
||||
static DOMString simpleName_InnerClass() {
|
||||
Class clazz = TestClass.class;
|
||||
return JSObject.domString( clazz.getSimpleName() );
|
||||
}
|
||||
|
||||
@Export
|
||||
static DOMString simpleName_LocalClass() {
|
||||
class Foobar {}
|
||||
Object obj = new Foobar();
|
||||
Class clazz = obj.getClass();
|
||||
return JSObject.domString( clazz.getSimpleName() );
|
||||
}
|
||||
|
||||
@Export
|
||||
static boolean getComponentType() {
|
||||
Class<?> clazz = byte.class;
|
||||
@ -385,6 +383,7 @@ public class StructsNonGC extends AbstractBaseTest {
|
||||
static class Abc2 extends Abc {
|
||||
Abc2 abc;
|
||||
|
||||
@Override
|
||||
void bar() {
|
||||
a = 3;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user