1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Thu Mar 12 12:07:54 2015 +0100
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Mar 13 11:41:04 2015 +0100
1.3 @@ -422,8 +422,10 @@
1.4 */
1.5 public static final class Flow {
1.6 private final MethodData m;
1.7 + private byte[] ops;
1.8 Flow(MethodData m) {
1.9 this.m = m;
1.10 + ops = new byte[m.getCode().length];
1.11 }
1.12
1.13 /** Access to bytecode of the method to analyse.
1.14 @@ -441,10 +443,46 @@
1.15 return m.getName();
1.16 }
1.17
1.18 - public void registerCycle(int offset) {
1.19 + public void beginLoopAt(int bci) {
1.20 + ops[bci] |= 0x10;
1.21 }
1.22
1.23 - public void registerIf(int offset) {
1.24 + public void beginIfAt(int bci) {
1.25 + ops[bci] |= 0x20;
1.26 + }
1.27 +
1.28 +
1.29 + public void breakAt(int bci) {
1.30 + ops[bci] |= 0x40;
1.31 + }
1.32 +
1.33 + public void beginElseAt(int bci) {
1.34 + ops[bci] |= 0x80;
1.35 + }
1.36 +
1.37 + public void endAt(int bci) {
1.38 + int cnt = (ops[bci] & 0x0f) + 1;
1.39 + int rest = ops[bci] & 0xf0;
1.40 + ops[bci] = (byte)(rest | cnt);
1.41 + }
1.42 +
1.43 + boolean isFlow(int at) {
1.44 + return ops[at] != 0;
1.45 + }
1.46 + boolean isLoop(int at) {
1.47 + return (ops[at] & 0x10) != 0;
1.48 + }
1.49 + boolean isIf(int at) {
1.50 + return (ops[at] & 0x20) != 0;
1.51 + }
1.52 + boolean isBreak(int at) {
1.53 + return (ops[at] & 0x40) != 0;
1.54 + }
1.55 + boolean isElse(int at) {
1.56 + return (ops[at] & 0x80) != 0;
1.57 + }
1.58 + int isEnd(int at) {
1.59 + return (ops[at] & 0x0f);
1.60 }
1.61
1.62 /** Provider of advanced analysis of the code flow inside of
2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Mar 12 12:07:54 2015 +0100
2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Mar 13 11:41:04 2015 +0100
2.3 @@ -466,9 +466,13 @@
2.4 didBranches = false;
2.5 lastStackFrame = 0;
2.6 } else {
2.7 - didBranches = true;
2.8 lastStackFrame = -1;
2.9 - append("\n var gt = 0;\n");
2.10 + if (flow == null) {
2.11 + didBranches = true;
2.12 + append("\n var gt = 0;\n");
2.13 + } else {
2.14 + didBranches = false;
2.15 + }
2.16 }
2.17
2.18 int openBraces = 0;
2.19 @@ -486,7 +490,7 @@
2.20 }
2.21 if (lastStackFrame != stackMapIterator.getFrameIndex()) {
2.22 smapper.flush(this);
2.23 - if (i != 0) {
2.24 + if (flow == null && i != 0) {
2.25 append(" }\n");
2.26 }
2.27 if (openBraces > 64) {
2.28 @@ -500,8 +504,16 @@
2.29 lastStackFrame = stackMapIterator.getFrameIndex();
2.30 lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
2.31 smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
2.32 - append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
2.33 - openBraces++;
2.34 + if (flow == null) {
2.35 + append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
2.36 + openBraces++;
2.37 + } else {
2.38 + if (!flow.isFlow(i)) {
2.39 + if (i != 0) {
2.40 + throw new IOException("Expecting flow suggestion at " + i);
2.41 + }
2.42 + }
2.43 + }
2.44 changeInCatch = true;
2.45 } else {
2.46 debug(" /* " + i + " */ ");
2.47 @@ -510,6 +522,20 @@
2.48 append("try {");
2.49 previousTrap = trap.current();
2.50 }
2.51 + if (flow != null) {
2.52 + if (flow.isLoop(i)) {
2.53 + append(" for (;;) {\n");
2.54 + }
2.55 + if (flow.isBreak(i)) {
2.56 + append("\n break;");
2.57 + }
2.58 + for (int j = 0; j < flow.isEnd(i); j++) {
2.59 + append("\n }");
2.60 + }
2.61 + if (flow.isElse(i)) {
2.62 + append(" else {\n");
2.63 + }
2.64 + }
2.65 final int c = readUByte(byteCodes, i);
2.66 switch (c) {
2.67 case opc_aload_0:
2.68 @@ -1091,8 +1117,10 @@
2.69 break;
2.70 case opc_goto: {
2.71 smapper.flush(this);
2.72 - int indx = i + readShortArg(byteCodes, i);
2.73 - goTo(this, flow, i, indx, topMostLabel);
2.74 + if (flow == null) {
2.75 + int indx = i + readShortArg(byteCodes, i);
2.76 + goTo(this, flow, i, indx, topMostLabel);
2.77 + }
2.78 i += 2;
2.79 break;
2.80 }
2.81 @@ -2275,6 +2303,13 @@
2.82 }
2.83
2.84 private static void goTo(Appendable out, Flow flow, int current, int to, int canBack) throws IOException {
2.85 + if (flow != null) {
2.86 + if (flow.isIf(current)) {
2.87 + out.append("{");
2.88 + return;
2.89 + }
2.90 + throw new IllegalStateException("Opn: ");
2.91 + }
2.92 if (to < current) {
2.93 if (canBack < to) {
2.94 out.append("{ gt = 0; continue X_" + to + "; }");