rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
branchclosure
changeset 861 f41a1fef7738
parent 848 677c9bcf507f
parent 843 140c739c607f
child 869 151f4ccd7673
     1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Mar 13 11:00:08 2013 +0100
     1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Mar 19 13:18:02 2013 +0100
     1.3 @@ -283,22 +283,36 @@
     1.4          TrapData[] previousTrap = null;
     1.5          boolean wide = false;
     1.6          
     1.7 -        out.append("\n  var gt = 0;\n  for(;;) switch(gt) {\n");
     1.8 +        out.append("\n  var gt = 0;\n");
     1.9 +        int openBraces = 0;
    1.10 +        int topMostLabel = 0;
    1.11          for (int i = 0; i < byteCodes.length; i++) {
    1.12              int prev = i;
    1.13              stackMapIterator.advanceTo(i);
    1.14              boolean changeInCatch = trap.advanceTo(i);
    1.15              if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
    1.16                  if (previousTrap != null) {
    1.17 -                    generateCatch(previousTrap);
    1.18 +                    generateCatch(previousTrap, i, topMostLabel);
    1.19                      previousTrap = null;
    1.20                  }
    1.21              }
    1.22              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
    1.23 +                if (i != 0) {
    1.24 +                    out.append("    }\n");
    1.25 +                }
    1.26 +                if (openBraces > 64) {
    1.27 +                    for (int c = 0; c < 64; c++) {
    1.28 +                        out.append("break;}\n");
    1.29 +                    }
    1.30 +                    openBraces = 1;
    1.31 +                    topMostLabel = i;
    1.32 +                }
    1.33 +                
    1.34                  lastStackFrame = stackMapIterator.getFrameIndex();
    1.35                  lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
    1.36                  smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
    1.37 -                out.append("    case " + i).append(": ");            
    1.38 +                out.append("    X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
    1.39 +                openBraces++;
    1.40                  changeInCatch = true;
    1.41              } else {
    1.42                  debug("    /* " + i + " */ ");
    1.43 @@ -801,133 +815,104 @@
    1.44                      break;
    1.45                  case opc_if_acmpeq:
    1.46                      i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
    1.47 -                                   "===");
    1.48 +                                   "===", topMostLabel);
    1.49                      break;
    1.50                  case opc_if_acmpne:
    1.51                      i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
    1.52 -                                   "!==");
    1.53 +                                   "!==", topMostLabel);
    1.54                      break;
    1.55                  case opc_if_icmpeq:
    1.56                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
    1.57 -                                   "==");
    1.58 +                                   "==", topMostLabel);
    1.59                      break;
    1.60                  case opc_ifeq: {
    1.61                      int indx = i + readIntArg(byteCodes, i);
    1.62 -                    emit(out, "if (@1 == 0) { gt = @2; continue; }",
    1.63 -                         smapper.popI(), Integer.toString(indx));
    1.64 +                    emitIf(out, "if (@1 == 0) ",
    1.65 +                         smapper.popI(), i, indx, topMostLabel);
    1.66                      i += 2;
    1.67                      break;
    1.68                  }
    1.69                  case opc_ifne: {
    1.70                      int indx = i + readIntArg(byteCodes, i);
    1.71 -                    emit(out, "if (@1 != 0) { gt = @2; continue; }",
    1.72 -                         smapper.popI(), Integer.toString(indx));
    1.73 +                    emitIf(out, "if (@1 != 0) ",
    1.74 +                         smapper.popI(), i, indx, topMostLabel);
    1.75                      i += 2;
    1.76                      break;
    1.77                  }
    1.78                  case opc_iflt: {
    1.79                      int indx = i + readIntArg(byteCodes, i);
    1.80 -                    emit(out, "if (@1 < 0) { gt = @2; continue; }",
    1.81 -                         smapper.popI(), Integer.toString(indx));
    1.82 +                    emitIf(out, "if (@1 < 0) ",
    1.83 +                         smapper.popI(), i, indx, topMostLabel);
    1.84                      i += 2;
    1.85                      break;
    1.86                  }
    1.87                  case opc_ifle: {
    1.88                      int indx = i + readIntArg(byteCodes, i);
    1.89 -                    emit(out, "if (@1 <= 0) { gt = @2; continue; }",
    1.90 -                         smapper.popI(), Integer.toString(indx));
    1.91 +                    emitIf(out, "if (@1 <= 0) ",
    1.92 +                         smapper.popI(), i, indx, topMostLabel);
    1.93                      i += 2;
    1.94                      break;
    1.95                  }
    1.96                  case opc_ifgt: {
    1.97                      int indx = i + readIntArg(byteCodes, i);
    1.98 -                    emit(out, "if (@1 > 0) { gt = @2; continue; }",
    1.99 -                         smapper.popI(), Integer.toString(indx));
   1.100 +                    emitIf(out, "if (@1 > 0) ",
   1.101 +                         smapper.popI(), i, indx, topMostLabel);
   1.102                      i += 2;
   1.103                      break;
   1.104                  }
   1.105                  case opc_ifge: {
   1.106                      int indx = i + readIntArg(byteCodes, i);
   1.107 -                    emit(out, "if (@1 >= 0) { gt = @2; continue; }",
   1.108 -                         smapper.popI(), Integer.toString(indx));
   1.109 +                    emitIf(out, "if (@1 >= 0) ",
   1.110 +                         smapper.popI(), i, indx, topMostLabel);
   1.111                      i += 2;
   1.112                      break;
   1.113                  }
   1.114                  case opc_ifnonnull: {
   1.115                      int indx = i + readIntArg(byteCodes, i);
   1.116 -                    emit(out, "if (@1 !== null) { gt = @2; continue; }",
   1.117 -                         smapper.popA(), Integer.toString(indx));
   1.118 +                    emitIf(out, "if (@1 !== null) ",
   1.119 +                         smapper.popA(), i, indx, topMostLabel);
   1.120                      i += 2;
   1.121                      break;
   1.122                  }
   1.123                  case opc_ifnull: {
   1.124                      int indx = i + readIntArg(byteCodes, i);
   1.125 -                    emit(out, "if (@1 === null) { gt = @2; continue; }",
   1.126 -                         smapper.popA(), Integer.toString(indx));
   1.127 +                    emitIf(out, "if (@1 === null) ",
   1.128 +                         smapper.popA(), i, indx, topMostLabel);
   1.129                      i += 2;
   1.130                      break;
   1.131                  }
   1.132                  case opc_if_icmpne:
   1.133                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   1.134 -                                   "!=");
   1.135 +                                   "!=", topMostLabel);
   1.136                      break;
   1.137                  case opc_if_icmplt:
   1.138                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   1.139 -                                   "<");
   1.140 +                                   "<", topMostLabel);
   1.141                      break;
   1.142                  case opc_if_icmple:
   1.143                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   1.144 -                                   "<=");
   1.145 +                                   "<=", topMostLabel);
   1.146                      break;
   1.147                  case opc_if_icmpgt:
   1.148                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   1.149 -                                   ">");
   1.150 +                                   ">", topMostLabel);
   1.151                      break;
   1.152                  case opc_if_icmpge:
   1.153                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   1.154 -                                   ">=");
   1.155 +                                   ">=", topMostLabel);
   1.156                      break;
   1.157                  case opc_goto: {
   1.158                      int indx = i + readIntArg(byteCodes, i);
   1.159 -                    emit(out, "gt = @1; continue;", Integer.toString(indx));
   1.160 +                    goTo(out, i, indx, topMostLabel);
   1.161                      i += 2;
   1.162                      break;
   1.163                  }
   1.164                  case opc_lookupswitch: {
   1.165 -                    int table = i / 4 * 4 + 4;
   1.166 -                    int dflt = i + readInt4(byteCodes, table);
   1.167 -                    table += 4;
   1.168 -                    int n = readInt4(byteCodes, table);
   1.169 -                    table += 4;
   1.170 -                    out.append("switch (").append(smapper.popI()).append(") {\n");
   1.171 -                    while (n-- > 0) {
   1.172 -                        int cnstnt = readInt4(byteCodes, table);
   1.173 -                        table += 4;
   1.174 -                        int offset = i + readInt4(byteCodes, table);
   1.175 -                        table += 4;
   1.176 -                        out.append("  case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
   1.177 -                    }
   1.178 -                    out.append("  default: gt = " + dflt).append("; continue;\n}");
   1.179 -                    i = table - 1;
   1.180 +                    i = generateLookupSwitch(i, byteCodes, smapper, topMostLabel);
   1.181                      break;
   1.182                  }
   1.183                  case opc_tableswitch: {
   1.184 -                    int table = i / 4 * 4 + 4;
   1.185 -                    int dflt = i + readInt4(byteCodes, table);
   1.186 -                    table += 4;
   1.187 -                    int low = readInt4(byteCodes, table);
   1.188 -                    table += 4;
   1.189 -                    int high = readInt4(byteCodes, table);
   1.190 -                    table += 4;
   1.191 -                    out.append("switch (").append(smapper.popI()).append(") {\n");
   1.192 -                    while (low <= high) {
   1.193 -                        int offset = i + readInt4(byteCodes, table);
   1.194 -                        table += 4;
   1.195 -                        out.append("  case " + low).append(": gt = " + offset).append("; continue;\n");
   1.196 -                        low++;
   1.197 -                    }
   1.198 -                    out.append("  default: gt = " + dflt).append("; continue;\n}");
   1.199 -                    i = table - 1;
   1.200 +                    i = generateTableSwitch(i, byteCodes, smapper, topMostLabel);
   1.201                      break;
   1.202                  }
   1.203                  case opc_invokeinterface: {
   1.204 @@ -954,50 +939,18 @@
   1.205                  }
   1.206                  case opc_newarray:
   1.207                      int atype = readUByte(byteCodes, ++i);
   1.208 -                    String jvmType;
   1.209 -                    switch (atype) {
   1.210 -                        case 4: jvmType = "[Z"; break;
   1.211 -                        case 5: jvmType = "[C"; break;
   1.212 -                        case 6: jvmType = "[F"; break;
   1.213 -                        case 7: jvmType = "[D"; break;
   1.214 -                        case 8: jvmType = "[B"; break;
   1.215 -                        case 9: jvmType = "[S"; break;
   1.216 -                        case 10: jvmType = "[I"; break;
   1.217 -                        case 11: jvmType = "[J"; break;
   1.218 -                        default: throw new IllegalStateException("Array type: " + atype);
   1.219 -                    }
   1.220 -                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
   1.221 -                         smapper.popI(), smapper.pushA(), jvmType);
   1.222 +                    generateNewArray(atype, smapper);
   1.223                      break;
   1.224                  case opc_anewarray: {
   1.225                      int type = readIntArg(byteCodes, i);
   1.226                      i += 2;
   1.227 -                    String typeName = jc.getClassName(type);
   1.228 -                    if (typeName.startsWith("[")) {
   1.229 -                        typeName = "[" + typeName;
   1.230 -                    } else {
   1.231 -                        typeName = "[L" + typeName + ";";
   1.232 -                    }
   1.233 -                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
   1.234 -                         smapper.popI(), smapper.pushA(), typeName);
   1.235 +                    generateANewArray(type, smapper);
   1.236                      break;
   1.237                  }
   1.238                  case opc_multianewarray: {
   1.239                      int type = readIntArg(byteCodes, i);
   1.240                      i += 2;
   1.241 -                    String typeName = jc.getClassName(type);
   1.242 -                    int dim = readUByte(byteCodes, ++i);
   1.243 -                    StringBuilder dims = new StringBuilder();
   1.244 -                    dims.append('[');
   1.245 -                    for (int d = 0; d < dim; d++) {
   1.246 -                        if (d != 0) {
   1.247 -                            dims.insert(1, ",");
   1.248 -                        }
   1.249 -                        dims.insert(1, smapper.popI());
   1.250 -                    }
   1.251 -                    dims.append(']');
   1.252 -                    emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
   1.253 -                         dims.toString(), smapper.pushA(), typeName);
   1.254 +                    i = generateMultiANewArray(type, byteCodes, i, smapper);
   1.255                      break;
   1.256                  }
   1.257                  case opc_arraylength:
   1.258 @@ -1265,32 +1218,13 @@
   1.259                  }
   1.260                  case opc_checkcast: {
   1.261                      int indx = readIntArg(byteCodes, i);
   1.262 -                    final String type = jc.getClassName(indx);
   1.263 -                    if (!type.startsWith("[")) {
   1.264 -                        emit(out,
   1.265 -                             "if (@1 !== null && !@1.$instOf_@2) throw {};",
   1.266 -                             smapper.getA(0), type.replace('/', '_'));
   1.267 -                    } else {
   1.268 -                        emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
   1.269 -                             smapper.getA(0), type
   1.270 -                        );
   1.271 -                    }
   1.272 +                    generateCheckcast(indx, smapper);
   1.273                      i += 2;
   1.274                      break;
   1.275                  }
   1.276                  case opc_instanceof: {
   1.277                      int indx = readIntArg(byteCodes, i);
   1.278 -                    final String type = jc.getClassName(indx);
   1.279 -                    if (!type.startsWith("[")) {
   1.280 -                        emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
   1.281 -                             smapper.popA(), smapper.pushI(),
   1.282 -                             type.replace('/', '_'));
   1.283 -                    } else {
   1.284 -                        emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
   1.285 -                            smapper.popA(), smapper.pushI(),
   1.286 -                            type
   1.287 -                        );
   1.288 -                    }
   1.289 +                    generateInstanceOf(indx, smapper);
   1.290                      i += 2;
   1.291                      break;
   1.292                  }
   1.293 @@ -1326,32 +1260,29 @@
   1.294                  }
   1.295              }
   1.296              if (debug(" //")) {
   1.297 -                for (int j = prev; j <= i; j++) {
   1.298 -                    out.append(" ");
   1.299 -                    final int cc = readUByte(byteCodes, j);
   1.300 -                    out.append(Integer.toString(cc));
   1.301 -                }
   1.302 +                generateByteCodeComment(prev, i, byteCodes);
   1.303              }
   1.304              out.append("\n");            
   1.305          }
   1.306          if (previousTrap != null) {
   1.307 -            generateCatch(previousTrap);
   1.308 +            generateCatch(previousTrap, byteCodes.length, topMostLabel);
   1.309          }
   1.310 -        out.append("  }\n");
   1.311 -        out.append("};");
   1.312 +        out.append("\n    }\n");
   1.313 +        while (openBraces-- > 0) {
   1.314 +            out.append('}');
   1.315 +        }
   1.316 +        out.append("\n};");
   1.317      }
   1.318  
   1.319 -    private int generateIf(byte[] byteCodes, int i,
   1.320 -                           final Variable v2, final Variable v1,
   1.321 -                           final String test) throws IOException {
   1.322 +    private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
   1.323          int indx = i + readIntArg(byteCodes, i);
   1.324          out.append("if (").append(v1)
   1.325             .append(' ').append(test).append(' ')
   1.326 -           .append(v2).append(") { gt = " + indx)
   1.327 -           .append("; continue; }");
   1.328 +           .append(v2).append(") ");
   1.329 +        goTo(out, i, indx, topMostLabel);
   1.330          return i + 2;
   1.331      }
   1.332 -
   1.333 +    
   1.334      private int readIntArg(byte[] byteCodes, int offsetInstruction) {
   1.335          final int indxHi = byteCodes[offsetInstruction + 1] << 8;
   1.336          final int indxLo = byteCodes[offsetInstruction + 2];
   1.337 @@ -1823,7 +1754,7 @@
   1.338          out.append(format, processed, length);
   1.339      }
   1.340  
   1.341 -    private void generateCatch(TrapData[] traps) throws IOException {
   1.342 +    private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException {
   1.343          out.append("} catch (e) {\n");
   1.344          int finallyPC = -1;
   1.345          for (TrapData e : traps) {
   1.346 @@ -1840,10 +1771,11 @@
   1.347                      out.append("  var stA0 = vm.java_lang_Throwable(true);");
   1.348                      out.append("  vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
   1.349                      out.append("}");
   1.350 -                    out.append("gt=" + e.handler_pc + "; continue;");
   1.351 +                    goTo(out, current, e.handler_pc, topMostLabel);
   1.352                  } else {
   1.353                      out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
   1.354 -                    out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
   1.355 +                    out.append("var stA0 = e;");
   1.356 +                    goTo(out, current, e.handler_pc, topMostLabel);
   1.357                      out.append("}\n");
   1.358                  }
   1.359              } else {
   1.360 @@ -1853,8 +1785,152 @@
   1.361          if (finallyPC == -1) {
   1.362              out.append("throw e;");
   1.363          } else {
   1.364 -            out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
   1.365 +            out.append("var stA0 = e;");
   1.366 +            goTo(out, current, finallyPC, topMostLabel);
   1.367          }
   1.368          out.append("\n}");
   1.369      }
   1.370 +
   1.371 +    private static void goTo(Appendable out, int current, int to, int canBack) throws IOException {
   1.372 +        if (to < current) {
   1.373 +            if (canBack < to) {
   1.374 +                out.append("{ gt = 0; continue X_" + to + "; }");
   1.375 +            } else {
   1.376 +                out.append("{ gt = " + to + "; continue X_0; }");
   1.377 +            }
   1.378 +        } else {
   1.379 +            out.append("{ gt = " + to + "; break IF; }");
   1.380 +        }
   1.381 +    }
   1.382 +
   1.383 +    private static void emitIf(
   1.384 +        Appendable out, String pattern, Variable param, 
   1.385 +        int current, int to, int canBack
   1.386 +    ) throws IOException {
   1.387 +        emit(out, pattern, param);
   1.388 +        goTo(out, current, to, canBack);
   1.389 +    }
   1.390 +
   1.391 +    private void generateNewArray(int atype, final StackMapper smapper) throws IOException, IllegalStateException {
   1.392 +        String jvmType;
   1.393 +        switch (atype) {
   1.394 +            case 4: jvmType = "[Z"; break;
   1.395 +            case 5: jvmType = "[C"; break;
   1.396 +            case 6: jvmType = "[F"; break;
   1.397 +            case 7: jvmType = "[D"; break;
   1.398 +            case 8: jvmType = "[B"; break;
   1.399 +            case 9: jvmType = "[S"; break;
   1.400 +            case 10: jvmType = "[I"; break;
   1.401 +            case 11: jvmType = "[J"; break;
   1.402 +            default: throw new IllegalStateException("Array type: " + atype);
   1.403 +        }
   1.404 +        emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
   1.405 +             smapper.popI(), smapper.pushA(), jvmType);
   1.406 +    }
   1.407 +
   1.408 +    private void generateANewArray(int type, final StackMapper smapper) throws IOException {
   1.409 +        String typeName = jc.getClassName(type);
   1.410 +        if (typeName.startsWith("[")) {
   1.411 +            typeName = "[" + typeName;
   1.412 +        } else {
   1.413 +            typeName = "[L" + typeName + ";";
   1.414 +        }
   1.415 +        emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
   1.416 +             smapper.popI(), smapper.pushA(), typeName);
   1.417 +    }
   1.418 +
   1.419 +    private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException {
   1.420 +        String typeName = jc.getClassName(type);
   1.421 +        int dim = readUByte(byteCodes, ++i);
   1.422 +        StringBuilder dims = new StringBuilder();
   1.423 +        dims.append('[');
   1.424 +        for (int d = 0; d < dim; d++) {
   1.425 +            if (d != 0) {
   1.426 +                dims.insert(1, ",");
   1.427 +            }
   1.428 +            dims.insert(1, smapper.popI());
   1.429 +        }
   1.430 +        dims.append(']');
   1.431 +        emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
   1.432 +             dims.toString(), smapper.pushA(), typeName);
   1.433 +        return i;
   1.434 +    }
   1.435 +
   1.436 +    private int generateTableSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
   1.437 +        int table = i / 4 * 4 + 4;
   1.438 +        int dflt = i + readInt4(byteCodes, table);
   1.439 +        table += 4;
   1.440 +        int low = readInt4(byteCodes, table);
   1.441 +        table += 4;
   1.442 +        int high = readInt4(byteCodes, table);
   1.443 +        table += 4;
   1.444 +        out.append("switch (").append(smapper.popI()).append(") {\n");
   1.445 +        while (low <= high) {
   1.446 +            int offset = i + readInt4(byteCodes, table);
   1.447 +            table += 4;
   1.448 +            out.append("  case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n');
   1.449 +            low++;
   1.450 +        }
   1.451 +        out.append("  default: ");
   1.452 +        goTo(out, i, dflt, topMostLabel);
   1.453 +        out.append("\n}");
   1.454 +        i = table - 1;
   1.455 +        return i;
   1.456 +    }
   1.457 +
   1.458 +    private int generateLookupSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
   1.459 +        int table = i / 4 * 4 + 4;
   1.460 +        int dflt = i + readInt4(byteCodes, table);
   1.461 +        table += 4;
   1.462 +        int n = readInt4(byteCodes, table);
   1.463 +        table += 4;
   1.464 +        out.append("switch (").append(smapper.popI()).append(") {\n");
   1.465 +        while (n-- > 0) {
   1.466 +            int cnstnt = readInt4(byteCodes, table);
   1.467 +            table += 4;
   1.468 +            int offset = i + readInt4(byteCodes, table);
   1.469 +            table += 4;
   1.470 +            out.append("  case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n');
   1.471 +        }
   1.472 +        out.append("  default: ");
   1.473 +        goTo(out, i, dflt, topMostLabel);
   1.474 +        out.append("\n}");
   1.475 +        i = table - 1;
   1.476 +        return i;
   1.477 +    }
   1.478 +
   1.479 +    private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
   1.480 +        final String type = jc.getClassName(indx);
   1.481 +        if (!type.startsWith("[")) {
   1.482 +            emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
   1.483 +                 smapper.popA(), smapper.pushI(),
   1.484 +                 type.replace('/', '_'));
   1.485 +        } else {
   1.486 +            emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
   1.487 +                smapper.popA(), smapper.pushI(),
   1.488 +                type
   1.489 +            );
   1.490 +        }
   1.491 +    }
   1.492 +
   1.493 +    private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
   1.494 +        final String type = jc.getClassName(indx);
   1.495 +        if (!type.startsWith("[")) {
   1.496 +            emit(out,
   1.497 +                 "if (@1 !== null && !@1.$instOf_@2) throw {};",
   1.498 +                 smapper.getA(0), type.replace('/', '_'));
   1.499 +        } else {
   1.500 +            emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
   1.501 +                 smapper.getA(0), type
   1.502 +            );
   1.503 +        }
   1.504 +    }
   1.505 +
   1.506 +    private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
   1.507 +        for (int j = prev; j <= i; j++) {
   1.508 +            out.append(" ");
   1.509 +            final int cc = readUByte(byteCodes, j);
   1.510 +            out.append(Integer.toString(cc));
   1.511 +        }
   1.512 +    }
   1.513  }