1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 16:36:09 2013 +0100
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 16:37:18 2013 +0100
1.3 @@ -270,6 +270,7 @@
1.4
1.5 int lastStackFrame = -1;
1.6 TrapData[] previousTrap = null;
1.7 + boolean wide = false;
1.8
1.9 out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
1.10 for (int i = 0; i < byteCodes.length; i++) {
1.11 @@ -295,7 +296,7 @@
1.12 out.append("try {");
1.13 previousTrap = trap.current();
1.14 }
1.15 - final int c = readByte(byteCodes, i);
1.16 + final int c = readUByte(byteCodes, i);
1.17 switch (c) {
1.18 case opc_aload_0:
1.19 emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
1.20 @@ -358,61 +359,91 @@
1.21 emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
1.22 break;
1.23 case opc_iload: {
1.24 - final int indx = readByte(byteCodes, ++i);
1.25 + ++i;
1.26 + final int indx = wide ? readUShort(byteCodes, i++)
1.27 + : readUByte(byteCodes, i);
1.28 + wide = false;
1.29 emit(out, "var @1 = @2;",
1.30 smapper.pushI(), lmapper.getI(indx));
1.31 break;
1.32 }
1.33 case opc_lload: {
1.34 - final int indx = readByte(byteCodes, ++i);
1.35 + ++i;
1.36 + final int indx = wide ? readUShort(byteCodes, i++)
1.37 + : readUByte(byteCodes, i);
1.38 + wide = false;
1.39 emit(out, "var @1 = @2;",
1.40 smapper.pushL(), lmapper.getL(indx));
1.41 break;
1.42 }
1.43 case opc_fload: {
1.44 - final int indx = readByte(byteCodes, ++i);
1.45 + ++i;
1.46 + final int indx = wide ? readUShort(byteCodes, i++)
1.47 + : readUByte(byteCodes, i);
1.48 + wide = false;
1.49 emit(out, "var @1 = @2;",
1.50 smapper.pushF(), lmapper.getF(indx));
1.51 break;
1.52 }
1.53 case opc_dload: {
1.54 - final int indx = readByte(byteCodes, ++i);
1.55 + ++i;
1.56 + final int indx = wide ? readUShort(byteCodes, i++)
1.57 + : readUByte(byteCodes, i);
1.58 + wide = false;
1.59 emit(out, "var @1 = @2;",
1.60 smapper.pushD(), lmapper.getD(indx));
1.61 break;
1.62 }
1.63 case opc_aload: {
1.64 - final int indx = readByte(byteCodes, ++i);
1.65 + ++i;
1.66 + final int indx = wide ? readUShort(byteCodes, i++)
1.67 + : readUByte(byteCodes, i);
1.68 + wide = false;
1.69 emit(out, "var @1 = @2;",
1.70 smapper.pushA(), lmapper.getA(indx));
1.71 break;
1.72 }
1.73 case opc_istore: {
1.74 - final int indx = readByte(byteCodes, ++i);
1.75 + ++i;
1.76 + final int indx = wide ? readUShort(byteCodes, i++)
1.77 + : readUByte(byteCodes, i);
1.78 + wide = false;
1.79 emit(out, "var @1 = @2;",
1.80 lmapper.setI(indx), smapper.popI());
1.81 break;
1.82 }
1.83 case opc_lstore: {
1.84 - final int indx = readByte(byteCodes, ++i);
1.85 + ++i;
1.86 + final int indx = wide ? readUShort(byteCodes, i++)
1.87 + : readUByte(byteCodes, i);
1.88 + wide = false;
1.89 emit(out, "var @1 = @2;",
1.90 lmapper.setL(indx), smapper.popL());
1.91 break;
1.92 }
1.93 case opc_fstore: {
1.94 - final int indx = readByte(byteCodes, ++i);
1.95 + ++i;
1.96 + final int indx = wide ? readUShort(byteCodes, i++)
1.97 + : readUByte(byteCodes, i);
1.98 + wide = false;
1.99 emit(out, "var @1 = @2;",
1.100 lmapper.setF(indx), smapper.popF());
1.101 break;
1.102 }
1.103 case opc_dstore: {
1.104 - final int indx = readByte(byteCodes, ++i);
1.105 + ++i;
1.106 + final int indx = wide ? readUShort(byteCodes, i++)
1.107 + : readUByte(byteCodes, i);
1.108 + wide = false;
1.109 emit(out, "var @1 = @2;",
1.110 lmapper.setD(indx), smapper.popD());
1.111 break;
1.112 }
1.113 case opc_astore: {
1.114 - final int indx = readByte(byteCodes, ++i);
1.115 + ++i;
1.116 + final int indx = wide ? readUShort(byteCodes, i++)
1.117 + : readUByte(byteCodes, i);
1.118 + wide = false;
1.119 emit(out, "var @1 = @2;",
1.120 lmapper.setA(indx), smapper.popA());
1.121 break;
1.122 @@ -588,8 +619,13 @@
1.123 emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
1.124 break;
1.125 case opc_iinc: {
1.126 - final int varIndx = readByte(byteCodes, ++i);
1.127 - final int incrBy = byteCodes[++i];
1.128 + ++i;
1.129 + final int varIndx = wide ? readUShort(byteCodes, i++)
1.130 + : readUByte(byteCodes, i);
1.131 + ++i;
1.132 + final int incrBy = wide ? readIntArg(byteCodes, i++)
1.133 + : byteCodes[i];
1.134 + wide = false;
1.135 if (incrBy == 1) {
1.136 emit(out, "@1++;", lmapper.getI(varIndx));
1.137 } else {
1.138 @@ -713,7 +749,7 @@
1.139 emit(out, "var @1 = 5;", smapper.pushI());
1.140 break;
1.141 case opc_ldc: {
1.142 - int indx = readByte(byteCodes, ++i);
1.143 + int indx = readUByte(byteCodes, ++i);
1.144 String v = encodeConstant(indx);
1.145 int type = VarType.fromConstantType(jc.getTag(indx));
1.146 emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.147 @@ -896,7 +932,7 @@
1.148 break;
1.149 }
1.150 case opc_newarray:
1.151 - int atype = readByte(byteCodes, ++i);
1.152 + int atype = readUByte(byteCodes, ++i);
1.153 String jvmType;
1.154 switch (atype) {
1.155 case 4: jvmType = "[Z"; break;
1.156 @@ -929,7 +965,7 @@
1.157 int type = readIntArg(byteCodes, i);
1.158 i += 2;
1.159 String typeName = jc.getClassName(type);
1.160 - int dim = readByte(byteCodes, ++i);
1.161 + int dim = readUByte(byteCodes, ++i);
1.162 StringBuilder dims = new StringBuilder();
1.163 dims.append('[');
1.164 for (int d = 0; d < dim; d++) {
1.165 @@ -1004,16 +1040,16 @@
1.166 break;
1.167 }
1.168 case opc_dup2: {
1.169 - if (smapper.get(0).isCategory2()) {
1.170 - final Variable v = smapper.get(0);
1.171 + final Variable vi1 = smapper.get(0);
1.172 +
1.173 + if (vi1.isCategory2()) {
1.174 emit(out, "var @1 = @2;",
1.175 - smapper.pushT(v.getType()), v);
1.176 + smapper.pushT(vi1.getType()), vi1);
1.177 } else {
1.178 - final Variable v1 = smapper.get(0);
1.179 - final Variable v2 = smapper.get(1);
1.180 + final Variable vi2 = smapper.get(1);
1.181 emit(out, "var @1 = @2, @3 = @4;",
1.182 - smapper.pushT(v2.getType()), v2,
1.183 - smapper.pushT(v1.getType()), v1);
1.184 + smapper.pushT(vi2.getType()), vi2,
1.185 + smapper.pushT(vi1.getType()), vi1);
1.186 }
1.187 break;
1.188 }
1.189 @@ -1028,10 +1064,11 @@
1.190 vo1, vi1, vo2, vi2, vo3, vo1);
1.191 break;
1.192 }
1.193 - case opc_dup_x2: {
1.194 - if (smapper.get(1).isCategory2()) {
1.195 - final Variable vi1 = smapper.pop();
1.196 - final Variable vi2 = smapper.pop();
1.197 + case opc_dup2_x1: {
1.198 + final Variable vi1 = smapper.pop();
1.199 + final Variable vi2 = smapper.pop();
1.200 +
1.201 + if (vi1.isCategory2()) {
1.202 final Variable vo3 = smapper.pushT(vi1.getType());
1.203 final Variable vo2 = smapper.pushT(vi2.getType());
1.204 final Variable vo1 = smapper.pushT(vi1.getType());
1.205 @@ -1039,8 +1076,32 @@
1.206 emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.207 vo1, vi1, vo2, vi2, vo3, vo1);
1.208 } else {
1.209 - final Variable vi1 = smapper.pop();
1.210 - final Variable vi2 = smapper.pop();
1.211 + final Variable vi3 = smapper.pop();
1.212 + final Variable vo5 = smapper.pushT(vi2.getType());
1.213 + final Variable vo4 = smapper.pushT(vi1.getType());
1.214 + final Variable vo3 = smapper.pushT(vi3.getType());
1.215 + final Variable vo2 = smapper.pushT(vi2.getType());
1.216 + final Variable vo1 = smapper.pushT(vi1.getType());
1.217 +
1.218 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.219 + vo1, vi1, vo2, vi2, vo3, vi3);
1.220 + emit(out, " @1 = @2, @3 = @4;",
1.221 + vo4, vo1, vo5, vo2);
1.222 + }
1.223 + break;
1.224 + }
1.225 + case opc_dup_x2: {
1.226 + final Variable vi1 = smapper.pop();
1.227 + final Variable vi2 = smapper.pop();
1.228 +
1.229 + if (vi2.isCategory2()) {
1.230 + final Variable vo3 = smapper.pushT(vi1.getType());
1.231 + final Variable vo2 = smapper.pushT(vi2.getType());
1.232 + final Variable vo1 = smapper.pushT(vi1.getType());
1.233 +
1.234 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.235 + vo1, vi1, vo2, vi2, vo3, vo1);
1.236 + } else {
1.237 final Variable vi3 = smapper.pop();
1.238 final Variable vo4 = smapper.pushT(vi1.getType());
1.239 final Variable vo3 = smapper.pushT(vi3.getType());
1.240 @@ -1052,6 +1113,76 @@
1.241 }
1.242 break;
1.243 }
1.244 + case opc_dup2_x2: {
1.245 + final Variable vi1 = smapper.pop();
1.246 + final Variable vi2 = smapper.pop();
1.247 +
1.248 + if (vi1.isCategory2()) {
1.249 + if (vi2.isCategory2()) {
1.250 + final Variable vo3 = smapper.pushT(vi1.getType());
1.251 + final Variable vo2 = smapper.pushT(vi2.getType());
1.252 + final Variable vo1 = smapper.pushT(vi1.getType());
1.253 +
1.254 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.255 + vo1, vi1, vo2, vi2, vo3, vo1);
1.256 + } else {
1.257 + final Variable vi3 = smapper.pop();
1.258 + final Variable vo4 = smapper.pushT(vi1.getType());
1.259 + final Variable vo3 = smapper.pushT(vi3.getType());
1.260 + final Variable vo2 = smapper.pushT(vi2.getType());
1.261 + final Variable vo1 = smapper.pushT(vi1.getType());
1.262 +
1.263 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.264 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.265 + }
1.266 + } else {
1.267 + final Variable vi3 = smapper.pop();
1.268 +
1.269 + if (vi3.isCategory2()) {
1.270 + final Variable vo5 = smapper.pushT(vi2.getType());
1.271 + final Variable vo4 = smapper.pushT(vi1.getType());
1.272 + final Variable vo3 = smapper.pushT(vi3.getType());
1.273 + final Variable vo2 = smapper.pushT(vi2.getType());
1.274 + final Variable vo1 = smapper.pushT(vi1.getType());
1.275 +
1.276 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.277 + vo1, vi1, vo2, vi2, vo3, vi3);
1.278 + emit(out, " @1 = @2, @3 = @4;",
1.279 + vo4, vo1, vo5, vo2);
1.280 + } else {
1.281 + final Variable vi4 = smapper.pop();
1.282 + final Variable vo6 = smapper.pushT(vi2.getType());
1.283 + final Variable vo5 = smapper.pushT(vi1.getType());
1.284 + final Variable vo4 = smapper.pushT(vi4.getType());
1.285 + final Variable vo3 = smapper.pushT(vi3.getType());
1.286 + final Variable vo2 = smapper.pushT(vi2.getType());
1.287 + final Variable vo1 = smapper.pushT(vi1.getType());
1.288 +
1.289 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
1.290 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
1.291 + emit(out, " @1 = @2, @3 = @4;",
1.292 + vo5, vo1, vo6, vo2);
1.293 + }
1.294 + }
1.295 + break;
1.296 + }
1.297 + case opc_swap: {
1.298 + final Variable vi1 = smapper.get(0);
1.299 + final Variable vi2 = smapper.get(1);
1.300 +
1.301 + if (vi1.getType() == vi2.getType()) {
1.302 + final Variable tmp = smapper.pushT(vi1.getType());
1.303 +
1.304 + emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
1.305 + tmp, vi1, vi2);
1.306 + smapper.pop(1);
1.307 + } else {
1.308 + smapper.pop(2);
1.309 + smapper.pushT(vi1.getType());
1.310 + smapper.pushT(vi2.getType());
1.311 + }
1.312 + break;
1.313 + }
1.314 case opc_bipush:
1.315 emit(out, "var @1 = @2;",
1.316 smapper.pushI(), Integer.toString(byteCodes[++i]));
1.317 @@ -1154,7 +1285,12 @@
1.318 break;
1.319 }
1.320
1.321 + case opc_wide:
1.322 + wide = true;
1.323 + break;
1.324 +
1.325 default: {
1.326 + wide = false;
1.327 emit(out, "throw 'unknown bytecode @1';",
1.328 Integer.toString(c));
1.329 }
1.330 @@ -1162,7 +1298,7 @@
1.331 if (debug(" //")) {
1.332 for (int j = prev; j <= i; j++) {
1.333 out.append(" ");
1.334 - final int cc = readByte(byteCodes, j);
1.335 + final int cc = readUByte(byteCodes, j);
1.336 out.append(Integer.toString(cc));
1.337 }
1.338 }
1.339 @@ -1198,10 +1334,15 @@
1.340 final int a = byteCodes[offsetInstruction + 3];
1.341 return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
1.342 }
1.343 - private int readByte(byte[] byteCodes, int offsetInstruction) {
1.344 + private int readUByte(byte[] byteCodes, int offsetInstruction) {
1.345 return byteCodes[offsetInstruction] & 0xff;
1.346 }
1.347 -
1.348 +
1.349 + private int readUShort(byte[] byteCodes, int offsetInstruction) {
1.350 + return ((byteCodes[offsetInstruction] & 0xff) << 8)
1.351 + | (byteCodes[offsetInstruction + 1] & 0xff);
1.352 + }
1.353 +
1.354 private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
1.355 int i = 0;
1.356 Boolean count = null;
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Fri Jan 25 16:36:09 2013 +0100
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Fri Jan 25 16:37:18 2013 +0100
2.3 @@ -45,13 +45,13 @@
2.4 return VarType.DOUBLE;
2.5 case RuntimeConstants.ITEM_Long:
2.6 return VarType.LONG;
2.7 + case RuntimeConstants.ITEM_Null:
2.8 + case RuntimeConstants.ITEM_InitObject:
2.9 case RuntimeConstants.ITEM_Object:
2.10 + case RuntimeConstants.ITEM_NewObject:
2.11 return VarType.REFERENCE;
2.12
2.13 case RuntimeConstants.ITEM_Bogus:
2.14 - case RuntimeConstants.ITEM_Null:
2.15 - case RuntimeConstants.ITEM_InitObject:
2.16 - case RuntimeConstants.ITEM_NewObject:
2.17 /* unclear how to handle for now */
2.18 default:
2.19 throw new IllegalStateException("Unhandled stack map type");