# HG changeset patch # User Jaroslav Tulach # Date 1441975869 -7200 # Node ID dd4dabfead82bbb7bf1145718b71d3ba81ffe0c3 # Parent e38cdcd3c997be12ca9e1f09432329d81fd82d2c Giving the flow analyzer chance to generate the whole function body diff -r e38cdcd3c997 -r dd4dabfead82 rt/flow/src/main/java/org/apidesign/bck2brwsr/flow/GraalFlowAnalyzer.java --- a/rt/flow/src/main/java/org/apidesign/bck2brwsr/flow/GraalFlowAnalyzer.java Fri Sep 11 14:23:06 2015 +0200 +++ b/rt/flow/src/main/java/org/apidesign/bck2brwsr/flow/GraalFlowAnalyzer.java Fri Sep 11 14:51:09 2015 +0200 @@ -17,6 +17,7 @@ */ package org.apidesign.bck2brwsr.flow; +import java.io.IOException; import org.apidesign.vm4brwsr.Bck2Brwsr; /** Poweful flow analyzer. Based on internals used by Graal JVM @@ -39,10 +40,11 @@ } @Override - public boolean analyze(final Bck2Brwsr.Flow result) { - // Delete the previous line and fix pom.xml, David. + public boolean analyze(final Bck2Brwsr.Flow result) throws IOException { + // Use Graal to generate optimal function, David. double x = com.oracle.graal.api.directives.GraalDirectives.FASTPATH_PROBABILITY; - return false; + result.emit("function() { return 922869; }"); + return true; } } } diff -r e38cdcd3c997 -r dd4dabfead82 rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java --- a/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java Fri Sep 11 14:23:06 2015 +0200 +++ b/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java Fri Sep 11 14:51:09 2015 +0200 @@ -17,6 +17,7 @@ */ package org.apidesign.bck2brwsr.flow; +import java.io.IOException; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -43,7 +44,7 @@ class MyFlow implements Flow.Analyzer { boolean called; @Override - public boolean analyze(Flow request) { + public boolean analyze(Flow request) throws IOException { if ( request.getMethodName().equals("simpleLoopTest") || request.getMethodName().equals("simpleLoopTestWithExit") || diff -r e38cdcd3c997 -r dd4dabfead82 rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Sep 11 14:23:06 2015 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Sep 11 14:51:09 2015 +0200 @@ -422,10 +422,10 @@ */ public static final class Flow { private final MethodData m; - private byte[] ops; - Flow(MethodData m) { + private final Appendable emit; + Flow(MethodData m, Appendable emit) { this.m = m; - ops = new byte[m.getCode().length]; + this.emit = emit; } /** Access to bytecode of the method to analyse. @@ -442,47 +442,12 @@ public String getMethodName() { return m.getName(); } - - public void beginLoopAt(int bci) { - ops[bci] |= 0x10; - } - - 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); + /** Emits JavaScript to the final JavaScript output. + * @param seq text to emit + */ + public void emit(CharSequence seq) throws IOException { + this.emit.append(seq); } /** Provider of advanced analysis of the code flow inside of @@ -500,7 +465,7 @@ * @return true if the analysis was successful, * false otherwise */ - public boolean analyze(Flow request); + public boolean analyze(Flow request) throws IOException; } } diff -r e38cdcd3c997 -r dd4dabfead82 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Sep 11 14:23:06 2015 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Sep 11 14:51:09 2015 +0200 @@ -22,6 +22,15 @@ import org.apidesign.bck2brwsr.core.JavaScriptBody; import org.apidesign.vm4brwsr.Bck2Brwsr.Flow; import static org.apidesign.vm4brwsr.ByteCodeParser.*; +import org.apidesign.vm4brwsr.ByteCodeParser.AnnotationParser; +import org.apidesign.vm4brwsr.ByteCodeParser.BootMethodData; +import org.apidesign.vm4brwsr.ByteCodeParser.CPX2; +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData; +import org.apidesign.vm4brwsr.ByteCodeParser.FieldData; +import org.apidesign.vm4brwsr.ByteCodeParser.MethodData; +import org.apidesign.vm4brwsr.ByteCodeParser.StackMapIterator; +import org.apidesign.vm4brwsr.ByteCodeParser.TrapData; +import org.apidesign.vm4brwsr.ByteCodeParser.TrapDataIterator; /** Translator of the code inside class files to JavaScript. * @@ -429,10 +438,21 @@ if (defineProp) { append("Object.defineProperty(").append(destObject). - append(", '").append(name).append("', { configurable: true, writable: true, value: m = function("); + append(", '").append(name).append("', { configurable: true, writable: true, value: m = "); } else { - append("m = ").append(destObject).append(".").append(name).append(" = function("); + append("m = ").append(destObject).append(".").append(name).append(" = "); } + Flow flow = checkFlow(m); + if (flow != null) { + // OK, assume generate + if (defineProp) { + append("\n});"); + } else { + append("\n;"); + } + return defineProp; + } + append("function("); lmapper.outputArguments(this, m.isStatic()); append(") {").append("\n"); @@ -450,7 +470,6 @@ } return defineProp; } - Flow flow = checkFlow(m); final StackMapper smapper = new StackMapper(); @@ -504,16 +523,8 @@ lastStackFrame = stackMapIterator.getFrameIndex(); lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals()); smapper.syncWithFrameStack(stackMapIterator.getFrameStack()); - 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); - } - } - } + append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n"); + openBraces++; changeInCatch = true; } else { debug(" /* " + i + " */ "); @@ -522,20 +533,6 @@ 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: @@ -2303,13 +2300,6 @@ } 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 + "; }"); @@ -2498,7 +2488,7 @@ System.err.println(msg); } - protected Flow checkFlow(MethodData byteCodes) { + protected Flow checkFlow(MethodData byteCodes) throws IOException { return null; } } diff -r e38cdcd3c997 -r dd4dabfead82 rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Sep 11 14:23:06 2015 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Sep 11 14:51:09 2015 +0200 @@ -425,11 +425,11 @@ } @Override - protected Flow checkFlow(MethodData byteCodes) { + protected Flow checkFlow(MethodData byteCodes) throws IOException { if (flow == null) { return null; } - Flow f = new Flow(byteCodes); + Flow f = new Flow(byteCodes, this); return flow.analyze(f) ? f : null; }