# HG changeset patch # User Lubomir Nerad # Date 1363695482 -3600 # Node ID f41a1fef7738eb2a5cab25283b817b27db77c222 # Parent 35507d1a50693e6b1eb7e60290768a177b6f90c7# Parent 094e10a975111d1c86ba888b0adb889c3ac4aac4 Merge with trunk diff -r 35507d1a5069 -r f41a1fef7738 benchmarks/matrix-multiplication/pom.xml --- a/benchmarks/matrix-multiplication/pom.xml Tue Mar 19 13:08:44 2013 +0100 +++ b/benchmarks/matrix-multiplication/pom.xml Tue Mar 19 13:18:02 2013 +0100 @@ -37,6 +37,36 @@ true + + org.codehaus.mojo + xml-maven-plugin + 1.0 + + + + transform + + install + + + + + + target/surefire-reports + target/surefire-reports + + TEST*.xml + + src/main/select-time.xsl + + + .csv + + + + + + diff -r 35507d1a5069 -r f41a1fef7738 benchmarks/matrix-multiplication/src/main/select-time.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmarks/matrix-multiplication/src/main/select-time.xsl Tue Mar 19 13:18:02 2013 +0100 @@ -0,0 +1,55 @@ + + + + + + + + End + + NaN + + + + + + + + + + , + + + + + + + + + + + , + + + + + + diff -r 35507d1a5069 -r f41a1fef7738 benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java --- a/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java Tue Mar 19 13:08:44 2013 +0100 +++ b/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java Tue Mar 19 13:18:02 2013 +0100 @@ -31,6 +31,22 @@ } @Compare(scripting = false) + public String oneIteration() throws IOException { + + Matrix m1 = new Matrix(5); + Matrix m2 = new Matrix(5); + + m1.generateData(); + m2.generateData(); + + Matrix res = m1.multiply(m2); + + StringBuilder sb = new StringBuilder(); + res.printOn(sb); + return sb.toString(); + } + + @Compare(scripting = false) public String tenThousandIterations() throws IOException { Matrix m1 = new Matrix(5); @@ -50,6 +66,27 @@ return sb.toString(); } + @Compare(scripting = false) + public String tenUselessIterations() throws IOException { + + Matrix m1 = new Matrix(5); + Matrix m2 = new Matrix(5); + + m1.generateData(); + m2.generateData(); + + Matrix res = null; + for (int i = 0; i < 10; i++) { + res = m1.multiply(m2); + m1 = res; + } + + StringBuilder sb = new StringBuilder(); + res.printOn(sb); + return sb.toString(); + } + + @Factory public static Object[] create() { return VMTest.create(MatrixTest.class); diff -r 35507d1a5069 -r f41a1fef7738 javaquery/demo-calculator-dynamic/nbactions.xml --- a/javaquery/demo-calculator-dynamic/nbactions.xml Tue Mar 19 13:08:44 2013 +0100 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml Tue Mar 19 13:18:02 2013 +0100 @@ -23,7 +23,7 @@ run process-classes - org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr + org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr diff -r 35507d1a5069 -r f41a1fef7738 javaquery/demo-calculator/nbactions.xml --- a/javaquery/demo-calculator/nbactions.xml Tue Mar 19 13:08:44 2013 +0100 +++ b/javaquery/demo-calculator/nbactions.xml Tue Mar 19 13:18:02 2013 +0100 @@ -23,7 +23,7 @@ run package - org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr + org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr true diff -r 35507d1a5069 -r f41a1fef7738 javaquery/demo-calculator/pom.xml --- a/javaquery/demo-calculator/pom.xml Tue Mar 19 13:08:44 2013 +0100 +++ b/javaquery/demo-calculator/pom.xml Tue Mar 19 13:18:02 2013 +0100 @@ -22,6 +22,7 @@ + j2js brwsr @@ -29,6 +30,7 @@ ${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/ index.xhtml + ${project.build.directory}/bck2brwsr.js @@ -102,13 +104,5 @@ javaquery.api 0.5-SNAPSHOT - - org.apidesign.bck2brwsr - vm4brwsr - js - zip - 0.5-SNAPSHOT - provided - diff -r 35507d1a5069 -r f41a1fef7738 javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml --- a/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Tue Mar 19 13:08:44 2013 +0100 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Tue Mar 19 13:18:02 2013 +0100 @@ -37,15 +37,6 @@ *:rt - - false - provided - - *:js - - true - / - @@ -53,6 +44,10 @@ / + ${project.build.directory}/bck2brwsr.js + / + + ${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml / index.xhtml diff -r 35507d1a5069 -r f41a1fef7738 rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Tue Mar 19 13:08:44 2013 +0100 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Tue Mar 19 13:18:02 2013 +0100 @@ -45,11 +45,17 @@ /** Root of the class files */ @Parameter(defaultValue="${project.build.directory}/classes") private File classes; - /** File to generate. Defaults bootjava.js in the first non-empty - package under the classes directory */ + /** JavaScript file to generate */ @Parameter private File javascript; + /** Additional classes that should be pre-compiled into the javascript + * file. By default compiles all classes found under classes + * directory and their transitive closure. + */ + @Parameter + private List compileclasses; + @Parameter(defaultValue="${project}") private MavenProject prj; @@ -67,13 +73,14 @@ throw new MojoExecutionException("Can't find " + classes); } - if (javascript == null) { - javascript = new File(findNonEmptyFolder(classes), "bootjava.js"); - } - List arr = new ArrayList(); long newest = collectAllClasses("", classes, arr); + if (compileclasses != null) { + arr.retainAll(compileclasses); + arr.addAll(compileclasses); + } + if (javascript.lastModified() > newest) { return; } @@ -88,17 +95,6 @@ } } - private static File findNonEmptyFolder(File dir) throws MojoExecutionException { - if (!dir.isDirectory()) { - throw new MojoExecutionException("Not a directory " + dir); - } - File[] arr = dir.listFiles(); - if (arr.length == 1 && arr[0].isDirectory()) { - return findNonEmptyFolder(arr[0]); - } - return dir; - } - private static long collectAllClasses(String prefix, File toCheck, List arr) { File[] files = toCheck.listFiles(); if (files != null) { @@ -111,7 +107,8 @@ } return newest; } else if (toCheck.getName().endsWith(".class")) { - arr.add(prefix.substring(0, prefix.length() - 7)); + final String cls = prefix.substring(0, prefix.length() - 7); + arr.add(cls); return toCheck.lastModified(); } else { return 0L; @@ -122,7 +119,9 @@ List arr = new ArrayList(); arr.add(root.toURI().toURL()); for (Artifact a : deps) { - arr.add(a.getFile().toURI().toURL()); + if (a.getFile() != null) { + arr.add(a.getFile().toURI().toURL()); + } } return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader()); } diff -r 35507d1a5069 -r f41a1fef7738 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 19 13:08:44 2013 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 19 13:18:02 2013 +0100 @@ -283,22 +283,36 @@ TrapData[] previousTrap = null; boolean wide = false; - out.append("\n var gt = 0;\n for(;;) switch(gt) {\n"); + out.append("\n var gt = 0;\n"); + int openBraces = 0; + int topMostLabel = 0; for (int i = 0; i < byteCodes.length; i++) { int prev = i; stackMapIterator.advanceTo(i); boolean changeInCatch = trap.advanceTo(i); if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) { if (previousTrap != null) { - generateCatch(previousTrap); + generateCatch(previousTrap, i, topMostLabel); previousTrap = null; } } if (lastStackFrame != stackMapIterator.getFrameIndex()) { + if (i != 0) { + out.append(" }\n"); + } + if (openBraces > 64) { + for (int c = 0; c < 64; c++) { + out.append("break;}\n"); + } + openBraces = 1; + topMostLabel = i; + } + lastStackFrame = stackMapIterator.getFrameIndex(); lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals()); smapper.syncWithFrameStack(stackMapIterator.getFrameStack()); - out.append(" case " + i).append(": "); + out.append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n"); + openBraces++; changeInCatch = true; } else { debug(" /* " + i + " */ "); @@ -801,133 +815,104 @@ break; case opc_if_acmpeq: i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(), - "==="); + "===", topMostLabel); break; case opc_if_acmpne: i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(), - "!=="); + "!==", topMostLabel); break; case opc_if_icmpeq: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - "=="); + "==", topMostLabel); break; case opc_ifeq: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 == 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 == 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_ifne: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 != 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 != 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_iflt: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 < 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 < 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_ifle: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 <= 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 <= 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_ifgt: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 > 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 > 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_ifge: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 >= 0) { gt = @2; continue; }", - smapper.popI(), Integer.toString(indx)); + emitIf(out, "if (@1 >= 0) ", + smapper.popI(), i, indx, topMostLabel); i += 2; break; } case opc_ifnonnull: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 !== null) { gt = @2; continue; }", - smapper.popA(), Integer.toString(indx)); + emitIf(out, "if (@1 !== null) ", + smapper.popA(), i, indx, topMostLabel); i += 2; break; } case opc_ifnull: { int indx = i + readIntArg(byteCodes, i); - emit(out, "if (@1 === null) { gt = @2; continue; }", - smapper.popA(), Integer.toString(indx)); + emitIf(out, "if (@1 === null) ", + smapper.popA(), i, indx, topMostLabel); i += 2; break; } case opc_if_icmpne: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - "!="); + "!=", topMostLabel); break; case opc_if_icmplt: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - "<"); + "<", topMostLabel); break; case opc_if_icmple: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - "<="); + "<=", topMostLabel); break; case opc_if_icmpgt: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - ">"); + ">", topMostLabel); break; case opc_if_icmpge: i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), - ">="); + ">=", topMostLabel); break; case opc_goto: { int indx = i + readIntArg(byteCodes, i); - emit(out, "gt = @1; continue;", Integer.toString(indx)); + goTo(out, i, indx, topMostLabel); i += 2; break; } case opc_lookupswitch: { - int table = i / 4 * 4 + 4; - int dflt = i + readInt4(byteCodes, table); - table += 4; - int n = readInt4(byteCodes, table); - table += 4; - out.append("switch (").append(smapper.popI()).append(") {\n"); - while (n-- > 0) { - int cnstnt = readInt4(byteCodes, table); - table += 4; - int offset = i + readInt4(byteCodes, table); - table += 4; - out.append(" case " + cnstnt).append(": gt = " + offset).append("; continue;\n"); - } - out.append(" default: gt = " + dflt).append("; continue;\n}"); - i = table - 1; + i = generateLookupSwitch(i, byteCodes, smapper, topMostLabel); break; } case opc_tableswitch: { - int table = i / 4 * 4 + 4; - int dflt = i + readInt4(byteCodes, table); - table += 4; - int low = readInt4(byteCodes, table); - table += 4; - int high = readInt4(byteCodes, table); - table += 4; - out.append("switch (").append(smapper.popI()).append(") {\n"); - while (low <= high) { - int offset = i + readInt4(byteCodes, table); - table += 4; - out.append(" case " + low).append(": gt = " + offset).append("; continue;\n"); - low++; - } - out.append(" default: gt = " + dflt).append("; continue;\n}"); - i = table - 1; + i = generateTableSwitch(i, byteCodes, smapper, topMostLabel); break; } case opc_invokeinterface: { @@ -954,50 +939,18 @@ } case opc_newarray: int atype = readUByte(byteCodes, ++i); - String jvmType; - switch (atype) { - case 4: jvmType = "[Z"; break; - case 5: jvmType = "[C"; break; - case 6: jvmType = "[F"; break; - case 7: jvmType = "[D"; break; - case 8: jvmType = "[B"; break; - case 9: jvmType = "[S"; break; - case 10: jvmType = "[I"; break; - case 11: jvmType = "[J"; break; - default: throw new IllegalStateException("Array type: " + atype); - } - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);", - smapper.popI(), smapper.pushA(), jvmType); + generateNewArray(atype, smapper); break; case opc_anewarray: { int type = readIntArg(byteCodes, i); i += 2; - String typeName = jc.getClassName(type); - if (typeName.startsWith("[")) { - typeName = "[" + typeName; - } else { - typeName = "[L" + typeName + ";"; - } - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);", - smapper.popI(), smapper.pushA(), typeName); + generateANewArray(type, smapper); break; } case opc_multianewarray: { int type = readIntArg(byteCodes, i); i += 2; - String typeName = jc.getClassName(type); - int dim = readUByte(byteCodes, ++i); - StringBuilder dims = new StringBuilder(); - dims.append('['); - for (int d = 0; d < dim; d++) { - if (d != 0) { - dims.insert(1, ","); - } - dims.insert(1, smapper.popI()); - } - dims.append(']'); - emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);", - dims.toString(), smapper.pushA(), typeName); + i = generateMultiANewArray(type, byteCodes, i, smapper); break; } case opc_arraylength: @@ -1265,32 +1218,13 @@ } case opc_checkcast: { int indx = readIntArg(byteCodes, i); - final String type = jc.getClassName(indx); - if (!type.startsWith("[")) { - emit(out, - "if (@1 !== null && !@1.$instOf_@2) throw {};", - smapper.getA(0), type.replace('/', '_')); - } else { - emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);", - smapper.getA(0), type - ); - } + generateCheckcast(indx, smapper); i += 2; break; } case opc_instanceof: { int indx = readIntArg(byteCodes, i); - final String type = jc.getClassName(indx); - if (!type.startsWith("[")) { - emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;", - smapper.popA(), smapper.pushI(), - type.replace('/', '_')); - } else { - emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);", - smapper.popA(), smapper.pushI(), - type - ); - } + generateInstanceOf(indx, smapper); i += 2; break; } @@ -1326,32 +1260,29 @@ } } if (debug(" //")) { - for (int j = prev; j <= i; j++) { - out.append(" "); - final int cc = readUByte(byteCodes, j); - out.append(Integer.toString(cc)); - } + generateByteCodeComment(prev, i, byteCodes); } out.append("\n"); } if (previousTrap != null) { - generateCatch(previousTrap); + generateCatch(previousTrap, byteCodes.length, topMostLabel); } - out.append(" }\n"); - out.append("};"); + out.append("\n }\n"); + while (openBraces-- > 0) { + out.append('}'); + } + out.append("\n};"); } - private int generateIf(byte[] byteCodes, int i, - final Variable v2, final Variable v1, - final String test) throws IOException { + private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException { int indx = i + readIntArg(byteCodes, i); out.append("if (").append(v1) .append(' ').append(test).append(' ') - .append(v2).append(") { gt = " + indx) - .append("; continue; }"); + .append(v2).append(") "); + goTo(out, i, indx, topMostLabel); return i + 2; } - + private int readIntArg(byte[] byteCodes, int offsetInstruction) { final int indxHi = byteCodes[offsetInstruction + 1] << 8; final int indxLo = byteCodes[offsetInstruction + 2]; @@ -1823,7 +1754,7 @@ out.append(format, processed, length); } - private void generateCatch(TrapData[] traps) throws IOException { + private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException { out.append("} catch (e) {\n"); int finallyPC = -1; for (TrapData e : traps) { @@ -1840,10 +1771,11 @@ out.append(" var stA0 = vm.java_lang_Throwable(true);"); out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());"); out.append("}"); - out.append("gt=" + e.handler_pc + "; continue;"); + goTo(out, current, e.handler_pc, topMostLabel); } else { out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {"); - out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;"); + out.append("var stA0 = e;"); + goTo(out, current, e.handler_pc, topMostLabel); out.append("}\n"); } } else { @@ -1853,8 +1785,152 @@ if (finallyPC == -1) { out.append("throw e;"); } else { - out.append("gt=" + finallyPC + "; var stA0 = e; continue;"); + out.append("var stA0 = e;"); + goTo(out, current, finallyPC, topMostLabel); } out.append("\n}"); } + + private static void goTo(Appendable out, int current, int to, int canBack) throws IOException { + if (to < current) { + if (canBack < to) { + out.append("{ gt = 0; continue X_" + to + "; }"); + } else { + out.append("{ gt = " + to + "; continue X_0; }"); + } + } else { + out.append("{ gt = " + to + "; break IF; }"); + } + } + + private static void emitIf( + Appendable out, String pattern, Variable param, + int current, int to, int canBack + ) throws IOException { + emit(out, pattern, param); + goTo(out, current, to, canBack); + } + + private void generateNewArray(int atype, final StackMapper smapper) throws IOException, IllegalStateException { + String jvmType; + switch (atype) { + case 4: jvmType = "[Z"; break; + case 5: jvmType = "[C"; break; + case 6: jvmType = "[F"; break; + case 7: jvmType = "[D"; break; + case 8: jvmType = "[B"; break; + case 9: jvmType = "[S"; break; + case 10: jvmType = "[I"; break; + case 11: jvmType = "[J"; break; + default: throw new IllegalStateException("Array type: " + atype); + } + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);", + smapper.popI(), smapper.pushA(), jvmType); + } + + private void generateANewArray(int type, final StackMapper smapper) throws IOException { + String typeName = jc.getClassName(type); + if (typeName.startsWith("[")) { + typeName = "[" + typeName; + } else { + typeName = "[L" + typeName + ";"; + } + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);", + smapper.popI(), smapper.pushA(), typeName); + } + + private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException { + String typeName = jc.getClassName(type); + int dim = readUByte(byteCodes, ++i); + StringBuilder dims = new StringBuilder(); + dims.append('['); + for (int d = 0; d < dim; d++) { + if (d != 0) { + dims.insert(1, ","); + } + dims.insert(1, smapper.popI()); + } + dims.append(']'); + emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);", + dims.toString(), smapper.pushA(), typeName); + return i; + } + + private int generateTableSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException { + int table = i / 4 * 4 + 4; + int dflt = i + readInt4(byteCodes, table); + table += 4; + int low = readInt4(byteCodes, table); + table += 4; + int high = readInt4(byteCodes, table); + table += 4; + out.append("switch (").append(smapper.popI()).append(") {\n"); + while (low <= high) { + int offset = i + readInt4(byteCodes, table); + table += 4; + out.append(" case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n'); + low++; + } + out.append(" default: "); + goTo(out, i, dflt, topMostLabel); + out.append("\n}"); + i = table - 1; + return i; + } + + private int generateLookupSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException { + int table = i / 4 * 4 + 4; + int dflt = i + readInt4(byteCodes, table); + table += 4; + int n = readInt4(byteCodes, table); + table += 4; + out.append("switch (").append(smapper.popI()).append(") {\n"); + while (n-- > 0) { + int cnstnt = readInt4(byteCodes, table); + table += 4; + int offset = i + readInt4(byteCodes, table); + table += 4; + out.append(" case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n'); + } + out.append(" default: "); + goTo(out, i, dflt, topMostLabel); + out.append("\n}"); + i = table - 1; + return i; + } + + private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException { + final String type = jc.getClassName(indx); + if (!type.startsWith("[")) { + emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;", + smapper.popA(), smapper.pushI(), + type.replace('/', '_')); + } else { + emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);", + smapper.popA(), smapper.pushI(), + type + ); + } + } + + private void generateCheckcast(int indx, final StackMapper smapper) throws IOException { + final String type = jc.getClassName(indx); + if (!type.startsWith("[")) { + emit(out, + "if (@1 !== null && !@1.$instOf_@2) throw {};", + smapper.getA(0), type.replace('/', '_')); + } else { + emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);", + smapper.getA(0), type + ); + } + } + + private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException { + for (int j = prev; j <= i; j++) { + out.append(" "); + final int cc = readUByte(byteCodes, j); + out.append(Integer.toString(cc)); + } + } } diff -r 35507d1a5069 -r f41a1fef7738 rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Tue Mar 19 13:08:44 2013 +0100 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Tue Mar 19 13:18:02 2013 +0100 @@ -115,7 +115,7 @@ if (sb.length() > 2000) { sb = dumpJS(sb); } - fail("Could not evaluate:\n" + sb, ex); + fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex); return null; } }