diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManager.java b/src/de/inetsoftware/jwebassembly/module/BranchManager.java index 2f49637..75bb9ab 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManager.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManager.java @@ -96,9 +96,6 @@ class BranchManager { breakOperations.clear(); root.endPos = code.getCodeSize(); exceptionTable = code.getExceptionTable(); - for( TryCatchFinally ex : exceptionTable ) { - allParsedOperations.add( new TryCatchParsedBlock( ex ) ); - } } /** @@ -172,8 +169,8 @@ class BranchManager { */ void calculate() { List parsedOperations = allParsedOperations; + addTryCatchBlocks( parsedOperations ); addLoops( parsedOperations ); - Collections.sort( parsedOperations ); normalizeEmptyThenBlocks( parsedOperations ); calculate( root, parsedOperations ); for( BreakBlock breakBlock : breakOperations ) { @@ -181,6 +178,49 @@ class BranchManager { } } + /** + * Add TryCatchParsedBlock to the parsed operations based on the excetion table from Java. + * + * @param parsedOperations + * the parsed operations + */ + private void addTryCatchBlocks( List parsedOperations ) { + int countOps = parsedOperations.size(); + + for( TryCatchFinally tryCatch : exceptionTable ) { + TryCatchParsedBlock node = new TryCatchParsedBlock( tryCatch ); + parsedOperations.add( node ); + + int gotoPos = tryCatch.getHandler() - 3; //tryCatch.getEnd() points some time before and some time after the goto + int endPos = root.endPos; + + // find all try blocks and the end position of the last catch/finally handler + int idx; + for( idx = 0; idx < countOps; idx++ ) { + ParsedBlock parsedBlock = parsedOperations.get( idx ); + + if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition + && parsedBlock.endPosition < endPos ) { + endPos = parsedBlock.endPosition; + break; + } + + if( parsedBlock.startPosition > gotoPos ) { + break; + } + + if( gotoPos < parsedBlock.endPosition && endPos > parsedBlock.endPosition ) { + endPos = parsedBlock.endPosition; + } + } + node.catchEndPosition = endPos; // we can not the endPosition here because this can change sorting of the blocks + } + + if( countOps != parsedOperations.size() ) { + parsedOperations.sort( null ); + } + } + /** * In the compiled Java byte code there is no marker for the start of loop. But we need this marker. That we add a * virtual loop operator on the target position of GOTO operators with a negative offset. @@ -237,11 +277,17 @@ class BranchManager { ParsedBlock prevBlock = parsedOperations.get( n ); switch( prevBlock.op ) { case SWITCH: - if( start < prevBlock.startPosition && prevBlock.endPosition > endPosition ) { + if( start <= prevBlock.startPosition && prevBlock.endPosition > endPosition ) { nextPosition = prevBlock.endPosition; endPosition = nextPosition; } break; + case TRY: + if( start <= prevBlock.startPosition && ((TryCatchParsedBlock)prevBlock).catchEndPosition > endPosition ) { + nextPosition = ((TryCatchParsedBlock)prevBlock).catchEndPosition; + endPosition = nextPosition; + } + break; default: } } @@ -338,7 +384,10 @@ class BranchManager { } } - parsedOperations.addAll( loops.values() ); + if( loops.size() > 0 ) { + parsedOperations.addAll( loops.values() ); + parsedOperations.sort( null ); + } } /** @@ -1634,6 +1683,7 @@ class BranchManager { */ private static class TryCatchParsedBlock extends ParsedBlock { private final TryCatchFinally tryCatch; + private int catchEndPosition; TryCatchParsedBlock( TryCatchFinally tryCatch ) { super( JavaBlockOperator.TRY, tryCatch.getStart(), tryCatch.getEnd() - tryCatch.getStart(), tryCatch.getStart(), -1 ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/Exceptions.java b/test/de/inetsoftware/jwebassembly/runtime/Exceptions.java index a3b699c..77e9a7e 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/Exceptions.java +++ b/test/de/inetsoftware/jwebassembly/runtime/Exceptions.java @@ -58,6 +58,7 @@ public class Exceptions extends AbstractBaseTest { addParam( list, script, "multiCatch2" ); addParam( list, script, "serialCatch" ); addParam( list, script, "tryReturn" ); + addParam( list, script, "whileTrueTryFinally" ); } rule.setTestParameters( list ); rule.setProperty( JWebAssembly.WASM_USE_EH, "true" ); @@ -258,6 +259,23 @@ public class Exceptions extends AbstractBaseTest { return 42; } + @Export + static int whileTrueTryFinally() { + int sw = 1; + LOOP: while( true ) { + try { + if( sw == 1 ) { + sw = 2; + continue LOOP; + } + } finally { + sw++; + } + break; + } + return sw; + } + // @Export // static int npe() { // Object obj = new NullPointerException();