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