1.1 --- a/benchmarks/matrix-multiplication/pom.xml Tue Mar 19 13:08:44 2013 +0100
1.2 +++ b/benchmarks/matrix-multiplication/pom.xml Tue Mar 19 13:18:02 2013 +0100
1.3 @@ -37,6 +37,36 @@
1.4 <skip>true</skip>
1.5 </configuration>
1.6 </plugin>
1.7 + <plugin>
1.8 + <groupId>org.codehaus.mojo</groupId>
1.9 + <artifactId>xml-maven-plugin</artifactId>
1.10 + <version>1.0</version>
1.11 + <executions>
1.12 + <execution>
1.13 + <goals>
1.14 + <goal>transform</goal>
1.15 + </goals>
1.16 + <phase>install</phase>
1.17 + </execution>
1.18 + </executions>
1.19 + <configuration>
1.20 + <transformationSets>
1.21 + <transformationSet>
1.22 + <dir>target/surefire-reports</dir>
1.23 + <outputDir>target/surefire-reports</outputDir>
1.24 + <includes>
1.25 + <include>TEST*.xml</include>
1.26 + </includes>
1.27 + <stylesheet>src/main/select-time.xsl</stylesheet>
1.28 + <fileMappers>
1.29 + <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
1.30 + <targetExtension>.csv</targetExtension>
1.31 + </fileMapper>
1.32 + </fileMappers>
1.33 + </transformationSet>
1.34 + </transformationSets>
1.35 + </configuration>
1.36 + </plugin>
1.37 </plugins>
1.38 </build>
1.39
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/benchmarks/matrix-multiplication/src/main/select-time.xsl Tue Mar 19 13:18:02 2013 +0100
2.3 @@ -0,0 +1,55 @@
2.4 +<?xml version="1.0" encoding="UTF-8"?>
2.5 +<!--
2.6 +
2.7 + Back 2 Browser Bytecode Translator
2.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.9 +
2.10 + This program is free software: you can redistribute it and/or modify
2.11 + it under the terms of the GNU General Public License as published by
2.12 + the Free Software Foundation, version 2 of the License.
2.13 +
2.14 + This program is distributed in the hope that it will be useful,
2.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
2.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.17 + GNU General Public License for more details.
2.18 +
2.19 + You should have received a copy of the GNU General Public License
2.20 + along with this program. Look for COPYING file in the top folder.
2.21 + If not, see http://opensource.org/licenses/GPL-2.0.
2.22 +
2.23 +-->
2.24 +
2.25 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
2.26 + <xsl:output method="text"/>
2.27 +
2.28 + <xsl:template match="/">
2.29 + <xsl:apply-templates mode="header" select="testsuite/testcase"/><xsl:text>End
2.30 +</xsl:text>
2.31 + <xsl:apply-templates mode="value" select="testsuite/testcase"/><xsl:text>NaN
2.32 +</xsl:text>
2.33 + </xsl:template>
2.34 +
2.35 +
2.36 + <xsl:template match="testcase" mode="header">
2.37 + <xsl:if test="contains(@name,'tenThousand')">
2.38 + <xsl:if test="not(contains(@name, '[Java]'))">
2.39 + <xsl:if test="not(contains(@name, '[Compare'))">
2.40 + <xsl:value-of select="@name"/>
2.41 + <xsl:text>,</xsl:text>
2.42 + </xsl:if>
2.43 + </xsl:if>
2.44 + </xsl:if>
2.45 + </xsl:template>
2.46 +
2.47 + <xsl:template match="testcase" mode="value">
2.48 + <xsl:if test="contains(@name,'tenThousand')">
2.49 + <xsl:if test="not(contains(@name, '[Java]'))">
2.50 + <xsl:if test="not(contains(@name, '[Compare'))">
2.51 + <xsl:value-of select="@time"/>
2.52 + <xsl:text>,</xsl:text>
2.53 + </xsl:if>
2.54 + </xsl:if>
2.55 + </xsl:if>
2.56 + </xsl:template>
2.57 +
2.58 +</xsl:stylesheet>
3.1 --- a/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java Tue Mar 19 13:08:44 2013 +0100
3.2 +++ b/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java Tue Mar 19 13:18:02 2013 +0100
3.3 @@ -31,6 +31,22 @@
3.4 }
3.5
3.6 @Compare(scripting = false)
3.7 + public String oneIteration() throws IOException {
3.8 +
3.9 + Matrix m1 = new Matrix(5);
3.10 + Matrix m2 = new Matrix(5);
3.11 +
3.12 + m1.generateData();
3.13 + m2.generateData();
3.14 +
3.15 + Matrix res = m1.multiply(m2);
3.16 +
3.17 + StringBuilder sb = new StringBuilder();
3.18 + res.printOn(sb);
3.19 + return sb.toString();
3.20 + }
3.21 +
3.22 + @Compare(scripting = false)
3.23 public String tenThousandIterations() throws IOException {
3.24
3.25 Matrix m1 = new Matrix(5);
3.26 @@ -50,6 +66,27 @@
3.27 return sb.toString();
3.28 }
3.29
3.30 + @Compare(scripting = false)
3.31 + public String tenUselessIterations() throws IOException {
3.32 +
3.33 + Matrix m1 = new Matrix(5);
3.34 + Matrix m2 = new Matrix(5);
3.35 +
3.36 + m1.generateData();
3.37 + m2.generateData();
3.38 +
3.39 + Matrix res = null;
3.40 + for (int i = 0; i < 10; i++) {
3.41 + res = m1.multiply(m2);
3.42 + m1 = res;
3.43 + }
3.44 +
3.45 + StringBuilder sb = new StringBuilder();
3.46 + res.printOn(sb);
3.47 + return sb.toString();
3.48 + }
3.49 +
3.50 +
3.51 @Factory
3.52 public static Object[] create() {
3.53 return VMTest.create(MatrixTest.class);
4.1 --- a/javaquery/demo-calculator-dynamic/nbactions.xml Tue Mar 19 13:08:44 2013 +0100
4.2 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml Tue Mar 19 13:18:02 2013 +0100
4.3 @@ -23,7 +23,7 @@
4.4 <actionName>run</actionName>
4.5 <goals>
4.6 <goal>process-classes</goal>
4.7 - <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
4.8 + <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
4.9 </goals>
4.10 </action>
4.11 </actions>
5.1 --- a/javaquery/demo-calculator/nbactions.xml Tue Mar 19 13:08:44 2013 +0100
5.2 +++ b/javaquery/demo-calculator/nbactions.xml Tue Mar 19 13:18:02 2013 +0100
5.3 @@ -23,7 +23,7 @@
5.4 <actionName>run</actionName>
5.5 <goals>
5.6 <goal>package</goal>
5.7 - <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
5.8 + <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
5.9 </goals>
5.10 <properties>
5.11 <skipTests>true</skipTests>
6.1 --- a/javaquery/demo-calculator/pom.xml Tue Mar 19 13:08:44 2013 +0100
6.2 +++ b/javaquery/demo-calculator/pom.xml Tue Mar 19 13:18:02 2013 +0100
6.3 @@ -22,6 +22,7 @@
6.4 <executions>
6.5 <execution>
6.6 <goals>
6.7 + <goal>j2js</goal>
6.8 <goal>brwsr</goal>
6.9 </goals>
6.10 </execution>
6.11 @@ -29,6 +30,7 @@
6.12 <configuration>
6.13 <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
6.14 <startpage>index.xhtml</startpage>
6.15 + <javascript>${project.build.directory}/bck2brwsr.js</javascript>
6.16 </configuration>
6.17 </plugin>
6.18 <plugin>
6.19 @@ -102,13 +104,5 @@
6.20 <artifactId>javaquery.api</artifactId>
6.21 <version>0.5-SNAPSHOT</version>
6.22 </dependency>
6.23 - <dependency>
6.24 - <groupId>org.apidesign.bck2brwsr</groupId>
6.25 - <artifactId>vm4brwsr</artifactId>
6.26 - <classifier>js</classifier>
6.27 - <type>zip</type>
6.28 - <version>0.5-SNAPSHOT</version>
6.29 - <scope>provided</scope>
6.30 - </dependency>
6.31 </dependencies>
6.32 </project>
7.1 --- a/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Tue Mar 19 13:08:44 2013 +0100
7.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Tue Mar 19 13:18:02 2013 +0100
7.3 @@ -37,15 +37,6 @@
7.4 <include>*:rt</include>
7.5 </includes>
7.6 </dependencySet>
7.7 - <dependencySet>
7.8 - <useProjectArtifact>false</useProjectArtifact>
7.9 - <scope>provided</scope>
7.10 - <includes>
7.11 - <include>*:js</include>
7.12 - </includes>
7.13 - <unpack>true</unpack>
7.14 - <outputDirectory>/</outputDirectory>
7.15 - </dependencySet>
7.16 </dependencySets>
7.17 <files>
7.18 <file>
7.19 @@ -53,6 +44,10 @@
7.20 <outputDirectory>/</outputDirectory>
7.21 </file>
7.22 <file>
7.23 + <source>${project.build.directory}/bck2brwsr.js</source>
7.24 + <outputDirectory>/</outputDirectory>
7.25 + </file>
7.26 + <file>
7.27 <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</source>
7.28 <outputDirectory>/</outputDirectory>
7.29 <destName>index.xhtml</destName>
8.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Tue Mar 19 13:08:44 2013 +0100
8.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Tue Mar 19 13:18:02 2013 +0100
8.3 @@ -45,11 +45,17 @@
8.4 /** Root of the class files */
8.5 @Parameter(defaultValue="${project.build.directory}/classes")
8.6 private File classes;
8.7 - /** File to generate. Defaults bootjava.js in the first non-empty
8.8 - package under the classes directory */
8.9 + /** JavaScript file to generate */
8.10 @Parameter
8.11 private File javascript;
8.12
8.13 + /** Additional classes that should be pre-compiled into the javascript
8.14 + * file. By default compiles all classes found under <code>classes</code>
8.15 + * directory and their transitive closure.
8.16 + */
8.17 + @Parameter
8.18 + private List<String> compileclasses;
8.19 +
8.20 @Parameter(defaultValue="${project}")
8.21 private MavenProject prj;
8.22
8.23 @@ -67,13 +73,14 @@
8.24 throw new MojoExecutionException("Can't find " + classes);
8.25 }
8.26
8.27 - if (javascript == null) {
8.28 - javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
8.29 - }
8.30 -
8.31 List<String> arr = new ArrayList<String>();
8.32 long newest = collectAllClasses("", classes, arr);
8.33
8.34 + if (compileclasses != null) {
8.35 + arr.retainAll(compileclasses);
8.36 + arr.addAll(compileclasses);
8.37 + }
8.38 +
8.39 if (javascript.lastModified() > newest) {
8.40 return;
8.41 }
8.42 @@ -88,17 +95,6 @@
8.43 }
8.44 }
8.45
8.46 - private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
8.47 - if (!dir.isDirectory()) {
8.48 - throw new MojoExecutionException("Not a directory " + dir);
8.49 - }
8.50 - File[] arr = dir.listFiles();
8.51 - if (arr.length == 1 && arr[0].isDirectory()) {
8.52 - return findNonEmptyFolder(arr[0]);
8.53 - }
8.54 - return dir;
8.55 - }
8.56 -
8.57 private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
8.58 File[] files = toCheck.listFiles();
8.59 if (files != null) {
8.60 @@ -111,7 +107,8 @@
8.61 }
8.62 return newest;
8.63 } else if (toCheck.getName().endsWith(".class")) {
8.64 - arr.add(prefix.substring(0, prefix.length() - 7));
8.65 + final String cls = prefix.substring(0, prefix.length() - 7);
8.66 + arr.add(cls);
8.67 return toCheck.lastModified();
8.68 } else {
8.69 return 0L;
8.70 @@ -122,7 +119,9 @@
8.71 List<URL> arr = new ArrayList<URL>();
8.72 arr.add(root.toURI().toURL());
8.73 for (Artifact a : deps) {
8.74 - arr.add(a.getFile().toURI().toURL());
8.75 + if (a.getFile() != null) {
8.76 + arr.add(a.getFile().toURI().toURL());
8.77 + }
8.78 }
8.79 return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
8.80 }
9.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 19 13:08:44 2013 +0100
9.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 19 13:18:02 2013 +0100
9.3 @@ -283,22 +283,36 @@
9.4 TrapData[] previousTrap = null;
9.5 boolean wide = false;
9.6
9.7 - out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
9.8 + out.append("\n var gt = 0;\n");
9.9 + int openBraces = 0;
9.10 + int topMostLabel = 0;
9.11 for (int i = 0; i < byteCodes.length; i++) {
9.12 int prev = i;
9.13 stackMapIterator.advanceTo(i);
9.14 boolean changeInCatch = trap.advanceTo(i);
9.15 if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
9.16 if (previousTrap != null) {
9.17 - generateCatch(previousTrap);
9.18 + generateCatch(previousTrap, i, topMostLabel);
9.19 previousTrap = null;
9.20 }
9.21 }
9.22 if (lastStackFrame != stackMapIterator.getFrameIndex()) {
9.23 + if (i != 0) {
9.24 + out.append(" }\n");
9.25 + }
9.26 + if (openBraces > 64) {
9.27 + for (int c = 0; c < 64; c++) {
9.28 + out.append("break;}\n");
9.29 + }
9.30 + openBraces = 1;
9.31 + topMostLabel = i;
9.32 + }
9.33 +
9.34 lastStackFrame = stackMapIterator.getFrameIndex();
9.35 lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
9.36 smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
9.37 - out.append(" case " + i).append(": ");
9.38 + out.append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
9.39 + openBraces++;
9.40 changeInCatch = true;
9.41 } else {
9.42 debug(" /* " + i + " */ ");
9.43 @@ -801,133 +815,104 @@
9.44 break;
9.45 case opc_if_acmpeq:
9.46 i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
9.47 - "===");
9.48 + "===", topMostLabel);
9.49 break;
9.50 case opc_if_acmpne:
9.51 i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
9.52 - "!==");
9.53 + "!==", topMostLabel);
9.54 break;
9.55 case opc_if_icmpeq:
9.56 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.57 - "==");
9.58 + "==", topMostLabel);
9.59 break;
9.60 case opc_ifeq: {
9.61 int indx = i + readIntArg(byteCodes, i);
9.62 - emit(out, "if (@1 == 0) { gt = @2; continue; }",
9.63 - smapper.popI(), Integer.toString(indx));
9.64 + emitIf(out, "if (@1 == 0) ",
9.65 + smapper.popI(), i, indx, topMostLabel);
9.66 i += 2;
9.67 break;
9.68 }
9.69 case opc_ifne: {
9.70 int indx = i + readIntArg(byteCodes, i);
9.71 - emit(out, "if (@1 != 0) { gt = @2; continue; }",
9.72 - smapper.popI(), Integer.toString(indx));
9.73 + emitIf(out, "if (@1 != 0) ",
9.74 + smapper.popI(), i, indx, topMostLabel);
9.75 i += 2;
9.76 break;
9.77 }
9.78 case opc_iflt: {
9.79 int indx = i + readIntArg(byteCodes, i);
9.80 - emit(out, "if (@1 < 0) { gt = @2; continue; }",
9.81 - smapper.popI(), Integer.toString(indx));
9.82 + emitIf(out, "if (@1 < 0) ",
9.83 + smapper.popI(), i, indx, topMostLabel);
9.84 i += 2;
9.85 break;
9.86 }
9.87 case opc_ifle: {
9.88 int indx = i + readIntArg(byteCodes, i);
9.89 - emit(out, "if (@1 <= 0) { gt = @2; continue; }",
9.90 - smapper.popI(), Integer.toString(indx));
9.91 + emitIf(out, "if (@1 <= 0) ",
9.92 + smapper.popI(), i, indx, topMostLabel);
9.93 i += 2;
9.94 break;
9.95 }
9.96 case opc_ifgt: {
9.97 int indx = i + readIntArg(byteCodes, i);
9.98 - emit(out, "if (@1 > 0) { gt = @2; continue; }",
9.99 - smapper.popI(), Integer.toString(indx));
9.100 + emitIf(out, "if (@1 > 0) ",
9.101 + smapper.popI(), i, indx, topMostLabel);
9.102 i += 2;
9.103 break;
9.104 }
9.105 case opc_ifge: {
9.106 int indx = i + readIntArg(byteCodes, i);
9.107 - emit(out, "if (@1 >= 0) { gt = @2; continue; }",
9.108 - smapper.popI(), Integer.toString(indx));
9.109 + emitIf(out, "if (@1 >= 0) ",
9.110 + smapper.popI(), i, indx, topMostLabel);
9.111 i += 2;
9.112 break;
9.113 }
9.114 case opc_ifnonnull: {
9.115 int indx = i + readIntArg(byteCodes, i);
9.116 - emit(out, "if (@1 !== null) { gt = @2; continue; }",
9.117 - smapper.popA(), Integer.toString(indx));
9.118 + emitIf(out, "if (@1 !== null) ",
9.119 + smapper.popA(), i, indx, topMostLabel);
9.120 i += 2;
9.121 break;
9.122 }
9.123 case opc_ifnull: {
9.124 int indx = i + readIntArg(byteCodes, i);
9.125 - emit(out, "if (@1 === null) { gt = @2; continue; }",
9.126 - smapper.popA(), Integer.toString(indx));
9.127 + emitIf(out, "if (@1 === null) ",
9.128 + smapper.popA(), i, indx, topMostLabel);
9.129 i += 2;
9.130 break;
9.131 }
9.132 case opc_if_icmpne:
9.133 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.134 - "!=");
9.135 + "!=", topMostLabel);
9.136 break;
9.137 case opc_if_icmplt:
9.138 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.139 - "<");
9.140 + "<", topMostLabel);
9.141 break;
9.142 case opc_if_icmple:
9.143 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.144 - "<=");
9.145 + "<=", topMostLabel);
9.146 break;
9.147 case opc_if_icmpgt:
9.148 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.149 - ">");
9.150 + ">", topMostLabel);
9.151 break;
9.152 case opc_if_icmpge:
9.153 i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
9.154 - ">=");
9.155 + ">=", topMostLabel);
9.156 break;
9.157 case opc_goto: {
9.158 int indx = i + readIntArg(byteCodes, i);
9.159 - emit(out, "gt = @1; continue;", Integer.toString(indx));
9.160 + goTo(out, i, indx, topMostLabel);
9.161 i += 2;
9.162 break;
9.163 }
9.164 case opc_lookupswitch: {
9.165 - int table = i / 4 * 4 + 4;
9.166 - int dflt = i + readInt4(byteCodes, table);
9.167 - table += 4;
9.168 - int n = readInt4(byteCodes, table);
9.169 - table += 4;
9.170 - out.append("switch (").append(smapper.popI()).append(") {\n");
9.171 - while (n-- > 0) {
9.172 - int cnstnt = readInt4(byteCodes, table);
9.173 - table += 4;
9.174 - int offset = i + readInt4(byteCodes, table);
9.175 - table += 4;
9.176 - out.append(" case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
9.177 - }
9.178 - out.append(" default: gt = " + dflt).append("; continue;\n}");
9.179 - i = table - 1;
9.180 + i = generateLookupSwitch(i, byteCodes, smapper, topMostLabel);
9.181 break;
9.182 }
9.183 case opc_tableswitch: {
9.184 - int table = i / 4 * 4 + 4;
9.185 - int dflt = i + readInt4(byteCodes, table);
9.186 - table += 4;
9.187 - int low = readInt4(byteCodes, table);
9.188 - table += 4;
9.189 - int high = readInt4(byteCodes, table);
9.190 - table += 4;
9.191 - out.append("switch (").append(smapper.popI()).append(") {\n");
9.192 - while (low <= high) {
9.193 - int offset = i + readInt4(byteCodes, table);
9.194 - table += 4;
9.195 - out.append(" case " + low).append(": gt = " + offset).append("; continue;\n");
9.196 - low++;
9.197 - }
9.198 - out.append(" default: gt = " + dflt).append("; continue;\n}");
9.199 - i = table - 1;
9.200 + i = generateTableSwitch(i, byteCodes, smapper, topMostLabel);
9.201 break;
9.202 }
9.203 case opc_invokeinterface: {
9.204 @@ -954,50 +939,18 @@
9.205 }
9.206 case opc_newarray:
9.207 int atype = readUByte(byteCodes, ++i);
9.208 - String jvmType;
9.209 - switch (atype) {
9.210 - case 4: jvmType = "[Z"; break;
9.211 - case 5: jvmType = "[C"; break;
9.212 - case 6: jvmType = "[F"; break;
9.213 - case 7: jvmType = "[D"; break;
9.214 - case 8: jvmType = "[B"; break;
9.215 - case 9: jvmType = "[S"; break;
9.216 - case 10: jvmType = "[I"; break;
9.217 - case 11: jvmType = "[J"; break;
9.218 - default: throw new IllegalStateException("Array type: " + atype);
9.219 - }
9.220 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
9.221 - smapper.popI(), smapper.pushA(), jvmType);
9.222 + generateNewArray(atype, smapper);
9.223 break;
9.224 case opc_anewarray: {
9.225 int type = readIntArg(byteCodes, i);
9.226 i += 2;
9.227 - String typeName = jc.getClassName(type);
9.228 - if (typeName.startsWith("[")) {
9.229 - typeName = "[" + typeName;
9.230 - } else {
9.231 - typeName = "[L" + typeName + ";";
9.232 - }
9.233 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
9.234 - smapper.popI(), smapper.pushA(), typeName);
9.235 + generateANewArray(type, smapper);
9.236 break;
9.237 }
9.238 case opc_multianewarray: {
9.239 int type = readIntArg(byteCodes, i);
9.240 i += 2;
9.241 - String typeName = jc.getClassName(type);
9.242 - int dim = readUByte(byteCodes, ++i);
9.243 - StringBuilder dims = new StringBuilder();
9.244 - dims.append('[');
9.245 - for (int d = 0; d < dim; d++) {
9.246 - if (d != 0) {
9.247 - dims.insert(1, ",");
9.248 - }
9.249 - dims.insert(1, smapper.popI());
9.250 - }
9.251 - dims.append(']');
9.252 - emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
9.253 - dims.toString(), smapper.pushA(), typeName);
9.254 + i = generateMultiANewArray(type, byteCodes, i, smapper);
9.255 break;
9.256 }
9.257 case opc_arraylength:
9.258 @@ -1265,32 +1218,13 @@
9.259 }
9.260 case opc_checkcast: {
9.261 int indx = readIntArg(byteCodes, i);
9.262 - final String type = jc.getClassName(indx);
9.263 - if (!type.startsWith("[")) {
9.264 - emit(out,
9.265 - "if (@1 !== null && !@1.$instOf_@2) throw {};",
9.266 - smapper.getA(0), type.replace('/', '_'));
9.267 - } else {
9.268 - 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);",
9.269 - smapper.getA(0), type
9.270 - );
9.271 - }
9.272 + generateCheckcast(indx, smapper);
9.273 i += 2;
9.274 break;
9.275 }
9.276 case opc_instanceof: {
9.277 int indx = readIntArg(byteCodes, i);
9.278 - final String type = jc.getClassName(indx);
9.279 - if (!type.startsWith("[")) {
9.280 - emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
9.281 - smapper.popA(), smapper.pushI(),
9.282 - type.replace('/', '_'));
9.283 - } else {
9.284 - emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
9.285 - smapper.popA(), smapper.pushI(),
9.286 - type
9.287 - );
9.288 - }
9.289 + generateInstanceOf(indx, smapper);
9.290 i += 2;
9.291 break;
9.292 }
9.293 @@ -1326,32 +1260,29 @@
9.294 }
9.295 }
9.296 if (debug(" //")) {
9.297 - for (int j = prev; j <= i; j++) {
9.298 - out.append(" ");
9.299 - final int cc = readUByte(byteCodes, j);
9.300 - out.append(Integer.toString(cc));
9.301 - }
9.302 + generateByteCodeComment(prev, i, byteCodes);
9.303 }
9.304 out.append("\n");
9.305 }
9.306 if (previousTrap != null) {
9.307 - generateCatch(previousTrap);
9.308 + generateCatch(previousTrap, byteCodes.length, topMostLabel);
9.309 }
9.310 - out.append(" }\n");
9.311 - out.append("};");
9.312 + out.append("\n }\n");
9.313 + while (openBraces-- > 0) {
9.314 + out.append('}');
9.315 + }
9.316 + out.append("\n};");
9.317 }
9.318
9.319 - private int generateIf(byte[] byteCodes, int i,
9.320 - final Variable v2, final Variable v1,
9.321 - final String test) throws IOException {
9.322 + private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
9.323 int indx = i + readIntArg(byteCodes, i);
9.324 out.append("if (").append(v1)
9.325 .append(' ').append(test).append(' ')
9.326 - .append(v2).append(") { gt = " + indx)
9.327 - .append("; continue; }");
9.328 + .append(v2).append(") ");
9.329 + goTo(out, i, indx, topMostLabel);
9.330 return i + 2;
9.331 }
9.332 -
9.333 +
9.334 private int readIntArg(byte[] byteCodes, int offsetInstruction) {
9.335 final int indxHi = byteCodes[offsetInstruction + 1] << 8;
9.336 final int indxLo = byteCodes[offsetInstruction + 2];
9.337 @@ -1823,7 +1754,7 @@
9.338 out.append(format, processed, length);
9.339 }
9.340
9.341 - private void generateCatch(TrapData[] traps) throws IOException {
9.342 + private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException {
9.343 out.append("} catch (e) {\n");
9.344 int finallyPC = -1;
9.345 for (TrapData e : traps) {
9.346 @@ -1840,10 +1771,11 @@
9.347 out.append(" var stA0 = vm.java_lang_Throwable(true);");
9.348 out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
9.349 out.append("}");
9.350 - out.append("gt=" + e.handler_pc + "; continue;");
9.351 + goTo(out, current, e.handler_pc, topMostLabel);
9.352 } else {
9.353 out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
9.354 - out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
9.355 + out.append("var stA0 = e;");
9.356 + goTo(out, current, e.handler_pc, topMostLabel);
9.357 out.append("}\n");
9.358 }
9.359 } else {
9.360 @@ -1853,8 +1785,152 @@
9.361 if (finallyPC == -1) {
9.362 out.append("throw e;");
9.363 } else {
9.364 - out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
9.365 + out.append("var stA0 = e;");
9.366 + goTo(out, current, finallyPC, topMostLabel);
9.367 }
9.368 out.append("\n}");
9.369 }
9.370 +
9.371 + private static void goTo(Appendable out, int current, int to, int canBack) throws IOException {
9.372 + if (to < current) {
9.373 + if (canBack < to) {
9.374 + out.append("{ gt = 0; continue X_" + to + "; }");
9.375 + } else {
9.376 + out.append("{ gt = " + to + "; continue X_0; }");
9.377 + }
9.378 + } else {
9.379 + out.append("{ gt = " + to + "; break IF; }");
9.380 + }
9.381 + }
9.382 +
9.383 + private static void emitIf(
9.384 + Appendable out, String pattern, Variable param,
9.385 + int current, int to, int canBack
9.386 + ) throws IOException {
9.387 + emit(out, pattern, param);
9.388 + goTo(out, current, to, canBack);
9.389 + }
9.390 +
9.391 + private void generateNewArray(int atype, final StackMapper smapper) throws IOException, IllegalStateException {
9.392 + String jvmType;
9.393 + switch (atype) {
9.394 + case 4: jvmType = "[Z"; break;
9.395 + case 5: jvmType = "[C"; break;
9.396 + case 6: jvmType = "[F"; break;
9.397 + case 7: jvmType = "[D"; break;
9.398 + case 8: jvmType = "[B"; break;
9.399 + case 9: jvmType = "[S"; break;
9.400 + case 10: jvmType = "[I"; break;
9.401 + case 11: jvmType = "[J"; break;
9.402 + default: throw new IllegalStateException("Array type: " + atype);
9.403 + }
9.404 + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
9.405 + smapper.popI(), smapper.pushA(), jvmType);
9.406 + }
9.407 +
9.408 + private void generateANewArray(int type, final StackMapper smapper) throws IOException {
9.409 + String typeName = jc.getClassName(type);
9.410 + if (typeName.startsWith("[")) {
9.411 + typeName = "[" + typeName;
9.412 + } else {
9.413 + typeName = "[L" + typeName + ";";
9.414 + }
9.415 + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
9.416 + smapper.popI(), smapper.pushA(), typeName);
9.417 + }
9.418 +
9.419 + private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException {
9.420 + String typeName = jc.getClassName(type);
9.421 + int dim = readUByte(byteCodes, ++i);
9.422 + StringBuilder dims = new StringBuilder();
9.423 + dims.append('[');
9.424 + for (int d = 0; d < dim; d++) {
9.425 + if (d != 0) {
9.426 + dims.insert(1, ",");
9.427 + }
9.428 + dims.insert(1, smapper.popI());
9.429 + }
9.430 + dims.append(']');
9.431 + emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
9.432 + dims.toString(), smapper.pushA(), typeName);
9.433 + return i;
9.434 + }
9.435 +
9.436 + private int generateTableSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
9.437 + int table = i / 4 * 4 + 4;
9.438 + int dflt = i + readInt4(byteCodes, table);
9.439 + table += 4;
9.440 + int low = readInt4(byteCodes, table);
9.441 + table += 4;
9.442 + int high = readInt4(byteCodes, table);
9.443 + table += 4;
9.444 + out.append("switch (").append(smapper.popI()).append(") {\n");
9.445 + while (low <= high) {
9.446 + int offset = i + readInt4(byteCodes, table);
9.447 + table += 4;
9.448 + out.append(" case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n');
9.449 + low++;
9.450 + }
9.451 + out.append(" default: ");
9.452 + goTo(out, i, dflt, topMostLabel);
9.453 + out.append("\n}");
9.454 + i = table - 1;
9.455 + return i;
9.456 + }
9.457 +
9.458 + private int generateLookupSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
9.459 + int table = i / 4 * 4 + 4;
9.460 + int dflt = i + readInt4(byteCodes, table);
9.461 + table += 4;
9.462 + int n = readInt4(byteCodes, table);
9.463 + table += 4;
9.464 + out.append("switch (").append(smapper.popI()).append(") {\n");
9.465 + while (n-- > 0) {
9.466 + int cnstnt = readInt4(byteCodes, table);
9.467 + table += 4;
9.468 + int offset = i + readInt4(byteCodes, table);
9.469 + table += 4;
9.470 + out.append(" case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n');
9.471 + }
9.472 + out.append(" default: ");
9.473 + goTo(out, i, dflt, topMostLabel);
9.474 + out.append("\n}");
9.475 + i = table - 1;
9.476 + return i;
9.477 + }
9.478 +
9.479 + private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
9.480 + final String type = jc.getClassName(indx);
9.481 + if (!type.startsWith("[")) {
9.482 + emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
9.483 + smapper.popA(), smapper.pushI(),
9.484 + type.replace('/', '_'));
9.485 + } else {
9.486 + emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
9.487 + smapper.popA(), smapper.pushI(),
9.488 + type
9.489 + );
9.490 + }
9.491 + }
9.492 +
9.493 + private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
9.494 + final String type = jc.getClassName(indx);
9.495 + if (!type.startsWith("[")) {
9.496 + emit(out,
9.497 + "if (@1 !== null && !@1.$instOf_@2) throw {};",
9.498 + smapper.getA(0), type.replace('/', '_'));
9.499 + } else {
9.500 + 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);",
9.501 + smapper.getA(0), type
9.502 + );
9.503 + }
9.504 + }
9.505 +
9.506 + private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
9.507 + for (int j = prev; j <= i; j++) {
9.508 + out.append(" ");
9.509 + final int cc = readUByte(byteCodes, j);
9.510 + out.append(Integer.toString(cc));
9.511 + }
9.512 + }
9.513 }
10.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Tue Mar 19 13:08:44 2013 +0100
10.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Tue Mar 19 13:18:02 2013 +0100
10.3 @@ -115,7 +115,7 @@
10.4 if (sb.length() > 2000) {
10.5 sb = dumpJS(sb);
10.6 }
10.7 - fail("Could not evaluate:\n" + sb, ex);
10.8 + fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
10.9 return null;
10.10 }
10.11 }