# HG changeset patch # User Jaroslav Tulach # Date 1426243264 -3600 # Node ID 6c1fa412c72d514d947898888336d4c1b851cf61 # Parent fbe883b5a7934745cee4c7f098f499c76d9fbfde Using the provided flow instead of "gt" & X_nn style diff -r fbe883b5a793 -r 6c1fa412c72d rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Thu Mar 12 12:07:54 2015 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Mar 13 11:41:04 2015 +0100 @@ -422,8 +422,10 @@ */ public static final class Flow { private final MethodData m; + private byte[] ops; Flow(MethodData m) { this.m = m; + ops = new byte[m.getCode().length]; } /** Access to bytecode of the method to analyse. @@ -441,10 +443,46 @@ return m.getName(); } - public void registerCycle(int offset) { + public void beginLoopAt(int bci) { + ops[bci] |= 0x10; } - public void registerIf(int offset) { + public void beginIfAt(int bci) { + ops[bci] |= 0x20; + } + + + public void breakAt(int bci) { + ops[bci] |= 0x40; + } + + public void beginElseAt(int bci) { + ops[bci] |= 0x80; + } + + public void endAt(int bci) { + int cnt = (ops[bci] & 0x0f) + 1; + int rest = ops[bci] & 0xf0; + ops[bci] = (byte)(rest | cnt); + } + + boolean isFlow(int at) { + return ops[at] != 0; + } + boolean isLoop(int at) { + return (ops[at] & 0x10) != 0; + } + boolean isIf(int at) { + return (ops[at] & 0x20) != 0; + } + boolean isBreak(int at) { + return (ops[at] & 0x40) != 0; + } + boolean isElse(int at) { + return (ops[at] & 0x80) != 0; + } + int isEnd(int at) { + return (ops[at] & 0x0f); } /** Provider of advanced analysis of the code flow inside of diff -r fbe883b5a793 -r 6c1fa412c72d rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Mar 12 12:07:54 2015 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Mar 13 11:41:04 2015 +0100 @@ -466,9 +466,13 @@ didBranches = false; lastStackFrame = 0; } else { - didBranches = true; lastStackFrame = -1; - append("\n var gt = 0;\n"); + if (flow == null) { + didBranches = true; + append("\n var gt = 0;\n"); + } else { + didBranches = false; + } } int openBraces = 0; @@ -486,7 +490,7 @@ } if (lastStackFrame != stackMapIterator.getFrameIndex()) { smapper.flush(this); - if (i != 0) { + if (flow == null && i != 0) { append(" }\n"); } if (openBraces > 64) { @@ -500,8 +504,16 @@ lastStackFrame = stackMapIterator.getFrameIndex(); lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals()); smapper.syncWithFrameStack(stackMapIterator.getFrameStack()); - append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n"); - openBraces++; + if (flow == null) { + append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n"); + openBraces++; + } else { + if (!flow.isFlow(i)) { + if (i != 0) { + throw new IOException("Expecting flow suggestion at " + i); + } + } + } changeInCatch = true; } else { debug(" /* " + i + " */ "); @@ -510,6 +522,20 @@ append("try {"); previousTrap = trap.current(); } + if (flow != null) { + if (flow.isLoop(i)) { + append(" for (;;) {\n"); + } + if (flow.isBreak(i)) { + append("\n break;"); + } + for (int j = 0; j < flow.isEnd(i); j++) { + append("\n }"); + } + if (flow.isElse(i)) { + append(" else {\n"); + } + } final int c = readUByte(byteCodes, i); switch (c) { case opc_aload_0: @@ -1091,8 +1117,10 @@ break; case opc_goto: { smapper.flush(this); - int indx = i + readShortArg(byteCodes, i); - goTo(this, flow, i, indx, topMostLabel); + if (flow == null) { + int indx = i + readShortArg(byteCodes, i); + goTo(this, flow, i, indx, topMostLabel); + } i += 2; break; } @@ -2275,6 +2303,13 @@ } private static void goTo(Appendable out, Flow flow, int current, int to, int canBack) throws IOException { + if (flow != null) { + if (flow.isIf(current)) { + out.append("{"); + return; + } + throw new IllegalStateException("Opn: "); + } if (to < current) { if (canBack < to) { out.append("{ gt = 0; continue X_" + to + "; }");