1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Feb 15 17:30:47 2014 +0100
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Feb 15 20:18:26 2014 +0100
1.3 @@ -572,116 +572,116 @@
1.4 emit(smapper, out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
1.5 break;
1.6 case opc_iadd:
1.7 - emit(smapper, out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
1.8 + smapper.replace(out, VarType.INTEGER, "@1.add32(@2)", smapper.getI(1), smapper.popI());
1.9 break;
1.10 case opc_ladd:
1.11 - emit(smapper, out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
1.12 + smapper.replace(out, VarType.LONG, "@1.add64(@2)", smapper.getL(1), smapper.popL());
1.13 break;
1.14 case opc_fadd:
1.15 - emit(smapper, out, "@1 += @2;", smapper.getF(1), smapper.popF());
1.16 + smapper.replace(out, VarType.FLOAT, "(@1 + @2)", smapper.getF(1), smapper.popF());
1.17 break;
1.18 case opc_dadd:
1.19 - emit(smapper, out, "@1 += @2;", smapper.getD(1), smapper.popD());
1.20 + smapper.replace(out, VarType.DOUBLE, "(@1 + @2)", smapper.getD(1), smapper.popD());
1.21 break;
1.22 case opc_isub:
1.23 - emit(smapper, out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
1.24 + smapper.replace(out, VarType.INTEGER, "@1.sub32(@2)", smapper.getI(1), smapper.popI());
1.25 break;
1.26 case opc_lsub:
1.27 - emit(smapper, out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
1.28 + smapper.replace(out, VarType.LONG, "@1.sub64(@2)", smapper.getL(1), smapper.popL());
1.29 break;
1.30 case opc_fsub:
1.31 - emit(smapper, out, "@1 -= @2;", smapper.getF(1), smapper.popF());
1.32 + smapper.replace(out, VarType.FLOAT, "(@1 - @2)", smapper.getF(1), smapper.popF());
1.33 break;
1.34 case opc_dsub:
1.35 - emit(smapper, out, "@1 -= @2;", smapper.getD(1), smapper.popD());
1.36 + smapper.replace(out, VarType.DOUBLE, "(@1 - @2)", smapper.getD(1), smapper.popD());
1.37 break;
1.38 case opc_imul:
1.39 - emit(smapper, out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
1.40 + smapper.replace(out, VarType.INTEGER, "@1.mul32(@2)", smapper.getI(1), smapper.popI());
1.41 break;
1.42 case opc_lmul:
1.43 - emit(smapper, out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
1.44 + smapper.replace(out, VarType.LONG, "@1.mul64(@2)", smapper.getL(1), smapper.popL());
1.45 break;
1.46 case opc_fmul:
1.47 - emit(smapper, out, "@1 *= @2;", smapper.getF(1), smapper.popF());
1.48 + smapper.replace(out, VarType.FLOAT, "(@1 * @2)", smapper.getF(1), smapper.popF());
1.49 break;
1.50 case opc_dmul:
1.51 - emit(smapper, out, "@1 *= @2;", smapper.getD(1), smapper.popD());
1.52 + smapper.replace(out, VarType.DOUBLE, "(@1 * @2)", smapper.getD(1), smapper.popD());
1.53 break;
1.54 case opc_idiv:
1.55 - emit(smapper, out, "@1 = @1.div32(@2);",
1.56 + smapper.replace(out, VarType.INTEGER, "@1.div32(@2)",
1.57 smapper.getI(1), smapper.popI());
1.58 break;
1.59 case opc_ldiv:
1.60 - emit(smapper, out, "@1 = @1.div64(@2);",
1.61 + smapper.replace(out, VarType.LONG, "@1.div64(@2)",
1.62 smapper.getL(1), smapper.popL());
1.63 break;
1.64 case opc_fdiv:
1.65 - emit(smapper, out, "@1 /= @2;", smapper.getF(1), smapper.popF());
1.66 + smapper.replace(out, VarType.FLOAT, "(@1 / @2)", smapper.getF(1), smapper.popF());
1.67 break;
1.68 case opc_ddiv:
1.69 - emit(smapper, out, "@1 /= @2;", smapper.getD(1), smapper.popD());
1.70 + smapper.replace(out, VarType.DOUBLE, "(@1 / @2)", smapper.getD(1), smapper.popD());
1.71 break;
1.72 case opc_irem:
1.73 - emit(smapper, out, "@1 = @1.mod32(@2);",
1.74 + smapper.replace(out, VarType.INTEGER, "@1.mod32(@2)",
1.75 smapper.getI(1), smapper.popI());
1.76 break;
1.77 case opc_lrem:
1.78 - emit(smapper, out, "@1 = @1.mod64(@2);",
1.79 + smapper.replace(out, VarType.LONG, "@1.mod64(@2)",
1.80 smapper.getL(1), smapper.popL());
1.81 break;
1.82 case opc_frem:
1.83 - emit(smapper, out, "@1 %= @2;", smapper.getF(1), smapper.popF());
1.84 + smapper.replace(out, VarType.FLOAT, "(@1 % @2)", smapper.getF(1), smapper.popF());
1.85 break;
1.86 case opc_drem:
1.87 - emit(smapper, out, "@1 %= @2;", smapper.getD(1), smapper.popD());
1.88 + smapper.replace(out, VarType.DOUBLE, "(@1 % @2)", smapper.getD(1), smapper.popD());
1.89 break;
1.90 case opc_iand:
1.91 - emit(smapper, out, "@1 &= @2;", smapper.getI(1), smapper.popI());
1.92 + smapper.replace(out, VarType.INTEGER, "(@1 & @2)", smapper.getI(1), smapper.popI());
1.93 break;
1.94 case opc_land:
1.95 - emit(smapper, out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
1.96 + smapper.replace(out, VarType.LONG, "@1.and64(@2)", smapper.getL(1), smapper.popL());
1.97 break;
1.98 case opc_ior:
1.99 - emit(smapper, out, "@1 |= @2;", smapper.getI(1), smapper.popI());
1.100 + smapper.replace(out, VarType.INTEGER, "(@1 | @2)", smapper.getI(1), smapper.popI());
1.101 break;
1.102 case opc_lor:
1.103 - emit(smapper, out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
1.104 + smapper.replace(out, VarType.LONG, "@1.or64(@2)", smapper.getL(1), smapper.popL());
1.105 break;
1.106 case opc_ixor:
1.107 - emit(smapper, out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
1.108 + smapper.replace(out, VarType.INTEGER, "(@1 ^ @2)", smapper.getI(1), smapper.popI());
1.109 break;
1.110 case opc_lxor:
1.111 - emit(smapper, out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
1.112 + smapper.replace(out, VarType.LONG, "@1.xor64(@2)", smapper.getL(1), smapper.popL());
1.113 break;
1.114 case opc_ineg:
1.115 - emit(smapper, out, "@1 = @1.neg32();", smapper.getI(0));
1.116 + smapper.replace(out, VarType.INTEGER, "@1.neg32()", smapper.getI(0));
1.117 break;
1.118 case opc_lneg:
1.119 - emit(smapper, out, "@1 = @1.neg64();", smapper.getL(0));
1.120 + smapper.replace(out, VarType.LONG, "@1.neg64()", smapper.getL(0));
1.121 break;
1.122 case opc_fneg:
1.123 - emit(smapper, out, "@1 = -@1;", smapper.getF(0));
1.124 + smapper.replace(out, VarType.FLOAT, "(-@1)", smapper.getF(0));
1.125 break;
1.126 case opc_dneg:
1.127 - emit(smapper, out, "@1 = -@1;", smapper.getD(0));
1.128 + smapper.replace(out, VarType.DOUBLE, "(-@1)", smapper.getD(0));
1.129 break;
1.130 case opc_ishl:
1.131 - emit(smapper, out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
1.132 + smapper.replace(out, VarType.INTEGER, "(@1 << @2)", smapper.getI(1), smapper.popI());
1.133 break;
1.134 case opc_lshl:
1.135 - emit(smapper, out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
1.136 + smapper.replace(out, VarType.LONG, "@1.shl64(@2)", smapper.getL(1), smapper.popI());
1.137 break;
1.138 case opc_ishr:
1.139 - emit(smapper, out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
1.140 + smapper.replace(out, VarType.INTEGER, "(@1 >> @2)", smapper.getI(1), smapper.popI());
1.141 break;
1.142 case opc_lshr:
1.143 - emit(smapper, out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
1.144 + smapper.replace(out, VarType.LONG, "@1.shr64(@2)", smapper.getL(1), smapper.popI());
1.145 break;
1.146 case opc_iushr:
1.147 - emit(smapper, out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
1.148 + smapper.replace(out, VarType.INTEGER, "(@1 >>> @2)", smapper.getI(1), smapper.popI());
1.149 break;
1.150 case opc_lushr:
1.151 - emit(smapper, out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
1.152 + smapper.replace(out, VarType.LONG, "@1.ushr64(@2)", smapper.getL(1), smapper.popI());
1.153 break;
1.154 case opc_iinc: {
1.155 ++i;
1.156 @@ -719,99 +719,99 @@
1.157 emit(smapper, out, "return @1;", smapper.popA());
1.158 break;
1.159 case opc_i2l:
1.160 - emit(smapper, out, "var @2 = @1;", smapper.popI(), smapper.pushL());
1.161 + smapper.replace(out, VarType.LONG, "@1", smapper.getI(0));
1.162 break;
1.163 case opc_i2f:
1.164 - emit(smapper, out, "var @2 = @1;", smapper.popI(), smapper.pushF());
1.165 + smapper.replace(out, VarType.FLOAT, "@1", smapper.getI(0));
1.166 break;
1.167 case opc_i2d:
1.168 - emit(smapper, out, "var @2 = @1;", smapper.popI(), smapper.pushD());
1.169 + smapper.replace(out, VarType.DOUBLE, "@1", smapper.getI(0));
1.170 break;
1.171 case opc_l2i:
1.172 - emit(smapper, out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
1.173 + smapper.replace(out, VarType.INTEGER, "@1.toInt32()", smapper.getL(0));
1.174 break;
1.175 // max int check?
1.176 case opc_l2f:
1.177 - emit(smapper, out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
1.178 + smapper.replace(out, VarType.FLOAT, "@1.toFP()", smapper.getL(0));
1.179 break;
1.180 case opc_l2d:
1.181 - emit(smapper, out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
1.182 + smapper.replace(out, VarType.DOUBLE, "@1.toFP()", smapper.getL(0));
1.183 break;
1.184 case opc_f2d:
1.185 - emit(smapper, out, "var @2 = @1;", smapper.popF(), smapper.pushD());
1.186 + smapper.replace(out, VarType.DOUBLE, "@1",
1.187 + smapper.getF(0));
1.188 break;
1.189 case opc_d2f:
1.190 - emit(smapper, out, "var @2 = @1;", smapper.popD(), smapper.pushF());
1.191 + smapper.replace(out, VarType.FLOAT, "@1",
1.192 + smapper.getD(0));
1.193 break;
1.194 case opc_f2i:
1.195 - emit(smapper, out, "var @2 = @1.toInt32();",
1.196 - smapper.popF(), smapper.pushI());
1.197 + smapper.replace(out, VarType.INTEGER, "@1.toInt32()",
1.198 + smapper.getF(0));
1.199 break;
1.200 case opc_f2l:
1.201 - emit(smapper, out, "var @2 = @1.toLong();",
1.202 - smapper.popF(), smapper.pushL());
1.203 + smapper.replace(out, VarType.LONG, "@1.toLong()",
1.204 + smapper.getF(0));
1.205 break;
1.206 case opc_d2i:
1.207 - emit(smapper, out, "var @2 = @1.toInt32();",
1.208 - smapper.popD(), smapper.pushI());
1.209 + smapper.replace(out, VarType.INTEGER, "@1.toInt32()",
1.210 + smapper.getD(0));
1.211 break;
1.212 case opc_d2l:
1.213 - emit(smapper, out, "var @2 = @1.toLong();",
1.214 - smapper.popD(), smapper.pushL());
1.215 + smapper.replace(out, VarType.LONG, "@1.toLong()", smapper.getD(0));
1.216 break;
1.217 case opc_i2b:
1.218 - emit(smapper, out, "var @1 = @1.toInt8();", smapper.getI(0));
1.219 + smapper.replace(out, VarType.INTEGER, "@1.toInt8()", smapper.getI(0));
1.220 break;
1.221 case opc_i2c:
1.222 - out.append("{ /* number conversion */ }");
1.223 break;
1.224 case opc_i2s:
1.225 - emit(smapper, out, "var @1 = @1.toInt16();", smapper.getI(0));
1.226 + smapper.replace(out, VarType.INTEGER, "@1.toInt16()", smapper.getI(0));
1.227 break;
1.228 case opc_aconst_null:
1.229 - emit(smapper, out, "var @1 = null;", smapper.pushA());
1.230 + smapper.assign(out, VarType.REFERENCE, "null");
1.231 break;
1.232 case opc_iconst_m1:
1.233 - emit(smapper, out, "var @1 = -1;", smapper.pushI());
1.234 + smapper.assign(out, VarType.INTEGER, "-1");
1.235 break;
1.236 case opc_iconst_0:
1.237 - emit(smapper, out, "var @1 = 0;", smapper.pushI());
1.238 + smapper.assign(out, VarType.INTEGER, "0");
1.239 break;
1.240 case opc_dconst_0:
1.241 - emit(smapper, out, "var @1 = 0;", smapper.pushD());
1.242 + smapper.assign(out, VarType.DOUBLE, "0");
1.243 break;
1.244 case opc_lconst_0:
1.245 - emit(smapper, out, "var @1 = 0;", smapper.pushL());
1.246 + smapper.assign(out, VarType.LONG, "0");
1.247 break;
1.248 case opc_fconst_0:
1.249 - emit(smapper, out, "var @1 = 0;", smapper.pushF());
1.250 + smapper.assign(out, VarType.FLOAT, "0");
1.251 break;
1.252 case opc_iconst_1:
1.253 - emit(smapper, out, "var @1 = 1;", smapper.pushI());
1.254 + smapper.assign(out, VarType.INTEGER, "1");
1.255 break;
1.256 case opc_lconst_1:
1.257 - emit(smapper, out, "var @1 = 1;", smapper.pushL());
1.258 + smapper.assign(out, VarType.LONG, "1");
1.259 break;
1.260 case opc_fconst_1:
1.261 - emit(smapper, out, "var @1 = 1;", smapper.pushF());
1.262 + smapper.assign(out, VarType.FLOAT, "1");
1.263 break;
1.264 case opc_dconst_1:
1.265 - emit(smapper, out, "var @1 = 1;", smapper.pushD());
1.266 + smapper.assign(out, VarType.DOUBLE, "1");
1.267 break;
1.268 case opc_iconst_2:
1.269 - emit(smapper, out, "var @1 = 2;", smapper.pushI());
1.270 + smapper.assign(out, VarType.INTEGER, "2");
1.271 break;
1.272 case opc_fconst_2:
1.273 - emit(smapper, out, "var @1 = 2;", smapper.pushF());
1.274 + smapper.assign(out, VarType.FLOAT, "2");
1.275 break;
1.276 case opc_iconst_3:
1.277 - emit(smapper, out, "var @1 = 3;", smapper.pushI());
1.278 + smapper.assign(out, VarType.INTEGER, "3");
1.279 break;
1.280 case opc_iconst_4:
1.281 - emit(smapper, out, "var @1 = 4;", smapper.pushI());
1.282 + smapper.assign(out, VarType.INTEGER, "4");
1.283 break;
1.284 case opc_iconst_5:
1.285 - emit(smapper, out, "var @1 = 5;", smapper.pushI());
1.286 + smapper.assign(out, VarType.INTEGER, "5");
1.287 break;
1.288 case opc_ldc: {
1.289 int indx = readUByte(byteCodes, ++i);
1.290 @@ -1066,8 +1066,8 @@
1.291 break;
1.292 }
1.293 case opc_dup_x1: {
1.294 - final Variable vi1 = smapper.pop();
1.295 - final Variable vi2 = smapper.pop();
1.296 + final Variable vi1 = smapper.pop(out);
1.297 + final Variable vi2 = smapper.pop(out);
1.298 final Variable vo3 = smapper.pushT(vi1.getType());
1.299 final Variable vo2 = smapper.pushT(vi2.getType());
1.300 final Variable vo1 = smapper.pushT(vi1.getType());
1.301 @@ -1077,8 +1077,8 @@
1.302 break;
1.303 }
1.304 case opc_dup2_x1: {
1.305 - final Variable vi1 = smapper.pop();
1.306 - final Variable vi2 = smapper.pop();
1.307 + final Variable vi1 = smapper.pop(out);
1.308 + final Variable vi2 = smapper.pop(out);
1.309
1.310 if (vi1.isCategory2()) {
1.311 final Variable vo3 = smapper.pushT(vi1.getType());
1.312 @@ -1088,7 +1088,7 @@
1.313 emit(smapper, out, "var @1 = @2, @3 = @4, @5 = @6;",
1.314 vo1, vi1, vo2, vi2, vo3, vo1);
1.315 } else {
1.316 - final Variable vi3 = smapper.pop();
1.317 + final Variable vi3 = smapper.pop(out);
1.318 final Variable vo5 = smapper.pushT(vi2.getType());
1.319 final Variable vo4 = smapper.pushT(vi1.getType());
1.320 final Variable vo3 = smapper.pushT(vi3.getType());
1.321 @@ -1103,8 +1103,8 @@
1.322 break;
1.323 }
1.324 case opc_dup_x2: {
1.325 - final Variable vi1 = smapper.pop();
1.326 - final Variable vi2 = smapper.pop();
1.327 + final Variable vi1 = smapper.pop(out);
1.328 + final Variable vi2 = smapper.pop(out);
1.329
1.330 if (vi2.isCategory2()) {
1.331 final Variable vo3 = smapper.pushT(vi1.getType());
1.332 @@ -1114,7 +1114,7 @@
1.333 emit(smapper, out, "var @1 = @2, @3 = @4, @5 = @6;",
1.334 vo1, vi1, vo2, vi2, vo3, vo1);
1.335 } else {
1.336 - final Variable vi3 = smapper.pop();
1.337 + final Variable vi3 = smapper.pop(out);
1.338 final Variable vo4 = smapper.pushT(vi1.getType());
1.339 final Variable vo3 = smapper.pushT(vi3.getType());
1.340 final Variable vo2 = smapper.pushT(vi2.getType());
1.341 @@ -1126,8 +1126,8 @@
1.342 break;
1.343 }
1.344 case opc_dup2_x2: {
1.345 - final Variable vi1 = smapper.pop();
1.346 - final Variable vi2 = smapper.pop();
1.347 + final Variable vi1 = smapper.pop(out);
1.348 + final Variable vi2 = smapper.pop(out);
1.349
1.350 if (vi1.isCategory2()) {
1.351 if (vi2.isCategory2()) {
1.352 @@ -1138,7 +1138,7 @@
1.353 emit(smapper, out, "var @1 = @2, @3 = @4, @5 = @6;",
1.354 vo1, vi1, vo2, vi2, vo3, vo1);
1.355 } else {
1.356 - final Variable vi3 = smapper.pop();
1.357 + final Variable vi3 = smapper.pop(out);
1.358 final Variable vo4 = smapper.pushT(vi1.getType());
1.359 final Variable vo3 = smapper.pushT(vi3.getType());
1.360 final Variable vo2 = smapper.pushT(vi2.getType());
1.361 @@ -1148,7 +1148,7 @@
1.362 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.363 }
1.364 } else {
1.365 - final Variable vi3 = smapper.pop();
1.366 + final Variable vi3 = smapper.pop(out);
1.367
1.368 if (vi3.isCategory2()) {
1.369 final Variable vo5 = smapper.pushT(vi2.getType());
1.370 @@ -1162,7 +1162,7 @@
1.371 emit(smapper, out, " @1 = @2, @3 = @4;",
1.372 vo4, vo1, vo5, vo2);
1.373 } else {
1.374 - final Variable vi4 = smapper.pop();
1.375 + final Variable vi4 = smapper.pop(out);
1.376 final Variable vo6 = smapper.pushT(vi2.getType());
1.377 final Variable vo5 = smapper.pushT(vi1.getType());
1.378 final Variable vo4 = smapper.pushT(vi4.getType());
1.379 @@ -1267,7 +1267,7 @@
1.380 break;
1.381 }
1.382 case opc_athrow: {
1.383 - final Variable v = smapper.popA();
1.384 + final CharSequence v = smapper.popA();
1.385 smapper.clear();
1.386
1.387 emit(smapper, out, "{ var @1 = @2; throw @2; }",
1.388 @@ -1312,7 +1312,7 @@
1.389 out.append("\n};");
1.390 }
1.391
1.392 - private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
1.393 + private int generateIf(byte[] byteCodes, int i, final CharSequence v2, final CharSequence v1, final String test, int topMostLabel) throws IOException {
1.394 int indx = i + readShortArg(byteCodes, i);
1.395 out.append("if (").append(v1)
1.396 .append(' ').append(test).append(' ')
1.397 @@ -1497,10 +1497,10 @@
1.398 String mn = findMethodName(mi, cnt, returnType);
1.399
1.400 final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
1.401 - final Variable[] vars = new Variable[numArguments];
1.402 + final CharSequence[] vars = new CharSequence[numArguments];
1.403
1.404 for (int j = numArguments - 1; j >= 0; --j) {
1.405 - vars[j] = mapper.pop();
1.406 + vars[j] = mapper.popValue();
1.407 }
1.408
1.409 if (returnType[0] != 'V') {
1.410 @@ -1545,7 +1545,7 @@
1.411 final Variable[] vars = new Variable[numArguments];
1.412
1.413 for (int j = numArguments - 1; j >= 0; --j) {
1.414 - vars[j] = mapper.pop();
1.415 + vars[j] = mapper.pop(out);
1.416 }
1.417
1.418 if (returnType[0] != 'V') {
1.419 @@ -2006,7 +2006,7 @@
1.420 private static void emitIf(
1.421 StackMapper sm,
1.422 Appendable out, String pattern,
1.423 - Variable param,
1.424 + CharSequence param,
1.425 int current, int to, int canBack
1.426 ) throws IOException {
1.427 sm.flush(out);
2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java Sat Feb 15 17:30:47 2014 +0100
2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java Sat Feb 15 20:18:26 2014 +0100
2.3 @@ -69,7 +69,16 @@
2.4
2.5 void assign(Appendable out, int varType, CharSequence s) throws IOException {
2.6 pushTypeAndValue(varType, s);
2.7 - flush(out);
2.8 + }
2.9 +
2.10 + void replace(Appendable out, int varType, String format, CharSequence... arr)
2.11 + throws IOException {
2.12 + StringBuilder sb = new StringBuilder();
2.13 + ByteCodeToJavaScript.emitImpl(sb, format, arr);
2.14 + String[] values = stackValues.toArray();
2.15 + final int last = stackTypeIndexPairs.getSize() - 1;
2.16 + values[last] = sb.toString();
2.17 + stackTypeIndexPairs.set(last, varType);
2.18 }
2.19
2.20 void flush(Appendable out) throws IOException {
2.21 @@ -84,33 +93,39 @@
2.22 }
2.23 }
2.24
2.25 - public Variable popI() {
2.26 + public CharSequence popI() {
2.27 return popT(VarType.INTEGER);
2.28 }
2.29
2.30 - public Variable popL() {
2.31 + public CharSequence popL() {
2.32 return popT(VarType.LONG);
2.33 }
2.34
2.35 - public Variable popF() {
2.36 + public CharSequence popF() {
2.37 return popT(VarType.FLOAT);
2.38 }
2.39
2.40 - public Variable popD() {
2.41 + public CharSequence popD() {
2.42 return popT(VarType.DOUBLE);
2.43 }
2.44
2.45 - public Variable popA() {
2.46 + public CharSequence popA() {
2.47 return popT(VarType.REFERENCE);
2.48 }
2.49
2.50 - public Variable popT(final int type) {
2.51 - final Variable variable = getT(0, type);
2.52 + public CharSequence popT(final int type) {
2.53 + final CharSequence variable = getT(0, type);
2.54 popImpl(1);
2.55 return variable;
2.56 }
2.57
2.58 - public Variable pop() {
2.59 + public CharSequence popValue() {
2.60 + final CharSequence variable = getT(0, -1);
2.61 + popImpl(1);
2.62 + return variable;
2.63 + }
2.64 + public Variable pop(Appendable out) throws IOException {
2.65 + flush(out);
2.66 final Variable variable = get(0);
2.67 popImpl(1);
2.68 return variable;
2.69 @@ -124,37 +139,41 @@
2.70 popImpl(count);
2.71 }
2.72
2.73 - public Variable getI(final int indexFromTop) {
2.74 + public CharSequence getI(final int indexFromTop) {
2.75 return getT(indexFromTop, VarType.INTEGER);
2.76 }
2.77
2.78 - public Variable getL(final int indexFromTop) {
2.79 + public CharSequence getL(final int indexFromTop) {
2.80 return getT(indexFromTop, VarType.LONG);
2.81 }
2.82
2.83 - public Variable getF(final int indexFromTop) {
2.84 + public CharSequence getF(final int indexFromTop) {
2.85 return getT(indexFromTop, VarType.FLOAT);
2.86 }
2.87
2.88 - public Variable getD(final int indexFromTop) {
2.89 + public CharSequence getD(final int indexFromTop) {
2.90 return getT(indexFromTop, VarType.DOUBLE);
2.91 }
2.92
2.93 - public Variable getA(final int indexFromTop) {
2.94 + public CharSequence getA(final int indexFromTop) {
2.95 return getT(indexFromTop, VarType.REFERENCE);
2.96 }
2.97
2.98 - public Variable getT(final int indexFromTop, final int type) {
2.99 + public CharSequence getT(final int indexFromTop, final int type) {
2.100 final int stackSize = stackTypeIndexPairs.getSize();
2.101 if (indexFromTop >= stackSize) {
2.102 throw new IllegalStateException("Stack underflow");
2.103 }
2.104 final int stackValue =
2.105 stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
2.106 - if ((stackValue & 0xff) != type) {
2.107 + if (type != -1 && (stackValue & 0xff) != type) {
2.108 throw new IllegalStateException("Type mismatch");
2.109 }
2.110 -
2.111 + String value =
2.112 + stackValues.getAndClear(stackSize - indexFromTop - 1);
2.113 + if (value != null) {
2.114 + return value;
2.115 + }
2.116 return getVariable(stackValue);
2.117 }
2.118
3.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Sat Feb 15 17:30:47 2014 +0100
3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Sat Feb 15 20:18:26 2014 +0100
3.3 @@ -105,7 +105,7 @@
3.4 }
3.5
3.6 int indexOf(String ic) {
3.7 - for (int i = 0; i < arr.length; i++) {
3.8 + if (arr != null) for (int i = 0; i < arr.length; i++) {
3.9 if (ic.equals(arr[i])) {
3.10 return i;
3.11 }
4.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/SizeOfAMethodTest.java Sat Feb 15 17:30:47 2014 +0100
4.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/SizeOfAMethodTest.java Sat Feb 15 20:18:26 2014 +0100
4.3 @@ -23,6 +23,8 @@
4.4
4.5 package org.apidesign.vm4brwsr;
4.6
4.7 +import java.io.IOException;
4.8 +import java.io.InputStream;
4.9 import static org.testng.Assert.assertEquals;
4.10 import static org.testng.Assert.assertTrue;
4.11 import org.testng.annotations.AfterClass;
4.12 @@ -34,26 +36,53 @@
4.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
4.14 */
4.15 public class SizeOfAMethodTest {
4.16 - private static TestVM code;
4.17 + private static String code;
4.18
4.19 @Test public void sumXYShouldBeSmall() {
4.20 - String s = code.codeSeq().toString();
4.21 + String s = code;
4.22 int beg = s.indexOf("c.sum__III");
4.23 int end = s.indexOf("c.sum__III.access");
4.24
4.25 - assertTrue(beg > 0, "Found sum method in " + code.toString());
4.26 - assertTrue(beg < end, "Found end of sum method in " + code.toString());
4.27 + assertTrue(beg > 0, "Found sum method in " + code);
4.28 + assertTrue(beg < end, "Found end of sum method in " + code);
4.29
4.30 String method = s.substring(beg, end);
4.31
4.32 +
4.33 + assertEquals(method.indexOf("st"), -1, "There should be no stack operations:\n" + method);
4.34 + }
4.35 +
4.36 + @Test public void emptyConstructorRequiresNoStack() {
4.37 + String s = code;
4.38 + int beg = s.indexOf("CLS.cons__V");
4.39 + int end = s.indexOf("CLS.cons__V.access");
4.40 +
4.41 + assertTrue(beg > 0, "Found constructor in " + code);
4.42 + assertTrue(beg < end, "Found end of constructor in " + code);
4.43 +
4.44 + String method = s.substring(beg, end);
4.45 + method = method.replace("constructor", "CNSTR");
4.46 +
4.47 assertEquals(method.indexOf("st"), -1, "There should be no stack operations:\n" + method);
4.48 }
4.49
4.50
4.51 @BeforeClass
4.52 public static void compileTheCode() throws Exception {
4.53 + final String res = "org/apidesign/vm4brwsr/StaticMethod";
4.54 StringBuilder sb = new StringBuilder();
4.55 - code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
4.56 + class JustStaticMethod implements Bck2Brwsr.Resources {
4.57 + @Override
4.58 + public InputStream get(String resource) throws IOException {
4.59 + final String cn = res + ".class";
4.60 + if (resource.equals(cn)) {
4.61 + return getClass().getClassLoader().getResourceAsStream(cn);
4.62 + }
4.63 + return null;
4.64 + }
4.65 + }
4.66 + Bck2Brwsr.generate(sb, new JustStaticMethod(), res);
4.67 + code = sb.toString();
4.68 }
4.69 @AfterClass
4.70 public static void releaseTheCode() {