The JavaScript VM is able to generate some (not yet valid) code. javap
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 17 Nov 2012 11:21:17 +0100
branchjavap
changeset 1702336c52d3ee5
parent 169 6f2aef4cf160
child 171 f61602ea7759
The JavaScript VM is able to generate some (not yet valid) code.
emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java
vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java
     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  }