diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManager.java b/src/de/inetsoftware/jwebassembly/module/BranchManager.java index 0755055..6b2a397 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManager.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManager.java @@ -208,12 +208,29 @@ class BranchManager { for( int n = b + 1; n < allParsedOperations.size(); n++ ) { ParsedBlock nextBlock = allParsedOperations.get( n ); if( nextBlock.op == JavaBlockOperator.IF && nextBlock.endPosition == nextPos ) { // Eclipse loop with normal goto - int conditionStart = parsedBlock.endPosition; - int conditionEnd = nextBlock.nextPosition; - convertToLoop( parsedBlock, conditionStart, conditionEnd ); allParsedOperations.remove( n ); ((IfParsedBlock)nextBlock).negateCompare(); + int conditionStart = parsedBlock.endPosition; + int conditionEnd = nextBlock.nextPosition; + if( conditionStart == conditionEnd ) { + // WHILE loop in ELSE block. + // The GOTO from the ELSE and the jump to the end of the WHILE loop is merged to one GOTO. + for( n = b - 1; n >= 0; n-- ) { + ParsedBlock prevBlock = allParsedOperations.get( n ); + if( prevBlock.endPosition > nextPos ) { + conditionStart = prevBlock.endPosition; + prevBlock.endPosition = parsedBlock.nextPosition; + // Create the second GOTO + allParsedOperations.add( b, new ParsedBlock( JavaBlockOperator.GOTO, parsedBlock.startPosition, parsedBlock.endPosition - parsedBlock.startPosition, parsedBlock.nextPosition, parsedBlock.lineNumber ) ); + // we have only 3 code positions but need 6 for two GOTO + parsedBlock.startPosition = parsedBlock.nextPosition; + break; + } + } + } + convertToLoop( parsedBlock, conditionStart, conditionEnd ); + // if conditions that point at the end of the loop for optimization must now point at start. for( n = b - 1; n >= 0; n-- ) { ParsedBlock prevBlock = allParsedOperations.get( n ); @@ -223,11 +240,16 @@ class BranchManager { } break; } - if( nextBlock.op == JavaBlockOperator.GOTO && nextBlock.endPosition == nextPos && n > 1 ) { // Eclipse loop with wide goto_w + if( nextBlock.op == JavaBlockOperator.GOTO && nextBlock.endPosition == nextPos ) { // Eclipse loop with wide goto_w ParsedBlock prevBlock = allParsedOperations.get( n - 1 ); if( prevBlock.op == JavaBlockOperator.IF && prevBlock.endPosition == nextBlock.nextPosition ) { int conditionStart = parsedBlock.endPosition; int conditionEnd = prevBlock.nextPosition; + if( conditionStart >= conditionEnd ) { + // WHILE loop in ELSE block. + // occur with java.math.BigInteger.add(int[],int[]) in Java 8 + break; + } convertToLoop( parsedBlock, conditionStart, conditionEnd ); allParsedOperations.remove( n ); allParsedOperations.remove( n - 1 ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index f96dba0..0dff120 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -51,6 +51,8 @@ public class ControlFlowOperators extends AbstractBaseTest { addParam( list, script, "doWhileLoopWithBreak" ); addParam( list, script, "whileLoop" ); addParam( list, script, "whileLoopWithContinue" ); + addParam( list, script, "whileLoopInElse_3" ); + addParam( list, script, "whileLoopInElse_13" ); addParam( list, script, "forLoop" ); addParam( list, script, "conditionalOperator" ); addParam( list, script, "conditionalOperator2" ); @@ -351,6 +353,29 @@ public class ControlFlowOperators extends AbstractBaseTest { return value; } + private static int whileLoopInElse( int yIndex ) { + int result = 0; + if( yIndex == 3 ) { + result = 42; + } else { + while( yIndex > 7 ) { + result++; + yIndex--; + } + } + return result; + } + + @Export + public static int whileLoopInElse_3() { + return whileLoopInElse( 3 ); + } + + @Export + public static int whileLoopInElse_13() { + return whileLoopInElse( 13 ); + } + @Export static int forLoop() { int a = 0;