From 442e0c896c6a48c1f0e8f832546640b314ca5274 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Mon, 6 Jun 2022 15:21:14 +0200 Subject: [PATCH] Use the normal break handling for the GOTO in the CASEs of an SWITCH. This eliminates the need to calculate the end of the SWITCH structure. #43 --- .../jwebassembly/module/BranchManager.java | 75 +++++-------------- .../runtime/ControlFlowOperators.java | 37 +++++++++ 2 files changed, 55 insertions(+), 57 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManager.java b/src/de/inetsoftware/jwebassembly/module/BranchManager.java index 9ff111d..77f9dca 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManager.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManager.java @@ -940,55 +940,7 @@ class BranchManager { } } - // handle the GOTO (breaks) at the end of the CASE blocks. - int lastBlockPosition = lastPosition; - for( Iterator it = parsedOperations.iterator(); it.hasNext(); ) { - ParsedBlock parsedBlock = it.next(); - int start = parsedBlock.startPosition; - if( start >= lastBlockPosition ) { - break; - } - switch( parsedBlock.op ) { - case GOTO: - case IF: - int end = parsedBlock.endPosition; - if( start < end ) { - BranchNode branch = blockNode; - while( branch.size() > 0 ) { - BranchNode node = branch.get( 0 ); - if( start > node.endPos ) { - if( end >= branch.endPos ) { - blockCount = 0; - BranchNode parentNode = branch; - while( parentNode != null && end > parentNode.endPos ) { - parentNode = parentNode.parent; - blockCount++; - } - WasmBlockOperator startOp; - if( parsedBlock.op == JavaBlockOperator.GOTO ) { - startOp = WasmBlockOperator.BR; - lastPosition = Math.max( lastPosition, end ); - } else { - startOp = WasmBlockOperator.BR_IF; - instructions.remove( ((IfParsedBlock)parsedBlock).jump ); - } - start++; - branch.add( new BranchNode( start, start, startOp, null, blockCount ) ); - it.remove(); - } - break; - } - branch = node; - } - - } - } - } - - // Create the main block around the switch - BranchNode switchNode = new BranchNode( startPosition, lastPosition, WasmBlockOperator.BLOCK, WasmBlockOperator.END, switchType ); - switchNode.add( blockNode ); - parent.add( switchNode ); + parent.add( blockNode ); if( brTableNode != null ) { // sort back in the natural order and create a br_table @@ -1000,11 +952,11 @@ class BranchManager { brTableNode.data = data; } - for( int i = 0; i < cases.length; i++ ) { - switchCase = cases[i]; - calculateSubOperations( switchCase.node, parsedOperations ); - } - calculateSubOperations( switchNode, parsedOperations ); + blockNode = cases[0].node; + do { + calculateSubOperations( blockNode, parsedOperations ); + blockNode = blockNode.parent; + } while( blockNode != parent ); } /** @@ -1473,8 +1425,7 @@ class BranchManager { * @return the new node */ private BranchNode addMiddleNode( BranchNode parent, int startPos, int endPos ) { - Object data = parent.data == switchType && parent.startPos == startPos ? switchType : null; - BranchNode middleNode = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END, data ); + BranchNode middleNode = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END ); int idx = 0; for( Iterator it = parent.iterator(); it.hasNext(); ) { BranchNode child = it.next(); @@ -1488,8 +1439,18 @@ class BranchManager { middleNode.add( child ); it.remove(); } + + // use same input parameter if parent or child start on same position + if( parent.startPos == startPos ) { + middleNode.data = parent.data; + } else if( middleNode.size() > 0 ) { + BranchNode child = middleNode.get( 0 ); + if( child.startPos == startPos ) { + middleNode.data = child.data; + } + } + parent.add( idx, middleNode ); - parent = middleNode; patchBrDeep( middleNode ); return middleNode; } diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index 566569e..b98f432 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -47,6 +47,7 @@ public class ControlFlowOperators extends AbstractBaseTest { addParam( list, script, "ifCompare" ); addParam( list, script, "switchDirect" ); addParam( list, script, "switchWithConditionMethodParams" ); + addParam( list, script, "switchWithConditionSelect" ); addParam( list, script, "endlessLoop" ); addParam( list, script, "doWhileLoop" ); addParam( list, script, "doWhileLoopTwoConditions" ); @@ -303,6 +304,42 @@ public class ControlFlowOperators extends AbstractBaseTest { return last; } + @Export + private static int switchWithConditionSelect() { + boolean cond = true; + int c1 = 1; + int c2 = 2; + int b; + switch( cond ? c1 : c2 ) { + case 1: + b = 17; + switch( cond ? c1 : c2 ) { + case 1: + b = 13; + break; + case 2: + b = 14; + break; + } + break; + case 2: + case 1001: + if( c1 == 1000 ) { + b = 1000; + break; + } else { + b = 1001; + } + //$FALL-THROUGH$ + case Integer.MAX_VALUE: + b = 3; + break; + default: + b = 9; + } + return b; + } + @Export static int endlessLoop() { int a = 0;