Optimize only simpleLoopTest... method and first check the generated code before compiling it as JavaScript flow
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 12 Mar 2015 12:07:54 +0100
branchflow
changeset 1815fbe883b5a793
parent 1814 ea9fd59c8b62
child 1816 6c1fa412c72d
Optimize only simpleLoopTest... method and first check the generated code before compiling it as JavaScript
rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/LoopControlTest.java
rt/flow/src/test/java/org/apidesign/bck2brwsr/flow/TestVM.java
     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