1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Apr 24 18:05:21 2014 +0200
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Apr 30 15:04:10 2014 +0200
1.3 @@ -25,14 +25,36 @@
1.4 *
1.5 * @author Jaroslav Tulach <jtulach@netbeans.org>
1.6 */
1.7 -abstract class ByteCodeToJavaScript {
1.8 +abstract class ByteCodeToJavaScript implements Appendable {
1.9 private ClassData jc;
1.10 - final Appendable out;
1.11 + private final Appendable out;
1.12 + private boolean outChanged;
1.13
1.14 protected ByteCodeToJavaScript(Appendable out) {
1.15 this.out = out;
1.16 }
1.17
1.18 + @Override
1.19 + public final Appendable append(CharSequence csq) throws IOException {
1.20 + out.append(csq);
1.21 + outChanged = true;
1.22 + return this;
1.23 + }
1.24 +
1.25 + @Override
1.26 + public final Appendable append(CharSequence csq, int start, int end) throws IOException {
1.27 + out.append(csq, start, end);
1.28 + outChanged = true;
1.29 + return this;
1.30 + }
1.31 +
1.32 + @Override
1.33 + public final Appendable append(char c) throws IOException {
1.34 + out.append(c);
1.35 + outChanged = true;
1.36 + return this;
1.37 + }
1.38 +
1.39 /* Collects additional required resources.
1.40 *
1.41 * @param internalClassName classes that were referenced and should be loaded in order the
1.42 @@ -99,7 +121,7 @@
1.43 * @throws IOException
1.44 */
1.45 boolean debug(String msg) throws IOException {
1.46 - out.append(msg);
1.47 + append(msg);
1.48 return true;
1.49 }
1.50
1.51 @@ -124,16 +146,34 @@
1.52 );
1.53 }
1.54 byte[] arrData = jc.findAnnotationData(true);
1.55 - String[] arr = findAnnotation(arrData, jc,
1.56 - "org.apidesign.bck2brwsr.core.ExtraJavaScript",
1.57 - "resource", "processByteCode"
1.58 - );
1.59 - if (arr != null) {
1.60 - if (!arr[0].isEmpty()) {
1.61 - requireScript(arr[0]);
1.62 + {
1.63 + String[] arr = findAnnotation(arrData, jc,
1.64 + "org.apidesign.bck2brwsr.core.ExtraJavaScript",
1.65 + "resource", "processByteCode"
1.66 + );
1.67 + if (arr != null) {
1.68 + if (!arr[0].isEmpty()) {
1.69 + requireScript(arr[0]);
1.70 + }
1.71 + if ("0".equals(arr[1])) {
1.72 + return null;
1.73 + }
1.74 }
1.75 - if ("0".equals(arr[1])) {
1.76 - return null;
1.77 + }
1.78 + {
1.79 + String[] arr = findAnnotation(arrData, jc,
1.80 + "net.java.html.js.JavaScriptResource",
1.81 + "value"
1.82 + );
1.83 + if (arr != null) {
1.84 + if (arr[0].startsWith("/")) {
1.85 + requireScript(arr[0]);
1.86 + } else {
1.87 + int last = jc.getClassName().lastIndexOf('/');
1.88 + requireScript(
1.89 + jc.getClassName().substring(0, last + 1).replace('.', '/') + arr[0]
1.90 + );
1.91 + }
1.92 }
1.93 }
1.94 String[] proto = findAnnotation(arrData, jc,
1.95 @@ -142,34 +182,39 @@
1.96 );
1.97 StringArray toInitilize = new StringArray();
1.98 final String className = className(jc);
1.99 - out.append("\n\n").append(assignClass(className));
1.100 - out.append("function ").append(className).append("() {");
1.101 - out.append("\n var CLS = ").append(className).append(';');
1.102 - out.append("\n if (!CLS.$class) {");
1.103 + append("\n\n").append(assignClass(className));
1.104 + append("function ").append(className).append("() {");
1.105 + append("\n var CLS = ").append(className).append(';');
1.106 + append("\n if (!CLS.$class) {");
1.107 if (proto == null) {
1.108 String sc = jc.getSuperClassName(); // with _
1.109 - out.append("\n var pp = ").
1.110 - append(accessClass(sc.replace('/', '_'))).append("(true);");
1.111 - out.append("\n var p = CLS.prototype = pp;");
1.112 - out.append("\n var c = p;");
1.113 - out.append("\n var sprcls = pp.constructor.$class;");
1.114 + append("\n var pp = ").
1.115 + append(accessClass(mangleClassName(sc))).append("(true);");
1.116 + append("\n var p = CLS.prototype = pp;");
1.117 + append("\n var c = p;");
1.118 + append("\n var sprcls = pp.constructor.$class;");
1.119 } else {
1.120 - out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
1.121 + append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
1.122 if (proto[0] == null) {
1.123 proto[0] = "p";
1.124 }
1.125 - out.append("\n var c = ").append(proto[0]).append(";");
1.126 - out.append("\n var sprcls = null;");
1.127 + append("\n var c = ").append(proto[0]).append(";");
1.128 + append("\n var sprcls = null;");
1.129 }
1.130 for (FieldData v : jc.getFields()) {
1.131 if (v.isStatic()) {
1.132 - out.append("\n CLS.").append(v.getName()).append(initField(v));
1.133 - out.append("\n c._").append(v.getName()).append(" = function (v) {")
1.134 - .append(" if (arguments.length == 1) CLS.").append(v.getName())
1.135 - .append(" = v; return CLS.").
1.136 + if ((v.access & ACC_FINAL) != 0 && v.hasConstantValue()) {
1.137 + if (v.getInternalSig().length() == 1 || v.getInternalSig().equals("Ljava/lang/String;")) {
1.138 + continue;
1.139 + }
1.140 + }
1.141 + append("\n CLS.fld_").append(v.getName()).append(initField(v));
1.142 + append("\n c._").append(v.getName()).append(" = function (v) {")
1.143 + .append(" if (arguments.length == 1) CLS.fld_").append(v.getName())
1.144 + .append(" = v; return CLS.fld_").
1.145 append(v.getName()).append("; };");
1.146 } else {
1.147 - out.append("\n c._").append(v.getName()).append(" = function (v) {")
1.148 + append("\n c._").append(v.getName()).append(" = function (v) {")
1.149 .append(" if (arguments.length == 1) this.fld_").
1.150 append(className).append('_').append(v.getName())
1.151 .append(" = v; return this.fld_").
1.152 @@ -187,14 +232,14 @@
1.153 );
1.154 if (only != null) {
1.155 if (only[0] != null && only[1] != null) {
1.156 - out.append("\n p.").append(only[0]).append(" = ")
1.157 + append("\n p.").append(only[0]).append(" = ")
1.158 .append(only[1]).append(";");
1.159 }
1.160 continue;
1.161 }
1.162 String destObject;
1.163 String mn;
1.164 - out.append("\n ");
1.165 + append("\n ");
1.166 if (m.isStatic()) {
1.167 destObject = "c";
1.168 mn = generateStaticMethod(destObject, m, toInitilize);
1.169 @@ -210,39 +255,47 @@
1.170 declaredMethod(m, destObject, mn);
1.171 byte[] runAnno = m.findAnnotationData(false);
1.172 if (runAnno != null) {
1.173 - out.append("\n ").append(destObject).append(".").append(mn).append(".anno = {");
1.174 - generateAnno(jc, out, runAnno);
1.175 - out.append("\n };");
1.176 + append("\n ").append(destObject).append(".").append(mn).append(".anno = {");
1.177 + generateAnno(jc, runAnno);
1.178 + append("\n };");
1.179 }
1.180 - out.append("\n ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
1.181 - out.append("\n ").append(destObject).append(".").append(mn).append(".cls = CLS;");
1.182 + append("\n ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
1.183 + append("\n ").append(destObject).append(".").append(mn).append(".cls = CLS;");
1.184 }
1.185 - out.append("\n c.constructor = CLS;");
1.186 - out.append("\n c['$instOf_").append(className).append("'] = true;");
1.187 + append("\n c.constructor = CLS;");
1.188 + append("\n function fillInstOf(x) {");
1.189 + String instOfName = "$instOf_" + className;
1.190 + append("\n x['").append(instOfName).append("'] = true;");
1.191 for (String superInterface : jc.getSuperInterfaces()) {
1.192 - out.append("\n c['$instOf_").append(superInterface.replace('/', '_')).append("'] = true;");
1.193 + String intrfc = superInterface.replace('/', '_');
1.194 + append("\n vm.").append(intrfc).append("(false)['fillInstOf'](x);");
1.195 + requireReference(superInterface);
1.196 }
1.197 - out.append("\n CLS.$class = 'temp';");
1.198 - out.append("\n CLS.$class = ");
1.199 - out.append(accessClass("java_lang_Class(true);"));
1.200 - out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
1.201 - out.append("\n CLS.$class.superclass = sprcls;");
1.202 - out.append("\n CLS.$class.access = ").append(jc.getAccessFlags()+";");
1.203 - out.append("\n CLS.$class.cnstr = CLS;");
1.204 + append("\n }");
1.205 + append("\n c['fillInstOf'] = fillInstOf;");
1.206 + append("\n fillInstOf(c);");
1.207 +// obfuscationDelegate.exportJSProperty(this, "c", instOfName);
1.208 + append("\n CLS.$class = 'temp';");
1.209 + append("\n CLS.$class = ");
1.210 + append(accessClass("java_lang_Class(true);"));
1.211 + append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
1.212 + append("\n CLS.$class.superclass = sprcls;");
1.213 + append("\n CLS.$class.access = ").append(jc.getAccessFlags()+";");
1.214 + append("\n CLS.$class.cnstr = CLS;");
1.215 byte[] classAnno = jc.findAnnotationData(false);
1.216 if (classAnno != null) {
1.217 - out.append("\n CLS.$class.anno = {");
1.218 - generateAnno(jc, out, classAnno);
1.219 - out.append("\n };");
1.220 + append("\n CLS.$class.anno = {");
1.221 + generateAnno(jc, classAnno);
1.222 + append("\n };");
1.223 }
1.224 for (String init : toInitilize.toArray()) {
1.225 - out.append("\n ").append(init).append("();");
1.226 + append("\n ").append(init).append("();");
1.227 }
1.228 - out.append("\n }");
1.229 - out.append("\n if (arguments.length === 0) {");
1.230 - out.append("\n if (!(this instanceof CLS)) {");
1.231 - out.append("\n return new CLS();");
1.232 - out.append("\n }");
1.233 + append("\n }");
1.234 + append("\n if (arguments.length === 0) {");
1.235 + append("\n if (!(this instanceof CLS)) {");
1.236 + append("\n return new CLS();");
1.237 + append("\n }");
1.238 for (FieldData v : jc.getFields()) {
1.239 byte[] onlyArr = v.findAnnotationData(true);
1.240 String[] only = findAnnotation(onlyArr, jc,
1.241 @@ -251,21 +304,21 @@
1.242 );
1.243 if (only != null) {
1.244 if (only[0] != null && only[1] != null) {
1.245 - out.append("\n p.").append(only[0]).append(" = ")
1.246 + append("\n p.").append(only[0]).append(" = ")
1.247 .append(only[1]).append(";");
1.248 }
1.249 continue;
1.250 }
1.251 if (!v.isStatic()) {
1.252 - out.append("\n this.fld_").
1.253 + append("\n this.fld_").
1.254 append(className).append('_').
1.255 append(v.getName()).append(initField(v));
1.256 }
1.257 }
1.258 - out.append("\n return this;");
1.259 - out.append("\n }");
1.260 - out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
1.261 - out.append("\n};");
1.262 + append("\n return this;");
1.263 + append("\n }");
1.264 + append("\n return arguments[0] ? new CLS() : CLS.prototype;");
1.265 + append("\n};");
1.266
1.267 declaredClass(jc, className);
1.268
1.269 @@ -305,34 +358,43 @@
1.270 final LocalsMapper lmapper =
1.271 new LocalsMapper(stackMapIterator.getArguments());
1.272
1.273 - out.append(destObject).append(".").append(name).append(" = function(");
1.274 - lmapper.outputArguments(out, m.isStatic());
1.275 - out.append(") {").append("\n");
1.276 + append(destObject).append(".").append(name).append(" = function(");
1.277 + lmapper.outputArguments(this, m.isStatic());
1.278 + append(") {").append("\n");
1.279
1.280 final byte[] byteCodes = m.getCode();
1.281 if (byteCodes == null) {
1.282 - out.append(" throw 'no code found for ")
1.283 + append(" throw 'no code found for ")
1.284 .append(jc.getClassName()).append('.')
1.285 .append(m.getName()).append("';\n");
1.286 - out.append("};");
1.287 + append("};");
1.288 return;
1.289 }
1.290
1.291 final StackMapper smapper = new StackMapper();
1.292
1.293 if (!m.isStatic()) {
1.294 - out.append(" var ").append(" lcA0 = this;\n");
1.295 + append(" var ").append(" lcA0 = this;\n");
1.296 }
1.297
1.298 - int lastStackFrame = -1;
1.299 + int lastStackFrame;
1.300 TrapData[] previousTrap = null;
1.301 boolean wide = false;
1.302 + boolean didBranches;
1.303 + if (stackMapIterator.isEmpty()) {
1.304 + didBranches = false;
1.305 + lastStackFrame = 0;
1.306 + } else {
1.307 + didBranches = true;
1.308 + lastStackFrame = -1;
1.309 + append("\n var gt = 0;\n");
1.310 + }
1.311
1.312 - out.append("\n var gt = 0;\n");
1.313 int openBraces = 0;
1.314 int topMostLabel = 0;
1.315 for (int i = 0; i < byteCodes.length; i++) {
1.316 int prev = i;
1.317 + outChanged = false;
1.318 stackMapIterator.advanceTo(i);
1.319 boolean changeInCatch = trap.advanceTo(i);
1.320 if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
1.321 @@ -342,12 +404,13 @@
1.322 }
1.323 }
1.324 if (lastStackFrame != stackMapIterator.getFrameIndex()) {
1.325 + smapper.flush(this);
1.326 if (i != 0) {
1.327 - out.append(" }\n");
1.328 + append(" }\n");
1.329 }
1.330 if (openBraces > 64) {
1.331 for (int c = 0; c < 64; c++) {
1.332 - out.append("break;}\n");
1.333 + append("break;}\n");
1.334 }
1.335 openBraces = 1;
1.336 topMostLabel = i;
1.337 @@ -356,85 +419,84 @@
1.338 lastStackFrame = stackMapIterator.getFrameIndex();
1.339 lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
1.340 smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
1.341 - out.append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
1.342 + append(" X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
1.343 openBraces++;
1.344 changeInCatch = true;
1.345 } else {
1.346 debug(" /* " + i + " */ ");
1.347 }
1.348 if (changeInCatch && trap.useTry()) {
1.349 - out.append("try {");
1.350 + append("try {");
1.351 previousTrap = trap.current();
1.352 }
1.353 final int c = readUByte(byteCodes, i);
1.354 switch (c) {
1.355 case opc_aload_0:
1.356 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
1.357 + smapper.assign(this, VarType.REFERENCE, lmapper.getA(0));
1.358 break;
1.359 case opc_iload_0:
1.360 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0));
1.361 + smapper.assign(this, VarType.INTEGER, lmapper.getI(0));
1.362 break;
1.363 case opc_lload_0:
1.364 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0));
1.365 + smapper.assign(this, VarType.LONG, lmapper.getL(0));
1.366 break;
1.367 case opc_fload_0:
1.368 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0));
1.369 + smapper.assign(this, VarType.FLOAT, lmapper.getF(0));
1.370 break;
1.371 case opc_dload_0:
1.372 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0));
1.373 + smapper.assign(this, VarType.DOUBLE, lmapper.getD(0));
1.374 break;
1.375 case opc_aload_1:
1.376 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1));
1.377 + smapper.assign(this, VarType.REFERENCE, lmapper.getA(1));
1.378 break;
1.379 case opc_iload_1:
1.380 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1));
1.381 + smapper.assign(this, VarType.INTEGER, lmapper.getI(1));
1.382 break;
1.383 case opc_lload_1:
1.384 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1));
1.385 + smapper.assign(this, VarType.LONG, lmapper.getL(1));
1.386 break;
1.387 case opc_fload_1:
1.388 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1));
1.389 + smapper.assign(this, VarType.FLOAT, lmapper.getF(1));
1.390 break;
1.391 case opc_dload_1:
1.392 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1));
1.393 + smapper.assign(this, VarType.DOUBLE, lmapper.getD(1));
1.394 break;
1.395 case opc_aload_2:
1.396 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2));
1.397 + smapper.assign(this, VarType.REFERENCE, lmapper.getA(2));
1.398 break;
1.399 case opc_iload_2:
1.400 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2));
1.401 + smapper.assign(this, VarType.INTEGER, lmapper.getI(2));
1.402 break;
1.403 case opc_lload_2:
1.404 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2));
1.405 + smapper.assign(this, VarType.LONG, lmapper.getL(2));
1.406 break;
1.407 case opc_fload_2:
1.408 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2));
1.409 + smapper.assign(this, VarType.FLOAT, lmapper.getF(2));
1.410 break;
1.411 case opc_dload_2:
1.412 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2));
1.413 + smapper.assign(this, VarType.DOUBLE, lmapper.getD(2));
1.414 break;
1.415 case opc_aload_3:
1.416 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3));
1.417 + smapper.assign(this, VarType.REFERENCE, lmapper.getA(3));
1.418 break;
1.419 case opc_iload_3:
1.420 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3));
1.421 + smapper.assign(this, VarType.INTEGER, lmapper.getI(3));
1.422 break;
1.423 case opc_lload_3:
1.424 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3));
1.425 + smapper.assign(this, VarType.LONG, lmapper.getL(3));
1.426 break;
1.427 case opc_fload_3:
1.428 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3));
1.429 + smapper.assign(this, VarType.FLOAT, lmapper.getF(3));
1.430 break;
1.431 case opc_dload_3:
1.432 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
1.433 + smapper.assign(this, VarType.DOUBLE, lmapper.getD(3));
1.434 break;
1.435 case opc_iload: {
1.436 ++i;
1.437 final int indx = wide ? readUShort(byteCodes, i++)
1.438 : readUByte(byteCodes, i);
1.439 wide = false;
1.440 - emit(out, "var @1 = @2;",
1.441 - smapper.pushI(), lmapper.getI(indx));
1.442 + smapper.assign(this, VarType.INTEGER, lmapper.getI(indx));
1.443 break;
1.444 }
1.445 case opc_lload: {
1.446 @@ -442,8 +504,7 @@
1.447 final int indx = wide ? readUShort(byteCodes, i++)
1.448 : readUByte(byteCodes, i);
1.449 wide = false;
1.450 - emit(out, "var @1 = @2;",
1.451 - smapper.pushL(), lmapper.getL(indx));
1.452 + smapper.assign(this, VarType.LONG, lmapper.getL(indx));
1.453 break;
1.454 }
1.455 case opc_fload: {
1.456 @@ -451,8 +512,7 @@
1.457 final int indx = wide ? readUShort(byteCodes, i++)
1.458 : readUByte(byteCodes, i);
1.459 wide = false;
1.460 - emit(out, "var @1 = @2;",
1.461 - smapper.pushF(), lmapper.getF(indx));
1.462 + smapper.assign(this, VarType.FLOAT, lmapper.getF(indx));
1.463 break;
1.464 }
1.465 case opc_dload: {
1.466 @@ -460,8 +520,7 @@
1.467 final int indx = wide ? readUShort(byteCodes, i++)
1.468 : readUByte(byteCodes, i);
1.469 wide = false;
1.470 - emit(out, "var @1 = @2;",
1.471 - smapper.pushD(), lmapper.getD(indx));
1.472 + smapper.assign(this, VarType.DOUBLE, lmapper.getD(indx));
1.473 break;
1.474 }
1.475 case opc_aload: {
1.476 @@ -469,8 +528,7 @@
1.477 final int indx = wide ? readUShort(byteCodes, i++)
1.478 : readUByte(byteCodes, i);
1.479 wide = false;
1.480 - emit(out, "var @1 = @2;",
1.481 - smapper.pushA(), lmapper.getA(indx));
1.482 + smapper.assign(this, VarType.REFERENCE, lmapper.getA(indx));
1.483 break;
1.484 }
1.485 case opc_istore: {
1.486 @@ -478,7 +536,7 @@
1.487 final int indx = wide ? readUShort(byteCodes, i++)
1.488 : readUByte(byteCodes, i);
1.489 wide = false;
1.490 - emit(out, "var @1 = @2;",
1.491 + emit(smapper, this, "var @1 = @2;",
1.492 lmapper.setI(indx), smapper.popI());
1.493 break;
1.494 }
1.495 @@ -487,7 +545,7 @@
1.496 final int indx = wide ? readUShort(byteCodes, i++)
1.497 : readUByte(byteCodes, i);
1.498 wide = false;
1.499 - emit(out, "var @1 = @2;",
1.500 + emit(smapper, this, "var @1 = @2;",
1.501 lmapper.setL(indx), smapper.popL());
1.502 break;
1.503 }
1.504 @@ -496,7 +554,7 @@
1.505 final int indx = wide ? readUShort(byteCodes, i++)
1.506 : readUByte(byteCodes, i);
1.507 wide = false;
1.508 - emit(out, "var @1 = @2;",
1.509 + emit(smapper, this, "var @1 = @2;",
1.510 lmapper.setF(indx), smapper.popF());
1.511 break;
1.512 }
1.513 @@ -505,7 +563,7 @@
1.514 final int indx = wide ? readUShort(byteCodes, i++)
1.515 : readUByte(byteCodes, i);
1.516 wide = false;
1.517 - emit(out, "var @1 = @2;",
1.518 + emit(smapper, this, "var @1 = @2;",
1.519 lmapper.setD(indx), smapper.popD());
1.520 break;
1.521 }
1.522 @@ -514,181 +572,181 @@
1.523 final int indx = wide ? readUShort(byteCodes, i++)
1.524 : readUByte(byteCodes, i);
1.525 wide = false;
1.526 - emit(out, "var @1 = @2;",
1.527 + emit(smapper, this, "var @1 = @2;",
1.528 lmapper.setA(indx), smapper.popA());
1.529 break;
1.530 }
1.531 case opc_astore_0:
1.532 - emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA());
1.533 + emit(smapper, this, "var @1 = @2;", lmapper.setA(0), smapper.popA());
1.534 break;
1.535 case opc_istore_0:
1.536 - emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI());
1.537 + emit(smapper, this, "var @1 = @2;", lmapper.setI(0), smapper.popI());
1.538 break;
1.539 case opc_lstore_0:
1.540 - emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL());
1.541 + emit(smapper, this, "var @1 = @2;", lmapper.setL(0), smapper.popL());
1.542 break;
1.543 case opc_fstore_0:
1.544 - emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF());
1.545 + emit(smapper, this, "var @1 = @2;", lmapper.setF(0), smapper.popF());
1.546 break;
1.547 case opc_dstore_0:
1.548 - emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD());
1.549 + emit(smapper, this, "var @1 = @2;", lmapper.setD(0), smapper.popD());
1.550 break;
1.551 case opc_astore_1:
1.552 - emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA());
1.553 + emit(smapper, this, "var @1 = @2;", lmapper.setA(1), smapper.popA());
1.554 break;
1.555 case opc_istore_1:
1.556 - emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI());
1.557 + emit(smapper, this, "var @1 = @2;", lmapper.setI(1), smapper.popI());
1.558 break;
1.559 case opc_lstore_1:
1.560 - emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL());
1.561 + emit(smapper, this, "var @1 = @2;", lmapper.setL(1), smapper.popL());
1.562 break;
1.563 case opc_fstore_1:
1.564 - emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF());
1.565 + emit(smapper, this, "var @1 = @2;", lmapper.setF(1), smapper.popF());
1.566 break;
1.567 case opc_dstore_1:
1.568 - emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD());
1.569 + emit(smapper, this, "var @1 = @2;", lmapper.setD(1), smapper.popD());
1.570 break;
1.571 case opc_astore_2:
1.572 - emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA());
1.573 + emit(smapper, this, "var @1 = @2;", lmapper.setA(2), smapper.popA());
1.574 break;
1.575 case opc_istore_2:
1.576 - emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI());
1.577 + emit(smapper, this, "var @1 = @2;", lmapper.setI(2), smapper.popI());
1.578 break;
1.579 case opc_lstore_2:
1.580 - emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL());
1.581 + emit(smapper, this, "var @1 = @2;", lmapper.setL(2), smapper.popL());
1.582 break;
1.583 case opc_fstore_2:
1.584 - emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF());
1.585 + emit(smapper, this, "var @1 = @2;", lmapper.setF(2), smapper.popF());
1.586 break;
1.587 case opc_dstore_2:
1.588 - emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD());
1.589 + emit(smapper, this, "var @1 = @2;", lmapper.setD(2), smapper.popD());
1.590 break;
1.591 case opc_astore_3:
1.592 - emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA());
1.593 + emit(smapper, this, "var @1 = @2;", lmapper.setA(3), smapper.popA());
1.594 break;
1.595 case opc_istore_3:
1.596 - emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI());
1.597 + emit(smapper, this, "var @1 = @2;", lmapper.setI(3), smapper.popI());
1.598 break;
1.599 case opc_lstore_3:
1.600 - emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL());
1.601 + emit(smapper, this, "var @1 = @2;", lmapper.setL(3), smapper.popL());
1.602 break;
1.603 case opc_fstore_3:
1.604 - emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF());
1.605 + emit(smapper, this, "var @1 = @2;", lmapper.setF(3), smapper.popF());
1.606 break;
1.607 case opc_dstore_3:
1.608 - emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
1.609 + emit(smapper, this, "var @1 = @2;", lmapper.setD(3), smapper.popD());
1.610 break;
1.611 case opc_iadd:
1.612 - emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
1.613 + smapper.replace(this, VarType.INTEGER, "(@1).add32(@2)", smapper.getI(1), smapper.popI());
1.614 break;
1.615 case opc_ladd:
1.616 - emit(out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
1.617 + smapper.replace(this, VarType.LONG, "(@1).add64(@2)", smapper.getL(1), smapper.popL());
1.618 break;
1.619 case opc_fadd:
1.620 - emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
1.621 + smapper.replace(this, VarType.FLOAT, "(@1 + @2)", smapper.getF(1), smapper.popF());
1.622 break;
1.623 case opc_dadd:
1.624 - emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
1.625 + smapper.replace(this, VarType.DOUBLE, "(@1 + @2)", smapper.getD(1), smapper.popD());
1.626 break;
1.627 case opc_isub:
1.628 - emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
1.629 + smapper.replace(this, VarType.INTEGER, "(@1).sub32(@2)", smapper.getI(1), smapper.popI());
1.630 break;
1.631 case opc_lsub:
1.632 - emit(out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
1.633 + smapper.replace(this, VarType.LONG, "(@1).sub64(@2)", smapper.getL(1), smapper.popL());
1.634 break;
1.635 case opc_fsub:
1.636 - emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
1.637 + smapper.replace(this, VarType.FLOAT, "(@1 - @2)", smapper.getF(1), smapper.popF());
1.638 break;
1.639 case opc_dsub:
1.640 - emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
1.641 + smapper.replace(this, VarType.DOUBLE, "(@1 - @2)", smapper.getD(1), smapper.popD());
1.642 break;
1.643 case opc_imul:
1.644 - emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
1.645 + smapper.replace(this, VarType.INTEGER, "(@1).mul32(@2)", smapper.getI(1), smapper.popI());
1.646 break;
1.647 case opc_lmul:
1.648 - emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
1.649 + smapper.replace(this, VarType.LONG, "(@1).mul64(@2)", smapper.getL(1), smapper.popL());
1.650 break;
1.651 case opc_fmul:
1.652 - emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
1.653 + smapper.replace(this, VarType.FLOAT, "(@1 * @2)", smapper.getF(1), smapper.popF());
1.654 break;
1.655 case opc_dmul:
1.656 - emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
1.657 + smapper.replace(this, VarType.DOUBLE, "(@1 * @2)", smapper.getD(1), smapper.popD());
1.658 break;
1.659 case opc_idiv:
1.660 - emit(out, "@1 = @1.div32(@2);",
1.661 + smapper.replace(this, VarType.INTEGER, "(@1).div32(@2)",
1.662 smapper.getI(1), smapper.popI());
1.663 break;
1.664 case opc_ldiv:
1.665 - emit(out, "@1 = @1.div64(@2);",
1.666 + smapper.replace(this, VarType.LONG, "(@1).div64(@2)",
1.667 smapper.getL(1), smapper.popL());
1.668 break;
1.669 case opc_fdiv:
1.670 - emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
1.671 + smapper.replace(this, VarType.FLOAT, "(@1 / @2)", smapper.getF(1), smapper.popF());
1.672 break;
1.673 case opc_ddiv:
1.674 - emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
1.675 + smapper.replace(this, VarType.DOUBLE, "(@1 / @2)", smapper.getD(1), smapper.popD());
1.676 break;
1.677 case opc_irem:
1.678 - emit(out, "@1 = @1.mod32(@2);",
1.679 + smapper.replace(this, VarType.INTEGER, "(@1).mod32(@2)",
1.680 smapper.getI(1), smapper.popI());
1.681 break;
1.682 case opc_lrem:
1.683 - emit(out, "@1 = @1.mod64(@2);",
1.684 + smapper.replace(this, VarType.LONG, "(@1).mod64(@2)",
1.685 smapper.getL(1), smapper.popL());
1.686 break;
1.687 case opc_frem:
1.688 - emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
1.689 + smapper.replace(this, VarType.FLOAT, "(@1 % @2)", smapper.getF(1), smapper.popF());
1.690 break;
1.691 case opc_drem:
1.692 - emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
1.693 + smapper.replace(this, VarType.DOUBLE, "(@1 % @2)", smapper.getD(1), smapper.popD());
1.694 break;
1.695 case opc_iand:
1.696 - emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
1.697 + smapper.replace(this, VarType.INTEGER, "(@1 & @2)", smapper.getI(1), smapper.popI());
1.698 break;
1.699 case opc_land:
1.700 - emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
1.701 + smapper.replace(this, VarType.LONG, "(@1).and64(@2)", smapper.getL(1), smapper.popL());
1.702 break;
1.703 case opc_ior:
1.704 - emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
1.705 + smapper.replace(this, VarType.INTEGER, "(@1 | @2)", smapper.getI(1), smapper.popI());
1.706 break;
1.707 case opc_lor:
1.708 - emit(out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
1.709 + smapper.replace(this, VarType.LONG, "(@1).or64(@2)", smapper.getL(1), smapper.popL());
1.710 break;
1.711 case opc_ixor:
1.712 - emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
1.713 + smapper.replace(this, VarType.INTEGER, "(@1 ^ @2)", smapper.getI(1), smapper.popI());
1.714 break;
1.715 case opc_lxor:
1.716 - emit(out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
1.717 + smapper.replace(this, VarType.LONG, "(@1).xor64(@2)", smapper.getL(1), smapper.popL());
1.718 break;
1.719 case opc_ineg:
1.720 - emit(out, "@1 = @1.neg32();", smapper.getI(0));
1.721 + smapper.replace(this, VarType.INTEGER, "(@1).neg32()", smapper.getI(0));
1.722 break;
1.723 case opc_lneg:
1.724 - emit(out, "@1 = @1.neg64();", smapper.getL(0));
1.725 + smapper.replace(this, VarType.LONG, "(@1).neg64()", smapper.getL(0));
1.726 break;
1.727 case opc_fneg:
1.728 - emit(out, "@1 = -@1;", smapper.getF(0));
1.729 + smapper.replace(this, VarType.FLOAT, "(-@1)", smapper.getF(0));
1.730 break;
1.731 case opc_dneg:
1.732 - emit(out, "@1 = -@1;", smapper.getD(0));
1.733 + smapper.replace(this, VarType.DOUBLE, "(-@1)", smapper.getD(0));
1.734 break;
1.735 case opc_ishl:
1.736 - emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
1.737 + smapper.replace(this, VarType.INTEGER, "(@1 << @2)", smapper.getI(1), smapper.popI());
1.738 break;
1.739 case opc_lshl:
1.740 - emit(out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
1.741 + smapper.replace(this, VarType.LONG, "(@1).shl64(@2)", smapper.getL(1), smapper.popI());
1.742 break;
1.743 case opc_ishr:
1.744 - emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
1.745 + smapper.replace(this, VarType.INTEGER, "(@1 >> @2)", smapper.getI(1), smapper.popI());
1.746 break;
1.747 case opc_lshr:
1.748 - emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
1.749 + smapper.replace(this, VarType.LONG, "(@1).shr64(@2)", smapper.getL(1), smapper.popI());
1.750 break;
1.751 case opc_iushr:
1.752 - emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
1.753 + smapper.replace(this, VarType.INTEGER, "(@1 >>> @2)", smapper.getI(1), smapper.popI());
1.754 break;
1.755 case opc_lushr:
1.756 - emit(out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
1.757 + smapper.replace(this, VarType.LONG, "(@1).ushr64(@2)", smapper.getL(1), smapper.popI());
1.758 break;
1.759 case opc_iinc: {
1.760 ++i;
1.761 @@ -699,132 +757,132 @@
1.762 : byteCodes[i];
1.763 wide = false;
1.764 if (incrBy == 1) {
1.765 - emit(out, "@1++;", lmapper.getI(varIndx));
1.766 + emit(smapper, this, "@1++;", lmapper.getI(varIndx));
1.767 } else {
1.768 - emit(out, "@1 += @2;",
1.769 + emit(smapper, this, "@1 += @2;",
1.770 lmapper.getI(varIndx),
1.771 Integer.toString(incrBy));
1.772 }
1.773 break;
1.774 }
1.775 case opc_return:
1.776 - emit(out, "return;");
1.777 + emit(smapper, this, "return;");
1.778 break;
1.779 case opc_ireturn:
1.780 - emit(out, "return @1;", smapper.popI());
1.781 + emit(smapper, this, "return @1;", smapper.popI());
1.782 break;
1.783 case opc_lreturn:
1.784 - emit(out, "return @1;", smapper.popL());
1.785 + emit(smapper, this, "return @1;", smapper.popL());
1.786 break;
1.787 case opc_freturn:
1.788 - emit(out, "return @1;", smapper.popF());
1.789 + emit(smapper, this, "return @1;", smapper.popF());
1.790 break;
1.791 case opc_dreturn:
1.792 - emit(out, "return @1;", smapper.popD());
1.793 + emit(smapper, this, "return @1;", smapper.popD());
1.794 break;
1.795 case opc_areturn:
1.796 - emit(out, "return @1;", smapper.popA());
1.797 + emit(smapper, this, "return @1;", smapper.popA());
1.798 break;
1.799 case opc_i2l:
1.800 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL());
1.801 + smapper.replace(this, VarType.LONG, "@1", smapper.getI(0));
1.802 break;
1.803 case opc_i2f:
1.804 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF());
1.805 + smapper.replace(this, VarType.FLOAT, "@1", smapper.getI(0));
1.806 break;
1.807 case opc_i2d:
1.808 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
1.809 + smapper.replace(this, VarType.DOUBLE, "@1", smapper.getI(0));
1.810 break;
1.811 case opc_l2i:
1.812 - emit(out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
1.813 + smapper.replace(this, VarType.INTEGER, "(@1).toInt32()", smapper.getL(0));
1.814 break;
1.815 // max int check?
1.816 case opc_l2f:
1.817 - emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
1.818 + smapper.replace(this, VarType.FLOAT, "(@1).toFP()", smapper.getL(0));
1.819 break;
1.820 case opc_l2d:
1.821 - emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
1.822 + smapper.replace(this, VarType.DOUBLE, "(@1).toFP()", smapper.getL(0));
1.823 break;
1.824 case opc_f2d:
1.825 - emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
1.826 + smapper.replace(this, VarType.DOUBLE, "@1",
1.827 + smapper.getF(0));
1.828 break;
1.829 case opc_d2f:
1.830 - emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
1.831 + smapper.replace(this, VarType.FLOAT, "@1",
1.832 + smapper.getD(0));
1.833 break;
1.834 case opc_f2i:
1.835 - emit(out, "var @2 = @1.toInt32();",
1.836 - smapper.popF(), smapper.pushI());
1.837 + smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
1.838 + smapper.getF(0));
1.839 break;
1.840 case opc_f2l:
1.841 - emit(out, "var @2 = @1.toLong();",
1.842 - smapper.popF(), smapper.pushL());
1.843 + smapper.replace(this, VarType.LONG, "(@1).toLong()",
1.844 + smapper.getF(0));
1.845 break;
1.846 case opc_d2i:
1.847 - emit(out, "var @2 = @1.toInt32();",
1.848 - smapper.popD(), smapper.pushI());
1.849 + smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
1.850 + smapper.getD(0));
1.851 break;
1.852 case opc_d2l:
1.853 - emit(out, "var @2 = @1.toLong();",
1.854 - smapper.popD(), smapper.pushL());
1.855 + smapper.replace(this, VarType.LONG, "(@1).toLong()", smapper.getD(0));
1.856 break;
1.857 case opc_i2b:
1.858 - emit(out, "var @1 = @1.toInt8();", smapper.getI(0));
1.859 + smapper.replace(this, VarType.INTEGER, "(@1).toInt8()", smapper.getI(0));
1.860 break;
1.861 case opc_i2c:
1.862 - out.append("{ /* number conversion */ }");
1.863 break;
1.864 case opc_i2s:
1.865 - emit(out, "var @1 = @1.toInt16();", smapper.getI(0));
1.866 + smapper.replace(this, VarType.INTEGER, "(@1).toInt16()", smapper.getI(0));
1.867 break;
1.868 case opc_aconst_null:
1.869 - emit(out, "var @1 = null;", smapper.pushA());
1.870 + smapper.assign(this, VarType.REFERENCE, "null");
1.871 break;
1.872 case opc_iconst_m1:
1.873 - emit(out, "var @1 = -1;", smapper.pushI());
1.874 + smapper.assign(this, VarType.INTEGER, "-1");
1.875 break;
1.876 case opc_iconst_0:
1.877 - emit(out, "var @1 = 0;", smapper.pushI());
1.878 + smapper.assign(this, VarType.INTEGER, "0");
1.879 break;
1.880 case opc_dconst_0:
1.881 - emit(out, "var @1 = 0;", smapper.pushD());
1.882 + smapper.assign(this, VarType.DOUBLE, "0");
1.883 break;
1.884 case opc_lconst_0:
1.885 - emit(out, "var @1 = 0;", smapper.pushL());
1.886 + smapper.assign(this, VarType.LONG, "0");
1.887 break;
1.888 case opc_fconst_0:
1.889 - emit(out, "var @1 = 0;", smapper.pushF());
1.890 + smapper.assign(this, VarType.FLOAT, "0");
1.891 break;
1.892 case opc_iconst_1:
1.893 - emit(out, "var @1 = 1;", smapper.pushI());
1.894 + smapper.assign(this, VarType.INTEGER, "1");
1.895 break;
1.896 case opc_lconst_1:
1.897 - emit(out, "var @1 = 1;", smapper.pushL());
1.898 + smapper.assign(this, VarType.LONG, "1");
1.899 break;
1.900 case opc_fconst_1:
1.901 - emit(out, "var @1 = 1;", smapper.pushF());
1.902 + smapper.assign(this, VarType.FLOAT, "1");
1.903 break;
1.904 case opc_dconst_1:
1.905 - emit(out, "var @1 = 1;", smapper.pushD());
1.906 + smapper.assign(this, VarType.DOUBLE, "1");
1.907 break;
1.908 case opc_iconst_2:
1.909 - emit(out, "var @1 = 2;", smapper.pushI());
1.910 + smapper.assign(this, VarType.INTEGER, "2");
1.911 break;
1.912 case opc_fconst_2:
1.913 - emit(out, "var @1 = 2;", smapper.pushF());
1.914 + smapper.assign(this, VarType.FLOAT, "2");
1.915 break;
1.916 case opc_iconst_3:
1.917 - emit(out, "var @1 = 3;", smapper.pushI());
1.918 + smapper.assign(this, VarType.INTEGER, "3");
1.919 break;
1.920 case opc_iconst_4:
1.921 - emit(out, "var @1 = 4;", smapper.pushI());
1.922 + smapper.assign(this, VarType.INTEGER, "4");
1.923 break;
1.924 case opc_iconst_5:
1.925 - emit(out, "var @1 = 5;", smapper.pushI());
1.926 + smapper.assign(this, VarType.INTEGER, "5");
1.927 break;
1.928 case opc_ldc: {
1.929 int indx = readUByte(byteCodes, ++i);
1.930 String v = encodeConstant(indx);
1.931 int type = VarType.fromConstantType(jc.getTag(indx));
1.932 - emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.933 + smapper.assign(this, type, v);
1.934 break;
1.935 }
1.936 case opc_ldc_w:
1.937 @@ -837,118 +895,122 @@
1.938 final Long lv = new Long(v);
1.939 final int low = (int)(lv.longValue() & 0xFFFFFFFF);
1.940 final int hi = (int)(lv.longValue() >> 32);
1.941 - emit(out, "var @1 = 0x@3.next32(0x@2);", smapper.pushL(),
1.942 - Integer.toHexString(low), Integer.toHexString(hi));
1.943 + if (hi == 0) {
1.944 + smapper.assign(this, VarType.LONG, "0x" + Integer.toHexString(low));
1.945 + } else {
1.946 + smapper.assign(this, VarType.LONG,
1.947 + "0x" + Integer.toHexString(hi) + ".next32(0x" +
1.948 + Integer.toHexString(low) + ")"
1.949 + );
1.950 + }
1.951 } else {
1.952 - emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.953 + smapper.assign(this, type, v);
1.954 }
1.955 break;
1.956 }
1.957 case opc_lcmp:
1.958 - emit(out, "var @3 = @2.compare64(@1);",
1.959 - smapper.popL(), smapper.popL(), smapper.pushI());
1.960 + smapper.replace(this, VarType.INTEGER, "(@2).compare64(@1)", smapper.popL(), smapper.getL(0));
1.961 break;
1.962 case opc_fcmpl:
1.963 case opc_fcmpg:
1.964 - emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
1.965 - smapper.popF(), smapper.popF(), smapper.pushI());
1.966 + smapper.replace(this, VarType.INTEGER, "(@2).compare(@1)", smapper.popF(), smapper.getF(0));
1.967 break;
1.968 case opc_dcmpl:
1.969 case opc_dcmpg:
1.970 - emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
1.971 - smapper.popD(), smapper.popD(), smapper.pushI());
1.972 + smapper.replace(this, VarType.INTEGER, "(@2).compare(@1)", smapper.popD(), smapper.getD(0));
1.973 break;
1.974 case opc_if_acmpeq:
1.975 - i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
1.976 + i = generateIf(smapper, byteCodes, i, smapper.popA(), smapper.popA(),
1.977 "===", topMostLabel);
1.978 break;
1.979 case opc_if_acmpne:
1.980 - i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
1.981 + i = generateIf(smapper, byteCodes, i, smapper.popA(), smapper.popA(),
1.982 "!==", topMostLabel);
1.983 break;
1.984 case opc_if_icmpeq:
1.985 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.986 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.987 "==", topMostLabel);
1.988 break;
1.989 case opc_ifeq: {
1.990 int indx = i + readShortArg(byteCodes, i);
1.991 - emitIf(out, "if (@1 == 0) ",
1.992 + emitIf(smapper, this, "if ((@1) == 0) ",
1.993 smapper.popI(), i, indx, topMostLabel);
1.994 i += 2;
1.995 break;
1.996 }
1.997 case opc_ifne: {
1.998 int indx = i + readShortArg(byteCodes, i);
1.999 - emitIf(out, "if (@1 != 0) ",
1.1000 + emitIf(smapper, this, "if ((@1) != 0) ",
1.1001 smapper.popI(), i, indx, topMostLabel);
1.1002 i += 2;
1.1003 break;
1.1004 }
1.1005 case opc_iflt: {
1.1006 int indx = i + readShortArg(byteCodes, i);
1.1007 - emitIf(out, "if (@1 < 0) ",
1.1008 + emitIf(smapper, this, "if ((@1) < 0) ",
1.1009 smapper.popI(), i, indx, topMostLabel);
1.1010 i += 2;
1.1011 break;
1.1012 }
1.1013 case opc_ifle: {
1.1014 int indx = i + readShortArg(byteCodes, i);
1.1015 - emitIf(out, "if (@1 <= 0) ",
1.1016 + emitIf(smapper, this, "if ((@1) <= 0) ",
1.1017 smapper.popI(), i, indx, topMostLabel);
1.1018 i += 2;
1.1019 break;
1.1020 }
1.1021 case opc_ifgt: {
1.1022 int indx = i + readShortArg(byteCodes, i);
1.1023 - emitIf(out, "if (@1 > 0) ",
1.1024 + emitIf(smapper, this, "if ((@1) > 0) ",
1.1025 smapper.popI(), i, indx, topMostLabel);
1.1026 i += 2;
1.1027 break;
1.1028 }
1.1029 case opc_ifge: {
1.1030 int indx = i + readShortArg(byteCodes, i);
1.1031 - emitIf(out, "if (@1 >= 0) ",
1.1032 + emitIf(smapper, this, "if ((@1) >= 0) ",
1.1033 smapper.popI(), i, indx, topMostLabel);
1.1034 i += 2;
1.1035 break;
1.1036 }
1.1037 case opc_ifnonnull: {
1.1038 int indx = i + readShortArg(byteCodes, i);
1.1039 - emitIf(out, "if (@1 !== null) ",
1.1040 + emitIf(smapper, this, "if ((@1) !== null) ",
1.1041 smapper.popA(), i, indx, topMostLabel);
1.1042 i += 2;
1.1043 break;
1.1044 }
1.1045 case opc_ifnull: {
1.1046 int indx = i + readShortArg(byteCodes, i);
1.1047 - emitIf(out, "if (@1 === null) ",
1.1048 + emitIf(smapper, this, "if ((@1) === null) ",
1.1049 smapper.popA(), i, indx, topMostLabel);
1.1050 i += 2;
1.1051 break;
1.1052 }
1.1053 case opc_if_icmpne:
1.1054 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.1055 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.1056 "!=", topMostLabel);
1.1057 break;
1.1058 case opc_if_icmplt:
1.1059 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.1060 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.1061 "<", topMostLabel);
1.1062 break;
1.1063 case opc_if_icmple:
1.1064 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.1065 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.1066 "<=", topMostLabel);
1.1067 break;
1.1068 case opc_if_icmpgt:
1.1069 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.1070 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.1071 ">", topMostLabel);
1.1072 break;
1.1073 case opc_if_icmpge:
1.1074 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.1075 + i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
1.1076 ">=", topMostLabel);
1.1077 break;
1.1078 case opc_goto: {
1.1079 + smapper.flush(this);
1.1080 int indx = i + readShortArg(byteCodes, i);
1.1081 - goTo(out, i, indx, topMostLabel);
1.1082 + goTo(this, i, indx, topMostLabel);
1.1083 i += 2;
1.1084 break;
1.1085 }
1.1086 @@ -976,8 +1038,8 @@
1.1087 case opc_new: {
1.1088 int indx = readUShortArg(byteCodes, i);
1.1089 String ci = jc.getClassName(indx);
1.1090 - emit(out, "var @1 = new @2;",
1.1091 - smapper.pushA(), accessClass(ci.replace('/', '_')));
1.1092 + emit(smapper, this, "var @1 = new @2;",
1.1093 + smapper.pushA(), accessClass(mangleClassName(ci)));
1.1094 addReference(ci);
1.1095 i += 2;
1.1096 break;
1.1097 @@ -999,54 +1061,53 @@
1.1098 break;
1.1099 }
1.1100 case opc_arraylength:
1.1101 - emit(out, "var @2 = @1.length;",
1.1102 - smapper.popA(), smapper.pushI());
1.1103 + smapper.replace(this, VarType.INTEGER, "(@1).length", smapper.getA(0));
1.1104 break;
1.1105 case opc_lastore:
1.1106 - emit(out, "Array.at(@3, @2, @1);",
1.1107 + emit(smapper, this, "Array.at(@3, @2, @1);",
1.1108 smapper.popL(), smapper.popI(), smapper.popA());
1.1109 break;
1.1110 case opc_fastore:
1.1111 - emit(out, "Array.at(@3, @2, @1);",
1.1112 + emit(smapper, this, "Array.at(@3, @2, @1);",
1.1113 smapper.popF(), smapper.popI(), smapper.popA());
1.1114 break;
1.1115 case opc_dastore:
1.1116 - emit(out, "Array.at(@3, @2, @1);",
1.1117 + emit(smapper, this, "Array.at(@3, @2, @1);",
1.1118 smapper.popD(), smapper.popI(), smapper.popA());
1.1119 break;
1.1120 case opc_aastore:
1.1121 - emit(out, "Array.at(@3, @2, @1);",
1.1122 + emit(smapper, this, "Array.at(@3, @2, @1);",
1.1123 smapper.popA(), smapper.popI(), smapper.popA());
1.1124 break;
1.1125 case opc_iastore:
1.1126 case opc_bastore:
1.1127 case opc_castore:
1.1128 case opc_sastore:
1.1129 - emit(out, "Array.at(@3, @2, @1);",
1.1130 + emit(smapper, this, "Array.at(@3, @2, @1);",
1.1131 smapper.popI(), smapper.popI(), smapper.popA());
1.1132 break;
1.1133 case opc_laload:
1.1134 - emit(out, "var @3 = Array.at(@2, @1);",
1.1135 - smapper.popI(), smapper.popA(), smapper.pushL());
1.1136 + smapper.replace(this, VarType.LONG, "Array.at(@2, @1)",
1.1137 + smapper.popI(), smapper.getA(0));
1.1138 break;
1.1139 case opc_faload:
1.1140 - emit(out, "var @3 = Array.at(@2, @1);",
1.1141 - smapper.popI(), smapper.popA(), smapper.pushF());
1.1142 + smapper.replace(this, VarType.FLOAT, "Array.at(@2, @1)",
1.1143 + smapper.popI(), smapper.getA(0));
1.1144 break;
1.1145 case opc_daload:
1.1146 - emit(out, "var @3 = Array.at(@2, @1);",
1.1147 - smapper.popI(), smapper.popA(), smapper.pushD());
1.1148 + smapper.replace(this, VarType.DOUBLE, "Array.at(@2, @1)",
1.1149 + smapper.popI(), smapper.getA(0));
1.1150 break;
1.1151 case opc_aaload:
1.1152 - emit(out, "var @3 = Array.at(@2, @1);",
1.1153 - smapper.popI(), smapper.popA(), smapper.pushA());
1.1154 + smapper.replace(this, VarType.REFERENCE, "Array.at(@2, @1)",
1.1155 + smapper.popI(), smapper.getA(0));
1.1156 break;
1.1157 case opc_iaload:
1.1158 case opc_baload:
1.1159 case opc_caload:
1.1160 case opc_saload:
1.1161 - emit(out, "var @3 = Array.at(@2, @1);",
1.1162 - smapper.popI(), smapper.popA(), smapper.pushI());
1.1163 + smapper.replace(this, VarType.INTEGER, "Array.at(@2, @1)",
1.1164 + smapper.popI(), smapper.getA(0));
1.1165 break;
1.1166 case opc_pop:
1.1167 case opc_pop2:
1.1168 @@ -1055,86 +1116,86 @@
1.1169 break;
1.1170 case opc_dup: {
1.1171 final Variable v = smapper.get(0);
1.1172 - emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v);
1.1173 + emit(smapper, this, "var @1 = @2;", smapper.pushT(v.getType()), v);
1.1174 break;
1.1175 }
1.1176 case opc_dup2: {
1.1177 final Variable vi1 = smapper.get(0);
1.1178
1.1179 if (vi1.isCategory2()) {
1.1180 - emit(out, "var @1 = @2;",
1.1181 + emit(smapper, this, "var @1 = @2;",
1.1182 smapper.pushT(vi1.getType()), vi1);
1.1183 } else {
1.1184 final Variable vi2 = smapper.get(1);
1.1185 - emit(out, "var @1 = @2, @3 = @4;",
1.1186 + emit(smapper, this, "var @1 = @2, @3 = @4;",
1.1187 smapper.pushT(vi2.getType()), vi2,
1.1188 smapper.pushT(vi1.getType()), vi1);
1.1189 }
1.1190 break;
1.1191 }
1.1192 case opc_dup_x1: {
1.1193 - final Variable vi1 = smapper.pop();
1.1194 - final Variable vi2 = smapper.pop();
1.1195 + final Variable vi1 = smapper.pop(this);
1.1196 + final Variable vi2 = smapper.pop(this);
1.1197 final Variable vo3 = smapper.pushT(vi1.getType());
1.1198 final Variable vo2 = smapper.pushT(vi2.getType());
1.1199 final Variable vo1 = smapper.pushT(vi1.getType());
1.1200
1.1201 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1202 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
1.1203 vo1, vi1, vo2, vi2, vo3, vo1);
1.1204 break;
1.1205 }
1.1206 case opc_dup2_x1: {
1.1207 - final Variable vi1 = smapper.pop();
1.1208 - final Variable vi2 = smapper.pop();
1.1209 + final Variable vi1 = smapper.pop(this);
1.1210 + final Variable vi2 = smapper.pop(this);
1.1211
1.1212 if (vi1.isCategory2()) {
1.1213 final Variable vo3 = smapper.pushT(vi1.getType());
1.1214 final Variable vo2 = smapper.pushT(vi2.getType());
1.1215 final Variable vo1 = smapper.pushT(vi1.getType());
1.1216
1.1217 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1218 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
1.1219 vo1, vi1, vo2, vi2, vo3, vo1);
1.1220 } else {
1.1221 - final Variable vi3 = smapper.pop();
1.1222 + final Variable vi3 = smapper.pop(this);
1.1223 final Variable vo5 = smapper.pushT(vi2.getType());
1.1224 final Variable vo4 = smapper.pushT(vi1.getType());
1.1225 final Variable vo3 = smapper.pushT(vi3.getType());
1.1226 final Variable vo2 = smapper.pushT(vi2.getType());
1.1227 final Variable vo1 = smapper.pushT(vi1.getType());
1.1228
1.1229 - emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.1230 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6,",
1.1231 vo1, vi1, vo2, vi2, vo3, vi3);
1.1232 - emit(out, " @1 = @2, @3 = @4;",
1.1233 + emit(smapper, this, " @1 = @2, @3 = @4;",
1.1234 vo4, vo1, vo5, vo2);
1.1235 }
1.1236 break;
1.1237 }
1.1238 case opc_dup_x2: {
1.1239 - final Variable vi1 = smapper.pop();
1.1240 - final Variable vi2 = smapper.pop();
1.1241 + final Variable vi1 = smapper.pop(this);
1.1242 + final Variable vi2 = smapper.pop(this);
1.1243
1.1244 if (vi2.isCategory2()) {
1.1245 final Variable vo3 = smapper.pushT(vi1.getType());
1.1246 final Variable vo2 = smapper.pushT(vi2.getType());
1.1247 final Variable vo1 = smapper.pushT(vi1.getType());
1.1248
1.1249 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1250 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
1.1251 vo1, vi1, vo2, vi2, vo3, vo1);
1.1252 } else {
1.1253 - final Variable vi3 = smapper.pop();
1.1254 + final Variable vi3 = smapper.pop(this);
1.1255 final Variable vo4 = smapper.pushT(vi1.getType());
1.1256 final Variable vo3 = smapper.pushT(vi3.getType());
1.1257 final Variable vo2 = smapper.pushT(vi2.getType());
1.1258 final Variable vo1 = smapper.pushT(vi1.getType());
1.1259
1.1260 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1261 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1262 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.1263 }
1.1264 break;
1.1265 }
1.1266 case opc_dup2_x2: {
1.1267 - final Variable vi1 = smapper.pop();
1.1268 - final Variable vi2 = smapper.pop();
1.1269 + final Variable vi1 = smapper.pop(this);
1.1270 + final Variable vi2 = smapper.pop(this);
1.1271
1.1272 if (vi1.isCategory2()) {
1.1273 if (vi2.isCategory2()) {
1.1274 @@ -1142,20 +1203,20 @@
1.1275 final Variable vo2 = smapper.pushT(vi2.getType());
1.1276 final Variable vo1 = smapper.pushT(vi1.getType());
1.1277
1.1278 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1279 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
1.1280 vo1, vi1, vo2, vi2, vo3, vo1);
1.1281 } else {
1.1282 - final Variable vi3 = smapper.pop();
1.1283 + final Variable vi3 = smapper.pop(this);
1.1284 final Variable vo4 = smapper.pushT(vi1.getType());
1.1285 final Variable vo3 = smapper.pushT(vi3.getType());
1.1286 final Variable vo2 = smapper.pushT(vi2.getType());
1.1287 final Variable vo1 = smapper.pushT(vi1.getType());
1.1288
1.1289 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1290 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1291 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.1292 }
1.1293 } else {
1.1294 - final Variable vi3 = smapper.pop();
1.1295 + final Variable vi3 = smapper.pop(this);
1.1296
1.1297 if (vi3.isCategory2()) {
1.1298 final Variable vo5 = smapper.pushT(vi2.getType());
1.1299 @@ -1164,12 +1225,12 @@
1.1300 final Variable vo2 = smapper.pushT(vi2.getType());
1.1301 final Variable vo1 = smapper.pushT(vi1.getType());
1.1302
1.1303 - emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.1304 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6,",
1.1305 vo1, vi1, vo2, vi2, vo3, vi3);
1.1306 - emit(out, " @1 = @2, @3 = @4;",
1.1307 + emit(smapper, this, " @1 = @2, @3 = @4;",
1.1308 vo4, vo1, vo5, vo2);
1.1309 } else {
1.1310 - final Variable vi4 = smapper.pop();
1.1311 + final Variable vi4 = smapper.pop(this);
1.1312 final Variable vo6 = smapper.pushT(vi2.getType());
1.1313 final Variable vo5 = smapper.pushT(vi1.getType());
1.1314 final Variable vo4 = smapper.pushT(vi4.getType());
1.1315 @@ -1177,9 +1238,9 @@
1.1316 final Variable vo2 = smapper.pushT(vi2.getType());
1.1317 final Variable vo1 = smapper.pushT(vi1.getType());
1.1318
1.1319 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
1.1320 + emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
1.1321 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
1.1322 - emit(out, " @1 = @2, @3 = @4;",
1.1323 + emit(smapper, this, " @1 = @2, @3 = @4;",
1.1324 vo5, vo1, vo6, vo2);
1.1325 }
1.1326 }
1.1327 @@ -1192,7 +1253,7 @@
1.1328 if (vi1.getType() == vi2.getType()) {
1.1329 final Variable tmp = smapper.pushT(vi1.getType());
1.1330
1.1331 - emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
1.1332 + emit(smapper, this, "var @1 = @2, @2 = @3, @3 = @1;",
1.1333 tmp, vi1, vi2);
1.1334 smapper.pop(1);
1.1335 } else {
1.1336 @@ -1203,26 +1264,26 @@
1.1337 break;
1.1338 }
1.1339 case opc_bipush:
1.1340 - emit(out, "var @1 = @2;",
1.1341 - smapper.pushI(), Integer.toString(byteCodes[++i]));
1.1342 + smapper.assign(this, VarType.INTEGER,
1.1343 + "(" + Integer.toString(byteCodes[++i]) + ")");
1.1344 break;
1.1345 case opc_sipush:
1.1346 - emit(out, "var @1 = @2;",
1.1347 - smapper.pushI(),
1.1348 - Integer.toString(readShortArg(byteCodes, i)));
1.1349 + smapper.assign(this, VarType.INTEGER,
1.1350 + "(" + Integer.toString(readShortArg(byteCodes, i)) + ")"
1.1351 + );
1.1352 i += 2;
1.1353 break;
1.1354 case opc_getfield: {
1.1355 int indx = readUShortArg(byteCodes, i);
1.1356 String[] fi = jc.getFieldInfoName(indx);
1.1357 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1358 - final String mangleClass = mangleSig(fi[0]);
1.1359 + final String mangleClass = mangleClassName(fi[0]);
1.1360 final String mangleClassAccess = accessClass(mangleClass);
1.1361 - emit(out, "var @2 = @3.call(@1);",
1.1362 - smapper.popA(),
1.1363 - smapper.pushT(type),
1.1364 + smapper.replace(this, type, "@2.call(@1)",
1.1365 + smapper.getA(0),
1.1366 accessField(mangleClassAccess + "(false)",
1.1367 - "_" + fi[1], fi));
1.1368 + "_" + fi[1], fi)
1.1369 + );
1.1370 i += 2;
1.1371 break;
1.1372 }
1.1373 @@ -1230,9 +1291,9 @@
1.1374 int indx = readUShortArg(byteCodes, i);
1.1375 String[] fi = jc.getFieldInfoName(indx);
1.1376 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1377 - final String mangleClass = mangleSig(fi[0]);
1.1378 + final String mangleClass = mangleClassName(fi[0]);
1.1379 final String mangleClassAccess = accessClass(mangleClass);
1.1380 - emit(out, "@3.call(@2, @1);",
1.1381 + emit(smapper, this, "@3.call(@2, @1);",
1.1382 smapper.popT(type),
1.1383 smapper.popA(),
1.1384 accessField(mangleClassAccess + "(false)",
1.1385 @@ -1244,11 +1305,8 @@
1.1386 int indx = readUShortArg(byteCodes, i);
1.1387 String[] fi = jc.getFieldInfoName(indx);
1.1388 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1389 - emit(out, "var @1 = @2();",
1.1390 - smapper.pushT(type),
1.1391 - accessField(accessClass(fi[0].replace('/', '_'))
1.1392 - + "(false)",
1.1393 - "_" + fi[1], fi));
1.1394 + String ac = accessClass(mangleClassName(fi[0]));
1.1395 + smapper.assign(this, type, ac + "(false)._" + fi[1] + "()");
1.1396 i += 2;
1.1397 addReference(fi[0]);
1.1398 break;
1.1399 @@ -1257,10 +1315,8 @@
1.1400 int indx = readUShortArg(byteCodes, i);
1.1401 String[] fi = jc.getFieldInfoName(indx);
1.1402 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1403 - emit(out, "@1(@2);",
1.1404 - accessField(accessClass(fi[0].replace('/', '_'))
1.1405 - + "(false)",
1.1406 - "_" + fi[1], fi),
1.1407 + emit(smapper, this, "@1(false)._@2(@3);",
1.1408 + accessClass(mangleClassName(fi[0])), fi[1],
1.1409 smapper.popT(type));
1.1410 i += 2;
1.1411 addReference(fi[0]);
1.1412 @@ -1279,22 +1335,22 @@
1.1413 break;
1.1414 }
1.1415 case opc_athrow: {
1.1416 - final Variable v = smapper.popA();
1.1417 + final CharSequence v = smapper.popA();
1.1418 smapper.clear();
1.1419
1.1420 - emit(out, "{ var @1 = @2; throw @2; }",
1.1421 + emit(smapper, this, "{ var @1 = @2; throw @2; }",
1.1422 smapper.pushA(), v);
1.1423 break;
1.1424 }
1.1425
1.1426 case opc_monitorenter: {
1.1427 - out.append("/* monitor enter */");
1.1428 + debug("/* monitor enter */");
1.1429 smapper.popA();
1.1430 break;
1.1431 }
1.1432
1.1433 case opc_monitorexit: {
1.1434 - out.append("/* monitor exit */");
1.1435 + debug("/* monitor exit */");
1.1436 smapper.popA();
1.1437 break;
1.1438 }
1.1439 @@ -1305,31 +1361,39 @@
1.1440
1.1441 default: {
1.1442 wide = false;
1.1443 - emit(out, "throw 'unknown bytecode @1';",
1.1444 + emit(smapper, this, "throw 'unknown bytecode @1';",
1.1445 Integer.toString(c));
1.1446 }
1.1447 }
1.1448 if (debug(" //")) {
1.1449 generateByteCodeComment(prev, i, byteCodes);
1.1450 }
1.1451 - out.append("\n");
1.1452 + if (outChanged) {
1.1453 + append("\n");
1.1454 + }
1.1455 }
1.1456 if (previousTrap != null) {
1.1457 generateCatch(previousTrap, byteCodes.length, topMostLabel);
1.1458 }
1.1459 - out.append("\n }\n");
1.1460 + if (didBranches) {
1.1461 + append("\n }\n");
1.1462 + }
1.1463 while (openBraces-- > 0) {
1.1464 - out.append('}');
1.1465 + append('}');
1.1466 }
1.1467 - out.append("\n};");
1.1468 + append("\n};");
1.1469 }
1.1470
1.1471 - private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
1.1472 + private int generateIf(StackMapper mapper, byte[] byteCodes,
1.1473 + int i, final CharSequence v2, final CharSequence v1,
1.1474 + final String test, int topMostLabel
1.1475 + ) throws IOException {
1.1476 + mapper.flush(this);
1.1477 int indx = i + readShortArg(byteCodes, i);
1.1478 - out.append("if (").append(v1)
1.1479 - .append(' ').append(test).append(' ')
1.1480 - .append(v2).append(") ");
1.1481 - goTo(out, i, indx, topMostLabel);
1.1482 + append("if ((").append(v1)
1.1483 + .append(") ").append(test).append(" (")
1.1484 + .append(v2).append(")) ");
1.1485 + goTo(this, i, indx, topMostLabel);
1.1486 return i + 2;
1.1487 }
1.1488
1.1489 @@ -1442,8 +1506,20 @@
1.1490 return mangleSig(sig, 0, sig.length());
1.1491 }
1.1492
1.1493 + private static String mangleMethodName(String name) {
1.1494 + StringBuilder sb = new StringBuilder(name.length() * 2);
1.1495 + int last = name.length();
1.1496 + for (int i = 0; i < last; i++) {
1.1497 + final char ch = name.charAt(i);
1.1498 + switch (ch) {
1.1499 + case '_': sb.append("_1"); break;
1.1500 + default: sb.append(ch); break;
1.1501 + }
1.1502 + }
1.1503 + return sb.toString();
1.1504 + }
1.1505 private static String mangleSig(String txt, int first, int last) {
1.1506 - StringBuilder sb = new StringBuilder();
1.1507 + StringBuilder sb = new StringBuilder((last - first) * 2);
1.1508 for (int i = first; i < last; i++) {
1.1509 final char ch = txt.charAt(i);
1.1510 switch (ch) {
1.1511 @@ -1456,6 +1532,10 @@
1.1512 }
1.1513 return sb.toString();
1.1514 }
1.1515 +
1.1516 + private static String mangleClassName(String name) {
1.1517 + return mangleSig(name);
1.1518 + }
1.1519
1.1520 private static String findMethodName(MethodData m, StringBuilder cnt) {
1.1521 StringBuilder name = new StringBuilder();
1.1522 @@ -1464,7 +1544,7 @@
1.1523 } else if ("<clinit>".equals(m.getName())) { // NOI18N
1.1524 name.append("class"); // NOI18N
1.1525 } else {
1.1526 - name.append(m.getName());
1.1527 + name.append(mangleMethodName(m.getName()));
1.1528 }
1.1529
1.1530 countArgs(m.getInternalSig(), new char[1], name, cnt);
1.1531 @@ -1478,7 +1558,7 @@
1.1532 if ("<init>".equals(nm)) { // NOI18N
1.1533 name.append("cons"); // NOI18N
1.1534 } else {
1.1535 - name.append(nm);
1.1536 + name.append(mangleMethodName(nm));
1.1537 }
1.1538 countArgs(descr, returnType, name, cnt);
1.1539 return name.toString();
1.1540 @@ -1493,14 +1573,14 @@
1.1541 String mn = findMethodName(mi, cnt, returnType);
1.1542
1.1543 final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
1.1544 - final Variable[] vars = new Variable[numArguments];
1.1545 + final CharSequence[] vars = new CharSequence[numArguments];
1.1546
1.1547 for (int j = numArguments - 1; j >= 0; --j) {
1.1548 - vars[j] = mapper.pop();
1.1549 + vars[j] = mapper.popValue();
1.1550 }
1.1551
1.1552 if (returnType[0] != 'V') {
1.1553 - out.append("var ")
1.1554 + append("var ")
1.1555 .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
1.1556 .append(" = ");
1.1557 }
1.1558 @@ -1510,20 +1590,20 @@
1.1559 if (mn.startsWith("cons_")) {
1.1560 object += ".constructor";
1.1561 }
1.1562 - out.append(accessStaticMethod(object, mn, mi));
1.1563 + append(accessStaticMethod(object, mn, mi));
1.1564 if (isStatic) {
1.1565 - out.append('(');
1.1566 + append('(');
1.1567 } else {
1.1568 - out.append(".call(");
1.1569 + append(".call(");
1.1570 }
1.1571 if (numArguments > 0) {
1.1572 - out.append(vars[0]);
1.1573 + append(vars[0]);
1.1574 for (int j = 1; j < numArguments; ++j) {
1.1575 - out.append(", ");
1.1576 - out.append(vars[j]);
1.1577 + append(", ");
1.1578 + append(vars[j]);
1.1579 }
1.1580 }
1.1581 - out.append(");");
1.1582 + append(");");
1.1583 i += 2;
1.1584 addReference(in);
1.1585 return i;
1.1586 @@ -1537,27 +1617,27 @@
1.1587 String mn = findMethodName(mi, cnt, returnType);
1.1588
1.1589 final int numArguments = cnt.length() + 1;
1.1590 - final Variable[] vars = new Variable[numArguments];
1.1591 + final CharSequence[] vars = new CharSequence[numArguments];
1.1592
1.1593 for (int j = numArguments - 1; j >= 0; --j) {
1.1594 - vars[j] = mapper.pop();
1.1595 + vars[j] = mapper.popValue();
1.1596 }
1.1597
1.1598 if (returnType[0] != 'V') {
1.1599 - out.append("var ")
1.1600 + append("var ")
1.1601 .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
1.1602 .append(" = ");
1.1603 }
1.1604
1.1605 - out.append(accessVirtualMethod(vars[0].toString(), mn, mi));
1.1606 - out.append('(');
1.1607 + append(accessVirtualMethod(vars[0].toString(), mn, mi));
1.1608 + append('(');
1.1609 String sep = "";
1.1610 for (int j = 1; j < numArguments; ++j) {
1.1611 - out.append(sep);
1.1612 - out.append(vars[j]);
1.1613 + append(sep);
1.1614 + append(vars[j]);
1.1615 sep = ", ";
1.1616 }
1.1617 - out.append(");");
1.1618 + append(");");
1.1619 i += 2;
1.1620 return i;
1.1621 }
1.1622 @@ -1587,10 +1667,10 @@
1.1623 String s = jc.stringValue(entryIndex, classRef);
1.1624 if (classRef[0] != null) {
1.1625 if (classRef[0].startsWith("[")) {
1.1626 - s = accessClass("java_lang_Class") + "(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('" + classRef[0] + "');";
1.1627 + s = accessClass("java_lang_Class") + "(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('" + classRef[0] + "')";
1.1628 } else {
1.1629 addReference(classRef[0]);
1.1630 - s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
1.1631 + s = accessClass(mangleClassName(s)) + "(false).constructor.$class";
1.1632 }
1.1633 }
1.1634 return s;
1.1635 @@ -1602,6 +1682,7 @@
1.1636 return null;
1.1637 }
1.1638 final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
1.1639 + final String htmlType = "Lnet/java/html/js/JavaScriptBody;";
1.1640 class P extends AnnotationParser {
1.1641 public P() {
1.1642 super(false, true);
1.1643 @@ -1610,6 +1691,8 @@
1.1644 int cnt;
1.1645 String[] args = new String[30];
1.1646 String body;
1.1647 + boolean javacall;
1.1648 + boolean html4j;
1.1649
1.1650 @Override
1.1651 protected void visitAttr(String type, String attr, String at, String value) {
1.1652 @@ -1622,6 +1705,18 @@
1.1653 throw new IllegalArgumentException(attr);
1.1654 }
1.1655 }
1.1656 + if (type.equals(htmlType)) {
1.1657 + html4j = true;
1.1658 + if ("body".equals(attr)) {
1.1659 + body = value;
1.1660 + } else if ("args".equals(attr)) {
1.1661 + args[cnt++] = value;
1.1662 + } else if ("javacall".equals(attr)) {
1.1663 + javacall = "1".equals(value);
1.1664 + } else {
1.1665 + throw new IllegalArgumentException(attr);
1.1666 + }
1.1667 + }
1.1668 }
1.1669 }
1.1670 P p = new P();
1.1671 @@ -1631,23 +1726,153 @@
1.1672 }
1.1673 StringBuilder cnt = new StringBuilder();
1.1674 final String mn = findMethodName(m, cnt);
1.1675 - out.append(destObject).append(".").append(mn);
1.1676 - out.append(" = function(");
1.1677 + append(destObject).append(".").append(mn);
1.1678 + append(" = function(");
1.1679 String space = "";
1.1680 int index = 0;
1.1681 + StringBuilder toValue = new StringBuilder();
1.1682 for (int i = 0; i < cnt.length(); i++) {
1.1683 - out.append(space);
1.1684 - space = outputArg(out, p.args, index);
1.1685 + append(space);
1.1686 + space = outputArg(this, p.args, index);
1.1687 + if (p.html4j && space.length() > 0) {
1.1688 + toValue.append("\n ").append(p.args[index]).append(" = vm.org_apidesign_bck2brwsr_emul_lang_System(false).toJS(").
1.1689 + append(p.args[index]).append(");");
1.1690 + }
1.1691 index++;
1.1692 }
1.1693 - out.append(") {").append("\n");
1.1694 - out.append(p.body);
1.1695 - out.append("\n}\n");
1.1696 + append(") {").append("\n");
1.1697 + append(toValue.toString());
1.1698 + if (p.javacall) {
1.1699 + int lastSlash = jc.getClassName().lastIndexOf('/');
1.1700 + final String pkg = jc.getClassName().substring(0, lastSlash);
1.1701 + append(mangleCallbacks(pkg, p.body));
1.1702 + requireReference(pkg + "/$JsCallbacks$");
1.1703 + } else {
1.1704 + append(p.body);
1.1705 + }
1.1706 + append("\n}\n");
1.1707 return mn;
1.1708 }
1.1709 +
1.1710 + private static CharSequence mangleCallbacks(String pkgName, String body) {
1.1711 + StringBuilder sb = new StringBuilder();
1.1712 + int pos = 0;
1.1713 + for (;;) {
1.1714 + int next = body.indexOf(".@", pos);
1.1715 + if (next == -1) {
1.1716 + sb.append(body.substring(pos));
1.1717 + body = sb.toString();
1.1718 + break;
1.1719 + }
1.1720 + int ident = next;
1.1721 + while (ident > 0) {
1.1722 + if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
1.1723 + ident++;
1.1724 + break;
1.1725 + }
1.1726 + }
1.1727 + String refId = body.substring(ident, next);
1.1728 +
1.1729 + sb.append(body.substring(pos, ident));
1.1730 +
1.1731 + int sigBeg = body.indexOf('(', next);
1.1732 + int sigEnd = body.indexOf(')', sigBeg);
1.1733 + int colon4 = body.indexOf("::", next);
1.1734 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
1.1735 + throw new IllegalStateException("Malformed body " + body);
1.1736 + }
1.1737 + String fqn = body.substring(next + 2, colon4);
1.1738 + String method = body.substring(colon4 + 2, sigBeg);
1.1739 + String params = body.substring(sigBeg, sigEnd + 1);
1.1740 +
1.1741 + int paramBeg = body.indexOf('(', sigEnd + 1);
1.1742 +
1.1743 + sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
1.1744 + sb.append(mangleJsCallbacks(fqn, method, params, false));
1.1745 + sb.append("(").append(refId);
1.1746 + if (body.charAt(paramBeg + 1) != ')') {
1.1747 + sb.append(",");
1.1748 + }
1.1749 + pos = paramBeg + 1;
1.1750 + }
1.1751 + sb = null;
1.1752 + pos = 0;
1.1753 + for (;;) {
1.1754 + int next = body.indexOf("@", pos);
1.1755 + if (next == -1) {
1.1756 + if (sb == null) {
1.1757 + return body;
1.1758 + }
1.1759 + sb.append(body.substring(pos));
1.1760 + return sb;
1.1761 + }
1.1762 + if (sb == null) {
1.1763 + sb = new StringBuilder();
1.1764 + }
1.1765 +
1.1766 + sb.append(body.substring(pos, next));
1.1767 +
1.1768 + int sigBeg = body.indexOf('(', next);
1.1769 + int sigEnd = body.indexOf(')', sigBeg);
1.1770 + int colon4 = body.indexOf("::", next);
1.1771 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
1.1772 + throw new IllegalStateException("Malformed body " + body);
1.1773 + }
1.1774 + String fqn = body.substring(next + 1, colon4);
1.1775 + String method = body.substring(colon4 + 2, sigBeg);
1.1776 + String params = body.substring(sigBeg, sigEnd + 1);
1.1777 +
1.1778 + int paramBeg = body.indexOf('(', sigEnd + 1);
1.1779 +
1.1780 + sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
1.1781 + sb.append(mangleJsCallbacks(fqn, method, params, true));
1.1782 + sb.append("(");
1.1783 + pos = paramBeg + 1;
1.1784 + }
1.1785 + }
1.1786 +
1.1787 + static String mangleJsCallbacks(String fqn, String method, String params, boolean isStatic) {
1.1788 + if (params.startsWith("(")) {
1.1789 + params = params.substring(1);
1.1790 + }
1.1791 + if (params.endsWith(")")) {
1.1792 + params = params.substring(0, params.length() - 1);
1.1793 + }
1.1794 + StringBuilder sb = new StringBuilder();
1.1795 + final String fqnu = fqn.replace('.', '_');
1.1796 + final String rfqn = mangleClassName(fqnu);
1.1797 + final String rm = mangleMethodName(method);
1.1798 + final String srp;
1.1799 + {
1.1800 + StringBuilder pb = new StringBuilder();
1.1801 + int len = params.length();
1.1802 + int indx = 0;
1.1803 + while (indx < len) {
1.1804 + char ch = params.charAt(indx);
1.1805 + if (ch == '[' || ch == 'L') {
1.1806 + pb.append("Ljava/lang/Object;");
1.1807 + indx = params.indexOf(';', indx) + 1;
1.1808 + } else {
1.1809 + pb.append(ch);
1.1810 + indx++;
1.1811 + }
1.1812 + }
1.1813 + srp = mangleSig(pb.toString());
1.1814 + }
1.1815 + final String rp = mangleSig(params);
1.1816 + final String mrp = mangleMethodName(rp);
1.1817 + sb.append(rfqn).append("$").append(rm).
1.1818 + append('$').append(mrp).append("__Ljava_lang_Object_2");
1.1819 + if (!isStatic) {
1.1820 + sb.append('L').append(fqnu).append("_2");
1.1821 + }
1.1822 + sb.append(srp);
1.1823 + return sb.toString();
1.1824 + }
1.1825 +
1.1826 private static String className(ClassData jc) {
1.1827 //return jc.getName().getInternalName().replace('/', '_');
1.1828 - return jc.getClassName().replace('/', '_');
1.1829 + return mangleClassName(jc.getClassName());
1.1830 }
1.1831
1.1832 private static String[] findAnnotation(
1.1833 @@ -1697,7 +1922,7 @@
1.1834 return " = null;";
1.1835 }
1.1836
1.1837 - private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
1.1838 + private void generateAnno(ClassData cd, byte[] data) throws IOException {
1.1839 AnnotationParser ap = new AnnotationParser(true, false) {
1.1840 int[] cnt = new int[32];
1.1841 int depth;
1.1842 @@ -1708,39 +1933,39 @@
1.1843 requireReference(slashType);
1.1844
1.1845 if (cnt[depth]++ > 0) {
1.1846 - out.append(",");
1.1847 + append(",");
1.1848 }
1.1849 if (top) {
1.1850 - out.append('"').append(attrType).append("\" : ");
1.1851 + append('"').append(attrType).append("\" : ");
1.1852 }
1.1853 - out.append("{\n");
1.1854 + append("{\n");
1.1855 cnt[++depth] = 0;
1.1856 }
1.1857
1.1858 @Override
1.1859 protected void visitAnnotationEnd(String type, boolean top) throws IOException {
1.1860 - out.append("\n}\n");
1.1861 + append("\n}\n");
1.1862 depth--;
1.1863 }
1.1864
1.1865 @Override
1.1866 protected void visitValueStart(String attrName, char type) throws IOException {
1.1867 if (cnt[depth]++ > 0) {
1.1868 - out.append(",\n");
1.1869 + append(",\n");
1.1870 }
1.1871 cnt[++depth] = 0;
1.1872 if (attrName != null) {
1.1873 - out.append(attrName).append(" : ");
1.1874 + append(attrName).append(" : ");
1.1875 }
1.1876 if (type == '[') {
1.1877 - out.append("[");
1.1878 + append("[");
1.1879 }
1.1880 }
1.1881
1.1882 @Override
1.1883 protected void visitValueEnd(String attrName, char type) throws IOException {
1.1884 if (type == '[') {
1.1885 - out.append("]");
1.1886 + append("]");
1.1887 }
1.1888 depth--;
1.1889 }
1.1890 @@ -1751,7 +1976,7 @@
1.1891 if (attr == null && value == null) {
1.1892 return;
1.1893 }
1.1894 - out.append(value);
1.1895 + append(value);
1.1896 }
1.1897
1.1898 @Override
1.1899 @@ -1760,8 +1985,8 @@
1.1900 final String slashType = attrType.substring(1, attrType.length() - 1);
1.1901 requireReference(slashType);
1.1902
1.1903 - out.append(accessClass(slashType.replace('/', '_')))
1.1904 - .append("(false).constructor.").append(value);
1.1905 + append(accessClass(mangleClassName(slashType)))
1.1906 + .append("(false).constructor.fld_").append(value);
1.1907 }
1.1908 };
1.1909 ap.parse(data, cd);
1.1910 @@ -1779,7 +2004,21 @@
1.1911 return ",";
1.1912 }
1.1913
1.1914 - private static void emit(final Appendable out,
1.1915 + final void emitNoFlush(
1.1916 + StackMapper sm,
1.1917 + final String format, final CharSequence... params
1.1918 + ) throws IOException {
1.1919 + emitImpl(this, format, params);
1.1920 + }
1.1921 + static final void emit(
1.1922 + StackMapper sm,
1.1923 + final Appendable out,
1.1924 + final String format, final CharSequence... params
1.1925 + ) throws IOException {
1.1926 + sm.flush(out);
1.1927 + emitImpl(out, format, params);
1.1928 + }
1.1929 + static void emitImpl(final Appendable out,
1.1930 final String format,
1.1931 final CharSequence... params) throws IOException {
1.1932 final int length = format.length();
1.1933 @@ -1805,7 +2044,7 @@
1.1934 }
1.1935
1.1936 private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException {
1.1937 - out.append("} catch (e) {\n");
1.1938 + append("} catch (e) {\n");
1.1939 int finallyPC = -1;
1.1940 for (TrapData e : traps) {
1.1941 if (e == null) {
1.1942 @@ -1814,22 +2053,22 @@
1.1943 if (e.catch_cpx != 0) { //not finally
1.1944 final String classInternalName = jc.getClassName(e.catch_cpx);
1.1945 addReference(classInternalName);
1.1946 - out.append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
1.1947 - out.append("if (e['$instOf_" + classInternalName.replace('/', '_') + "']) {");
1.1948 - out.append("var stA0 = e;");
1.1949 - goTo(out, current, e.handler_pc, topMostLabel);
1.1950 - out.append("}\n");
1.1951 + append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
1.1952 + append("if (e['$instOf_" + classInternalName.replace('/', '_') + "']) {");
1.1953 + append("var stA0 = e;");
1.1954 + goTo(this, current, e.handler_pc, topMostLabel);
1.1955 + append("}\n");
1.1956 } else {
1.1957 finallyPC = e.handler_pc;
1.1958 }
1.1959 }
1.1960 if (finallyPC == -1) {
1.1961 - out.append("throw e;");
1.1962 + append("throw e;");
1.1963 } else {
1.1964 - out.append("var stA0 = e;");
1.1965 - goTo(out, current, finallyPC, topMostLabel);
1.1966 + append("var stA0 = e;");
1.1967 + goTo(this, current, finallyPC, topMostLabel);
1.1968 }
1.1969 - out.append("\n}");
1.1970 + append("\n}");
1.1971 }
1.1972
1.1973 private static void goTo(Appendable out, int current, int to, int canBack) throws IOException {
1.1974 @@ -1845,10 +2084,13 @@
1.1975 }
1.1976
1.1977 private static void emitIf(
1.1978 - Appendable out, String pattern, Variable param,
1.1979 + StackMapper sm,
1.1980 + Appendable out, String pattern,
1.1981 + CharSequence param,
1.1982 int current, int to, int canBack
1.1983 ) throws IOException {
1.1984 - emit(out, pattern, param);
1.1985 + sm.flush(out);
1.1986 + emitImpl(out, pattern, param);
1.1987 goTo(out, current, to, canBack);
1.1988 }
1.1989
1.1990 @@ -1865,7 +2107,8 @@
1.1991 case 11: jvmType = "[J"; break;
1.1992 default: throw new IllegalStateException("Array type: " + atype);
1.1993 }
1.1994 - emit(out, "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);",
1.1995 + emit(smapper, this,
1.1996 + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);",
1.1997 smapper.popI(), smapper.pushA(), jvmType);
1.1998 }
1.1999
1.2000 @@ -1876,7 +2119,8 @@
1.2001 } else {
1.2002 typeName = "[L" + typeName + ";";
1.2003 }
1.2004 - emit(out, "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);",
1.2005 + emit(smapper, this,
1.2006 + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);",
1.2007 smapper.popI(), smapper.pushA(), typeName);
1.2008 }
1.2009
1.2010 @@ -1892,7 +2136,8 @@
1.2011 dims.insert(1, smapper.popI());
1.2012 }
1.2013 dims.append(']');
1.2014 - emit(out, "var @2 = Array.prototype['multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II']('@3', @1, 0);",
1.2015 + emit(smapper, this,
1.2016 + "var @2 = Array.prototype['multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II']('@3', @1, 0);",
1.2017 dims.toString(), smapper.pushA(), typeName);
1.2018 return i;
1.2019 }
1.2020 @@ -1905,16 +2150,18 @@
1.2021 table += 4;
1.2022 int high = readInt4(byteCodes, table);
1.2023 table += 4;
1.2024 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.2025 + final CharSequence swVar = smapper.popValue();
1.2026 + smapper.flush(this);
1.2027 + append("switch (").append(swVar).append(") {\n");
1.2028 while (low <= high) {
1.2029 int offset = i + readInt4(byteCodes, table);
1.2030 table += 4;
1.2031 - out.append(" case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n');
1.2032 + append(" case " + low).append(":"); goTo(this, i, offset, topMostLabel); append('\n');
1.2033 low++;
1.2034 }
1.2035 - out.append(" default: ");
1.2036 - goTo(out, i, dflt, topMostLabel);
1.2037 - out.append("\n}");
1.2038 + append(" default: ");
1.2039 + goTo(this, i, dflt, topMostLabel);
1.2040 + append("\n}");
1.2041 i = table - 1;
1.2042 return i;
1.2043 }
1.2044 @@ -1925,17 +2172,19 @@
1.2045 table += 4;
1.2046 int n = readInt4(byteCodes, table);
1.2047 table += 4;
1.2048 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.2049 + final CharSequence swVar = smapper.popValue();
1.2050 + smapper.flush(this);
1.2051 + append("switch (").append(swVar).append(") {\n");
1.2052 while (n-- > 0) {
1.2053 int cnstnt = readInt4(byteCodes, table);
1.2054 table += 4;
1.2055 int offset = i + readInt4(byteCodes, table);
1.2056 table += 4;
1.2057 - out.append(" case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n');
1.2058 + append(" case " + cnstnt).append(": "); goTo(this, i, offset, topMostLabel); append('\n');
1.2059 }
1.2060 - out.append(" default: ");
1.2061 - goTo(out, i, dflt, topMostLabel);
1.2062 - out.append("\n}");
1.2063 + append(" default: ");
1.2064 + goTo(this, i, dflt, topMostLabel);
1.2065 + append("\n}");
1.2066 i = table - 1;
1.2067 return i;
1.2068 }
1.2069 @@ -1943,11 +2192,13 @@
1.2070 private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
1.2071 final String type = jc.getClassName(indx);
1.2072 if (!type.startsWith("[")) {
1.2073 - emit(out, "var @2 = @1 != null && @1['$instOf_@3'] ? 1 : 0;",
1.2074 + emit(smapper, this,
1.2075 + "var @2 = @1 != null && @1['$instOf_@3'] ? 1 : 0;",
1.2076 smapper.popA(), smapper.pushI(),
1.2077 type.replace('/', '_'));
1.2078 } else {
1.2079 - 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.2080 + emit(smapper, this,
1.2081 + "var @2 = vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@3')['isInstance__ZLjava_lang_Object_2'](@1);",
1.2082 smapper.popA(), smapper.pushI(),
1.2083 type
1.2084 );
1.2085 @@ -1957,21 +2208,22 @@
1.2086 private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
1.2087 final String type = jc.getClassName(indx);
1.2088 if (!type.startsWith("[")) {
1.2089 - emit(out,
1.2090 + emitNoFlush(smapper,
1.2091 "if (@1 !== null && !@1['$instOf_@2']) throw vm.java_lang_ClassCastException(true);",
1.2092 - smapper.getA(0), type.replace('/', '_'));
1.2093 + smapper.getT(0, VarType.REFERENCE, false), type.replace('/', '_'));
1.2094 } else {
1.2095 - 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.2096 - smapper.getA(0), type
1.2097 + emitNoFlush(smapper,
1.2098 + "vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@2')['cast__Ljava_lang_Object_2Ljava_lang_Object_2'](@1);",
1.2099 + smapper.getT(0, VarType.REFERENCE, false), type
1.2100 );
1.2101 }
1.2102 }
1.2103
1.2104 private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
1.2105 for (int j = prev; j <= i; j++) {
1.2106 - out.append(" ");
1.2107 + append(" ");
1.2108 final int cc = readUByte(byteCodes, j);
1.2109 - out.append(Integer.toString(cc));
1.2110 + append(Integer.toString(cc));
1.2111 }
1.2112 }
1.2113 }