From 8f1cc4bf974c1487d21e42858eaa880b4257ed47 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Mon, 25 May 2020 19:28:47 +0200 Subject: [PATCH] fix IF-GOTO analyzing for multiple sub IF inside the THEN part. --- .../jwebassembly/module/BranchManger.java | 56 +++++++++++++++---- .../runtime/ControlFlowOperators.java | 21 +++++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 251b0b5..41cbb41 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -156,8 +156,27 @@ class BranchManger { */ void calculate() { addLoops(); - Collections.sort( allParsedOperations ); - calculate( root, allParsedOperations ); + List parsedOperations = allParsedOperations; + Collections.sort( parsedOperations ); +// +// int parsedOpCount = parsedOperations.size(); +// for( int i = 0; i < parsedOpCount; i++ ) { +// ParsedBlock startBlock = parsedOperations.get( i ); +// if( startBlock.op == JavaBlockOperator.IF ) { +// int jumpPos = startBlock.endPosition; +// for( int k = i + 1; k < parsedOpCount; k++ ) { +// ParsedBlock parsedBlock = parsedOperations.get( k ); +// if( parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition ) { +// if( jumpPos == parsedBlock.endPosition ) { +// startBlock.endPosition = parsedBlock.startPosition; +// break; +// } +// } +// } +// } +// } + + calculate( root, parsedOperations ); } /** @@ -430,15 +449,30 @@ class BranchManger { * @return the calculated positions */ private IfPositions searchElsePosition( IfParsedBlock startBlock, List parsedOperations ) { - // first search for first GOTO, any IF that point after the GOTO can not be part of the primary IF condition. - // This occur with a second IF inside of the THEN. This can jump directly to the end of the ELSE. - int maxElse = Integer.MAX_VALUE; + // find the end position of the else block + int endElse = startBlock.endPosition; int parsedOpCount = parsedOperations.size(); for( int i = 0; i < parsedOpCount; i++ ) { ParsedBlock parsedBlock = parsedOperations.get( i ); - if( parsedBlock.op == JavaBlockOperator.GOTO ) { - maxElse = parsedBlock.endPosition; + switch( parsedBlock.op ) { + case IF: + case GOTO: + if( parsedBlock.startPosition < endElse ) { + endElse = Math.max( endElse, parsedBlock.endPosition ); + } + break; + } + if( parsedBlock.startPosition > endElse ) { + parsedOpCount = i; + break; + } + } + // first search for the first GOTO, any IF that point after the GOTO can not be part of the primary IF condition. + // This occur with a second IF inside of the THEN. This can jump directly to the end of the ELSE. + for( int i = 0; i < parsedOpCount; i++ ) { + ParsedBlock parsedBlock = parsedOperations.get( i ); + if( parsedBlock.op == JavaBlockOperator.GOTO ) { // find the last IF that point to this GOTO int gotoNext = parsedBlock.nextPosition; for( ; i > 0; i-- ) { @@ -457,7 +491,7 @@ class BranchManger { int elsePos = startBlock.endPosition; for( ; ifCount < parsedOpCount; ifCount++ ) { ParsedBlock parsedBlock = parsedOperations.get( ifCount ); - if( parsedBlock.op != JavaBlockOperator.IF || parsedBlock.endPosition < elsePos || parsedBlock.endPosition > maxElse ) { + if( parsedBlock.op != JavaBlockOperator.IF || parsedBlock.endPosition < elsePos || parsedBlock.endPosition > endElse ) { // seems a second IF inside the THEN part. break; } @@ -1455,13 +1489,13 @@ class BranchManger { * Positions inside a IF control structure. */ private static class IfPositions { - /** Count of boolean operations in the IF condition */ + /** Count of boolean operations in the IF top level condition. This can be (&&) or (||) operations. */ private int ifCount; - /** The position of the first instruction in the THEN part */ + /** The position of the first instruction in the THEN part. */ private int thenPos; - /** The position of the first instruction in the ELSE part */ + /** The position of the first instruction in the ELSE part. */ private int elsePos; } } diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index a44ae16..acb7f43 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -74,6 +74,7 @@ public class ControlFlowOperators extends AbstractBaseTest { addParam( list, script, "ifAndOr8" ); addParam( list, script, "ifWithoutElseAndLoop" ); addParam( list, script, "ifOrWithMulti" ); + addParam( list, script, "ifMultipleInsideThen" ); addParam( list, script, "stringSwitchNormalFoo" ); addParam( list, script, "stringSwitchNormalBar" ); addParam( list, script, "stringSwitchNormalDefault" ); @@ -511,6 +512,26 @@ public class ControlFlowOperators extends AbstractBaseTest { return len; } + @Export + static int ifMultipleInsideThen() { + int result = 0; + if( (result == 7) || (result == 13) ) { + // multiple IF inside the primary IF + if( result == -1 ) { + result = 1; + } else { + result = 2; + } + + if( result > result ) { + result = 3; + } + } else { + result = 4; + } + return result; + } + @Export static int stringSwitchNormalFoo() { return stringSwitchNormal( "foo" );