From 66945d2974cd37f3dc41a5df9a7547e18d18611a Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Thu, 21 Mar 2019 21:14:21 +0100 Subject: [PATCH] improve "goto_w" support --- .../jwebassembly/module/BranchManger.java | 82 +++++++++++++------ .../jwebassembly/runtime/Wide.java | 25 ++++-- 2 files changed, 72 insertions(+), 35 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 3653edc..3ea1641 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -179,37 +179,26 @@ class BranchManger { int nextPos = parsedBlock.nextPosition; for( int n = b + 1; n < allParsedOperations.size(); n++ ) { ParsedBlock nextBlock = allParsedOperations.get( n ); - if( nextBlock.op == JavaBlockOperator.IF && nextBlock.endPosition == nextPos ) { - int conditionStart = parsedBlock.endPosition; // 15 - int conditionEnd = nextBlock.nextPosition; // 22 - int conditionNew = parsedBlock.startPosition; // 4 - int conditionIdx = -1; - - int i; - for( i = 0; i < instructions.size(); i++ ) { - WasmInstruction instr = instructions.get( i ); - int codePos = instr.getCodePosition(); - if( codePos == nextPos ) { - conditionIdx = i; - } - if( codePos >= conditionEnd ) { - break; - } - if( codePos >= conditionStart ) { - instr.setCodePosition( conditionNew ); - instructions.remove( i ); - instructions.add( conditionIdx++, instr ); - } - } - - parsedBlock.op = JavaBlockOperator.LOOP; - parsedBlock.endPosition = conditionEnd; + 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 ); - instructions.add( i, new WasmBlockInstruction( WasmBlockOperator.BR, 0, conditionNew ) ); - instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew ) ); ((IfParsedBlock)nextBlock).negateCompare(); break; } + if( nextBlock.op == JavaBlockOperator.GOTO && nextBlock.endPosition == nextPos && n > 1 ) { // Eclipse loop with wide goto_w + ParsedBlock prevBlock = allParsedOperations.get( n - 1 ); + if( prevBlock.op == JavaBlockOperator.IF && prevBlock.endPosition == nextBlock.nextPosition ) { + System.err.println( nextBlock ); + int conditionStart = parsedBlock.endPosition; + int conditionEnd = prevBlock.nextPosition; + convertToLoop( parsedBlock, conditionStart, conditionEnd ); + allParsedOperations.remove( n ); + allParsedOperations.remove( n - 1 ); + break; + } + } } break; default: @@ -220,6 +209,45 @@ class BranchManger { allParsedOperations.addAll( loops.values() ); } + /** + * Convert the GOTO block with condition at the end into a loop block and move the condition from the end to the + * start like wasm it required. + * + * @param gotoBlock + * the goto block + * @param conditionStart + * the code position where condition code start + * @param conditionEnd + * the end position + */ + private void convertToLoop( ParsedBlock gotoBlock, int conditionStart, int conditionEnd ) { + int conditionNew = gotoBlock.startPosition; + int nextPos = gotoBlock.nextPosition; + int conditionIdx = -1; + + int i; + for( i = 0; i < instructions.size(); i++ ) { + WasmInstruction instr = instructions.get( i ); + int codePos = instr.getCodePosition(); + if( codePos == nextPos ) { + conditionIdx = i; + } + if( codePos >= conditionEnd ) { + break; + } + if( codePos >= conditionStart ) { + instr.setCodePosition( conditionNew ); + instructions.remove( i ); + instructions.add( conditionIdx++, instr ); + } + } + + gotoBlock.op = JavaBlockOperator.LOOP; + gotoBlock.endPosition = conditionEnd; + instructions.add( i, new WasmBlockInstruction( WasmBlockOperator.BR, 0, conditionNew ) ); + instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew ) ); + } + /** * Calculate the branch tree for the given branch and parsed sub operations. * diff --git a/test/de/inetsoftware/jwebassembly/runtime/Wide.java b/test/de/inetsoftware/jwebassembly/runtime/Wide.java index 346f532..f0c9b9e 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/Wide.java +++ b/test/de/inetsoftware/jwebassembly/runtime/Wide.java @@ -39,26 +39,35 @@ public class Wide extends AbstractBaseTest { ArrayList list = new ArrayList<>(); for( ScriptEngine[] val : ScriptEngine.testParams() ) { ScriptEngine script = val[0]; - addParam( list, script, "abc" ); + addParam( list, script, "thenBranch" ); + addParam( list, script, "elseBranch" ); } return list; } static class TestClass { + @Export + static int thenBranch() { + return wide(true); + } + + @Export + static int elseBranch() { + return wide(false); + } + /** * more as 255 variable slots * @return */ @Export - static int abc() { + static int wide( boolean then) { int i = 42; - if( 42 == i ) { -// TODO -// for( int j = 0; j < 10; j++ ) { -// i++; -// } - i++; + if( then ) { + for( int j = 0; j < 10; j++ ) { + i++; + } } else { int j = 0; long a0 = 0;