vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
branchregisters
changeset 281 f2352e0b713e
parent 242 8bd4adaf6590
child 282 a98d6c5a545e
     1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Dec 03 14:44:49 2012 +0100
     1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Dec 07 15:02:35 2012 +0100
     1.3 @@ -241,12 +241,15 @@
     1.4          // so this might generate more stack variables than we need
     1.5          final int maxStack = m.getMaxStack();
     1.6          if (maxStack > 0) {
     1.7 -            out.append("\n  var ").append(mapper.constructVariableName(0));
     1.8 -            for (int i = 1; i < maxStack; ++i) {
     1.9 -                out.append(", ");
    1.10 -                out.append(mapper.constructVariableName(i));
    1.11 +            // TODO: generate only used stack variables
    1.12 +            for (int j = 0; j <= Variable.LAST_TYPE; ++j) {
    1.13 +                out.append("\n  var ").append(Variable.getStackVariable(j, 0));
    1.14 +                for (int i = 1; i < maxStack; ++i) {
    1.15 +                    out.append(", ");
    1.16 +                    out.append(Variable.getStackVariable(j, i));
    1.17 +                }
    1.18 +                out.append(';');
    1.19              }
    1.20 -            out.append(';');
    1.21          }
    1.22  
    1.23          int lastStackFrame = -1;
    1.24 @@ -257,7 +260,7 @@
    1.25              stackMapIterator.advanceTo(i);
    1.26              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
    1.27                  lastStackFrame = stackMapIterator.getFrameIndex();
    1.28 -                mapper.reset(stackMapIterator.getFrameStackItemsCount());
    1.29 +                mapper.syncWithFrameStack(stackMapIterator.getFrameStack());
    1.30                  out.append("    case " + i).append(": ");
    1.31              } else {
    1.32                  out.append("    /* " + i).append(" */ ");
    1.33 @@ -265,162 +268,330 @@
    1.34              final int c = readByte(byteCodes, i);
    1.35              switch (c) {
    1.36                  case opc_aload_0:
    1.37 +                    out.append(mapper.pushA()).append(" = arg0;");
    1.38 +                    break;
    1.39                  case opc_iload_0:
    1.40 +                    out.append(mapper.pushI()).append(" = arg0;");
    1.41 +                    break;
    1.42                  case opc_lload_0:
    1.43 +                    out.append(mapper.pushL()).append(" = arg0;");
    1.44 +                    break;
    1.45                  case opc_fload_0:
    1.46 +                    out.append(mapper.pushF()).append(" = arg0;");
    1.47 +                    break;
    1.48                  case opc_dload_0:
    1.49 -                    out.append(mapper.push()).append(" = arg0;");
    1.50 +                    out.append(mapper.pushD()).append(" = arg0;");
    1.51                      break;
    1.52                  case opc_aload_1:
    1.53 +                    out.append(mapper.pushA()).append(" = arg1;");
    1.54 +                    break;
    1.55                  case opc_iload_1:
    1.56 +                    out.append(mapper.pushI()).append(" = arg1;");
    1.57 +                    break;
    1.58                  case opc_lload_1:
    1.59 +                    out.append(mapper.pushL()).append(" = arg1;");
    1.60 +                    break;
    1.61                  case opc_fload_1:
    1.62 +                    out.append(mapper.pushF()).append(" = arg1;");
    1.63 +                    break;
    1.64                  case opc_dload_1:
    1.65 -                    out.append(mapper.push()).append(" = arg1;");
    1.66 +                    out.append(mapper.pushD()).append(" = arg1;");
    1.67                      break;
    1.68                  case opc_aload_2:
    1.69 +                    out.append(mapper.pushA()).append(" = arg2;");
    1.70 +                    break;
    1.71                  case opc_iload_2:
    1.72 +                    out.append(mapper.pushI()).append(" = arg2;");
    1.73 +                    break;
    1.74                  case opc_lload_2:
    1.75 +                    out.append(mapper.pushL()).append(" = arg2;");
    1.76 +                    break;
    1.77                  case opc_fload_2:
    1.78 +                    out.append(mapper.pushF()).append(" = arg2;");
    1.79 +                    break;
    1.80                  case opc_dload_2:
    1.81 -                    out.append(mapper.push()).append(" = arg2;");
    1.82 +                    out.append(mapper.pushD()).append(" = arg2;");
    1.83                      break;
    1.84                  case opc_aload_3:
    1.85 +                    out.append(mapper.pushA()).append(" = arg3;");
    1.86 +                    break;
    1.87                  case opc_iload_3:
    1.88 +                    out.append(mapper.pushI()).append(" = arg3;");
    1.89 +                    break;
    1.90                  case opc_lload_3:
    1.91 +                    out.append(mapper.pushL()).append(" = arg3;");
    1.92 +                    break;
    1.93                  case opc_fload_3:
    1.94 +                    out.append(mapper.pushF()).append(" = arg3;");
    1.95 +                    break;
    1.96                  case opc_dload_3:
    1.97 -                    out.append(mapper.push()).append(" = arg3;");
    1.98 +                    out.append(mapper.pushD()).append(" = arg3;");
    1.99                      break;
   1.100 -                case opc_iload:
   1.101 -                case opc_lload:
   1.102 -                case opc_fload:
   1.103 -                case opc_dload:
   1.104 +                case opc_iload: {
   1.105 +                    final int indx = readByte(byteCodes, ++i);
   1.106 +                    out.append(mapper.pushI()).append(" = ")
   1.107 +                       .append("arg").append(indx + ";");
   1.108 +                    break;
   1.109 +                }
   1.110 +                case opc_lload: {
   1.111 +                    final int indx = readByte(byteCodes, ++i);
   1.112 +                    out.append(mapper.pushL()).append(" = ")
   1.113 +                       .append("arg").append(indx + ";");
   1.114 +                    break;
   1.115 +                }
   1.116 +                case opc_fload: {
   1.117 +                    final int indx = readByte(byteCodes, ++i);
   1.118 +                    out.append(mapper.pushF()).append(" = ")
   1.119 +                       .append("arg").append(indx + ";");
   1.120 +                    break;
   1.121 +                }
   1.122 +                case opc_dload: {
   1.123 +                    final int indx = readByte(byteCodes, ++i);
   1.124 +                    out.append(mapper.pushD()).append(" = ")
   1.125 +                       .append("arg").append(indx + ";");
   1.126 +                    break;
   1.127 +                }
   1.128                  case opc_aload: {
   1.129                      final int indx = readByte(byteCodes, ++i);
   1.130 -                    out.append(mapper.push())
   1.131 -                       .append(" = arg")
   1.132 -                       .append(indx + ";");
   1.133 +                    out.append(mapper.pushA()).append(" = ")
   1.134 +                       .append("arg").append(indx + ";");
   1.135                      break;
   1.136                  }
   1.137 -                case opc_istore:
   1.138 -                case opc_lstore:
   1.139 -                case opc_fstore:
   1.140 -                case opc_dstore:
   1.141 +                case opc_istore: {
   1.142 +                    final int indx = readByte(byteCodes, ++i);
   1.143 +                    out.append("arg" + indx).append(" = ")
   1.144 +                       .append(mapper.popI()).append(';');
   1.145 +                    break;
   1.146 +                }
   1.147 +                case opc_lstore: {
   1.148 +                    final int indx = readByte(byteCodes, ++i);
   1.149 +                    out.append("arg" + indx).append(" = ")
   1.150 +                       .append(mapper.popL()).append(';');
   1.151 +                    break;
   1.152 +                }
   1.153 +                case opc_fstore: {
   1.154 +                    final int indx = readByte(byteCodes, ++i);
   1.155 +                    out.append("arg" + indx).append(" = ")
   1.156 +                       .append(mapper.popF()).append(';');
   1.157 +                    break;
   1.158 +                }
   1.159 +                case opc_dstore: {
   1.160 +                    final int indx = readByte(byteCodes, ++i);
   1.161 +                    out.append("arg" + indx).append(" = ")
   1.162 +                       .append(mapper.popD()).append(';');
   1.163 +                    break;
   1.164 +                }
   1.165                  case opc_astore: {
   1.166                      final int indx = readByte(byteCodes, ++i);
   1.167 -                    out.append("arg" + indx)
   1.168 -                       .append(" = ")
   1.169 -                       .append(mapper.pop())
   1.170 -                       .append(';');
   1.171 +                    out.append("arg" + indx).append(" = ")
   1.172 +                       .append(mapper.popA()).append(';');
   1.173                      break;
   1.174                  }
   1.175                  case opc_astore_0:
   1.176 +                    out.append("arg0 = ").append(mapper.popA()).append(';');
   1.177 +                    break;
   1.178                  case opc_istore_0:
   1.179 +                    out.append("arg0 = ").append(mapper.popI()).append(';');
   1.180 +                    break;
   1.181                  case opc_lstore_0:
   1.182 +                    out.append("arg0 = ").append(mapper.popL()).append(';');
   1.183 +                    break;
   1.184                  case opc_fstore_0:
   1.185 +                    out.append("arg0 = ").append(mapper.popF()).append(';');
   1.186 +                    break;
   1.187                  case opc_dstore_0:
   1.188 -                    out.append("arg0 = ").append(mapper.pop()).append(';');
   1.189 +                    out.append("arg0 = ").append(mapper.popD()).append(';');
   1.190                      break;
   1.191                  case opc_astore_1:
   1.192 +                    out.append("arg1 = ").append(mapper.popA()).append(';');
   1.193 +                    break;
   1.194                  case opc_istore_1:
   1.195 +                    out.append("arg1 = ").append(mapper.popI()).append(';');
   1.196 +                    break;
   1.197                  case opc_lstore_1:
   1.198 +                    out.append("arg1 = ").append(mapper.popL()).append(';');
   1.199 +                    break;
   1.200                  case opc_fstore_1:
   1.201 +                    out.append("arg1 = ").append(mapper.popF()).append(';');
   1.202 +                    break;
   1.203                  case opc_dstore_1:
   1.204 -                    out.append("arg1 = ").append(mapper.pop()).append(';');
   1.205 +                    out.append("arg1 = ").append(mapper.popD()).append(';');
   1.206                      break;
   1.207                  case opc_astore_2:
   1.208 +                    out.append("arg2 = ").append(mapper.popA()).append(';');
   1.209 +                    break;
   1.210                  case opc_istore_2:
   1.211 +                    out.append("arg2 = ").append(mapper.popI()).append(';');
   1.212 +                    break;
   1.213                  case opc_lstore_2:
   1.214 +                    out.append("arg2 = ").append(mapper.popL()).append(';');
   1.215 +                    break;
   1.216                  case opc_fstore_2:
   1.217 +                    out.append("arg2 = ").append(mapper.popF()).append(';');
   1.218 +                    break;
   1.219                  case opc_dstore_2:
   1.220 -                    out.append("arg2 = ").append(mapper.pop()).append(';');
   1.221 +                    out.append("arg2 = ").append(mapper.popD()).append(';');
   1.222                      break;
   1.223                  case opc_astore_3:
   1.224 +                    out.append("arg3 = ").append(mapper.popA()).append(';');
   1.225 +                    break;
   1.226                  case opc_istore_3:
   1.227 +                    out.append("arg3 = ").append(mapper.popI()).append(';');
   1.228 +                    break;
   1.229                  case opc_lstore_3:
   1.230 +                    out.append("arg3 = ").append(mapper.popL()).append(';');
   1.231 +                    break;
   1.232                  case opc_fstore_3:
   1.233 +                    out.append("arg3 = ").append(mapper.popF()).append(';');
   1.234 +                    break;
   1.235                  case opc_dstore_3:
   1.236 -                    out.append("arg3 = ").append(mapper.pop()).append(';');
   1.237 +                    out.append("arg3 = ").append(mapper.popD()).append(';');
   1.238                      break;
   1.239                  case opc_iadd:
   1.240 +                    out.append(mapper.getI(1)).append(" += ")
   1.241 +                       .append(mapper.popI()).append(';');
   1.242 +                    break;
   1.243                  case opc_ladd:
   1.244 +                    out.append(mapper.getL(1)).append(" += ")
   1.245 +                       .append(mapper.popL()).append(';');
   1.246 +                    break;
   1.247                  case opc_fadd:
   1.248 +                    out.append(mapper.getF(1)).append(" += ")
   1.249 +                       .append(mapper.popF()).append(';');
   1.250 +                    break;
   1.251                  case opc_dadd:
   1.252 -                    out.append(mapper.get(1)).append(" += ")
   1.253 -                       .append(mapper.pop()).append(';');
   1.254 +                    out.append(mapper.getD(1)).append(" += ")
   1.255 +                       .append(mapper.popD()).append(';');
   1.256                      break;
   1.257                  case opc_isub:
   1.258 +                    out.append(mapper.getI(1)).append(" -= ")
   1.259 +                       .append(mapper.popI()).append(';');
   1.260 +                    break;
   1.261                  case opc_lsub:
   1.262 +                    out.append(mapper.getL(1)).append(" -= ")
   1.263 +                       .append(mapper.popL()).append(';');
   1.264 +                    break;
   1.265                  case opc_fsub:
   1.266 +                    out.append(mapper.getF(1)).append(" -= ")
   1.267 +                       .append(mapper.popF()).append(';');
   1.268 +                    break;
   1.269                  case opc_dsub:
   1.270 -                    out.append(mapper.get(1)).append(" -= ")
   1.271 -                       .append(mapper.pop()).append(';');
   1.272 +                    out.append(mapper.getD(1)).append(" -= ")
   1.273 +                       .append(mapper.popD()).append(';');
   1.274                      break;
   1.275                  case opc_imul:
   1.276 +                    out.append(mapper.getI(1)).append(" *= ")
   1.277 +                       .append(mapper.popI()).append(';');
   1.278 +                    break;
   1.279                  case opc_lmul:
   1.280 +                    out.append(mapper.getL(1)).append(" *= ")
   1.281 +                       .append(mapper.popL()).append(';');
   1.282 +                    break;
   1.283                  case opc_fmul:
   1.284 +                    out.append(mapper.getF(1)).append(" *= ")
   1.285 +                       .append(mapper.popF()).append(';');
   1.286 +                    break;
   1.287                  case opc_dmul:
   1.288 -                    out.append(mapper.get(1)).append(" *= ")
   1.289 -                       .append(mapper.pop()).append(';');
   1.290 +                    out.append(mapper.getD(1)).append(" *= ")
   1.291 +                       .append(mapper.popD()).append(';');
   1.292                      break;
   1.293                  case opc_idiv:
   1.294 +                    out.append(mapper.getI(1)).append(" = ")
   1.295 +                       .append("Math.floor(").append(mapper.getI(1))
   1.296 +                       .append(" / ").append(mapper.popI()).append(");");
   1.297 +                    break;
   1.298                  case opc_ldiv:
   1.299 -                    out.append(mapper.get(1))
   1.300 -                       .append(" = Math.floor(")
   1.301 -                       .append(mapper.get(1))
   1.302 -                       .append(" / ")
   1.303 -                       .append(mapper.pop())
   1.304 -                       .append(");");
   1.305 +                    out.append(mapper.getL(1)).append(" = ")
   1.306 +                       .append("Math.floor(").append(mapper.getL(1))
   1.307 +                       .append(" / ").append(mapper.popL()).append(");");
   1.308                      break;
   1.309                  case opc_fdiv:
   1.310 +                    out.append(mapper.getF(1)).append(" /= ")
   1.311 +                       .append(mapper.popF()).append(';');
   1.312 +                    break;
   1.313                  case opc_ddiv:
   1.314 -                    out.append(mapper.get(1)).append(" /= ")
   1.315 -                       .append(mapper.pop()).append(';');
   1.316 +                    out.append(mapper.getD(1)).append(" /= ")
   1.317 +                       .append(mapper.popD()).append(';');
   1.318                      break;
   1.319                  case opc_irem:
   1.320 +                    out.append(mapper.getI(1)).append(" %= ")
   1.321 +                       .append(mapper.popI()).append(';');
   1.322 +                    break;
   1.323                  case opc_lrem:
   1.324 +                    out.append(mapper.getL(1)).append(" %= ")
   1.325 +                       .append(mapper.popL()).append(';');
   1.326 +                    break;
   1.327                  case opc_frem:
   1.328 +                    out.append(mapper.getF(1)).append(" %= ")
   1.329 +                       .append(mapper.popF()).append(';');
   1.330 +                    break;
   1.331                  case opc_drem:
   1.332 -                    out.append(mapper.get(1)).append(" %= ")
   1.333 -                       .append(mapper.pop()).append(';');
   1.334 +                    out.append(mapper.getD(1)).append(" %= ")
   1.335 +                       .append(mapper.popD()).append(';');
   1.336                      break;
   1.337                  case opc_iand:
   1.338 +                    out.append(mapper.getI(1)).append(" &= ")
   1.339 +                       .append(mapper.popI()).append(';');
   1.340 +                    break;
   1.341                  case opc_land:
   1.342 -                    out.append(mapper.get(1)).append(" &= ")
   1.343 -                       .append(mapper.pop()).append(';');
   1.344 +                    out.append(mapper.getL(1)).append(" &= ")
   1.345 +                       .append(mapper.popL()).append(';');
   1.346                      break;
   1.347                  case opc_ior:
   1.348 +                    out.append(mapper.getI(1)).append(" |= ")
   1.349 +                       .append(mapper.popI()).append(';');
   1.350 +                    break;
   1.351                  case opc_lor:
   1.352 -                    out.append(mapper.get(1)).append(" |= ")
   1.353 -                       .append(mapper.pop()).append(';');
   1.354 +                    out.append(mapper.getL(1)).append(" |= ")
   1.355 +                       .append(mapper.popL()).append(';');
   1.356                      break;
   1.357                  case opc_ixor:
   1.358 +                    out.append(mapper.getI(1)).append(" ^= ")
   1.359 +                       .append(mapper.popI()).append(';');
   1.360 +                    break;
   1.361                  case opc_lxor:
   1.362 -                    out.append(mapper.get(1)).append(" ^= ")
   1.363 -                       .append(mapper.pop()).append(';');
   1.364 +                    out.append(mapper.getL(1)).append(" ^= ")
   1.365 +                       .append(mapper.popL()).append(';');
   1.366                      break;
   1.367                  case opc_ineg:
   1.368 +                    out.append(mapper.getI(0)).append(" = -")
   1.369 +                       .append(mapper.getI(0)).append(';');
   1.370 +                    break;
   1.371                  case opc_lneg:
   1.372 +                    out.append(mapper.getL(0)).append(" = -")
   1.373 +                       .append(mapper.getL(0)).append(';');
   1.374 +                    break;
   1.375                  case opc_fneg:
   1.376 +                    out.append(mapper.getF(0)).append(" = -")
   1.377 +                       .append(mapper.getF(0)).append(';');
   1.378 +                    break;
   1.379                  case opc_dneg:
   1.380 -                    out.append(mapper.get(0)).append(" = -")
   1.381 -                       .append(mapper.get(0)).append(';');
   1.382 +                    out.append(mapper.getD(0)).append(" = -")
   1.383 +                       .append(mapper.getD(0)).append(';');
   1.384                      break;
   1.385                  case opc_ishl:
   1.386 +                    out.append(mapper.getI(1)).append(" <<= ")
   1.387 +                       .append(mapper.popI()).append(';');
   1.388 +                    break;
   1.389                  case opc_lshl:
   1.390 -                    out.append(mapper.get(1)).append(" <<= ")
   1.391 -                       .append(mapper.pop()).append(';');
   1.392 +                    out.append(mapper.getL(1)).append(" <<= ")
   1.393 +                       .append(mapper.popI()).append(';');
   1.394                      break;
   1.395                  case opc_ishr:
   1.396 +                    out.append(mapper.getI(1)).append(" >>= ")
   1.397 +                       .append(mapper.popI()).append(';');
   1.398 +                    break;
   1.399                  case opc_lshr:
   1.400 -                    out.append(mapper.get(1)).append(" >>= ")
   1.401 -                       .append(mapper.pop()).append(';');
   1.402 +                    out.append(mapper.getL(1)).append(" >>= ")
   1.403 +                       .append(mapper.popI()).append(';');
   1.404                      break;
   1.405                  case opc_iushr:
   1.406 +                    out.append(mapper.getI(1)).append(" >>>= ")
   1.407 +                       .append(mapper.popI()).append(';');
   1.408 +                    break;
   1.409                  case opc_lushr:
   1.410 -                    out.append(mapper.get(1)).append(" >>>= ")
   1.411 -                       .append(mapper.pop()).append(';');
   1.412 +                    out.append(mapper.getL(1)).append(" >>>= ")
   1.413 +                       .append(mapper.popI()).append(';');
   1.414                      break;
   1.415                  case opc_iinc: {
   1.416                      final int varIndx = readByte(byteCodes, ++i);
   1.417 @@ -436,75 +607,149 @@
   1.418                      out.append("return;");
   1.419                      break;
   1.420                  case opc_ireturn:
   1.421 +                    out.append("return ").append(mapper.popI()).append(';');
   1.422 +                    break;
   1.423                  case opc_lreturn:
   1.424 +                    out.append("return ").append(mapper.popL()).append(';');
   1.425 +                    break;
   1.426                  case opc_freturn:
   1.427 +                    out.append("return ").append(mapper.popF()).append(';');
   1.428 +                    break;
   1.429                  case opc_dreturn:
   1.430 +                    out.append("return ").append(mapper.popD()).append(';');
   1.431 +                    break;
   1.432                  case opc_areturn:
   1.433 -                    out.append("return ").append(mapper.pop()).append(';');
   1.434 +                    out.append("return ").append(mapper.popA()).append(';');
   1.435                      break;
   1.436 -                case opc_i2l:
   1.437 -                case opc_i2f:
   1.438 -                case opc_i2d:
   1.439 -                case opc_l2i:
   1.440 +                case opc_i2l: {
   1.441 +                    final Variable v = mapper.popI();
   1.442 +                    out.append(mapper.pushL()).append(" = ")
   1.443 +                       .append(v).append(';');
   1.444 +                    break;
   1.445 +                }
   1.446 +                case opc_i2f: {
   1.447 +                    final Variable v = mapper.popI();
   1.448 +                    out.append(mapper.pushF()).append(" = ")
   1.449 +                       .append(v).append(';');
   1.450 +                    break;
   1.451 +                }
   1.452 +                case opc_i2d: {
   1.453 +                    final Variable v = mapper.popI();
   1.454 +                    out.append(mapper.pushD()).append(" = ")
   1.455 +                       .append(v).append(';');
   1.456 +                    break;
   1.457 +                }
   1.458 +                case opc_l2i: {
   1.459 +                    final Variable v = mapper.popL();
   1.460 +                    out.append(mapper.pushI()).append(" = ")
   1.461 +                       .append(v).append(';');
   1.462 +                    break;
   1.463 +                }
   1.464                      // max int check?
   1.465 -                case opc_l2f:
   1.466 -                case opc_l2d:
   1.467 -                case opc_f2d:
   1.468 -                case opc_d2f:
   1.469 -                    out.append("/* number conversion */");
   1.470 +                case opc_l2f: {
   1.471 +                    final Variable v = mapper.popL();
   1.472 +                    out.append(mapper.pushF()).append(" = ")
   1.473 +                       .append(v).append(';');
   1.474                      break;
   1.475 -                case opc_f2i:
   1.476 -                case opc_f2l:
   1.477 -                case opc_d2i:
   1.478 -                case opc_d2l:
   1.479 -                    out.append(mapper.get(0))
   1.480 -                       .append(" = Math.floor(")
   1.481 -                       .append(mapper.get(0))
   1.482 -                       .append(");");
   1.483 +                }
   1.484 +                case opc_l2d: {
   1.485 +                    final Variable v = mapper.popL();
   1.486 +                    out.append(mapper.pushD()).append(" = ")
   1.487 +                       .append(v).append(';');
   1.488                      break;
   1.489 +                }
   1.490 +                case opc_f2d: {
   1.491 +                    final Variable v = mapper.popF();
   1.492 +                    out.append(mapper.pushD()).append(" = ")
   1.493 +                       .append(v).append(';');
   1.494 +                    break;
   1.495 +                }
   1.496 +                case opc_d2f: {
   1.497 +                    final Variable v = mapper.popD();
   1.498 +                    out.append(mapper.pushF()).append(" = ")
   1.499 +                       .append(v).append(';');
   1.500 +                    break;
   1.501 +                }
   1.502 +                case opc_f2i: {
   1.503 +                    final Variable v = mapper.popF();
   1.504 +                    out.append(mapper.pushI()).append(" = ")
   1.505 +                       .append("Math.floor(").append(v).append(");");
   1.506 +                    break;
   1.507 +                }
   1.508 +                case opc_f2l: {
   1.509 +                    final Variable v = mapper.popF();
   1.510 +                    out.append(mapper.pushL()).append(" = ")
   1.511 +                       .append("Math.floor(").append(v).append(");");
   1.512 +                    break;
   1.513 +                }
   1.514 +                case opc_d2i: {
   1.515 +                    final Variable v = mapper.popD();
   1.516 +                    out.append(mapper.pushI()).append(" = ")
   1.517 +                       .append("Math.floor(").append(v).append(");");
   1.518 +                    break;
   1.519 +                }
   1.520 +                case opc_d2l: {
   1.521 +                    final Variable v = mapper.popD();
   1.522 +                    out.append(mapper.pushL()).append(" = ")
   1.523 +                       .append("Math.floor(").append(v).append(");");
   1.524 +                    break;
   1.525 +                }
   1.526                  case opc_i2b:
   1.527                  case opc_i2c:
   1.528                  case opc_i2s:
   1.529                      out.append("/* number conversion */");
   1.530                      break;
   1.531                  case opc_aconst_null:
   1.532 -                    out.append(mapper.push()).append(" = null;");
   1.533 +                    out.append(mapper.pushA()).append(" = null;");
   1.534                      break;
   1.535                  case opc_iconst_m1:
   1.536 -                    out.append(mapper.push()).append(" = -1;");
   1.537 +                    out.append(mapper.pushI()).append(" = -1;");
   1.538                      break;
   1.539                  case opc_iconst_0:
   1.540 +                    out.append(mapper.pushI()).append(" = 0;");
   1.541 +                    break;
   1.542                  case opc_dconst_0:
   1.543 +                    out.append(mapper.pushD()).append(" = 0;");
   1.544 +                    break;
   1.545                  case opc_lconst_0:
   1.546 +                    out.append(mapper.pushL()).append(" = 0;");
   1.547 +                    break;
   1.548                  case opc_fconst_0:
   1.549 -                    out.append(mapper.push()).append(" = 0;");
   1.550 +                    out.append(mapper.pushF()).append(" = 0;");
   1.551                      break;
   1.552                  case opc_iconst_1:
   1.553 +                    out.append(mapper.pushI()).append(" = 1;");
   1.554 +                    break;
   1.555                  case opc_lconst_1:
   1.556 +                    out.append(mapper.pushL()).append(" = 1;");
   1.557 +                    break;
   1.558                  case opc_fconst_1:
   1.559 +                    out.append(mapper.pushF()).append(" = 1;");
   1.560 +                    break;
   1.561                  case opc_dconst_1:
   1.562 -                    out.append(mapper.push()).append(" = 1;");
   1.563 +                    out.append(mapper.pushD()).append(" = 1;");
   1.564                      break;
   1.565                  case opc_iconst_2:
   1.566 +                    out.append(mapper.pushI()).append(" = 2;");
   1.567 +                    break;
   1.568                  case opc_fconst_2:
   1.569 -                    out.append(mapper.push()).append(" = 2;");
   1.570 +                    out.append(mapper.pushF()).append(" = 2;");
   1.571                      break;
   1.572                  case opc_iconst_3:
   1.573 -                    out.append(mapper.push()).append(" = 3;");
   1.574 +                    out.append(mapper.pushI()).append(" = 3;");
   1.575                      break;
   1.576                  case opc_iconst_4:
   1.577 -                    out.append(mapper.push()).append(" = 4;");
   1.578 +                    out.append(mapper.pushI()).append(" = 4;");
   1.579                      break;
   1.580                  case opc_iconst_5:
   1.581 -                    out.append(mapper.push()).append(" = 5;");
   1.582 +                    out.append(mapper.pushI()).append(" = 5;");
   1.583                      break;
   1.584                  case opc_ldc: {
   1.585                      int indx = readByte(byteCodes, ++i);
   1.586                      String v = encodeConstant(indx);
   1.587 -                    out.append(mapper.push())
   1.588 -                       .append(" = ")
   1.589 -                       .append(v)
   1.590 -                       .append(';');
   1.591 +                    int type = constantToVariableType(jc.getTag(indx));
   1.592 +                    out.append(mapper.pushT(type)).append(" = ")
   1.593 +                       .append(v).append(';');
   1.594                      break;
   1.595                  }
   1.596                  case opc_ldc_w:
   1.597 @@ -512,44 +757,38 @@
   1.598                      int indx = readIntArg(byteCodes, i);
   1.599                      i += 2;
   1.600                      String v = encodeConstant(indx);
   1.601 -                    out.append(mapper.push())
   1.602 -                       .append(" = ")
   1.603 -                       .append(v)
   1.604 -                       .append(';');
   1.605 +                    int type = constantToVariableType(jc.getTag(indx));
   1.606 +                    out.append(mapper.pushT(type)).append(" = ")
   1.607 +                       .append(v).append(';');
   1.608                      break;
   1.609                  }
   1.610                  case opc_lcmp:
   1.611 +                    generateCmp(mapper.popL(), mapper.popL(), mapper.pushI());
   1.612 +                    break;
   1.613                  case opc_fcmpl:
   1.614                  case opc_fcmpg:
   1.615 +                    generateCmp(mapper.popF(), mapper.popF(), mapper.pushI());
   1.616 +                    break;
   1.617                  case opc_dcmpl:
   1.618 -                case opc_dcmpg: {
   1.619 -                    out.append(mapper.get(1))
   1.620 -                       .append(" = (")
   1.621 -                       .append(mapper.get(1))
   1.622 -                       .append(" == ")
   1.623 -                       .append(mapper.get(0))
   1.624 -                       .append(") ? 0 : ((")
   1.625 -                       .append(mapper.get(1))
   1.626 -                       .append(" < ")
   1.627 -                       .append(mapper.get(0))
   1.628 -                       .append(") ? -1 : 1);");
   1.629 -
   1.630 -                    mapper.pop(1);
   1.631 +                case opc_dcmpg:
   1.632 +                    generateCmp(mapper.popD(), mapper.popD(), mapper.pushI());
   1.633                      break;
   1.634 -                }
   1.635                  case opc_if_acmpeq:
   1.636 -                    i = generateIf(byteCodes, i, mapper, "===");
   1.637 +                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   1.638 +                                   "===");
   1.639                      break;
   1.640                  case opc_if_acmpne:
   1.641 -                    i = generateIf(byteCodes, i, mapper, "!=");
   1.642 +                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   1.643 +                                   "!=");
   1.644                      break;
   1.645                  case opc_if_icmpeq: {
   1.646 -                    i = generateIf(byteCodes, i, mapper, "==");
   1.647 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.648 +                                   "==");
   1.649                      break;
   1.650                  }
   1.651                  case opc_ifeq: {
   1.652                      int indx = i + readIntArg(byteCodes, i);
   1.653 -                    out.append("if (").append(mapper.pop())
   1.654 +                    out.append("if (").append(mapper.popI())
   1.655                                        .append(" == 0) { gt = " + indx);
   1.656                      out.append("; continue; }");
   1.657                      i += 2;
   1.658 @@ -557,7 +796,7 @@
   1.659                  }
   1.660                  case opc_ifne: {
   1.661                      int indx = i + readIntArg(byteCodes, i);
   1.662 -                    out.append("if (").append(mapper.pop())
   1.663 +                    out.append("if (").append(mapper.popI())
   1.664                                        .append(" != 0) { gt = " + indx);
   1.665                      out.append("; continue; }");
   1.666                      i += 2;
   1.667 @@ -565,7 +804,7 @@
   1.668                  }
   1.669                  case opc_iflt: {
   1.670                      int indx = i + readIntArg(byteCodes, i);
   1.671 -                    out.append("if (").append(mapper.pop())
   1.672 +                    out.append("if (").append(mapper.popI())
   1.673                                        .append(" < 0) { gt = " + indx);
   1.674                      out.append("; continue; }");
   1.675                      i += 2;
   1.676 @@ -573,7 +812,7 @@
   1.677                  }
   1.678                  case opc_ifle: {
   1.679                      int indx = i + readIntArg(byteCodes, i);
   1.680 -                    out.append("if (").append(mapper.pop())
   1.681 +                    out.append("if (").append(mapper.popI())
   1.682                                        .append(" <= 0) { gt = " + indx);
   1.683                      out.append("; continue; }");
   1.684                      i += 2;
   1.685 @@ -581,7 +820,7 @@
   1.686                  }
   1.687                  case opc_ifgt: {
   1.688                      int indx = i + readIntArg(byteCodes, i);
   1.689 -                    out.append("if (").append(mapper.pop())
   1.690 +                    out.append("if (").append(mapper.popI())
   1.691                                        .append(" > 0) { gt = " + indx);
   1.692                      out.append("; continue; }");
   1.693                      i += 2;
   1.694 @@ -589,7 +828,7 @@
   1.695                  }
   1.696                  case opc_ifge: {
   1.697                      int indx = i + readIntArg(byteCodes, i);
   1.698 -                    out.append("if (").append(mapper.pop())
   1.699 +                    out.append("if (").append(mapper.popI())
   1.700                                        .append(" >= 0) { gt = " + indx);
   1.701                      out.append("; continue; }");
   1.702                      i += 2;
   1.703 @@ -597,7 +836,7 @@
   1.704                  }
   1.705                  case opc_ifnonnull: {
   1.706                      int indx = i + readIntArg(byteCodes, i);
   1.707 -                    out.append("if (").append(mapper.pop())
   1.708 +                    out.append("if (").append(mapper.popA())
   1.709                                        .append(" !== null) { gt = " + indx);
   1.710                      out.append("; continue; }");
   1.711                      i += 2;
   1.712 @@ -605,26 +844,31 @@
   1.713                  }
   1.714                  case opc_ifnull: {
   1.715                      int indx = i + readIntArg(byteCodes, i);
   1.716 -                    out.append("if (").append(mapper.pop())
   1.717 +                    out.append("if (").append(mapper.popA())
   1.718                                        .append(" === null) { gt = " + indx);
   1.719                      out.append("; continue; }");
   1.720                      i += 2;
   1.721                      break;
   1.722                  }
   1.723                  case opc_if_icmpne:
   1.724 -                    i = generateIf(byteCodes, i, mapper, "!=");
   1.725 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.726 +                                   "!=");
   1.727                      break;
   1.728                  case opc_if_icmplt:
   1.729 -                    i = generateIf(byteCodes, i, mapper, "<");
   1.730 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.731 +                                   "<");
   1.732                      break;
   1.733                  case opc_if_icmple:
   1.734 -                    i = generateIf(byteCodes, i, mapper, "<=");
   1.735 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.736 +                                   "<=");
   1.737                      break;
   1.738                  case opc_if_icmpgt:
   1.739 -                    i = generateIf(byteCodes, i, mapper, ">");
   1.740 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.741 +                                   ">");
   1.742                      break;
   1.743                  case opc_if_icmpge:
   1.744 -                    i = generateIf(byteCodes, i, mapper, ">=");
   1.745 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   1.746 +                                   ">=");
   1.747                      break;
   1.748                  case opc_goto: {
   1.749                      int indx = i + readIntArg(byteCodes, i);
   1.750 @@ -638,7 +882,7 @@
   1.751                      table += 4;
   1.752                      int n = readInt4(byteCodes, table);
   1.753                      table += 4;
   1.754 -                    out.append("switch (").append(mapper.pop()).append(") {\n");
   1.755 +                    out.append("switch (").append(mapper.popI()).append(") {\n");
   1.756                      while (n-- > 0) {
   1.757                          int cnstnt = readInt4(byteCodes, table);
   1.758                          table += 4;
   1.759 @@ -658,7 +902,7 @@
   1.760                      table += 4;
   1.761                      int high = readInt4(byteCodes, table);
   1.762                      table += 4;
   1.763 -                    out.append("switch (").append(mapper.pop()).append(") {\n");
   1.764 +                    out.append("switch (").append(mapper.popI()).append(") {\n");
   1.765                      while (low <= high) {
   1.766                          int offset = i + readInt4(byteCodes, table);
   1.767                          table += 4;
   1.768 @@ -685,7 +929,7 @@
   1.769                  case opc_new: {
   1.770                      int indx = readIntArg(byteCodes, i);
   1.771                      String ci = jc.getClassName(indx);
   1.772 -                    out.append(mapper.push()).append(" = ");
   1.773 +                    out.append(mapper.pushA()).append(" = ");
   1.774                      out.append("new ").append(ci.replace('/','_'));
   1.775                      out.append(';');
   1.776                      addReference(ci);
   1.777 @@ -694,28 +938,26 @@
   1.778                  }
   1.779                  case opc_newarray: {
   1.780                      ++i; // skip type of array
   1.781 -                    out.append(mapper.get(0))
   1.782 -                       .append(" = new Array(")
   1.783 -                       .append(mapper.get(0))
   1.784 -                       .append(").fillNulls();");
   1.785 +                    final Variable v = mapper.popI();
   1.786 +                    out.append(mapper.pushA()).append(" = ")
   1.787 +                       .append("new Array(").append(v).append(").fillNulls();");
   1.788                      break;
   1.789                  }
   1.790                  case opc_anewarray: {
   1.791                      i += 2; // skip type of array
   1.792 -                    out.append(mapper.get(0))
   1.793 -                       .append(" = new Array(")
   1.794 -                       .append(mapper.get(0))
   1.795 -                       .append(").fillNulls();");
   1.796 +                    final Variable v = mapper.popI();
   1.797 +                    out.append(mapper.pushA()).append(" = ")
   1.798 +                       .append("new Array(").append(v).append(").fillNulls();");
   1.799                      break;
   1.800                  }
   1.801                  case opc_multianewarray: {
   1.802                      i += 2;
   1.803                      int dim = readByte(byteCodes, ++i);
   1.804 -                    out.append("{ var a0 = new Array(").append(mapper.pop())
   1.805 +                    out.append("{ var a0 = new Array(").append(mapper.popI())
   1.806                         .append(").fillNulls();");
   1.807                      for (int d = 1; d < dim; d++) {
   1.808                          out.append("\n  var l" + d).append(" = ")
   1.809 -                           .append(mapper.pop()).append(';');
   1.810 +                           .append(mapper.popI()).append(';');
   1.811                          out.append("\n  for (var i" + d).append (" = 0; i" + d).
   1.812                              append(" < a" + (d - 1)).
   1.813                              append(".length; i" + d).append("++) {");
   1.814 @@ -727,41 +969,94 @@
   1.815                      for (int d = 1; d < dim; d++) {
   1.816                          out.append("\n  }");
   1.817                      }
   1.818 -                    out.append("\n").append(mapper.push()).append(" = a0; }");
   1.819 +                    out.append("\n").append(mapper.pushA()).append(" = a0; }");
   1.820                      break;
   1.821                  }
   1.822 -                case opc_arraylength:
   1.823 -                    out.append(mapper.get(0)).append(" = ")
   1.824 -                       .append(mapper.get(0)).append(".length;");
   1.825 +                case opc_arraylength: {
   1.826 +                    final Variable v = mapper.popA();
   1.827 +                    out.append(mapper.pushI()).append(" = ")
   1.828 +                       .append(v).append(".length;");
   1.829                      break;
   1.830 +                }
   1.831 +                case opc_lastore: {
   1.832 +                    out.append(mapper.getA(2)).append('[')
   1.833 +                                              .append(mapper.getI(1))
   1.834 +                                              .append(']')
   1.835 +                       .append(" = ").append(mapper.getL(0)).append(';');
   1.836 +                    mapper.pop(3);
   1.837 +                    break;
   1.838 +                }
   1.839 +                case opc_fastore: {
   1.840 +                    out.append(mapper.getA(2)).append('[')
   1.841 +                                              .append(mapper.getI(1))
   1.842 +                                              .append(']')
   1.843 +                       .append(" = ").append(mapper.getF(0)).append(';');
   1.844 +                    mapper.pop(3);
   1.845 +                    break;
   1.846 +                }
   1.847 +                case opc_dastore: {
   1.848 +                    out.append(mapper.getA(2)).append('[')
   1.849 +                                              .append(mapper.getI(1))
   1.850 +                                              .append(']')
   1.851 +                       .append(" = ").append(mapper.getD(0)).append(';');
   1.852 +                    mapper.pop(3);
   1.853 +                    break;
   1.854 +                }
   1.855 +                case opc_aastore: {
   1.856 +                    out.append(mapper.getA(2)).append('[')
   1.857 +                                              .append(mapper.getI(1))
   1.858 +                                              .append(']')
   1.859 +                       .append(" = ").append(mapper.getA(0)).append(';');
   1.860 +                    mapper.pop(3);
   1.861 +                    break;
   1.862 +                }
   1.863                  case opc_iastore:
   1.864 -                case opc_lastore:
   1.865 -                case opc_fastore:
   1.866 -                case opc_dastore:
   1.867 -                case opc_aastore:
   1.868                  case opc_bastore:
   1.869                  case opc_castore:
   1.870                  case opc_sastore: {
   1.871 -                    out.append(mapper.get(2))
   1.872 -                       .append('[').append(mapper.get(1)).append(']')
   1.873 -                       .append(" = ")
   1.874 -                       .append(mapper.get(0))
   1.875 -                       .append(';');
   1.876 +                    out.append(mapper.getA(2)).append('[')
   1.877 +                                              .append(mapper.getI(1))
   1.878 +                                              .append(']')
   1.879 +                       .append(" = ").append(mapper.getI(0)).append(';');
   1.880                      mapper.pop(3);
   1.881                      break;
   1.882                  }
   1.883 +                case opc_laload: {
   1.884 +                    final Variable vidx = mapper.popI();
   1.885 +                    final Variable varr = mapper.popA();
   1.886 +                    out.append(mapper.pushL()).append(" = ")
   1.887 +                       .append(varr).append('[').append(vidx).append("];");
   1.888 +                    break;
   1.889 +                }
   1.890 +                case opc_faload: {
   1.891 +                    final Variable vidx = mapper.popI();
   1.892 +                    final Variable varr = mapper.popA();
   1.893 +                    out.append(mapper.pushF()).append(" = ")
   1.894 +                       .append(varr).append('[').append(vidx).append("];");
   1.895 +                    break;
   1.896 +                }
   1.897 +                case opc_daload: {
   1.898 +                    final Variable vidx = mapper.popI();
   1.899 +                    final Variable varr = mapper.popA();
   1.900 +                    out.append(mapper.pushD()).append(" = ")
   1.901 +                       .append(varr).append('[').append(vidx).append("];");
   1.902 +                    break;
   1.903 +                }
   1.904 +                case opc_aaload: {
   1.905 +                    final Variable vidx = mapper.popI();
   1.906 +                    final Variable varr = mapper.popA();
   1.907 +                    out.append(mapper.pushA()).append(" = ")
   1.908 +                       .append(varr).append('[').append(vidx).append("];");
   1.909 +                    break;
   1.910 +                }
   1.911                  case opc_iaload:
   1.912 -                case opc_laload:
   1.913 -                case opc_faload:
   1.914 -                case opc_daload:
   1.915 -                case opc_aaload:
   1.916                  case opc_baload:
   1.917                  case opc_caload:
   1.918                  case opc_saload: {
   1.919 -                    out.append(mapper.get(1))
   1.920 -                       .append(" = ")
   1.921 -                       .append(mapper.get(1))
   1.922 -                       .append('[').append(mapper.pop()).append("];");
   1.923 +                    final Variable vidx = mapper.popI();
   1.924 +                    final Variable varr = mapper.popA();
   1.925 +                    out.append(mapper.pushI()).append(" = ")
   1.926 +                       .append(varr).append('[').append(vidx).append("];");
   1.927                      break;
   1.928                  }
   1.929                  case opc_pop:
   1.930 @@ -769,38 +1064,80 @@
   1.931                      mapper.pop(1);
   1.932                      out.append("/* pop */");
   1.933                      break;
   1.934 -                case opc_dup:
   1.935 -                    out.append(mapper.push()).append(" = ")
   1.936 -                       .append(mapper.get(1)).append(';');
   1.937 +                case opc_dup: {
   1.938 +                    final Variable v = mapper.get(0);
   1.939 +                    out.append(mapper.pushT(v.getType())).append(" = ")
   1.940 +                       .append(v).append(';');
   1.941                      break;
   1.942 -                case opc_dup_x1:
   1.943 +                }
   1.944 +                case opc_dup2: {
   1.945 +                    if (mapper.get(0).isCategory2()) {
   1.946 +                        final Variable v = mapper.get(0);
   1.947 +                        out.append(mapper.pushT(v.getType())).append(" = ")
   1.948 +                           .append(v).append(';');
   1.949 +                    } else {
   1.950 +                        final Variable v1 = mapper.get(0);
   1.951 +                        final Variable v2 = mapper.get(1);
   1.952 +                        out.append("{ ");
   1.953 +                        out.append(mapper.pushT(v2.getType())).append(" = ")
   1.954 +                           .append(v2).append("; ");
   1.955 +                        out.append(mapper.pushT(v1.getType())).append(" = ")
   1.956 +                           .append(v1).append("; ");
   1.957 +                        out.append('}');
   1.958 +                    }
   1.959 +                    break;
   1.960 +                }
   1.961 +                case opc_dup_x1: {
   1.962 +                    final Variable vi1 = mapper.pop();
   1.963 +                    final Variable vi2 = mapper.pop();
   1.964 +                    final Variable vo3 = mapper.pushT(vi1.getType());
   1.965 +                    final Variable vo2 = mapper.pushT(vi2.getType());
   1.966 +                    final Variable vo1 = mapper.pushT(vi1.getType());
   1.967 +
   1.968                      out.append("{ ");
   1.969 -                    out.append(mapper.push()).append(" = ")
   1.970 -                       .append(mapper.get(1)).append("; ");
   1.971 -                    out.append(mapper.get(1)).append(" = ")
   1.972 -                       .append(mapper.get(2)).append("; ");
   1.973 -                    out.append(mapper.get(2)).append(" = ")
   1.974 -                       .append(mapper.get(0)).append("; ");
   1.975 +                    out.append(vo1).append(" = ").append(vi1).append("; ");
   1.976 +                    out.append(vo2).append(" = ").append(vi2).append("; ");
   1.977 +                    out.append(vo3).append(" = ").append(vo1).append("; ");
   1.978                      out.append('}');
   1.979                      break;
   1.980 -                case opc_dup_x2:
   1.981 -                    out.append("{ ");
   1.982 -                    out.append(mapper.push()).append(" = ")
   1.983 -                       .append(mapper.get(1)).append("; ");
   1.984 -                    out.append(mapper.get(1)).append(" = ")
   1.985 -                       .append(mapper.get(2)).append("; ");
   1.986 -                    out.append(mapper.get(2)).append(" = ")
   1.987 -                       .append(mapper.get(3)).append("; ");
   1.988 -                    out.append(mapper.get(3)).append(" = ")
   1.989 -                       .append(mapper.get(0)).append("; ");
   1.990 -                    out.append('}');
   1.991 +                }
   1.992 +                case opc_dup_x2: {
   1.993 +                    if (mapper.get(1).isCategory2()) {
   1.994 +                        final Variable vi1 = mapper.pop();
   1.995 +                        final Variable vi2 = mapper.pop();
   1.996 +                        final Variable vo3 = mapper.pushT(vi1.getType());
   1.997 +                        final Variable vo2 = mapper.pushT(vi2.getType());
   1.998 +                        final Variable vo1 = mapper.pushT(vi1.getType());
   1.999 +
  1.1000 +                        out.append("{ ");
  1.1001 +                        out.append(vo1).append(" = ").append(vi1).append("; ");
  1.1002 +                        out.append(vo2).append(" = ").append(vi2).append("; ");
  1.1003 +                        out.append(vo3).append(" = ").append(vo1).append("; ");
  1.1004 +                        out.append('}');
  1.1005 +                    } else {
  1.1006 +                        final Variable vi1 = mapper.pop();
  1.1007 +                        final Variable vi2 = mapper.pop();
  1.1008 +                        final Variable vi3 = mapper.pop();
  1.1009 +                        final Variable vo4 = mapper.pushT(vi1.getType());
  1.1010 +                        final Variable vo3 = mapper.pushT(vi3.getType());
  1.1011 +                        final Variable vo2 = mapper.pushT(vi2.getType());
  1.1012 +                        final Variable vo1 = mapper.pushT(vi1.getType());
  1.1013 +
  1.1014 +                        out.append("{ ");
  1.1015 +                        out.append(vo1).append(" = ").append(vi1).append("; ");
  1.1016 +                        out.append(vo2).append(" = ").append(vi2).append("; ");
  1.1017 +                        out.append(vo3).append(" = ").append(vi3).append("; ");
  1.1018 +                        out.append(vo4).append(" = ").append(vo1).append("; ");
  1.1019 +                        out.append('}');
  1.1020 +                    }
  1.1021                      break;
  1.1022 +                }
  1.1023                  case opc_bipush:
  1.1024 -                    out.append(mapper.push()).append(" = ")
  1.1025 +                    out.append(mapper.pushI()).append(" = ")
  1.1026                         .append(Integer.toString(byteCodes[++i])).append(';');
  1.1027                      break;
  1.1028                  case opc_sipush:
  1.1029 -                    out.append(mapper.push()).append(" = ")
  1.1030 +                    out.append(mapper.pushI()).append(" = ")
  1.1031                         .append(Integer.toString(readIntArg(byteCodes, i)))
  1.1032                         .append(';');
  1.1033                      i += 2;
  1.1034 @@ -808,48 +1145,51 @@
  1.1035                  case opc_getfield: {
  1.1036                      int indx = readIntArg(byteCodes, i);
  1.1037                      String[] fi = jc.getFieldInfoName(indx);
  1.1038 -                    out.append(mapper.get(0)).append(" = ")
  1.1039 -                       .append(mapper.get(0)).append(".fld_")
  1.1040 -                       .append(fi[1]).append(';');
  1.1041 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  1.1042 +                    final Variable v = mapper.popA();
  1.1043 +                    out.append(mapper.pushT(type)).append(" = ")
  1.1044 +                       .append(v).append(".fld_").append(fi[1]).append(';');
  1.1045                      i += 2;
  1.1046                      break;
  1.1047                  }
  1.1048                  case opc_getstatic: {
  1.1049                      int indx = readIntArg(byteCodes, i);
  1.1050                      String[] fi = jc.getFieldInfoName(indx);
  1.1051 -                    out.append(mapper.push()).append(" = ")
  1.1052 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  1.1053 +                    out.append(mapper.pushT(type)).append(" = ")
  1.1054                         .append(fi[0].replace('/', '_'))
  1.1055                         .append('.').append(fi[1]).append(';');
  1.1056                      i += 2;
  1.1057                      addReference(fi[0]);
  1.1058                      break;
  1.1059                  }
  1.1060 -                case opc_putstatic: {
  1.1061 -                    int indx = readIntArg(byteCodes, i);
  1.1062 -                    String[] fi = jc.getFieldInfoName(indx);
  1.1063 -                    out.append(fi[0].replace('/', '_'));
  1.1064 -                    out.append('.').append(fi[1]).append(" = ")
  1.1065 -                       .append(mapper.pop()).append(';');
  1.1066 -                    i += 2;
  1.1067 -                    addReference(fi[0]);
  1.1068 -                    break;
  1.1069 -                }
  1.1070                  case opc_putfield: {
  1.1071                      int indx = readIntArg(byteCodes, i);
  1.1072                      String[] fi = jc.getFieldInfoName(indx);
  1.1073 -                    out.append(mapper.get(1)).append(".fld_").append(fi[1])
  1.1074 -                       .append(" = ")
  1.1075 -                       .append(mapper.get(0)).append(';');
  1.1076 -                    mapper.pop(2);
  1.1077 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  1.1078 +                    final Variable v = mapper.popT(type);
  1.1079 +                    out.append(mapper.popA()).append(".fld_").append(fi[1])
  1.1080 +                       .append(" = ").append(v).append(';');
  1.1081                      i += 2;
  1.1082                      break;
  1.1083                  }
  1.1084 +                case opc_putstatic: {
  1.1085 +                    int indx = readIntArg(byteCodes, i);
  1.1086 +                    String[] fi = jc.getFieldInfoName(indx);
  1.1087 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  1.1088 +                    out.append(fi[0].replace('/', '_'));
  1.1089 +                    out.append('.').append(fi[1]).append(" = ")
  1.1090 +                       .append(mapper.popT(type)).append(';');
  1.1091 +                    i += 2;
  1.1092 +                    addReference(fi[0]);
  1.1093 +                    break;
  1.1094 +                }
  1.1095                  case opc_checkcast: {
  1.1096                      int indx = readIntArg(byteCodes, i);
  1.1097                      final String type = jc.getClassName(indx);
  1.1098                      if (!type.startsWith("[")) {
  1.1099                          // no way to check arrays right now
  1.1100 -                        out.append("if (").append(mapper.get(0))
  1.1101 +                        out.append("if (").append(mapper.getA(0))
  1.1102                             .append(".$instOf_").append(type.replace('/', '_'))
  1.1103                             .append(" != 1) throw {};"); // XXX proper exception
  1.1104                      }
  1.1105 @@ -859,33 +1199,36 @@
  1.1106                  case opc_instanceof: {
  1.1107                      int indx = readIntArg(byteCodes, i);
  1.1108                      final String type = jc.getClassName(indx);
  1.1109 -                    out.append(mapper.get(0)).append(" = ")
  1.1110 -                       .append(mapper.get(0)).append(".$instOf_")
  1.1111 -                       .append(type.replace('/', '_'))
  1.1112 +                    final Variable v = mapper.popA();
  1.1113 +                    out.append(mapper.pushI()).append(" = ")
  1.1114 +                       .append(v).append(".$instOf_")
  1.1115 +                                 .append(type.replace('/', '_'))
  1.1116                         .append(" ? 1 : 0;");
  1.1117                      i += 2;
  1.1118                      break;
  1.1119                  }
  1.1120                  case opc_athrow: {
  1.1121 +                    final Variable v = mapper.popA();
  1.1122 +                    mapper.clear();
  1.1123 +
  1.1124                      out.append("{ ");
  1.1125 -                    out.append(mapper.bottom()).append(" = ")
  1.1126 -                       .append(mapper.top()).append("; ");
  1.1127 -                    out.append("throw ").append(mapper.bottom()).append("; ");
  1.1128 +                    out.append(mapper.pushA()).append(" = ")
  1.1129 +                       .append(v).append("; ");
  1.1130 +                    out.append("throw ").append(v).append("; ");
  1.1131                      out.append('}');
  1.1132  
  1.1133 -                    mapper.reset(1);
  1.1134                      break;
  1.1135                  }
  1.1136  
  1.1137                  case opc_monitorenter: {
  1.1138                      out.append("/* monitor enter */");
  1.1139 -                    mapper.pop(1);
  1.1140 +                    mapper.popA();
  1.1141                      break;
  1.1142                  }
  1.1143  
  1.1144                  case opc_monitorexit: {
  1.1145                      out.append("/* monitor exit */");
  1.1146 -                    mapper.pop(1);
  1.1147 +                    mapper.popA();
  1.1148                      break;
  1.1149                  }
  1.1150  
  1.1151 @@ -903,22 +1246,28 @@
  1.1152              out.append("\n");
  1.1153          }
  1.1154          out.append("  }\n");
  1.1155 -
  1.1156 -        if (mapper.getMaxStackSize() > maxStack) {
  1.1157 -            throw new IllegalStateException("Incorrect stack usage");
  1.1158 -        }
  1.1159      }
  1.1160  
  1.1161 -    private int generateIf(byte[] byteCodes, int i, final StackToVariableMapper mapper, final String test) throws IOException {
  1.1162 +    private int generateIf(byte[] byteCodes, int i,
  1.1163 +                           final Variable v2, final Variable v1,
  1.1164 +                           final String test) throws IOException {
  1.1165          int indx = i + readIntArg(byteCodes, i);
  1.1166 -        out.append("if (").append(mapper.get(1))
  1.1167 +        out.append("if (").append(v1)
  1.1168             .append(' ').append(test).append(' ')
  1.1169 -           .append(mapper.get(0)).append(") { gt = " + indx)
  1.1170 +           .append(v2).append(") { gt = " + indx)
  1.1171             .append("; continue; }");
  1.1172 -        mapper.pop(2);
  1.1173          return i + 2;
  1.1174      }
  1.1175  
  1.1176 +    private void generateCmp(Variable v2, Variable v1, Variable vr)
  1.1177 +            throws IOException {
  1.1178 +        out.append(vr).append(" = ")
  1.1179 +           .append('(').append(v1).append(" == ").append(v2).append(')')
  1.1180 +           .append(" ? 0")
  1.1181 +           .append(" : ((").append(v1).append(" < ").append(v2).append(')')
  1.1182 +           .append(" ? -1 : 1);");
  1.1183 +    }
  1.1184 +
  1.1185      private int readIntArg(byte[] byteCodes, int offsetInstruction) {
  1.1186          final int indxHi = byteCodes[offsetInstruction + 1] << 8;
  1.1187          final int indxLo = byteCodes[offsetInstruction + 2];
  1.1188 @@ -935,7 +1284,7 @@
  1.1189          return byteCodes[offsetInstruction] & 0xff;
  1.1190      }
  1.1191      
  1.1192 -    private static void countArgs(String descriptor, boolean[] hasReturnType, StringBuilder sig, StringBuilder cnt) {
  1.1193 +    private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
  1.1194          int i = 0;
  1.1195          Boolean count = null;
  1.1196          boolean array = false;
  1.1197 @@ -971,17 +1320,19 @@
  1.1198                              cnt.append('0');
  1.1199                          }
  1.1200                      } else {
  1.1201 -                        hasReturnType[0] = true;
  1.1202                          sig.insert(firstPos, ch);
  1.1203                          if (array) {
  1.1204 +                            returnType[0] = '[';
  1.1205                              sig.insert(firstPos, 'A');
  1.1206 +                        } else {
  1.1207 +                            returnType[0] = ch;
  1.1208                          }
  1.1209                      }
  1.1210                      array = false;
  1.1211                      continue;
  1.1212                  case 'V': 
  1.1213                      assert !count;
  1.1214 -                    hasReturnType[0] = false;
  1.1215 +                    returnType[0] = 'V';
  1.1216                      sig.insert(firstPos, 'V');
  1.1217                      continue;
  1.1218                  case 'L':
  1.1219 @@ -999,7 +1350,7 @@
  1.1220                          if (array) {
  1.1221                              sig.insert(firstPos, 'A');
  1.1222                          }
  1.1223 -                        hasReturnType[0] = true;
  1.1224 +                        returnType[0] = 'L';
  1.1225                      }
  1.1226                      i = next + 1;
  1.1227                      continue;
  1.1228 @@ -1022,12 +1373,11 @@
  1.1229              name.append(m.getName());
  1.1230          } 
  1.1231          
  1.1232 -        boolean hasReturn[] = { false };
  1.1233 -        countArgs(findDescriptor(m.getInternalSig()), hasReturn, name, cnt);
  1.1234 +        countArgs(findDescriptor(m.getInternalSig()), new char[1], name, cnt);
  1.1235          return name.toString();
  1.1236      }
  1.1237  
  1.1238 -    private String findMethodName(String[] mi, StringBuilder cnt, boolean[] hasReturn) {
  1.1239 +    private String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) {
  1.1240          StringBuilder name = new StringBuilder();
  1.1241          String descr = mi[2];//mi.getDescriptor();
  1.1242          String nm= mi[1];
  1.1243 @@ -1036,7 +1386,7 @@
  1.1244          } else {
  1.1245              name.append(nm);
  1.1246          }
  1.1247 -        countArgs(findDescriptor(descr), hasReturn, name, cnt);
  1.1248 +        countArgs(findDescriptor(descr), returnType, name, cnt);
  1.1249          return name.toString();
  1.1250      }
  1.1251  
  1.1252 @@ -1044,15 +1394,20 @@
  1.1253      throws IOException {
  1.1254          int methodIndex = readIntArg(byteCodes, i);
  1.1255          String[] mi = jc.getFieldInfoName(methodIndex);
  1.1256 -        boolean[] hasReturn = { false };
  1.1257 +        char[] returnType = { 'V' };
  1.1258          StringBuilder cnt = new StringBuilder();
  1.1259 -        String mn = findMethodName(mi, cnt, hasReturn);
  1.1260 +        String mn = findMethodName(mi, cnt, returnType);
  1.1261  
  1.1262          final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
  1.1263 +        final Variable[] vars = new Variable[numArguments];
  1.1264  
  1.1265 -        if (hasReturn[0]) {
  1.1266 -            out.append((numArguments > 0) ? mapper.get(numArguments - 1)
  1.1267 -                                          : mapper.push()).append(" = ");
  1.1268 +        for (int j = numArguments - 1; j >= 0; --j) {
  1.1269 +            vars[j] = mapper.pop();
  1.1270 +        }
  1.1271 +
  1.1272 +        if (returnType[0] != 'V') {
  1.1273 +            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  1.1274 +               .append(" = ");
  1.1275          }
  1.1276  
  1.1277          final String in = mi[0];
  1.1278 @@ -1061,16 +1416,13 @@
  1.1279          out.append(mn);
  1.1280          out.append('(');
  1.1281          if (numArguments > 0) {
  1.1282 -            out.append(mapper.get(numArguments - 1));
  1.1283 -            for (int j = numArguments - 2; j >= 0; --j) {
  1.1284 +            out.append(vars[0]);
  1.1285 +            for (int j = 1; j < numArguments; ++j) {
  1.1286                  out.append(", ");
  1.1287 -                out.append(mapper.get(j));
  1.1288 +                out.append(vars[j]);
  1.1289              }
  1.1290          }
  1.1291          out.append(");");
  1.1292 -        if (numArguments > 0) {
  1.1293 -            mapper.pop(hasReturn[0] ? numArguments - 1 : numArguments);
  1.1294 -        }
  1.1295          i += 2;
  1.1296          addReference(in);
  1.1297          return i;
  1.1298 @@ -1079,26 +1431,31 @@
  1.1299      throws IOException {
  1.1300          int methodIndex = readIntArg(byteCodes, i);
  1.1301          String[] mi = jc.getFieldInfoName(methodIndex);
  1.1302 -        boolean[] hasReturn = { false };
  1.1303 +        char[] returnType = { 'V' };
  1.1304          StringBuilder cnt = new StringBuilder();
  1.1305 -        String mn = findMethodName(mi, cnt, hasReturn);
  1.1306 +        String mn = findMethodName(mi, cnt, returnType);
  1.1307  
  1.1308 -        final int numArguments = cnt.length();
  1.1309 +        final int numArguments = cnt.length() + 1;
  1.1310 +        final Variable[] vars = new Variable[numArguments];
  1.1311  
  1.1312 -        if (hasReturn[0]) {
  1.1313 -            out.append(mapper.get(numArguments)).append(" = ");
  1.1314 +        for (int j = numArguments - 1; j >= 0; --j) {
  1.1315 +            vars[j] = mapper.pop();
  1.1316          }
  1.1317  
  1.1318 -        out.append(mapper.get(numArguments)).append('.');
  1.1319 +        if (returnType[0] != 'V') {
  1.1320 +            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  1.1321 +               .append(" = ");
  1.1322 +        }
  1.1323 +
  1.1324 +        out.append(vars[0]).append('.');
  1.1325          out.append(mn);
  1.1326          out.append('(');
  1.1327 -        out.append(mapper.get(numArguments));
  1.1328 -        for (int j = numArguments - 1; j >= 0; --j) {
  1.1329 +        out.append(vars[0]);
  1.1330 +        for (int j = 1; j < numArguments; ++j) {
  1.1331              out.append(", ");
  1.1332 -            out.append(mapper.get(j));
  1.1333 +            out.append(vars[j]);
  1.1334          }
  1.1335          out.append(");");
  1.1336 -        mapper.pop(hasReturn[0] ? numArguments : numArguments + 1);
  1.1337          i += 2;
  1.1338          return i;
  1.1339      }
  1.1340 @@ -1236,4 +1593,54 @@
  1.1341          }
  1.1342          return " = null;";
  1.1343      }
  1.1344 +
  1.1345 +    private static int constantToVariableType(final byte constantTag) {
  1.1346 +        switch (constantTag) {
  1.1347 +            case CONSTANT_INTEGER:
  1.1348 +                return Variable.TYPE_INT;
  1.1349 +            case CONSTANT_FLOAT:
  1.1350 +                return Variable.TYPE_FLOAT;
  1.1351 +            case CONSTANT_LONG:
  1.1352 +                return Variable.TYPE_LONG;
  1.1353 +            case CONSTANT_DOUBLE:
  1.1354 +                return Variable.TYPE_DOUBLE;
  1.1355 +
  1.1356 +            case CONSTANT_CLASS:
  1.1357 +            case CONSTANT_UTF8:
  1.1358 +            case CONSTANT_UNICODE:
  1.1359 +            case CONSTANT_STRING:
  1.1360 +                return Variable.TYPE_REF;
  1.1361 +
  1.1362 +            case CONSTANT_FIELD:
  1.1363 +            case CONSTANT_METHOD:
  1.1364 +            case CONSTANT_INTERFACEMETHOD:
  1.1365 +            case CONSTANT_NAMEANDTYPE:
  1.1366 +                /* unclear how to handle for now */
  1.1367 +            default:
  1.1368 +                throw new IllegalStateException("Unhandled constant tag");
  1.1369 +        }
  1.1370 +    }
  1.1371 +
  1.1372 +    private static int fieldToVariableType(final char fieldType) {
  1.1373 +        switch (fieldType) {
  1.1374 +            case 'B':
  1.1375 +            case 'C':
  1.1376 +            case 'S':
  1.1377 +            case 'Z':
  1.1378 +            case 'I':
  1.1379 +                return Variable.TYPE_INT;
  1.1380 +            case 'J':
  1.1381 +                return Variable.TYPE_LONG;
  1.1382 +            case 'F':
  1.1383 +                return Variable.TYPE_FLOAT;
  1.1384 +            case 'D':
  1.1385 +                return Variable.TYPE_DOUBLE;
  1.1386 +            case 'L':
  1.1387 +            case '[':
  1.1388 +                return Variable.TYPE_REF;
  1.1389 +
  1.1390 +            default:
  1.1391 +                throw new IllegalStateException("Unhandled field type");
  1.1392 +        }
  1.1393 +    }
  1.1394  }