Optimize only simpleLoopTest... method and first check the generated code before compiling it as JavaScript
1.1 --- a/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java Thu Mar 12 11:16:15 2015 +0100
1.2 +++ b/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java Thu Mar 12 12:07:54 2015 +0100
1.3 @@ -41,8 +41,12 @@
1.4 boolean called;
1.5 @Override
1.6 public boolean analyze(Flow request) {
1.7 - called = true;
1.8 - return GraalFlowAnalyzer.getDefault().analyze(request);
1.9 + if (request.getMethodName().equals("simpleLoopTestWithExit")) {
1.10 + called = true;
1.11 + return GraalFlowAnalyzer.getDefault().analyze(request);
1.12 + } else {
1.13 + return false;
1.14 + }
1.15 }
1.16 }
1.17 MyFlow flow = new MyFlow();
1.18 @@ -72,6 +76,9 @@
1.19 assertNotEquals(end, -1, "Control loop end defined" + code);
1.20 final String body = code.substring(begin, end);
1.21 assertFalse(body.contains("gt"), "No gt control flow used: " + body);
1.22 +
1.23 + int exp = LoopControl.simpleLoopTestWithExit(123);
1.24 + vm.assertExec("Is the code compilable?", LoopControl.class, "simpleLoopTestWithExit__II", exp, 123);
1.25 }
1.26
1.27 }
2.1 --- a/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/TestVM.java Thu Mar 12 11:16:15 2015 +0100
2.2 +++ b/rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/TestVM.java Thu Mar 12 12:07:54 2015 +0100
2.3 @@ -42,16 +42,15 @@
2.4 import static org.testng.Assert.*;
2.5
2.6 public final class TestVM {
2.7 - private final Invocable code;
2.8 + private final ScriptEngine js;
2.9 + private Invocable code;
2.10 private final CharSequence codeSeq;
2.11 - private final Object bck2brwsr;
2.12 + private Object bck2brwsr;
2.13
2.14
2.15 - private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
2.16 - this.code = code;
2.17 + private TestVM(ScriptEngine js, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
2.18 + this.js = js;
2.19 this.codeSeq = codeSeq;
2.20 - this.bck2brwsr = ((ScriptEngine)code).eval("bck2brwsr(function(n) { return loader.get(n); })");
2.21 - ((ScriptEngine)code).getContext().setAttribute("loader", this, ScriptContext.ENGINE_SCOPE);
2.22 }
2.23
2.24 public Object execCode(
2.25 @@ -60,11 +59,11 @@
2.26 ) throws Exception {
2.27 Object ret = null;
2.28 try {
2.29 - ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
2.30 + ret = getCode().invokeMethod(bck2brwsr, "loadClass", clazz.getName());
2.31 List<Object> ma = new ArrayList<Object>();
2.32 ma.add(method);
2.33 ma.addAll(Arrays.asList(args));
2.34 - ret = code.invokeMethod(ret, "invoke", ma.toArray());
2.35 + ret = getCode().invokeMethod(ret, "invoke", ma.toArray());
2.36 } catch (ScriptException ex) {
2.37 fail("Execution failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
2.38 } catch (NoSuchMethodException ex) {
2.39 @@ -80,11 +79,11 @@
2.40 // in case of Long it is necessary convert it to number
2.41 // since the Long is represented by two numbers in JavaScript
2.42 try {
2.43 - final Object toFP = ((ScriptEngine)code).eval("Number.prototype.toFP");
2.44 + final Object toFP = ((ScriptEngine)getCode()).eval("Number.prototype.toFP");
2.45 if (ret instanceof Long) {
2.46 - ret = code.invokeMethod(toFP, "call", ret);
2.47 + ret = getCode().invokeMethod(toFP, "call", ret);
2.48 }
2.49 - ret = code.invokeFunction("Number", ret);
2.50 + ret = getCode().invokeFunction("Number", ret);
2.51 } catch (ScriptException ex) {
2.52 fail("Conversion to number failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
2.53 } catch (NoSuchMethodException ex) {
2.54 @@ -144,96 +143,7 @@
2.55 eng[0] = js;
2.56 }
2.57 try {
2.58 - Object res = js.eval(sb.toString());
2.59 - assertTrue(js instanceof Invocable, "It is invocable object: " + res);
2.60 - return new TestVM((Invocable) js, sb);
2.61 - } catch (Exception ex) {
2.62 - if (sb.length() > 2000) {
2.63 - sb = dumpJS(sb);
2.64 - }
2.65 - fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
2.66 - return null;
2.67 - }
2.68 - }
2.69 -
2.70 - static TestVM compileClassAsExtension(
2.71 - StringBuilder sb, ScriptEngine[] eng,
2.72 - String name, final String resourceName, final String resourceContent
2.73 - ) throws ScriptException, IOException {
2.74 - return compileClassesAsExtension(sb, eng, resourceName, resourceContent, name);
2.75 - }
2.76 - static TestVM compileClassesAsExtension(
2.77 - StringBuilder sb, ScriptEngine[] eng,
2.78 - final String resourceName, final String resourceContent, String... names
2.79 - ) throws ScriptException, IOException {
2.80 - if (sb == null) {
2.81 - sb = new StringBuilder();
2.82 - }
2.83 - if (eng[0] == null) {
2.84 - ScriptEngineManager sem = new ScriptEngineManager();
2.85 - ScriptEngine js = sem.getEngineByExtension("js");
2.86 - eng[0] = js;
2.87 - Bck2Brwsr.newCompiler().resources(new EmulationResources())
2.88 - .obfuscation(ObfuscationLevel.NONE).generate(sb);
2.89 - }
2.90 - Set<String> exp = new HashSet<String>();
2.91 - for (String n : names) {
2.92 - int last = n.lastIndexOf('/');
2.93 - exp.add(n.substring(0, last + 1));
2.94 - }
2.95 - Bck2Brwsr b2b = Bck2Brwsr.newCompiler().
2.96 - resources(new EmulationResources() {
2.97 - @Override
2.98 - public InputStream get(String name) throws IOException {
2.99 - if (name.equals(resourceName)) {
2.100 - return new ByteArrayInputStream(resourceContent.getBytes("UTF-8"));
2.101 - }
2.102 - return super.get(name);
2.103 - }
2.104 - }).
2.105 - addClasses(names).
2.106 - addResources("org/apidesign/vm4brwsr/obj.js").
2.107 - addExported(exp.toArray(new String[0])).
2.108 - obfuscation(ObfuscationLevel.FULL).
2.109 - library();
2.110 - if (resourceName != null) {
2.111 - b2b = b2b.addResources(resourceName);
2.112 - }
2.113 - b2b.generate(sb);
2.114 - try {
2.115 - defineAtoB(eng[0]);
2.116 - Object res = eng[0].eval(sb.toString());
2.117 - assertTrue(eng[0] instanceof Invocable, "It is invocable object: " + res);
2.118 - return new TestVM((Invocable) eng[0], sb);
2.119 - } catch (Exception ex) {
2.120 - if (sb.length() > 2000) {
2.121 - sb = dumpJS(sb);
2.122 - }
2.123 - fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
2.124 - return null;
2.125 - }
2.126 - }
2.127 -
2.128 - static TestVM compileClassAndResources(StringBuilder sb, ScriptEngine[] eng, String name, String... resources) throws ScriptException, IOException {
2.129 - if (sb == null) {
2.130 - sb = new StringBuilder();
2.131 - }
2.132 - Bck2Brwsr b2b = Bck2Brwsr.newCompiler().
2.133 - resources(new EmulationResources()).
2.134 - addRootClasses(name).
2.135 - addResources(resources);
2.136 - b2b.generate(sb);
2.137 - ScriptEngineManager sem = new ScriptEngineManager();
2.138 - ScriptEngine js = sem.getEngineByExtension("js");
2.139 - if (eng != null) {
2.140 - eng[0] = js;
2.141 - }
2.142 - try {
2.143 - defineAtoB(js);
2.144 -
2.145 - Object res = js.eval(sb.toString());
2.146 - assertTrue(js instanceof Invocable, "It is invocable object: " + res);
2.147 - return new TestVM((Invocable) js, sb);
2.148 + return new TestVM(js, sb);
2.149 } catch (Exception ex) {
2.150 if (sb.length() > 2000) {
2.151 sb = dumpJS(sb);
2.152 @@ -243,20 +153,16 @@
2.153 }
2.154 }
2.155
2.156 - private static void defineAtoB(ScriptEngine js) throws ScriptException {
2.157 - js.eval("atob = function(s) { return new String(org.apidesign.vm4brwsr.ResourcesTest.parseBase64Binary(s)); }");
2.158 - }
2.159 -
2.160 Object loadClass(String loadClass, String name) throws ScriptException, NoSuchMethodException {
2.161 - return code.invokeMethod(bck2brwsr, "loadClass", LoopControl.class.getName());
2.162 + return getCode().invokeMethod(bck2brwsr, "loadClass", LoopControl.class.getName());
2.163 }
2.164
2.165 Object invokeMethod(Object obj, String method, Object... params) throws ScriptException, NoSuchMethodException {
2.166 - return code.invokeMethod(obj, method, params);
2.167 + return getCode().invokeMethod(obj, method, params);
2.168 }
2.169
2.170 Object invokeFunction(String methodName, Object... args) throws ScriptException, NoSuchMethodException {
2.171 - return code.invokeFunction(methodName, args);
2.172 + return getCode().invokeFunction(methodName, args);
2.173 }
2.174
2.175 static StringBuilder dumpJS(CharSequence sb) throws IOException {
2.176 @@ -279,6 +185,19 @@
2.177 final CharSequence codeSeq() {
2.178 return codeSeq;
2.179 }
2.180 +
2.181 + /**
2.182 + * @return the code
2.183 + */
2.184 + private Invocable getCode() throws ScriptException {
2.185 + if (code == null) {
2.186 + Object res = js.eval(code.toString());
2.187 + code = (Invocable) js;
2.188 + this.bck2brwsr = ((ScriptEngine)code).eval("bck2brwsr(function(n) { return loader.get(n); })");
2.189 + ((ScriptEngine)code).getContext().setAttribute("loader", this, ScriptContext.ENGINE_SCOPE);
2.190 + }
2.191 + return (Invocable)code;
2.192 + }
2.193
2.194 private static class EmulationResources implements Bck2Brwsr.Resources {
2.195 @Override