The JavaScript VM is able to generate some (not yet valid) code.
1.1 --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Fri Nov 16 08:26:55 2012 +0100
1.2 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Sat Nov 17 11:21:17 2012 +0100
1.3 @@ -1367,6 +1367,14 @@
1.4 function java_lang_String_substringLjava_lang_StringII(arg0,arg1,arg2) {
1.5 return arg0.toString().substring(arg1, arg2);
1.6 }
1.7 +
1.8 +function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) {
1.9 + return arg0.toString().replace(arg1, arg2);
1.10 +}
1.11 +function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) {
1.12 + return arg0.toString().indexOf(arg1.toString()) >= 0;
1.13 +}
1.14 +
1.15 /*
1.16 function java_lang_String_subSequenceLjava_lang_CharSequenceII(arg0,arg1,arg2) {
1.17 var arg3;
1.18 @@ -1428,96 +1436,6 @@
1.19 case 57: return stack.pop(); // 176
1.20 }
1.21 }
1.22 -function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) {
1.23 - var arg3;
1.24 - var arg4;
1.25 - var arg5;
1.26 - var arg6;
1.27 - var arg7;
1.28 - var arg8;
1.29 - var arg9;
1.30 -;
1.31 - var stack = new Array(5);
1.32 - var gt = 0;
1.33 - for(;;) switch(gt) {
1.34 - case 0: stack.push(arg1); // 27
1.35 - case 1: stack.push(arg2); // 28
1.36 - case 2: if (stack.pop() == stack.pop()) { gt = 140; continue; } // 159 0 138
1.37 - case 5: stack.push(arg0); // 42
1.38 - case 6: stack.push(stack.pop().count); // 180 1 97
1.39 - case 9: arg3 = stack.pop(); // 62
1.40 - case 10: // 2
1.41 - case 11: arg4 = stack.pop() // 54 4
1.42 - case 13: stack.push(arg0); // 42
1.43 - case 14: stack.push(stack.pop().value); // 180 1 100
1.44 - case 17: arg5 = stack.pop() // 58 5
1.45 - case 19: stack.push(arg0); // 42
1.46 - case 20: stack.push(stack.pop().offset); // 180 1 99
1.47 - case 23: arg6 = stack.pop() // 54 6
1.48 - case 25: arg4++; // 132 4 1
1.49 - case 28: stack.push(arg4); // 21 4
1.50 - case 30: stack.push(arg3); // 29
1.51 - case 31: if (stack.pop() <= stack.pop()) { gt = 49; continue; } // 162 0 18
1.52 - case 34: stack.push(arg5); // 25 5
1.53 - case 36: stack.push(arg6); // 21 6
1.54 - case 38: stack.push(arg4); // 21 4
1.55 - case 40: stack.push(stack.pop() + stack.pop()); // 96
1.56 - case 41: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
1.57 - case 42: stack.push(arg1); // 27
1.58 - case 43: if (stack.pop() != stack.pop()) { gt = 25; continue; } // 160 255 238
1.59 - case 46: gt = 49; continue; // 167 0 3
1.60 - case 49: stack.push(arg4); // 21 4
1.61 - case 51: stack.push(arg3); // 29
1.62 - case 52: if (stack.pop() <= stack.pop()) { gt = 140; continue; } // 162 0 88
1.63 - case 55: stack.push(arg3); // 29
1.64 - case 56: stack.push(new Array(stack.pop())); // 188 5
1.65 - case 58: arg7 = stack.pop() // 58 7
1.66 - case 60: stack.push(0); // 3
1.67 - case 61: arg8 = stack.pop() // 54 8
1.68 - case 63: stack.push(arg8); // 21 8
1.69 - case 65: stack.push(arg4); // 21 4
1.70 - case 67: if (stack.pop() <= stack.pop()) { gt = 89; continue; } // 162 0 22
1.71 - case 70: stack.push(arg7); // 25 7
1.72 - case 72: stack.push(arg8); // 21 8
1.73 - case 74: stack.push(arg5); // 25 5
1.74 - case 76: stack.push(arg6); // 21 6
1.75 - case 78: stack.push(arg8); // 21 8
1.76 - case 80: stack.push(stack.pop() + stack.pop()); // 96
1.77 - case 81: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
1.78 - case 82: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
1.79 - case 83: arg8++; // 132 8 1
1.80 - case 86: gt = 63; continue; // 167 255 233
1.81 - case 89: stack.push(arg4); // 21 4
1.82 - case 91: stack.push(arg3); // 29
1.83 - case 92: if (stack.pop() <= stack.pop()) { gt = 128; continue; } // 162 0 36
1.84 - case 95: stack.push(arg5); // 25 5
1.85 - case 97: stack.push(arg6); // 21 6
1.86 - case 99: stack.push(arg4); // 21 4
1.87 - case 101: stack.push(stack.pop() + stack.pop()); // 96
1.88 - case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52
1.89 - case 103: arg8 = stack.pop() // 54 8
1.90 - case 105: stack.push(arg7); // 25 7
1.91 - case 107: stack.push(arg4); // 21 4
1.92 - case 109: stack.push(arg8); // 21 8
1.93 - case 111: stack.push(arg1); // 27
1.94 - case 112: if (stack.pop() != stack.pop()) { gt = 119; continue; } // 160 0 7
1.95 - case 115: stack.push(arg2); // 28
1.96 - case 116: gt = 121; continue; // 167 0 5
1.97 - case 119: stack.push(arg8); // 21 8
1.98 - case 121: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85
1.99 - case 122: arg4++; // 132 4 1
1.100 - case 125: gt = 89; continue; // 167 255 220
1.101 - case 128: stack.push(new java_lang_String); // 187 0 200
1.102 - case 131: stack.push(stack[stack.length - 1]); // 89
1.103 - case 132: stack.push(0); // 3
1.104 - case 133: stack.push(arg3); // 29
1.105 - case 134: stack.push(arg7); // 25 7
1.106 - case 136: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137
1.107 - case 139: return stack.pop(); // 176
1.108 - case 140: stack.push(arg0); // 42
1.109 - case 141: return stack.pop(); // 176
1.110 - }
1.111 -}
1.112 function java_lang_String_matchesZLjava_lang_String(arg0,arg1) {
1.113 var arg2;
1.114 ;
1.115 @@ -1530,24 +1448,6 @@
1.116 case 5: return stack.pop(); // 172
1.117 }
1.118 }
1.119 -function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) {
1.120 - var arg2;
1.121 -;
1.122 - var stack = new Array(2);
1.123 - var gt = 0;
1.124 - for(;;) switch(gt) {
1.125 - case 0: stack.push(arg0); // 42
1.126 - case 1: stack.push(arg1); // 43
1.127 - case 2: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132
1.128 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_String(self, v0)); } // 182 1 149
1.129 - case 8: // 2
1.130 - case 9: if (stack.pop() >= stack.pop()) { gt = 16; continue; } // 164 0 7
1.131 - case 12: stack.push(1); // 4
1.132 - case 13: gt = 17; continue; // 167 0 4
1.133 - case 16: stack.push(0); // 3
1.134 - case 17: return stack.pop(); // 172
1.135 - }
1.136 -}
1.137 function java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) {
1.138 var arg3;
1.139 ;
1.140 @@ -2455,6 +2355,8 @@
1.141 String.prototype.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
1.142 String.prototype.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI;
1.143 String.prototype.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII;
1.144 +String.prototype.replaceLjava_lang_StringCC = java_lang_String_replaceLjava_lang_StringCC;
1.145 +String.prototype.containsZLjava_lang_CharSequence = java_lang_String_containsZLjava_lang_CharSequence;
1.146 String.prototype.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object;
1.147 String.prototype.toCharArrayAC = java_lang_String_toCharArrayAC;
1.148 String.prototype.$instOf_java_lang_String = true;
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Nov 16 08:26:55 2012 +0100
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Nov 17 11:21:17 2012 +0100
2.3 @@ -19,7 +19,6 @@
2.4
2.5 import java.io.IOException;
2.6 import java.io.InputStream;
2.7 -import org.apidesign.bck2brwsr.core.ExtraJavaScript;
2.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.9 import org.apidesign.javap.AnnotationParser;
2.10 import org.apidesign.javap.ClassData;
2.11 @@ -64,7 +63,10 @@
2.12 public String compile(InputStream classFile) throws IOException {
2.13 this.jc = new ClassData(classFile);
2.14 byte[] arrData = jc.findAnnotationData(true);
2.15 - String[] arr = findAnnotation(arrData, jc, ExtraJavaScript.class.getName(), "resource", "processByteCode");
2.16 + String[] arr = findAnnotation(arrData, jc,
2.17 + "org.apidesign.bck2brwsr.core.ExtraJavaScript",
2.18 + "resource", "processByteCode"
2.19 + );
2.20 if (arr != null) {
2.21 requireScript(arr[0]);
2.22 if ("0".equals(arr[1])) {
2.23 @@ -651,6 +653,12 @@
2.24 case opc_dup:
2.25 out.append("stack.push(stack[stack.length - 1]);");
2.26 break;
2.27 + case opc_dup_x1:
2.28 + out.append("{ var v1 = stack.pop(); var v2 = stack.pop(); stack.push(v1); stack.push(v2); stack.push(v1); }");
2.29 + break;
2.30 + case opc_dup_x2:
2.31 + out.append("{ var v1 = stack.pop(); var v2 = stack.pop(); var v3 = stack.pop(); stack.push(v1); stack.push(v3); stack.push(v2); stack.push(v1); }");
2.32 + break;
2.33 case opc_bipush:
2.34 out.append("stack.push(" + byteCodes[++i] + ");");
2.35 break;
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Sat Nov 17 11:21:17 2012 +0100
3.3 @@ -0,0 +1,46 @@
3.4 +/**
3.5 + * Back 2 Browser Bytecode Translator
3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 + *
3.8 + * This program is free software: you can redistribute it and/or modify
3.9 + * it under the terms of the GNU General Public License as published by
3.10 + * the Free Software Foundation, version 2 of the License.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details.
3.16 + *
3.17 + * You should have received a copy of the GNU General Public License
3.18 + * along with this program. Look for COPYING file in the top folder.
3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
3.20 + */
3.21 +package org.apidesign.vm4brwsr;
3.22 +
3.23 +import java.io.ByteArrayInputStream;
3.24 +import java.io.IOException;
3.25 +
3.26 +/**
3.27 + *
3.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.29 + */
3.30 +class VMinVM extends ByteCodeToJavaScript {
3.31 + private VMinVM(Appendable out) {
3.32 + super(out);
3.33 + }
3.34 +
3.35 + static String toJavaScript(byte[] is) throws IOException {
3.36 + StringBuilder sb = new StringBuilder();
3.37 + new VMinVM(sb).compile(new ByteArrayInputStream(is));
3.38 + return sb.toString().toString();
3.39 + }
3.40 +
3.41 + @Override
3.42 + protected boolean requireReference(String internalClassName) {
3.43 + return false;
3.44 + }
3.45 +
3.46 + @Override
3.47 + protected void requireScript(String resourcePath) {
3.48 + }
3.49 +}
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Nov 16 08:26:55 2012 +0100
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Sat Nov 17 11:21:17 2012 +0100
4.3 @@ -17,6 +17,10 @@
4.4 */
4.5 package org.apidesign.vm4brwsr;
4.6
4.7 +import java.io.File;
4.8 +import java.io.FileWriter;
4.9 +import java.io.IOException;
4.10 +import java.io.InputStream;
4.11 import static org.testng.Assert.*;
4.12 import javax.script.Invocable;
4.13 import org.testng.annotations.BeforeClass;
4.14 @@ -32,24 +36,47 @@
4.15 private static Invocable code;
4.16
4.17 @Test public void compareTheGeneratedCode() throws Exception {
4.18 - StringBuilder hotspot = new StringBuilder();
4.19 - GenJS.compile(hotspot, "org/apidesign/vm4brwsr/Array");
4.20 + byte[] arr = readClass("/org/apidesign/vm4brwsr/Array.class");
4.21 + String ret1 = VMinVM.toJavaScript(arr);
4.22
4.23 - Object ret = code.invokeFunction(
4.24 - "org_apidesign_vm4brwsr_GenJS_toStringLjava_lang_StringLjava_lang_String",
4.25 - "org/apidesign/vm4brwsr/Array"
4.26 - );
4.27 + Object ret;
4.28 + try {
4.29 + ret = code.invokeFunction(
4.30 + "org_apidesign_vm4brwsr_VMinVM_toJavaScriptLjava_lang_StringAB",
4.31 + arr
4.32 + );
4.33 + } catch (Exception ex) {
4.34 + File f = File.createTempFile("execution", ".js");
4.35 + FileWriter w = new FileWriter(f);
4.36 + w.append(codeSeq);
4.37 + w.close();
4.38 + throw new Exception(ex.getMessage() + " file: " + f, ex);
4.39 + }
4.40 +
4.41 +
4.42 assertTrue(ret instanceof String, "It is string: " + ret);
4.43
4.44 - assertEquals((String)ret, hotspot.toString(), "The code is the same");
4.45 + assertEquals((String)ret, ret1.toString(), "The code is the same");
4.46 }
4.47
4.48 @BeforeClass
4.49 public void compileTheCode() throws Exception {
4.50 StringBuilder sb = new StringBuilder();
4.51 code = StaticMethodTest.compileClass(sb,
4.52 - "org/apidesign/vm4brwsr/GenJS"
4.53 + "org/apidesign/vm4brwsr/VMinVM"
4.54 );
4.55 codeSeq = sb;
4.56 }
4.57 +
4.58 + private static byte[] readClass(String res) throws IOException {
4.59 + InputStream is1 = VMinVMTest.class.getResourceAsStream(res);
4.60 + assertNotNull(is1, "Stream found");
4.61 + byte[] arr = new byte[is1.available()];
4.62 + int len = is1.read(arr);
4.63 + is1.close();
4.64 + if (len != arr.length) {
4.65 + throw new IOException("Wrong len " + len + " for arr: " + arr.length);
4.66 + }
4.67 + return arr;
4.68 + }
4.69 }