# HG changeset patch # User Jaroslav Tulach # Date 1349833662 25200 # Node ID 437df2a719e7c1ab1439103e67dadee84ed969ca # Parent 519bcc6999c4549dde2c5fb6cf3976d0cb6098f1 Better order of static initializers diff -r 519bcc6999c4 -r 437df2a719e7 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 18:26:23 2012 -0700 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 18:47:42 2012 -0700 @@ -70,11 +70,12 @@ * JVM form so String is java/lang/String. Can be null * if one is not interested in knowing references * @param scripts write only collection with names of resources to read + * @return the initialization code for this class, if any. Otherwise null * * @throws IOException if something goes wrong during read or write or translating */ - public static void compile( + public static String compile( InputStream classFile, Appendable out, Collection references, Collection scripts @@ -88,7 +89,7 @@ scripts.add(res); final AnnotationComponent process = a.getComponent("processByteCode"); if (process != null && "const=0".equals(process.getValue().toString())) { - return; + return null; } } @@ -132,9 +133,12 @@ for (ClassName superInterface : jc.getInterfaces()) { out.append("\n" + className + ".prototype.$instOf_").append(superInterface.getInternalName().replace('/', '_')).append(" = true;"); } + + StringBuilder sb = new StringBuilder(); for (String init : toInitilize) { - out.append("\n").append(init).append("();"); + sb.append("\n").append(init).append("();"); } + return sb.toString(); } private void generateStaticMethod(Method m, List toInitilize) throws IOException { if (javaScriptBody(m, true)) { diff -r 519bcc6999c4 -r 437df2a719e7 vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Tue Oct 09 18:26:23 2012 -0700 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Tue Oct 09 18:47:42 2012 -0700 @@ -7,11 +7,13 @@ import java.io.Writer; import java.net.URL; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; -import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Set; +import java.util.Map; /** Generator of JavaScript from bytecode of classes on classpath of the VM. * @@ -36,64 +38,85 @@ compile(out, Arrays.asList(names)); } static void compile(Appendable out, List names) throws IOException { - Set processed = new HashSet(); - LinkedList toProcess = new LinkedList(names); - for (;;) { - toProcess.removeAll(processed); - if (toProcess.isEmpty()) { - break; - } - String name = toProcess.getFirst(); - processed.add(name); - if (name.startsWith("java/") - && !name.equals("java/lang/Object") - && !name.equals("java/lang/Class") - && !name.equals("java/lang/Number") - && !name.equals("java/lang/Integer") - && !name.equals("java/lang/Throwable") - && !name.equals("java/lang/Exception") - && !name.equals("java/lang/RuntimeException") - && !name.equals("java/lang/UnsupportedOperationException") - && !name.equals("java/lang/String") - && !name.equals("java/lang/String$CaseInsensitiveComparator") - && !name.equals("java/lang/StringBuilder") - && !name.equals("java/lang/AbstractStringBuilder") - ) { - continue; - } - InputStream is = loadClass(name); - if (is == null) { - throw new IOException("Can't find class " + name); - } - LinkedList scripts = new LinkedList(); - try { - ByteCodeToJavaScript.compile(is, out, toProcess, scripts); - } catch (RuntimeException ex) { - if (out instanceof CharSequence) { - CharSequence seq = (CharSequence)out; - int lastBlock = seq.length(); - while (lastBlock-- >= 0) { - if (seq.charAt(lastBlock) == '{') { - break; + for (String baseClass : names) { + Map processed = new HashMap(); + LinkedList toProcess = new LinkedList(); + toProcess.add(baseClass); + for (;;) { + String name = null; + Iterator it = toProcess.iterator(); + while (it.hasNext() && name == null) { + String n = it.next(); + if (processed.get(n) != null) { + continue; + } + name = n; + } + if (name == null) { + break; + } + if (name.startsWith("java/") + && !name.equals("java/lang/Object") + && !name.equals("java/lang/Class") + && !name.equals("java/lang/Number") + && !name.equals("java/lang/Integer") + && !name.equals("java/lang/Throwable") + && !name.equals("java/lang/Exception") + && !name.equals("java/lang/RuntimeException") + && !name.equals("java/lang/UnsupportedOperationException") + && !name.equals("java/lang/String") + && !name.equals("java/lang/String$CaseInsensitiveComparator") + && !name.equals("java/lang/StringBuilder") + && !name.equals("java/lang/AbstractStringBuilder") + ) { + processed.put(name, ""); + continue; + } + InputStream is = loadClass(name); + if (is == null) { + throw new IOException("Can't find class " + name); + } + LinkedList scripts = new LinkedList(); + try { + String initCode = ByteCodeToJavaScript.compile(is, out, toProcess, scripts); + processed.put(name, initCode == null ? "" : initCode); + } catch (RuntimeException ex) { + if (out instanceof CharSequence) { + CharSequence seq = (CharSequence)out; + int lastBlock = seq.length(); + while (lastBlock-- >= 0) { + if (seq.charAt(lastBlock) == '{') { + break; + } } + throw new IOException("Error while compiling " + name + "\n" + + seq.subSequence(lastBlock + 1, seq.length()), ex + ); + } else { + throw new IOException("Error while compiling " + name + "\n" + + out, ex + ); } - throw new IOException("Error while compiling " + name + "\n" - + seq.subSequence(lastBlock + 1, seq.length()), ex - ); - } else { - throw new IOException("Error while compiling " + name + "\n" - + out, ex - ); + } + for (String resource : scripts) { + InputStream emul = GenJS.class.getResourceAsStream(resource); + if (emul == null) { + throw new IOException("Can't find " + resource); + } + readResource(emul, out); } } - for (String resource : scripts) { - InputStream emul = GenJS.class.getResourceAsStream(resource); - if (emul == null) { - throw new IOException("Can't find " + resource); + + Collections.reverse(toProcess); + + for (String clazz : toProcess) { + String initCode = processed.remove(clazz); + if (initCode != null) { + out.append(initCode).append("\n"); } - readResource(emul, out); } } + } private static void readResource(InputStream emul, Appendable out) throws IOException { try { diff -r 519bcc6999c4 -r 437df2a719e7 vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 18:26:23 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 18:47:42 2012 -0700 @@ -100,4 +100,9 @@ public static String i2s(int i) { throw new IllegalStateException(); } + + static { + // check order of initializers + StaticUse.NON_NULL.equals(new Object()); + } } diff -r 519bcc6999c4 -r 437df2a719e7 vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java Tue Oct 09 18:47:42 2012 -0700 @@ -0,0 +1,5 @@ +package org.apidesign.vm4brwsr; + +public class StaticUse { + public static final Object NON_NULL = new Object(); +}