diff -r ea12a3bb4b33 -r 4fef6b767f61 rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Feb 24 11:12:53 2015 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Wed Mar 11 18:58:39 2015 +0100 @@ -82,12 +82,12 @@ private final Resources res; private final Boolean extension; private final StringArray classpath; + private final Flow.Analyzer flow; private Bck2Brwsr( - ObfuscationLevel level, - StringArray exported, StringArray classes, StringArray resources, - Resources res, - Boolean extension, StringArray classpath + ObfuscationLevel level, StringArray exported, + StringArray classes, StringArray resources, Resources res, + Boolean extension, StringArray classpath, Flow.Analyzer flow ) { this.level = level; this.exported = exported; @@ -96,6 +96,7 @@ this.res = res; this.extension = extension; this.classpath = classpath; + this.flow = flow; } /** Helper method to generate virtual machine from bytes served by a resources @@ -135,7 +136,7 @@ return new Bck2Brwsr( ObfuscationLevel.NONE, new StringArray(), new StringArray(), new StringArray(), - null, false, null + null, false, null, null ); } @@ -156,7 +157,7 @@ public Bck2Brwsr addExported(String... exported) { return new Bck2Brwsr( level, this.exported.addAndNew(exported), - classes, resources, res, extension, classpath + classes, resources, res, extension, classpath, flow ); } @@ -197,7 +198,7 @@ } else { return new Bck2Brwsr(level, exported, this.classes.addAndNew(classes), resources, res, - extension, classpath); + extension, classpath, flow); } } @@ -217,7 +218,7 @@ return this; } else { return new Bck2Brwsr(level, exported, this.classes, - this.resources.addAndNew(resources), res, extension, classpath + this.resources.addAndNew(resources), res, extension, classpath, flow ); } } @@ -231,7 +232,7 @@ * @since 0.5 */ public Bck2Brwsr obfuscation(ObfuscationLevel level) { - return new Bck2Brwsr(level, exported, classes, resources, res, extension, classpath); + return new Bck2Brwsr(level, exported, classes, resources, res, extension, classpath, flow); } /** A way to change the provider of additional resources (classes) for the @@ -245,7 +246,7 @@ public Bck2Brwsr resources(Resources res) { return new Bck2Brwsr( level, exported, classes, resources, - res, extension, classpath + res, extension, classpath, flow ); } @@ -272,7 +273,7 @@ return new Bck2Brwsr( level, exported, classes, resources, res, true, - StringArray.asList(classpath) + StringArray.asList(classpath), flow ); } @@ -289,7 +290,7 @@ public Bck2Brwsr standalone(boolean includeVM) { return new Bck2Brwsr( level, exported, classes, resources, - res, includeVM ? false : null, null + res, includeVM ? false : null, null, flow ); } @@ -319,6 +320,21 @@ return resources(new LdrRsrcs(loader, ignoreBootClassPath)); } + /** A way to register flow analyzer. Such analyzer can optimize the + * representation of cycles inside of method bodies. + * + * @param flow the analyzer to be consulted with each method body + * @return new instance of the compiler with all values being the same, just + * different flow analyzer + * @since 0.15 + */ + public Bck2Brwsr flowAnalyzer(Flow.Analyzer flow) { + return new Bck2Brwsr( + level, exported, classes, resources, res, + extension, classpath, flow + ); + } + /** Generates virtual machine based on previous configuration of the * compiler. * @@ -373,6 +389,10 @@ StringArray classpath() { return classpath; } + + Flow.Analyzer flow() { + return flow; + } /** Provider of resources (classes and other files). The * {@link #generate(java.lang.Appendable, org.apidesign.vm4brwsr.Bck2Brwsr.Resources, java.lang.String[]) @@ -391,4 +411,51 @@ */ public InputStream get(String resource) throws IOException; } + + /** Represents control flow inside single method. + * Passed into {@link Analyzer#analyze(byte[], org.apidesign.vm4brwsr.Bck2Brwsr.Flow)} + * method that can be registed via {@link Bck2Brwsr#flowAnalyzer(org.apidesign.vm4brwsr.Bck2Brwsr.Flow.Analyzer)} + * method. + * + * @since 0.15 + */ + public static final class Flow { + private final byte[] byteCode; + Flow(byte[] byteCode) { + this.byteCode = byteCode; + } + + /** Access to bytecode of the method to analyse. + * + * @return unmodifiable bytecode of the instructions in the method body + */ + public byte[] getMethodByteCode() { + return byteCode; + } + + public void registerCycle(int offset) { + } + + public void registerIf(int offset) { + } + + /** Provider of advanced analysis of the code flow inside of + * method bodies. Register via {@link Bck2Brwsr#flowAnalyzer(org.apidesign.vm4brwsr.Bck2Brwsr.Flow.Analyzer)} + * when constructing the {@link Bck2Brwsr#newCompiler() compiler}. + * + * @since 0.15 + */ + public interface Analyzer { + /** Called to analyze method bodies and offer better control flow. + * + * + * @param request flow computation request and also a + * callback interface with methods to define the flow + * @return true if the analysis was successful, + * false otherwise + */ + public boolean analyze(Flow request); + } + } + }