1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 11:00:52 2013 +0100
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sun Jan 27 10:19:02 2013 +0100
1.3 @@ -114,11 +114,6 @@
1.4 out.append("\n\n").append(assignClass(className));
1.5 out.append("function CLS() {");
1.6 out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
1.7 - for (FieldData v : jc.getFields()) {
1.8 - if (v.isStatic()) {
1.9 - out.append("\n CLS.").append(v.getName()).append(initField(v));
1.10 - }
1.11 - }
1.12 if (proto == null) {
1.13 String sc = jc.getSuperClassName(); // with _
1.14 out.append("\n var pp = ").
1.15 @@ -134,6 +129,18 @@
1.16 out.append("\n var c = ").append(proto[0]).append(";");
1.17 out.append("\n var sprcls = null;");
1.18 }
1.19 + for (FieldData v : jc.getFields()) {
1.20 + if (v.isStatic()) {
1.21 + out.append("\n CLS.").append(v.getName()).append(initField(v));
1.22 + } else {
1.23 + out.append("\n c._").append(v.getName()).append(" = function (v) {")
1.24 + .append(" if (arguments.length == 1) this.fld_").
1.25 + append(className).append('_').append(v.getName())
1.26 + .append(" = v; return this.fld_").
1.27 + append(className).append('_').append(v.getName())
1.28 + .append("; };");
1.29 + }
1.30 + }
1.31 for (MethodData m : jc.getMethods()) {
1.32 byte[] onlyArr = m.findAnnotationData(true);
1.33 String[] only = findAnnotation(onlyArr, jc,
1.34 @@ -206,13 +213,14 @@
1.35 }
1.36 if (!v.isStatic()) {
1.37 out.append("\n this.fld_").
1.38 + append(className).append('_').
1.39 append(v.getName()).append(initField(v));
1.40 }
1.41 }
1.42 out.append("\n return this;");
1.43 out.append("\n }");
1.44 out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
1.45 - out.append("\n}");
1.46 + out.append("\n};");
1.47 StringBuilder sb = new StringBuilder();
1.48 for (String init : toInitilize.toArray()) {
1.49 sb.append("\n").append(init).append("();");
1.50 @@ -270,6 +278,7 @@
1.51
1.52 int lastStackFrame = -1;
1.53 TrapData[] previousTrap = null;
1.54 + boolean wide = false;
1.55
1.56 out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
1.57 for (int i = 0; i < byteCodes.length; i++) {
1.58 @@ -295,7 +304,7 @@
1.59 out.append("try {");
1.60 previousTrap = trap.current();
1.61 }
1.62 - final int c = readByte(byteCodes, i);
1.63 + final int c = readUByte(byteCodes, i);
1.64 switch (c) {
1.65 case opc_aload_0:
1.66 emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
1.67 @@ -358,61 +367,91 @@
1.68 emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
1.69 break;
1.70 case opc_iload: {
1.71 - final int indx = readByte(byteCodes, ++i);
1.72 + ++i;
1.73 + final int indx = wide ? readUShort(byteCodes, i++)
1.74 + : readUByte(byteCodes, i);
1.75 + wide = false;
1.76 emit(out, "var @1 = @2;",
1.77 smapper.pushI(), lmapper.getI(indx));
1.78 break;
1.79 }
1.80 case opc_lload: {
1.81 - final int indx = readByte(byteCodes, ++i);
1.82 + ++i;
1.83 + final int indx = wide ? readUShort(byteCodes, i++)
1.84 + : readUByte(byteCodes, i);
1.85 + wide = false;
1.86 emit(out, "var @1 = @2;",
1.87 smapper.pushL(), lmapper.getL(indx));
1.88 break;
1.89 }
1.90 case opc_fload: {
1.91 - final int indx = readByte(byteCodes, ++i);
1.92 + ++i;
1.93 + final int indx = wide ? readUShort(byteCodes, i++)
1.94 + : readUByte(byteCodes, i);
1.95 + wide = false;
1.96 emit(out, "var @1 = @2;",
1.97 smapper.pushF(), lmapper.getF(indx));
1.98 break;
1.99 }
1.100 case opc_dload: {
1.101 - final int indx = readByte(byteCodes, ++i);
1.102 + ++i;
1.103 + final int indx = wide ? readUShort(byteCodes, i++)
1.104 + : readUByte(byteCodes, i);
1.105 + wide = false;
1.106 emit(out, "var @1 = @2;",
1.107 smapper.pushD(), lmapper.getD(indx));
1.108 break;
1.109 }
1.110 case opc_aload: {
1.111 - final int indx = readByte(byteCodes, ++i);
1.112 + ++i;
1.113 + final int indx = wide ? readUShort(byteCodes, i++)
1.114 + : readUByte(byteCodes, i);
1.115 + wide = false;
1.116 emit(out, "var @1 = @2;",
1.117 smapper.pushA(), lmapper.getA(indx));
1.118 break;
1.119 }
1.120 case opc_istore: {
1.121 - final int indx = readByte(byteCodes, ++i);
1.122 + ++i;
1.123 + final int indx = wide ? readUShort(byteCodes, i++)
1.124 + : readUByte(byteCodes, i);
1.125 + wide = false;
1.126 emit(out, "var @1 = @2;",
1.127 lmapper.setI(indx), smapper.popI());
1.128 break;
1.129 }
1.130 case opc_lstore: {
1.131 - final int indx = readByte(byteCodes, ++i);
1.132 + ++i;
1.133 + final int indx = wide ? readUShort(byteCodes, i++)
1.134 + : readUByte(byteCodes, i);
1.135 + wide = false;
1.136 emit(out, "var @1 = @2;",
1.137 lmapper.setL(indx), smapper.popL());
1.138 break;
1.139 }
1.140 case opc_fstore: {
1.141 - final int indx = readByte(byteCodes, ++i);
1.142 + ++i;
1.143 + final int indx = wide ? readUShort(byteCodes, i++)
1.144 + : readUByte(byteCodes, i);
1.145 + wide = false;
1.146 emit(out, "var @1 = @2;",
1.147 lmapper.setF(indx), smapper.popF());
1.148 break;
1.149 }
1.150 case opc_dstore: {
1.151 - final int indx = readByte(byteCodes, ++i);
1.152 + ++i;
1.153 + final int indx = wide ? readUShort(byteCodes, i++)
1.154 + : readUByte(byteCodes, i);
1.155 + wide = false;
1.156 emit(out, "var @1 = @2;",
1.157 lmapper.setD(indx), smapper.popD());
1.158 break;
1.159 }
1.160 case opc_astore: {
1.161 - final int indx = readByte(byteCodes, ++i);
1.162 + ++i;
1.163 + final int indx = wide ? readUShort(byteCodes, i++)
1.164 + : readUByte(byteCodes, i);
1.165 + wide = false;
1.166 emit(out, "var @1 = @2;",
1.167 lmapper.setA(indx), smapper.popA());
1.168 break;
1.169 @@ -588,8 +627,13 @@
1.170 emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
1.171 break;
1.172 case opc_iinc: {
1.173 - final int varIndx = readByte(byteCodes, ++i);
1.174 - final int incrBy = byteCodes[++i];
1.175 + ++i;
1.176 + final int varIndx = wide ? readUShort(byteCodes, i++)
1.177 + : readUByte(byteCodes, i);
1.178 + ++i;
1.179 + final int incrBy = wide ? readIntArg(byteCodes, i++)
1.180 + : byteCodes[i];
1.181 + wide = false;
1.182 if (incrBy == 1) {
1.183 emit(out, "@1++;", lmapper.getI(varIndx));
1.184 } else {
1.185 @@ -713,7 +757,7 @@
1.186 emit(out, "var @1 = 5;", smapper.pushI());
1.187 break;
1.188 case opc_ldc: {
1.189 - int indx = readByte(byteCodes, ++i);
1.190 + int indx = readUByte(byteCodes, ++i);
1.191 String v = encodeConstant(indx);
1.192 int type = VarType.fromConstantType(jc.getTag(indx));
1.193 emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.194 @@ -904,7 +948,7 @@
1.195 break;
1.196 }
1.197 case opc_newarray:
1.198 - int atype = readByte(byteCodes, ++i);
1.199 + int atype = readUByte(byteCodes, ++i);
1.200 String jvmType;
1.201 switch (atype) {
1.202 case 4: jvmType = "[Z"; break;
1.203 @@ -937,7 +981,7 @@
1.204 int type = readIntArg(byteCodes, i);
1.205 i += 2;
1.206 String typeName = jc.getClassName(type);
1.207 - int dim = readByte(byteCodes, ++i);
1.208 + int dim = readUByte(byteCodes, ++i);
1.209 StringBuilder dims = new StringBuilder();
1.210 dims.append('[');
1.211 for (int d = 0; d < dim; d++) {
1.212 @@ -1012,16 +1056,16 @@
1.213 break;
1.214 }
1.215 case opc_dup2: {
1.216 - if (smapper.get(0).isCategory2()) {
1.217 - final Variable v = smapper.get(0);
1.218 + final Variable vi1 = smapper.get(0);
1.219 +
1.220 + if (vi1.isCategory2()) {
1.221 emit(out, "var @1 = @2;",
1.222 - smapper.pushT(v.getType()), v);
1.223 + smapper.pushT(vi1.getType()), vi1);
1.224 } else {
1.225 - final Variable v1 = smapper.get(0);
1.226 - final Variable v2 = smapper.get(1);
1.227 + final Variable vi2 = smapper.get(1);
1.228 emit(out, "var @1 = @2, @3 = @4;",
1.229 - smapper.pushT(v2.getType()), v2,
1.230 - smapper.pushT(v1.getType()), v1);
1.231 + smapper.pushT(vi2.getType()), vi2,
1.232 + smapper.pushT(vi1.getType()), vi1);
1.233 }
1.234 break;
1.235 }
1.236 @@ -1036,10 +1080,11 @@
1.237 vo1, vi1, vo2, vi2, vo3, vo1);
1.238 break;
1.239 }
1.240 - case opc_dup_x2: {
1.241 - if (smapper.get(1).isCategory2()) {
1.242 - final Variable vi1 = smapper.pop();
1.243 - final Variable vi2 = smapper.pop();
1.244 + case opc_dup2_x1: {
1.245 + final Variable vi1 = smapper.pop();
1.246 + final Variable vi2 = smapper.pop();
1.247 +
1.248 + if (vi1.isCategory2()) {
1.249 final Variable vo3 = smapper.pushT(vi1.getType());
1.250 final Variable vo2 = smapper.pushT(vi2.getType());
1.251 final Variable vo1 = smapper.pushT(vi1.getType());
1.252 @@ -1047,8 +1092,32 @@
1.253 emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.254 vo1, vi1, vo2, vi2, vo3, vo1);
1.255 } else {
1.256 - final Variable vi1 = smapper.pop();
1.257 - final Variable vi2 = smapper.pop();
1.258 + final Variable vi3 = smapper.pop();
1.259 + final Variable vo5 = smapper.pushT(vi2.getType());
1.260 + final Variable vo4 = smapper.pushT(vi1.getType());
1.261 + final Variable vo3 = smapper.pushT(vi3.getType());
1.262 + final Variable vo2 = smapper.pushT(vi2.getType());
1.263 + final Variable vo1 = smapper.pushT(vi1.getType());
1.264 +
1.265 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.266 + vo1, vi1, vo2, vi2, vo3, vi3);
1.267 + emit(out, " @1 = @2, @3 = @4;",
1.268 + vo4, vo1, vo5, vo2);
1.269 + }
1.270 + break;
1.271 + }
1.272 + case opc_dup_x2: {
1.273 + final Variable vi1 = smapper.pop();
1.274 + final Variable vi2 = smapper.pop();
1.275 +
1.276 + if (vi2.isCategory2()) {
1.277 + final Variable vo3 = smapper.pushT(vi1.getType());
1.278 + final Variable vo2 = smapper.pushT(vi2.getType());
1.279 + final Variable vo1 = smapper.pushT(vi1.getType());
1.280 +
1.281 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.282 + vo1, vi1, vo2, vi2, vo3, vo1);
1.283 + } else {
1.284 final Variable vi3 = smapper.pop();
1.285 final Variable vo4 = smapper.pushT(vi1.getType());
1.286 final Variable vo3 = smapper.pushT(vi3.getType());
1.287 @@ -1060,6 +1129,76 @@
1.288 }
1.289 break;
1.290 }
1.291 + case opc_dup2_x2: {
1.292 + final Variable vi1 = smapper.pop();
1.293 + final Variable vi2 = smapper.pop();
1.294 +
1.295 + if (vi1.isCategory2()) {
1.296 + if (vi2.isCategory2()) {
1.297 + final Variable vo3 = smapper.pushT(vi1.getType());
1.298 + final Variable vo2 = smapper.pushT(vi2.getType());
1.299 + final Variable vo1 = smapper.pushT(vi1.getType());
1.300 +
1.301 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.302 + vo1, vi1, vo2, vi2, vo3, vo1);
1.303 + } else {
1.304 + final Variable vi3 = smapper.pop();
1.305 + final Variable vo4 = smapper.pushT(vi1.getType());
1.306 + final Variable vo3 = smapper.pushT(vi3.getType());
1.307 + final Variable vo2 = smapper.pushT(vi2.getType());
1.308 + final Variable vo1 = smapper.pushT(vi1.getType());
1.309 +
1.310 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.311 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.312 + }
1.313 + } else {
1.314 + final Variable vi3 = smapper.pop();
1.315 +
1.316 + if (vi3.isCategory2()) {
1.317 + final Variable vo5 = smapper.pushT(vi2.getType());
1.318 + final Variable vo4 = smapper.pushT(vi1.getType());
1.319 + final Variable vo3 = smapper.pushT(vi3.getType());
1.320 + final Variable vo2 = smapper.pushT(vi2.getType());
1.321 + final Variable vo1 = smapper.pushT(vi1.getType());
1.322 +
1.323 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.324 + vo1, vi1, vo2, vi2, vo3, vi3);
1.325 + emit(out, " @1 = @2, @3 = @4;",
1.326 + vo4, vo1, vo5, vo2);
1.327 + } else {
1.328 + final Variable vi4 = smapper.pop();
1.329 + final Variable vo6 = smapper.pushT(vi2.getType());
1.330 + final Variable vo5 = smapper.pushT(vi1.getType());
1.331 + final Variable vo4 = smapper.pushT(vi4.getType());
1.332 + final Variable vo3 = smapper.pushT(vi3.getType());
1.333 + final Variable vo2 = smapper.pushT(vi2.getType());
1.334 + final Variable vo1 = smapper.pushT(vi1.getType());
1.335 +
1.336 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
1.337 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
1.338 + emit(out, " @1 = @2, @3 = @4;",
1.339 + vo5, vo1, vo6, vo2);
1.340 + }
1.341 + }
1.342 + break;
1.343 + }
1.344 + case opc_swap: {
1.345 + final Variable vi1 = smapper.get(0);
1.346 + final Variable vi2 = smapper.get(1);
1.347 +
1.348 + if (vi1.getType() == vi2.getType()) {
1.349 + final Variable tmp = smapper.pushT(vi1.getType());
1.350 +
1.351 + emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
1.352 + tmp, vi1, vi2);
1.353 + smapper.pop(1);
1.354 + } else {
1.355 + smapper.pop(2);
1.356 + smapper.pushT(vi1.getType());
1.357 + smapper.pushT(vi2.getType());
1.358 + }
1.359 + break;
1.360 + }
1.361 case opc_bipush:
1.362 emit(out, "var @1 = @2;",
1.363 smapper.pushI(), Integer.toString(byteCodes[++i]));
1.364 @@ -1074,8 +1213,26 @@
1.365 int indx = readIntArg(byteCodes, i);
1.366 String[] fi = jc.getFieldInfoName(indx);
1.367 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.368 - emit(out, "var @2 = @1.fld_@3;",
1.369 - smapper.popA(), smapper.pushT(type), fi[1]);
1.370 + final String mangleClass = mangleSig(fi[0]);
1.371 + final String mangleClassAccess = accessClass(mangleClass);
1.372 + emit(out, "var @2 = @4(false)._@3.call(@1);",
1.373 + smapper.popA(),
1.374 + smapper.pushT(type), fi[1], mangleClassAccess
1.375 + );
1.376 + i += 2;
1.377 + break;
1.378 + }
1.379 + case opc_putfield: {
1.380 + int indx = readIntArg(byteCodes, i);
1.381 + String[] fi = jc.getFieldInfoName(indx);
1.382 + final int type = VarType.fromFieldType(fi[2].charAt(0));
1.383 + final String mangleClass = mangleSig(fi[0]);
1.384 + final String mangleClassAccess = accessClass(mangleClass);
1.385 + emit(out, "@4(false)._@3.call(@2, @1);",
1.386 + smapper.popT(type),
1.387 + smapper.popA(), fi[1],
1.388 + mangleClassAccess
1.389 + );
1.390 i += 2;
1.391 break;
1.392 }
1.393 @@ -1090,15 +1247,6 @@
1.394 addReference(fi[0]);
1.395 break;
1.396 }
1.397 - case opc_putfield: {
1.398 - int indx = readIntArg(byteCodes, i);
1.399 - String[] fi = jc.getFieldInfoName(indx);
1.400 - final int type = VarType.fromFieldType(fi[2].charAt(0));
1.401 - emit(out, "@2.fld_@3 = @1;",
1.402 - smapper.popT(type), smapper.popA(), fi[1]);
1.403 - i += 2;
1.404 - break;
1.405 - }
1.406 case opc_putstatic: {
1.407 int indx = readIntArg(byteCodes, i);
1.408 String[] fi = jc.getFieldInfoName(indx);
1.409 @@ -1114,11 +1262,13 @@
1.410 int indx = readIntArg(byteCodes, i);
1.411 final String type = jc.getClassName(indx);
1.412 if (!type.startsWith("[")) {
1.413 - // no way to check arrays right now
1.414 - // XXX proper exception
1.415 emit(out,
1.416 "if (@1 !== null && !@1.$instOf_@2) throw {};",
1.417 smapper.getA(0), type.replace('/', '_'));
1.418 + } else {
1.419 + 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);",
1.420 + smapper.getA(0), type
1.421 + );
1.422 }
1.423 i += 2;
1.424 break;
1.425 @@ -1126,9 +1276,16 @@
1.426 case opc_instanceof: {
1.427 int indx = readIntArg(byteCodes, i);
1.428 final String type = jc.getClassName(indx);
1.429 - emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
1.430 - smapper.popA(), smapper.pushI(),
1.431 - type.replace('/', '_'));
1.432 + if (!type.startsWith("[")) {
1.433 + emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
1.434 + smapper.popA(), smapper.pushI(),
1.435 + type.replace('/', '_'));
1.436 + } else {
1.437 + emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
1.438 + smapper.popA(), smapper.pushI(),
1.439 + type
1.440 + );
1.441 + }
1.442 i += 2;
1.443 break;
1.444 }
1.445 @@ -1153,7 +1310,12 @@
1.446 break;
1.447 }
1.448
1.449 + case opc_wide:
1.450 + wide = true;
1.451 + break;
1.452 +
1.453 default: {
1.454 + wide = false;
1.455 emit(out, "throw 'unknown bytecode @1';",
1.456 Integer.toString(c));
1.457 }
1.458 @@ -1161,7 +1323,7 @@
1.459 if (debug(" //")) {
1.460 for (int j = prev; j <= i; j++) {
1.461 out.append(" ");
1.462 - final int cc = readByte(byteCodes, j);
1.463 + final int cc = readUByte(byteCodes, j);
1.464 out.append(Integer.toString(cc));
1.465 }
1.466 }
1.467 @@ -1197,10 +1359,15 @@
1.468 final int a = byteCodes[offsetInstruction + 3];
1.469 return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
1.470 }
1.471 - private int readByte(byte[] byteCodes, int offsetInstruction) {
1.472 + private int readUByte(byte[] byteCodes, int offsetInstruction) {
1.473 return byteCodes[offsetInstruction] & 0xff;
1.474 }
1.475 -
1.476 +
1.477 + private int readUShort(byte[] byteCodes, int offsetInstruction) {
1.478 + return ((byteCodes[offsetInstruction] & 0xff) << 8)
1.479 + | (byteCodes[offsetInstruction + 1] & 0xff);
1.480 + }
1.481 +
1.482 private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
1.483 int i = 0;
1.484 Boolean count = null;
1.485 @@ -1278,6 +1445,10 @@
1.486 }
1.487 }
1.488
1.489 + static String mangleSig(String sig) {
1.490 + return mangleSig(sig, 0, sig.length());
1.491 + }
1.492 +
1.493 private static String mangleSig(String txt, int first, int last) {
1.494 StringBuilder sb = new StringBuilder();
1.495 for (int i = first; i < last; i++) {
1.496 @@ -1424,8 +1595,12 @@
1.497 String[] classRef = { null };
1.498 String s = jc.stringValue(entryIndex, classRef);
1.499 if (classRef[0] != null) {
1.500 - addReference(classRef[0]);
1.501 - s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
1.502 + if (classRef[0].startsWith("[")) {
1.503 + s = accessClass("java_lang_Class") + "(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('" + classRef[0] + "');";
1.504 + } else {
1.505 + addReference(classRef[0]);
1.506 + s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
1.507 + }
1.508 }
1.509 return s;
1.510 }