1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Feb 14 12:06:16 2013 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1820 +0,0 @@
1.4 -/**
1.5 - * Back 2 Browser Bytecode Translator
1.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 - *
1.8 - * This program is free software: you can redistribute it and/or modify
1.9 - * it under the terms of the GNU General Public License as published by
1.10 - * the Free Software Foundation, version 2 of the License.
1.11 - *
1.12 - * This program is distributed in the hope that it will be useful,
1.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 - * GNU General Public License for more details.
1.16 - *
1.17 - * You should have received a copy of the GNU General Public License
1.18 - * along with this program. Look for COPYING file in the top folder.
1.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 - */
1.21 -package org.apidesign.vm4brwsr;
1.22 -
1.23 -import java.io.IOException;
1.24 -import java.io.InputStream;
1.25 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.26 -import org.apidesign.javap.AnnotationParser;
1.27 -import org.apidesign.javap.ClassData;
1.28 -import org.apidesign.javap.FieldData;
1.29 -import org.apidesign.javap.MethodData;
1.30 -import org.apidesign.javap.StackMapIterator;
1.31 -import static org.apidesign.javap.RuntimeConstants.*;
1.32 -import org.apidesign.javap.TrapData;
1.33 -import org.apidesign.javap.TrapDataIterator;
1.34 -
1.35 -/** Translator of the code inside class files to JavaScript.
1.36 - *
1.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
1.38 - */
1.39 -abstract class ByteCodeToJavaScript {
1.40 - private ClassData jc;
1.41 - final Appendable out;
1.42 -
1.43 - protected ByteCodeToJavaScript(Appendable out) {
1.44 - this.out = out;
1.45 - }
1.46 -
1.47 - /* Collects additional required resources.
1.48 - *
1.49 - * @param internalClassName classes that were referenced and should be loaded in order the
1.50 - * generated JavaScript code works properly. The names are in internal
1.51 - * JVM form so String is <code>java/lang/String</code>.
1.52 - */
1.53 - protected abstract boolean requireReference(String internalClassName);
1.54 -
1.55 - /*
1.56 - * @param resourcePath name of resources to read
1.57 - */
1.58 - protected abstract void requireScript(String resourcePath) throws IOException;
1.59 -
1.60 - /** Allows subclasses to redefine what field a function representing a
1.61 - * class gets assigned. By default it returns the suggested name followed
1.62 - * by <code>" = "</code>;
1.63 - *
1.64 - * @param className suggested name of the class
1.65 - */
1.66 - /* protected */ String assignClass(String className) {
1.67 - return className + " = ";
1.68 - }
1.69 - /* protected */ String accessClass(String classOperation) {
1.70 - return classOperation;
1.71 - }
1.72 -
1.73 - /** Prints out a debug message.
1.74 - *
1.75 - * @param msg the message
1.76 - * @return true if the message has been printed
1.77 - * @throws IOException
1.78 - */
1.79 - boolean debug(String msg) throws IOException {
1.80 - out.append(msg);
1.81 - return true;
1.82 - }
1.83 -
1.84 - /**
1.85 - * Converts a given class file to a JavaScript version.
1.86 - *
1.87 - * @param classFile input stream with code of the .class file
1.88 - * @return the initialization code for this class, if any. Otherwise <code>null</code>
1.89 - *
1.90 - * @throws IOException if something goes wrong during read or write or translating
1.91 - */
1.92 -
1.93 - public String compile(InputStream classFile) throws IOException {
1.94 - this.jc = new ClassData(classFile);
1.95 - if (jc.getMajor_version() < 50) {
1.96 - throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "."
1.97 - + jc.getMinor_version() + " - recompile with -target 1.6 (at least)."
1.98 - );
1.99 - }
1.100 - byte[] arrData = jc.findAnnotationData(true);
1.101 - String[] arr = findAnnotation(arrData, jc,
1.102 - "org.apidesign.bck2brwsr.core.ExtraJavaScript",
1.103 - "resource", "processByteCode"
1.104 - );
1.105 - if (arr != null) {
1.106 - requireScript(arr[0]);
1.107 - if ("0".equals(arr[1])) {
1.108 - return null;
1.109 - }
1.110 - }
1.111 - String[] proto = findAnnotation(arrData, jc,
1.112 - "org.apidesign.bck2brwsr.core.JavaScriptPrototype",
1.113 - "container", "prototype"
1.114 - );
1.115 - StringArray toInitilize = new StringArray();
1.116 - final String className = className(jc);
1.117 - out.append("\n\n").append(assignClass(className));
1.118 - out.append("function CLS() {");
1.119 - out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
1.120 - if (proto == null) {
1.121 - String sc = jc.getSuperClassName(); // with _
1.122 - out.append("\n var pp = ").
1.123 - append(accessClass(sc.replace('/', '_'))).append("(true);");
1.124 - out.append("\n var p = CLS.prototype = pp;");
1.125 - out.append("\n var c = p;");
1.126 - out.append("\n var sprcls = pp.constructor.$class;");
1.127 - } else {
1.128 - out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
1.129 - if (proto[0] == null) {
1.130 - proto[0] = "p";
1.131 - }
1.132 - out.append("\n var c = ").append(proto[0]).append(";");
1.133 - out.append("\n var sprcls = null;");
1.134 - }
1.135 - for (FieldData v : jc.getFields()) {
1.136 - if (v.isStatic()) {
1.137 - out.append("\n CLS.").append(v.getName()).append(initField(v));
1.138 - } else {
1.139 - out.append("\n c._").append(v.getName()).append(" = function (v) {")
1.140 - .append(" if (arguments.length == 1) this.fld_").
1.141 - append(className).append('_').append(v.getName())
1.142 - .append(" = v; return this.fld_").
1.143 - append(className).append('_').append(v.getName())
1.144 - .append("; };");
1.145 - }
1.146 - }
1.147 - for (MethodData m : jc.getMethods()) {
1.148 - byte[] onlyArr = m.findAnnotationData(true);
1.149 - String[] only = findAnnotation(onlyArr, jc,
1.150 - "org.apidesign.bck2brwsr.core.JavaScriptOnly",
1.151 - "name", "value"
1.152 - );
1.153 - if (only != null) {
1.154 - if (only[0] != null && only[1] != null) {
1.155 - out.append("\n p.").append(only[0]).append(" = ")
1.156 - .append(only[1]).append(";");
1.157 - }
1.158 - continue;
1.159 - }
1.160 - String prefix;
1.161 - String mn;
1.162 - if (m.isStatic()) {
1.163 - prefix = "\n c.";
1.164 - mn = generateStaticMethod(prefix, m, toInitilize);
1.165 - } else {
1.166 - if (m.isConstructor()) {
1.167 - prefix = "\n CLS.";
1.168 - mn = generateInstanceMethod(prefix, m);
1.169 - } else {
1.170 - prefix = "\n c.";
1.171 - mn = generateInstanceMethod(prefix, m);
1.172 - }
1.173 - }
1.174 - byte[] runAnno = m.findAnnotationData(false);
1.175 - if (runAnno != null) {
1.176 - out.append(prefix).append(mn).append(".anno = {");
1.177 - generateAnno(jc, out, runAnno);
1.178 - out.append("\n };");
1.179 - }
1.180 - out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
1.181 - }
1.182 - out.append("\n c.constructor = CLS;");
1.183 - out.append("\n c.$instOf_").append(className).append(" = true;");
1.184 - for (String superInterface : jc.getSuperInterfaces()) {
1.185 - out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
1.186 - }
1.187 - out.append("\n CLS.$class = ");
1.188 - out.append(accessClass("java_lang_Class(true);"));
1.189 - out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
1.190 - out.append("\n CLS.$class.superclass = sprcls;");
1.191 - out.append("\n CLS.$class.access = ").append(jc.getAccessFlags()+";");
1.192 - out.append("\n CLS.$class.cnstr = CLS;");
1.193 - byte[] classAnno = jc.findAnnotationData(false);
1.194 - if (classAnno != null) {
1.195 - out.append("\n CLS.$class.anno = {");
1.196 - generateAnno(jc, out, classAnno);
1.197 - out.append("\n };");
1.198 - }
1.199 - out.append("\n }");
1.200 - out.append("\n if (arguments.length === 0) {");
1.201 - out.append("\n if (!(this instanceof CLS)) {");
1.202 - out.append("\n return new CLS();");
1.203 - out.append("\n }");
1.204 - for (FieldData v : jc.getFields()) {
1.205 - byte[] onlyArr = v.findAnnotationData(true);
1.206 - String[] only = findAnnotation(onlyArr, jc,
1.207 - "org.apidesign.bck2brwsr.core.JavaScriptOnly",
1.208 - "name", "value"
1.209 - );
1.210 - if (only != null) {
1.211 - if (only[0] != null && only[1] != null) {
1.212 - out.append("\n p.").append(only[0]).append(" = ")
1.213 - .append(only[1]).append(";");
1.214 - }
1.215 - continue;
1.216 - }
1.217 - if (!v.isStatic()) {
1.218 - out.append("\n this.fld_").
1.219 - append(className).append('_').
1.220 - append(v.getName()).append(initField(v));
1.221 - }
1.222 - }
1.223 - out.append("\n return this;");
1.224 - out.append("\n }");
1.225 - out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
1.226 - out.append("\n};");
1.227 - StringBuilder sb = new StringBuilder();
1.228 - for (String init : toInitilize.toArray()) {
1.229 - sb.append("\n").append(init).append("();");
1.230 - }
1.231 - return sb.toString();
1.232 - }
1.233 - private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
1.234 - String jsb = javaScriptBody(prefix, m, true);
1.235 - if (jsb != null) {
1.236 - return jsb;
1.237 - }
1.238 - final String mn = findMethodName(m, new StringBuilder());
1.239 - if (mn.equals("class__V")) {
1.240 - toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
1.241 - }
1.242 - generateMethod(prefix, mn, m);
1.243 - return mn;
1.244 - }
1.245 -
1.246 - private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
1.247 - String jsb = javaScriptBody(prefix, m, false);
1.248 - if (jsb != null) {
1.249 - return jsb;
1.250 - }
1.251 - final String mn = findMethodName(m, new StringBuilder());
1.252 - generateMethod(prefix, mn, m);
1.253 - return mn;
1.254 - }
1.255 -
1.256 - private void generateMethod(String prefix, String name, MethodData m)
1.257 - throws IOException {
1.258 - final StackMapIterator stackMapIterator = m.createStackMapIterator();
1.259 - TrapDataIterator trap = m.getTrapDataIterator();
1.260 - final LocalsMapper lmapper =
1.261 - new LocalsMapper(stackMapIterator.getArguments());
1.262 -
1.263 - out.append(prefix).append(name).append(" = function(");
1.264 - lmapper.outputArguments(out, m.isStatic());
1.265 - out.append(") {").append("\n");
1.266 -
1.267 - final byte[] byteCodes = m.getCode();
1.268 - if (byteCodes == null) {
1.269 - out.append(" throw 'no code found for ")
1.270 - .append(jc.getClassName()).append('.')
1.271 - .append(m.getName()).append("';\n");
1.272 - out.append("};");
1.273 - return;
1.274 - }
1.275 -
1.276 - final StackMapper smapper = new StackMapper();
1.277 -
1.278 - if (!m.isStatic()) {
1.279 - out.append(" var ").append(" lcA0 = this;\n");
1.280 - }
1.281 -
1.282 - int lastStackFrame = -1;
1.283 - TrapData[] previousTrap = null;
1.284 - boolean wide = false;
1.285 -
1.286 - out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
1.287 - for (int i = 0; i < byteCodes.length; i++) {
1.288 - int prev = i;
1.289 - stackMapIterator.advanceTo(i);
1.290 - boolean changeInCatch = trap.advanceTo(i);
1.291 - if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
1.292 - if (previousTrap != null) {
1.293 - generateCatch(previousTrap);
1.294 - previousTrap = null;
1.295 - }
1.296 - }
1.297 - if (lastStackFrame != stackMapIterator.getFrameIndex()) {
1.298 - lastStackFrame = stackMapIterator.getFrameIndex();
1.299 - lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
1.300 - smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
1.301 - out.append(" case " + i).append(": ");
1.302 - changeInCatch = true;
1.303 - } else {
1.304 - debug(" /* " + i + " */ ");
1.305 - }
1.306 - if (changeInCatch && trap.useTry()) {
1.307 - out.append("try {");
1.308 - previousTrap = trap.current();
1.309 - }
1.310 - final int c = readUByte(byteCodes, i);
1.311 - switch (c) {
1.312 - case opc_aload_0:
1.313 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
1.314 - break;
1.315 - case opc_iload_0:
1.316 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0));
1.317 - break;
1.318 - case opc_lload_0:
1.319 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0));
1.320 - break;
1.321 - case opc_fload_0:
1.322 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0));
1.323 - break;
1.324 - case opc_dload_0:
1.325 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0));
1.326 - break;
1.327 - case opc_aload_1:
1.328 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1));
1.329 - break;
1.330 - case opc_iload_1:
1.331 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1));
1.332 - break;
1.333 - case opc_lload_1:
1.334 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1));
1.335 - break;
1.336 - case opc_fload_1:
1.337 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1));
1.338 - break;
1.339 - case opc_dload_1:
1.340 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1));
1.341 - break;
1.342 - case opc_aload_2:
1.343 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2));
1.344 - break;
1.345 - case opc_iload_2:
1.346 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2));
1.347 - break;
1.348 - case opc_lload_2:
1.349 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2));
1.350 - break;
1.351 - case opc_fload_2:
1.352 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2));
1.353 - break;
1.354 - case opc_dload_2:
1.355 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2));
1.356 - break;
1.357 - case opc_aload_3:
1.358 - emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3));
1.359 - break;
1.360 - case opc_iload_3:
1.361 - emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3));
1.362 - break;
1.363 - case opc_lload_3:
1.364 - emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3));
1.365 - break;
1.366 - case opc_fload_3:
1.367 - emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3));
1.368 - break;
1.369 - case opc_dload_3:
1.370 - emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
1.371 - break;
1.372 - case opc_iload: {
1.373 - ++i;
1.374 - final int indx = wide ? readUShort(byteCodes, i++)
1.375 - : readUByte(byteCodes, i);
1.376 - wide = false;
1.377 - emit(out, "var @1 = @2;",
1.378 - smapper.pushI(), lmapper.getI(indx));
1.379 - break;
1.380 - }
1.381 - case opc_lload: {
1.382 - ++i;
1.383 - final int indx = wide ? readUShort(byteCodes, i++)
1.384 - : readUByte(byteCodes, i);
1.385 - wide = false;
1.386 - emit(out, "var @1 = @2;",
1.387 - smapper.pushL(), lmapper.getL(indx));
1.388 - break;
1.389 - }
1.390 - case opc_fload: {
1.391 - ++i;
1.392 - final int indx = wide ? readUShort(byteCodes, i++)
1.393 - : readUByte(byteCodes, i);
1.394 - wide = false;
1.395 - emit(out, "var @1 = @2;",
1.396 - smapper.pushF(), lmapper.getF(indx));
1.397 - break;
1.398 - }
1.399 - case opc_dload: {
1.400 - ++i;
1.401 - final int indx = wide ? readUShort(byteCodes, i++)
1.402 - : readUByte(byteCodes, i);
1.403 - wide = false;
1.404 - emit(out, "var @1 = @2;",
1.405 - smapper.pushD(), lmapper.getD(indx));
1.406 - break;
1.407 - }
1.408 - case opc_aload: {
1.409 - ++i;
1.410 - final int indx = wide ? readUShort(byteCodes, i++)
1.411 - : readUByte(byteCodes, i);
1.412 - wide = false;
1.413 - emit(out, "var @1 = @2;",
1.414 - smapper.pushA(), lmapper.getA(indx));
1.415 - break;
1.416 - }
1.417 - case opc_istore: {
1.418 - ++i;
1.419 - final int indx = wide ? readUShort(byteCodes, i++)
1.420 - : readUByte(byteCodes, i);
1.421 - wide = false;
1.422 - emit(out, "var @1 = @2;",
1.423 - lmapper.setI(indx), smapper.popI());
1.424 - break;
1.425 - }
1.426 - case opc_lstore: {
1.427 - ++i;
1.428 - final int indx = wide ? readUShort(byteCodes, i++)
1.429 - : readUByte(byteCodes, i);
1.430 - wide = false;
1.431 - emit(out, "var @1 = @2;",
1.432 - lmapper.setL(indx), smapper.popL());
1.433 - break;
1.434 - }
1.435 - case opc_fstore: {
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 - lmapper.setF(indx), smapper.popF());
1.442 - break;
1.443 - }
1.444 - case opc_dstore: {
1.445 - ++i;
1.446 - final int indx = wide ? readUShort(byteCodes, i++)
1.447 - : readUByte(byteCodes, i);
1.448 - wide = false;
1.449 - emit(out, "var @1 = @2;",
1.450 - lmapper.setD(indx), smapper.popD());
1.451 - break;
1.452 - }
1.453 - case opc_astore: {
1.454 - ++i;
1.455 - final int indx = wide ? readUShort(byteCodes, i++)
1.456 - : readUByte(byteCodes, i);
1.457 - wide = false;
1.458 - emit(out, "var @1 = @2;",
1.459 - lmapper.setA(indx), smapper.popA());
1.460 - break;
1.461 - }
1.462 - case opc_astore_0:
1.463 - emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA());
1.464 - break;
1.465 - case opc_istore_0:
1.466 - emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI());
1.467 - break;
1.468 - case opc_lstore_0:
1.469 - emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL());
1.470 - break;
1.471 - case opc_fstore_0:
1.472 - emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF());
1.473 - break;
1.474 - case opc_dstore_0:
1.475 - emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD());
1.476 - break;
1.477 - case opc_astore_1:
1.478 - emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA());
1.479 - break;
1.480 - case opc_istore_1:
1.481 - emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI());
1.482 - break;
1.483 - case opc_lstore_1:
1.484 - emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL());
1.485 - break;
1.486 - case opc_fstore_1:
1.487 - emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF());
1.488 - break;
1.489 - case opc_dstore_1:
1.490 - emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD());
1.491 - break;
1.492 - case opc_astore_2:
1.493 - emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA());
1.494 - break;
1.495 - case opc_istore_2:
1.496 - emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI());
1.497 - break;
1.498 - case opc_lstore_2:
1.499 - emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL());
1.500 - break;
1.501 - case opc_fstore_2:
1.502 - emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF());
1.503 - break;
1.504 - case opc_dstore_2:
1.505 - emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD());
1.506 - break;
1.507 - case opc_astore_3:
1.508 - emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA());
1.509 - break;
1.510 - case opc_istore_3:
1.511 - emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI());
1.512 - break;
1.513 - case opc_lstore_3:
1.514 - emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL());
1.515 - break;
1.516 - case opc_fstore_3:
1.517 - emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF());
1.518 - break;
1.519 - case opc_dstore_3:
1.520 - emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
1.521 - break;
1.522 - case opc_iadd:
1.523 - emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
1.524 - break;
1.525 - case opc_ladd:
1.526 - emit(out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
1.527 - break;
1.528 - case opc_fadd:
1.529 - emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
1.530 - break;
1.531 - case opc_dadd:
1.532 - emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
1.533 - break;
1.534 - case opc_isub:
1.535 - emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
1.536 - break;
1.537 - case opc_lsub:
1.538 - emit(out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
1.539 - break;
1.540 - case opc_fsub:
1.541 - emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
1.542 - break;
1.543 - case opc_dsub:
1.544 - emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
1.545 - break;
1.546 - case opc_imul:
1.547 - emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
1.548 - break;
1.549 - case opc_lmul:
1.550 - emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
1.551 - break;
1.552 - case opc_fmul:
1.553 - emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
1.554 - break;
1.555 - case opc_dmul:
1.556 - emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
1.557 - break;
1.558 - case opc_idiv:
1.559 - emit(out, "@1 = Math.floor(@1 / @2);",
1.560 - smapper.getI(1), smapper.popI());
1.561 - break;
1.562 - case opc_ldiv:
1.563 - emit(out, "@1 = @1.div64(@2);",
1.564 - smapper.getL(1), smapper.popL());
1.565 - break;
1.566 - case opc_fdiv:
1.567 - emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
1.568 - break;
1.569 - case opc_ddiv:
1.570 - emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
1.571 - break;
1.572 - case opc_irem:
1.573 - emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
1.574 - break;
1.575 - case opc_lrem:
1.576 - emit(out, "@1 = @1.mod64(@2);",
1.577 - smapper.getL(1), smapper.popL());
1.578 - break;
1.579 - case opc_frem:
1.580 - emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
1.581 - break;
1.582 - case opc_drem:
1.583 - emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
1.584 - break;
1.585 - case opc_iand:
1.586 - emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
1.587 - break;
1.588 - case opc_land:
1.589 - emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
1.590 - break;
1.591 - case opc_ior:
1.592 - emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
1.593 - break;
1.594 - case opc_lor:
1.595 - emit(out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
1.596 - break;
1.597 - case opc_ixor:
1.598 - emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
1.599 - break;
1.600 - case opc_lxor:
1.601 - emit(out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
1.602 - break;
1.603 - case opc_ineg:
1.604 - emit(out, "@1 = @1.neg32();", smapper.getI(0));
1.605 - break;
1.606 - case opc_lneg:
1.607 - emit(out, "@1 = @1.neg64();", smapper.getL(0));
1.608 - break;
1.609 - case opc_fneg:
1.610 - emit(out, "@1 = -@1;", smapper.getF(0));
1.611 - break;
1.612 - case opc_dneg:
1.613 - emit(out, "@1 = -@1;", smapper.getD(0));
1.614 - break;
1.615 - case opc_ishl:
1.616 - emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
1.617 - break;
1.618 - case opc_lshl:
1.619 - emit(out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
1.620 - break;
1.621 - case opc_ishr:
1.622 - emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
1.623 - break;
1.624 - case opc_lshr:
1.625 - emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
1.626 - break;
1.627 - case opc_iushr:
1.628 - emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
1.629 - break;
1.630 - case opc_lushr:
1.631 - emit(out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
1.632 - break;
1.633 - case opc_iinc: {
1.634 - ++i;
1.635 - final int varIndx = wide ? readUShort(byteCodes, i++)
1.636 - : readUByte(byteCodes, i);
1.637 - ++i;
1.638 - final int incrBy = wide ? readShort(byteCodes, i++)
1.639 - : byteCodes[i];
1.640 - wide = false;
1.641 - if (incrBy == 1) {
1.642 - emit(out, "@1++;", lmapper.getI(varIndx));
1.643 - } else {
1.644 - emit(out, "@1 += @2;",
1.645 - lmapper.getI(varIndx),
1.646 - Integer.toString(incrBy));
1.647 - }
1.648 - break;
1.649 - }
1.650 - case opc_return:
1.651 - emit(out, "return;");
1.652 - break;
1.653 - case opc_ireturn:
1.654 - emit(out, "return @1;", smapper.popI());
1.655 - break;
1.656 - case opc_lreturn:
1.657 - emit(out, "return @1;", smapper.popL());
1.658 - break;
1.659 - case opc_freturn:
1.660 - emit(out, "return @1;", smapper.popF());
1.661 - break;
1.662 - case opc_dreturn:
1.663 - emit(out, "return @1;", smapper.popD());
1.664 - break;
1.665 - case opc_areturn:
1.666 - emit(out, "return @1;", smapper.popA());
1.667 - break;
1.668 - case opc_i2l:
1.669 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL());
1.670 - break;
1.671 - case opc_i2f:
1.672 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF());
1.673 - break;
1.674 - case opc_i2d:
1.675 - emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
1.676 - break;
1.677 - case opc_l2i:
1.678 - emit(out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
1.679 - break;
1.680 - // max int check?
1.681 - case opc_l2f:
1.682 - emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
1.683 - break;
1.684 - case opc_l2d:
1.685 - emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
1.686 - break;
1.687 - case opc_f2d:
1.688 - emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
1.689 - break;
1.690 - case opc_d2f:
1.691 - emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
1.692 - break;
1.693 - case opc_f2i:
1.694 - emit(out, "var @2 = Math.floor(@1);",
1.695 - smapper.popF(), smapper.pushI());
1.696 - break;
1.697 - case opc_f2l:
1.698 - emit(out, "var @2 = Math.floor(@1).toLong();",
1.699 - smapper.popF(), smapper.pushL());
1.700 - break;
1.701 - case opc_d2i:
1.702 - emit(out, "var @2 = Math.floor(@1);",
1.703 - smapper.popD(), smapper.pushI());
1.704 - break;
1.705 - case opc_d2l:
1.706 - emit(out, "var @2 = Math.floor(@1).toLong();",
1.707 - smapper.popD(), smapper.pushL());
1.708 - break;
1.709 - case opc_i2b:
1.710 - emit(out, "var @1 = @1.toInt8();", smapper.getI(0));
1.711 - break;
1.712 - case opc_i2c:
1.713 - out.append("{ /* number conversion */ }");
1.714 - break;
1.715 - case opc_i2s:
1.716 - emit(out, "var @1 = @1.toInt16();", smapper.getI(0));
1.717 - break;
1.718 - case opc_aconst_null:
1.719 - emit(out, "var @1 = null;", smapper.pushA());
1.720 - break;
1.721 - case opc_iconst_m1:
1.722 - emit(out, "var @1 = -1;", smapper.pushI());
1.723 - break;
1.724 - case opc_iconst_0:
1.725 - emit(out, "var @1 = 0;", smapper.pushI());
1.726 - break;
1.727 - case opc_dconst_0:
1.728 - emit(out, "var @1 = 0;", smapper.pushD());
1.729 - break;
1.730 - case opc_lconst_0:
1.731 - emit(out, "var @1 = 0;", smapper.pushL());
1.732 - break;
1.733 - case opc_fconst_0:
1.734 - emit(out, "var @1 = 0;", smapper.pushF());
1.735 - break;
1.736 - case opc_iconst_1:
1.737 - emit(out, "var @1 = 1;", smapper.pushI());
1.738 - break;
1.739 - case opc_lconst_1:
1.740 - emit(out, "var @1 = 1;", smapper.pushL());
1.741 - break;
1.742 - case opc_fconst_1:
1.743 - emit(out, "var @1 = 1;", smapper.pushF());
1.744 - break;
1.745 - case opc_dconst_1:
1.746 - emit(out, "var @1 = 1;", smapper.pushD());
1.747 - break;
1.748 - case opc_iconst_2:
1.749 - emit(out, "var @1 = 2;", smapper.pushI());
1.750 - break;
1.751 - case opc_fconst_2:
1.752 - emit(out, "var @1 = 2;", smapper.pushF());
1.753 - break;
1.754 - case opc_iconst_3:
1.755 - emit(out, "var @1 = 3;", smapper.pushI());
1.756 - break;
1.757 - case opc_iconst_4:
1.758 - emit(out, "var @1 = 4;", smapper.pushI());
1.759 - break;
1.760 - case opc_iconst_5:
1.761 - emit(out, "var @1 = 5;", smapper.pushI());
1.762 - break;
1.763 - case opc_ldc: {
1.764 - int indx = readUByte(byteCodes, ++i);
1.765 - String v = encodeConstant(indx);
1.766 - int type = VarType.fromConstantType(jc.getTag(indx));
1.767 - emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.768 - break;
1.769 - }
1.770 - case opc_ldc_w:
1.771 - case opc_ldc2_w: {
1.772 - int indx = readIntArg(byteCodes, i);
1.773 - i += 2;
1.774 - String v = encodeConstant(indx);
1.775 - int type = VarType.fromConstantType(jc.getTag(indx));
1.776 - if (type == VarType.LONG) {
1.777 - final Long lv = new Long(v);
1.778 - final int low = (int)(lv.longValue() & 0xFFFFFFFF);
1.779 - final int hi = (int)(lv.longValue() >> 32);
1.780 - emit(out, "var @1 = 0x@3.next32(0x@2);", smapper.pushL(),
1.781 - Integer.toHexString(low), Integer.toHexString(hi));
1.782 - } else {
1.783 - emit(out, "var @1 = @2;", smapper.pushT(type), v);
1.784 - }
1.785 - break;
1.786 - }
1.787 - case opc_lcmp:
1.788 - emit(out, "var @3 = @2.compare64(@1);",
1.789 - smapper.popL(), smapper.popL(), smapper.pushI());
1.790 - break;
1.791 - case opc_fcmpl:
1.792 - case opc_fcmpg:
1.793 - emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
1.794 - smapper.popF(), smapper.popF(), smapper.pushI());
1.795 - break;
1.796 - case opc_dcmpl:
1.797 - case opc_dcmpg:
1.798 - emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
1.799 - smapper.popD(), smapper.popD(), smapper.pushI());
1.800 - break;
1.801 - case opc_if_acmpeq:
1.802 - i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
1.803 - "===");
1.804 - break;
1.805 - case opc_if_acmpne:
1.806 - i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
1.807 - "!=");
1.808 - break;
1.809 - case opc_if_icmpeq:
1.810 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.811 - "==");
1.812 - break;
1.813 - case opc_ifeq: {
1.814 - int indx = i + readIntArg(byteCodes, i);
1.815 - emit(out, "if (@1 == 0) { gt = @2; continue; }",
1.816 - smapper.popI(), Integer.toString(indx));
1.817 - i += 2;
1.818 - break;
1.819 - }
1.820 - case opc_ifne: {
1.821 - int indx = i + readIntArg(byteCodes, i);
1.822 - emit(out, "if (@1 != 0) { gt = @2; continue; }",
1.823 - smapper.popI(), Integer.toString(indx));
1.824 - i += 2;
1.825 - break;
1.826 - }
1.827 - case opc_iflt: {
1.828 - int indx = i + readIntArg(byteCodes, i);
1.829 - emit(out, "if (@1 < 0) { gt = @2; continue; }",
1.830 - smapper.popI(), Integer.toString(indx));
1.831 - i += 2;
1.832 - break;
1.833 - }
1.834 - case opc_ifle: {
1.835 - int indx = i + readIntArg(byteCodes, i);
1.836 - emit(out, "if (@1 <= 0) { gt = @2; continue; }",
1.837 - smapper.popI(), Integer.toString(indx));
1.838 - i += 2;
1.839 - break;
1.840 - }
1.841 - case opc_ifgt: {
1.842 - int indx = i + readIntArg(byteCodes, i);
1.843 - emit(out, "if (@1 > 0) { gt = @2; continue; }",
1.844 - smapper.popI(), Integer.toString(indx));
1.845 - i += 2;
1.846 - break;
1.847 - }
1.848 - case opc_ifge: {
1.849 - int indx = i + readIntArg(byteCodes, i);
1.850 - emit(out, "if (@1 >= 0) { gt = @2; continue; }",
1.851 - smapper.popI(), Integer.toString(indx));
1.852 - i += 2;
1.853 - break;
1.854 - }
1.855 - case opc_ifnonnull: {
1.856 - int indx = i + readIntArg(byteCodes, i);
1.857 - emit(out, "if (@1 !== null) { gt = @2; continue; }",
1.858 - smapper.popA(), Integer.toString(indx));
1.859 - i += 2;
1.860 - break;
1.861 - }
1.862 - case opc_ifnull: {
1.863 - int indx = i + readIntArg(byteCodes, i);
1.864 - emit(out, "if (@1 === null) { gt = @2; continue; }",
1.865 - smapper.popA(), Integer.toString(indx));
1.866 - i += 2;
1.867 - break;
1.868 - }
1.869 - case opc_if_icmpne:
1.870 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.871 - "!=");
1.872 - break;
1.873 - case opc_if_icmplt:
1.874 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.875 - "<");
1.876 - break;
1.877 - case opc_if_icmple:
1.878 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.879 - "<=");
1.880 - break;
1.881 - case opc_if_icmpgt:
1.882 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.883 - ">");
1.884 - break;
1.885 - case opc_if_icmpge:
1.886 - i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
1.887 - ">=");
1.888 - break;
1.889 - case opc_goto: {
1.890 - int indx = i + readIntArg(byteCodes, i);
1.891 - emit(out, "gt = @1; continue;", Integer.toString(indx));
1.892 - i += 2;
1.893 - break;
1.894 - }
1.895 - case opc_lookupswitch: {
1.896 - int table = i / 4 * 4 + 4;
1.897 - int dflt = i + readInt4(byteCodes, table);
1.898 - table += 4;
1.899 - int n = readInt4(byteCodes, table);
1.900 - table += 4;
1.901 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.902 - while (n-- > 0) {
1.903 - int cnstnt = readInt4(byteCodes, table);
1.904 - table += 4;
1.905 - int offset = i + readInt4(byteCodes, table);
1.906 - table += 4;
1.907 - out.append(" case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
1.908 - }
1.909 - out.append(" default: gt = " + dflt).append("; continue;\n}");
1.910 - i = table - 1;
1.911 - break;
1.912 - }
1.913 - case opc_tableswitch: {
1.914 - int table = i / 4 * 4 + 4;
1.915 - int dflt = i + readInt4(byteCodes, table);
1.916 - table += 4;
1.917 - int low = readInt4(byteCodes, table);
1.918 - table += 4;
1.919 - int high = readInt4(byteCodes, table);
1.920 - table += 4;
1.921 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.922 - while (low <= high) {
1.923 - int offset = i + readInt4(byteCodes, table);
1.924 - table += 4;
1.925 - out.append(" case " + low).append(": gt = " + offset).append("; continue;\n");
1.926 - low++;
1.927 - }
1.928 - out.append(" default: gt = " + dflt).append("; continue;\n}");
1.929 - i = table - 1;
1.930 - break;
1.931 - }
1.932 - case opc_invokeinterface: {
1.933 - i = invokeVirtualMethod(byteCodes, i, smapper) + 2;
1.934 - break;
1.935 - }
1.936 - case opc_invokevirtual:
1.937 - i = invokeVirtualMethod(byteCodes, i, smapper);
1.938 - break;
1.939 - case opc_invokespecial:
1.940 - i = invokeStaticMethod(byteCodes, i, smapper, false);
1.941 - break;
1.942 - case opc_invokestatic:
1.943 - i = invokeStaticMethod(byteCodes, i, smapper, true);
1.944 - break;
1.945 - case opc_new: {
1.946 - int indx = readIntArg(byteCodes, i);
1.947 - String ci = jc.getClassName(indx);
1.948 - emit(out, "var @1 = new @2;",
1.949 - smapper.pushA(), accessClass(ci.replace('/', '_')));
1.950 - addReference(ci);
1.951 - i += 2;
1.952 - break;
1.953 - }
1.954 - case opc_newarray:
1.955 - int atype = readUByte(byteCodes, ++i);
1.956 - String jvmType;
1.957 - switch (atype) {
1.958 - case 4: jvmType = "[Z"; break;
1.959 - case 5: jvmType = "[C"; break;
1.960 - case 6: jvmType = "[F"; break;
1.961 - case 7: jvmType = "[D"; break;
1.962 - case 8: jvmType = "[B"; break;
1.963 - case 9: jvmType = "[S"; break;
1.964 - case 10: jvmType = "[I"; break;
1.965 - case 11: jvmType = "[J"; break;
1.966 - default: throw new IllegalStateException("Array type: " + atype);
1.967 - }
1.968 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
1.969 - smapper.popI(), smapper.pushA(), jvmType);
1.970 - break;
1.971 - case opc_anewarray: {
1.972 - int type = readIntArg(byteCodes, i);
1.973 - i += 2;
1.974 - String typeName = jc.getClassName(type);
1.975 - if (typeName.startsWith("[")) {
1.976 - typeName = "[" + typeName;
1.977 - } else {
1.978 - typeName = "[L" + typeName + ";";
1.979 - }
1.980 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
1.981 - smapper.popI(), smapper.pushA(), typeName);
1.982 - break;
1.983 - }
1.984 - case opc_multianewarray: {
1.985 - int type = readIntArg(byteCodes, i);
1.986 - i += 2;
1.987 - String typeName = jc.getClassName(type);
1.988 - int dim = readUByte(byteCodes, ++i);
1.989 - StringBuilder dims = new StringBuilder();
1.990 - dims.append('[');
1.991 - for (int d = 0; d < dim; d++) {
1.992 - if (d != 0) {
1.993 - dims.append(",");
1.994 - }
1.995 - dims.append(smapper.popI());
1.996 - }
1.997 - dims.append(']');
1.998 - emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
1.999 - dims.toString(), smapper.pushA(), typeName);
1.1000 - break;
1.1001 - }
1.1002 - case opc_arraylength:
1.1003 - emit(out, "var @2 = @1.length;",
1.1004 - smapper.popA(), smapper.pushI());
1.1005 - break;
1.1006 - case opc_lastore:
1.1007 - emit(out, "@3.at(@2, @1);",
1.1008 - smapper.popL(), smapper.popI(), smapper.popA());
1.1009 - break;
1.1010 - case opc_fastore:
1.1011 - emit(out, "@3.at(@2, @1);",
1.1012 - smapper.popF(), smapper.popI(), smapper.popA());
1.1013 - break;
1.1014 - case opc_dastore:
1.1015 - emit(out, "@3.at(@2, @1);",
1.1016 - smapper.popD(), smapper.popI(), smapper.popA());
1.1017 - break;
1.1018 - case opc_aastore:
1.1019 - emit(out, "@3.at(@2, @1);",
1.1020 - smapper.popA(), smapper.popI(), smapper.popA());
1.1021 - break;
1.1022 - case opc_iastore:
1.1023 - case opc_bastore:
1.1024 - case opc_castore:
1.1025 - case opc_sastore:
1.1026 - emit(out, "@3.at(@2, @1);",
1.1027 - smapper.popI(), smapper.popI(), smapper.popA());
1.1028 - break;
1.1029 - case opc_laload:
1.1030 - emit(out, "var @3 = @2.at(@1);",
1.1031 - smapper.popI(), smapper.popA(), smapper.pushL());
1.1032 - break;
1.1033 - case opc_faload:
1.1034 - emit(out, "var @3 = @2.at(@1);",
1.1035 - smapper.popI(), smapper.popA(), smapper.pushF());
1.1036 - break;
1.1037 - case opc_daload:
1.1038 - emit(out, "var @3 = @2.at(@1);",
1.1039 - smapper.popI(), smapper.popA(), smapper.pushD());
1.1040 - break;
1.1041 - case opc_aaload:
1.1042 - emit(out, "var @3 = @2.at(@1);",
1.1043 - smapper.popI(), smapper.popA(), smapper.pushA());
1.1044 - break;
1.1045 - case opc_iaload:
1.1046 - case opc_baload:
1.1047 - case opc_caload:
1.1048 - case opc_saload:
1.1049 - emit(out, "var @3 = @2.at(@1);",
1.1050 - smapper.popI(), smapper.popA(), smapper.pushI());
1.1051 - break;
1.1052 - case opc_pop:
1.1053 - case opc_pop2:
1.1054 - smapper.pop(1);
1.1055 - debug("/* pop */");
1.1056 - break;
1.1057 - case opc_dup: {
1.1058 - final Variable v = smapper.get(0);
1.1059 - emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v);
1.1060 - break;
1.1061 - }
1.1062 - case opc_dup2: {
1.1063 - final Variable vi1 = smapper.get(0);
1.1064 -
1.1065 - if (vi1.isCategory2()) {
1.1066 - emit(out, "var @1 = @2;",
1.1067 - smapper.pushT(vi1.getType()), vi1);
1.1068 - } else {
1.1069 - final Variable vi2 = smapper.get(1);
1.1070 - emit(out, "var @1 = @2, @3 = @4;",
1.1071 - smapper.pushT(vi2.getType()), vi2,
1.1072 - smapper.pushT(vi1.getType()), vi1);
1.1073 - }
1.1074 - break;
1.1075 - }
1.1076 - case opc_dup_x1: {
1.1077 - final Variable vi1 = smapper.pop();
1.1078 - final Variable vi2 = smapper.pop();
1.1079 - final Variable vo3 = smapper.pushT(vi1.getType());
1.1080 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1081 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1082 -
1.1083 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1084 - vo1, vi1, vo2, vi2, vo3, vo1);
1.1085 - break;
1.1086 - }
1.1087 - case opc_dup2_x1: {
1.1088 - final Variable vi1 = smapper.pop();
1.1089 - final Variable vi2 = smapper.pop();
1.1090 -
1.1091 - if (vi1.isCategory2()) {
1.1092 - final Variable vo3 = smapper.pushT(vi1.getType());
1.1093 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1094 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1095 -
1.1096 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1097 - vo1, vi1, vo2, vi2, vo3, vo1);
1.1098 - } else {
1.1099 - final Variable vi3 = smapper.pop();
1.1100 - final Variable vo5 = smapper.pushT(vi2.getType());
1.1101 - final Variable vo4 = smapper.pushT(vi1.getType());
1.1102 - final Variable vo3 = smapper.pushT(vi3.getType());
1.1103 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1104 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1105 -
1.1106 - emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.1107 - vo1, vi1, vo2, vi2, vo3, vi3);
1.1108 - emit(out, " @1 = @2, @3 = @4;",
1.1109 - vo4, vo1, vo5, vo2);
1.1110 - }
1.1111 - break;
1.1112 - }
1.1113 - case opc_dup_x2: {
1.1114 - final Variable vi1 = smapper.pop();
1.1115 - final Variable vi2 = smapper.pop();
1.1116 -
1.1117 - if (vi2.isCategory2()) {
1.1118 - final Variable vo3 = smapper.pushT(vi1.getType());
1.1119 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1120 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1121 -
1.1122 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1123 - vo1, vi1, vo2, vi2, vo3, vo1);
1.1124 - } else {
1.1125 - final Variable vi3 = smapper.pop();
1.1126 - final Variable vo4 = smapper.pushT(vi1.getType());
1.1127 - final Variable vo3 = smapper.pushT(vi3.getType());
1.1128 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1129 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1130 -
1.1131 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1132 - vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.1133 - }
1.1134 - break;
1.1135 - }
1.1136 - case opc_dup2_x2: {
1.1137 - final Variable vi1 = smapper.pop();
1.1138 - final Variable vi2 = smapper.pop();
1.1139 -
1.1140 - if (vi1.isCategory2()) {
1.1141 - if (vi2.isCategory2()) {
1.1142 - final Variable vo3 = smapper.pushT(vi1.getType());
1.1143 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1144 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1145 -
1.1146 - emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
1.1147 - vo1, vi1, vo2, vi2, vo3, vo1);
1.1148 - } else {
1.1149 - final Variable vi3 = smapper.pop();
1.1150 - final Variable vo4 = smapper.pushT(vi1.getType());
1.1151 - final Variable vo3 = smapper.pushT(vi3.getType());
1.1152 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1153 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1154 -
1.1155 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
1.1156 - vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
1.1157 - }
1.1158 - } else {
1.1159 - final Variable vi3 = smapper.pop();
1.1160 -
1.1161 - if (vi3.isCategory2()) {
1.1162 - final Variable vo5 = smapper.pushT(vi2.getType());
1.1163 - final Variable vo4 = smapper.pushT(vi1.getType());
1.1164 - final Variable vo3 = smapper.pushT(vi3.getType());
1.1165 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1166 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1167 -
1.1168 - emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
1.1169 - vo1, vi1, vo2, vi2, vo3, vi3);
1.1170 - emit(out, " @1 = @2, @3 = @4;",
1.1171 - vo4, vo1, vo5, vo2);
1.1172 - } else {
1.1173 - final Variable vi4 = smapper.pop();
1.1174 - final Variable vo6 = smapper.pushT(vi2.getType());
1.1175 - final Variable vo5 = smapper.pushT(vi1.getType());
1.1176 - final Variable vo4 = smapper.pushT(vi4.getType());
1.1177 - final Variable vo3 = smapper.pushT(vi3.getType());
1.1178 - final Variable vo2 = smapper.pushT(vi2.getType());
1.1179 - final Variable vo1 = smapper.pushT(vi1.getType());
1.1180 -
1.1181 - emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
1.1182 - vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
1.1183 - emit(out, " @1 = @2, @3 = @4;",
1.1184 - vo5, vo1, vo6, vo2);
1.1185 - }
1.1186 - }
1.1187 - break;
1.1188 - }
1.1189 - case opc_swap: {
1.1190 - final Variable vi1 = smapper.get(0);
1.1191 - final Variable vi2 = smapper.get(1);
1.1192 -
1.1193 - if (vi1.getType() == vi2.getType()) {
1.1194 - final Variable tmp = smapper.pushT(vi1.getType());
1.1195 -
1.1196 - emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
1.1197 - tmp, vi1, vi2);
1.1198 - smapper.pop(1);
1.1199 - } else {
1.1200 - smapper.pop(2);
1.1201 - smapper.pushT(vi1.getType());
1.1202 - smapper.pushT(vi2.getType());
1.1203 - }
1.1204 - break;
1.1205 - }
1.1206 - case opc_bipush:
1.1207 - emit(out, "var @1 = @2;",
1.1208 - smapper.pushI(), Integer.toString(byteCodes[++i]));
1.1209 - break;
1.1210 - case opc_sipush:
1.1211 - emit(out, "var @1 = @2;",
1.1212 - smapper.pushI(),
1.1213 - Integer.toString(readIntArg(byteCodes, i)));
1.1214 - i += 2;
1.1215 - break;
1.1216 - case opc_getfield: {
1.1217 - int indx = readIntArg(byteCodes, i);
1.1218 - String[] fi = jc.getFieldInfoName(indx);
1.1219 - final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1220 - final String mangleClass = mangleSig(fi[0]);
1.1221 - final String mangleClassAccess = accessClass(mangleClass);
1.1222 - emit(out, "var @2 = @4(false)._@3.call(@1);",
1.1223 - smapper.popA(),
1.1224 - smapper.pushT(type), fi[1], mangleClassAccess
1.1225 - );
1.1226 - i += 2;
1.1227 - break;
1.1228 - }
1.1229 - case opc_putfield: {
1.1230 - int indx = readIntArg(byteCodes, i);
1.1231 - String[] fi = jc.getFieldInfoName(indx);
1.1232 - final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1233 - final String mangleClass = mangleSig(fi[0]);
1.1234 - final String mangleClassAccess = accessClass(mangleClass);
1.1235 - emit(out, "@4(false)._@3.call(@2, @1);",
1.1236 - smapper.popT(type),
1.1237 - smapper.popA(), fi[1],
1.1238 - mangleClassAccess
1.1239 - );
1.1240 - i += 2;
1.1241 - break;
1.1242 - }
1.1243 - case opc_getstatic: {
1.1244 - int indx = readIntArg(byteCodes, i);
1.1245 - String[] fi = jc.getFieldInfoName(indx);
1.1246 - final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1247 - emit(out, "var @1 = @2(false).constructor.@3;",
1.1248 - smapper.pushT(type),
1.1249 - accessClass(fi[0].replace('/', '_')), fi[1]);
1.1250 - i += 2;
1.1251 - addReference(fi[0]);
1.1252 - break;
1.1253 - }
1.1254 - case opc_putstatic: {
1.1255 - int indx = readIntArg(byteCodes, i);
1.1256 - String[] fi = jc.getFieldInfoName(indx);
1.1257 - final int type = VarType.fromFieldType(fi[2].charAt(0));
1.1258 - emit(out, "@1(false).constructor.@2 = @3;",
1.1259 - accessClass(fi[0].replace('/', '_')), fi[1],
1.1260 - smapper.popT(type));
1.1261 - i += 2;
1.1262 - addReference(fi[0]);
1.1263 - break;
1.1264 - }
1.1265 - case opc_checkcast: {
1.1266 - int indx = readIntArg(byteCodes, i);
1.1267 - final String type = jc.getClassName(indx);
1.1268 - if (!type.startsWith("[")) {
1.1269 - emit(out,
1.1270 - "if (@1 !== null && !@1.$instOf_@2) throw {};",
1.1271 - smapper.getA(0), type.replace('/', '_'));
1.1272 - } else {
1.1273 - 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.1274 - smapper.getA(0), type
1.1275 - );
1.1276 - }
1.1277 - i += 2;
1.1278 - break;
1.1279 - }
1.1280 - case opc_instanceof: {
1.1281 - int indx = readIntArg(byteCodes, i);
1.1282 - final String type = jc.getClassName(indx);
1.1283 - if (!type.startsWith("[")) {
1.1284 - emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
1.1285 - smapper.popA(), smapper.pushI(),
1.1286 - type.replace('/', '_'));
1.1287 - } else {
1.1288 - 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.1289 - smapper.popA(), smapper.pushI(),
1.1290 - type
1.1291 - );
1.1292 - }
1.1293 - i += 2;
1.1294 - break;
1.1295 - }
1.1296 - case opc_athrow: {
1.1297 - final Variable v = smapper.popA();
1.1298 - smapper.clear();
1.1299 -
1.1300 - emit(out, "{ var @1 = @2; throw @2; }",
1.1301 - smapper.pushA(), v);
1.1302 - break;
1.1303 - }
1.1304 -
1.1305 - case opc_monitorenter: {
1.1306 - out.append("/* monitor enter */");
1.1307 - smapper.popA();
1.1308 - break;
1.1309 - }
1.1310 -
1.1311 - case opc_monitorexit: {
1.1312 - out.append("/* monitor exit */");
1.1313 - smapper.popA();
1.1314 - break;
1.1315 - }
1.1316 -
1.1317 - case opc_wide:
1.1318 - wide = true;
1.1319 - break;
1.1320 -
1.1321 - default: {
1.1322 - wide = false;
1.1323 - emit(out, "throw 'unknown bytecode @1';",
1.1324 - Integer.toString(c));
1.1325 - }
1.1326 - }
1.1327 - if (debug(" //")) {
1.1328 - for (int j = prev; j <= i; j++) {
1.1329 - out.append(" ");
1.1330 - final int cc = readUByte(byteCodes, j);
1.1331 - out.append(Integer.toString(cc));
1.1332 - }
1.1333 - }
1.1334 - out.append("\n");
1.1335 - }
1.1336 - if (previousTrap != null) {
1.1337 - generateCatch(previousTrap);
1.1338 - }
1.1339 - out.append(" }\n");
1.1340 - out.append("};");
1.1341 - }
1.1342 -
1.1343 - private int generateIf(byte[] byteCodes, int i,
1.1344 - final Variable v2, final Variable v1,
1.1345 - final String test) throws IOException {
1.1346 - int indx = i + readIntArg(byteCodes, i);
1.1347 - out.append("if (").append(v1)
1.1348 - .append(' ').append(test).append(' ')
1.1349 - .append(v2).append(") { gt = " + indx)
1.1350 - .append("; continue; }");
1.1351 - return i + 2;
1.1352 - }
1.1353 -
1.1354 - private int readIntArg(byte[] byteCodes, int offsetInstruction) {
1.1355 - final int indxHi = byteCodes[offsetInstruction + 1] << 8;
1.1356 - final int indxLo = byteCodes[offsetInstruction + 2];
1.1357 - return (indxHi & 0xffffff00) | (indxLo & 0xff);
1.1358 - }
1.1359 - private int readInt4(byte[] byteCodes, int offset) {
1.1360 - final int d = byteCodes[offset + 0] << 24;
1.1361 - final int c = byteCodes[offset + 1] << 16;
1.1362 - final int b = byteCodes[offset + 2] << 8;
1.1363 - final int a = byteCodes[offset + 3];
1.1364 - return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
1.1365 - }
1.1366 - private int readUByte(byte[] byteCodes, int offset) {
1.1367 - return byteCodes[offset] & 0xff;
1.1368 - }
1.1369 -
1.1370 - private int readUShort(byte[] byteCodes, int offset) {
1.1371 - return ((byteCodes[offset] & 0xff) << 8)
1.1372 - | (byteCodes[offset + 1] & 0xff);
1.1373 - }
1.1374 -
1.1375 - private int readShort(byte[] byteCodes, int offset) {
1.1376 - return (byteCodes[offset] << 8)
1.1377 - | (byteCodes[offset + 1] & 0xff);
1.1378 - }
1.1379 -
1.1380 - private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
1.1381 - int i = 0;
1.1382 - Boolean count = null;
1.1383 - boolean array = false;
1.1384 - sig.append("__");
1.1385 - int firstPos = sig.length();
1.1386 - while (i < descriptor.length()) {
1.1387 - char ch = descriptor.charAt(i++);
1.1388 - switch (ch) {
1.1389 - case '(':
1.1390 - count = true;
1.1391 - continue;
1.1392 - case ')':
1.1393 - count = false;
1.1394 - continue;
1.1395 - case 'B':
1.1396 - case 'C':
1.1397 - case 'D':
1.1398 - case 'F':
1.1399 - case 'I':
1.1400 - case 'J':
1.1401 - case 'S':
1.1402 - case 'Z':
1.1403 - if (count) {
1.1404 - if (array) {
1.1405 - sig.append("_3");
1.1406 - }
1.1407 - sig.append(ch);
1.1408 - if (ch == 'J' || ch == 'D') {
1.1409 - cnt.append('1');
1.1410 - } else {
1.1411 - cnt.append('0');
1.1412 - }
1.1413 - } else {
1.1414 - sig.insert(firstPos, ch);
1.1415 - if (array) {
1.1416 - returnType[0] = '[';
1.1417 - sig.insert(firstPos, "_3");
1.1418 - } else {
1.1419 - returnType[0] = ch;
1.1420 - }
1.1421 - }
1.1422 - array = false;
1.1423 - continue;
1.1424 - case 'V':
1.1425 - assert !count;
1.1426 - returnType[0] = 'V';
1.1427 - sig.insert(firstPos, 'V');
1.1428 - continue;
1.1429 - case 'L':
1.1430 - int next = descriptor.indexOf(';', i);
1.1431 - String realSig = mangleSig(descriptor, i - 1, next + 1);
1.1432 - if (count) {
1.1433 - if (array) {
1.1434 - sig.append("_3");
1.1435 - }
1.1436 - sig.append(realSig);
1.1437 - cnt.append('0');
1.1438 - } else {
1.1439 - sig.insert(firstPos, realSig);
1.1440 - if (array) {
1.1441 - sig.insert(firstPos, "_3");
1.1442 - }
1.1443 - returnType[0] = 'L';
1.1444 - }
1.1445 - i = next + 1;
1.1446 - array = false;
1.1447 - continue;
1.1448 - case '[':
1.1449 - array = true;
1.1450 - continue;
1.1451 - default:
1.1452 - throw new IllegalStateException("Invalid char: " + ch);
1.1453 - }
1.1454 - }
1.1455 - }
1.1456 -
1.1457 - static String mangleSig(String sig) {
1.1458 - return mangleSig(sig, 0, sig.length());
1.1459 - }
1.1460 -
1.1461 - private static String mangleSig(String txt, int first, int last) {
1.1462 - StringBuilder sb = new StringBuilder();
1.1463 - for (int i = first; i < last; i++) {
1.1464 - final char ch = txt.charAt(i);
1.1465 - switch (ch) {
1.1466 - case '/': sb.append('_'); break;
1.1467 - case '_': sb.append("_1"); break;
1.1468 - case ';': sb.append("_2"); break;
1.1469 - case '[': sb.append("_3"); break;
1.1470 - default: sb.append(ch); break;
1.1471 - }
1.1472 - }
1.1473 - return sb.toString();
1.1474 - }
1.1475 -
1.1476 - private static String findMethodName(MethodData m, StringBuilder cnt) {
1.1477 - StringBuilder name = new StringBuilder();
1.1478 - if ("<init>".equals(m.getName())) { // NOI18N
1.1479 - name.append("cons"); // NOI18N
1.1480 - } else if ("<clinit>".equals(m.getName())) { // NOI18N
1.1481 - name.append("class"); // NOI18N
1.1482 - } else {
1.1483 - name.append(m.getName());
1.1484 - }
1.1485 -
1.1486 - countArgs(m.getInternalSig(), new char[1], name, cnt);
1.1487 - return name.toString();
1.1488 - }
1.1489 -
1.1490 - static String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) {
1.1491 - StringBuilder name = new StringBuilder();
1.1492 - String descr = mi[2];//mi.getDescriptor();
1.1493 - String nm= mi[1];
1.1494 - if ("<init>".equals(nm)) { // NOI18N
1.1495 - name.append("cons"); // NOI18N
1.1496 - } else {
1.1497 - name.append(nm);
1.1498 - }
1.1499 - countArgs(descr, returnType, name, cnt);
1.1500 - return name.toString();
1.1501 - }
1.1502 -
1.1503 - private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
1.1504 - throws IOException {
1.1505 - int methodIndex = readIntArg(byteCodes, i);
1.1506 - String[] mi = jc.getFieldInfoName(methodIndex);
1.1507 - char[] returnType = { 'V' };
1.1508 - StringBuilder cnt = new StringBuilder();
1.1509 - String mn = findMethodName(mi, cnt, returnType);
1.1510 -
1.1511 - final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
1.1512 - final Variable[] vars = new Variable[numArguments];
1.1513 -
1.1514 - for (int j = numArguments - 1; j >= 0; --j) {
1.1515 - vars[j] = mapper.pop();
1.1516 - }
1.1517 -
1.1518 - if (returnType[0] != 'V') {
1.1519 - out.append("var ")
1.1520 - .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
1.1521 - .append(" = ");
1.1522 - }
1.1523 -
1.1524 - final String in = mi[0];
1.1525 - out.append(accessClass(in.replace('/', '_')));
1.1526 - out.append("(false).");
1.1527 - if (mn.startsWith("cons_")) {
1.1528 - out.append("constructor.");
1.1529 - }
1.1530 - out.append(mn);
1.1531 - if (isStatic) {
1.1532 - out.append('(');
1.1533 - } else {
1.1534 - out.append(".call(");
1.1535 - }
1.1536 - if (numArguments > 0) {
1.1537 - out.append(vars[0]);
1.1538 - for (int j = 1; j < numArguments; ++j) {
1.1539 - out.append(", ");
1.1540 - out.append(vars[j]);
1.1541 - }
1.1542 - }
1.1543 - out.append(");");
1.1544 - i += 2;
1.1545 - addReference(in);
1.1546 - return i;
1.1547 - }
1.1548 - private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
1.1549 - throws IOException {
1.1550 - int methodIndex = readIntArg(byteCodes, i);
1.1551 - String[] mi = jc.getFieldInfoName(methodIndex);
1.1552 - char[] returnType = { 'V' };
1.1553 - StringBuilder cnt = new StringBuilder();
1.1554 - String mn = findMethodName(mi, cnt, returnType);
1.1555 -
1.1556 - final int numArguments = cnt.length() + 1;
1.1557 - final Variable[] vars = new Variable[numArguments];
1.1558 -
1.1559 - for (int j = numArguments - 1; j >= 0; --j) {
1.1560 - vars[j] = mapper.pop();
1.1561 - }
1.1562 -
1.1563 - if (returnType[0] != 'V') {
1.1564 - out.append("var ")
1.1565 - .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
1.1566 - .append(" = ");
1.1567 - }
1.1568 -
1.1569 - out.append(vars[0]).append('.');
1.1570 - out.append(mn);
1.1571 - out.append('(');
1.1572 - String sep = "";
1.1573 - for (int j = 1; j < numArguments; ++j) {
1.1574 - out.append(sep);
1.1575 - out.append(vars[j]);
1.1576 - sep = ", ";
1.1577 - }
1.1578 - out.append(");");
1.1579 - i += 2;
1.1580 - return i;
1.1581 - }
1.1582 -
1.1583 - private void addReference(String cn) throws IOException {
1.1584 - if (requireReference(cn)) {
1.1585 - debug(" /* needs " + cn + " */");
1.1586 - }
1.1587 - }
1.1588 -
1.1589 - private void outType(String d, StringBuilder out) {
1.1590 - int arr = 0;
1.1591 - while (d.charAt(0) == '[') {
1.1592 - out.append('A');
1.1593 - d = d.substring(1);
1.1594 - }
1.1595 - if (d.charAt(0) == 'L') {
1.1596 - assert d.charAt(d.length() - 1) == ';';
1.1597 - out.append(d.replace('/', '_').substring(0, d.length() - 1));
1.1598 - } else {
1.1599 - out.append(d);
1.1600 - }
1.1601 - }
1.1602 -
1.1603 - private String encodeConstant(int entryIndex) throws IOException {
1.1604 - String[] classRef = { null };
1.1605 - String s = jc.stringValue(entryIndex, classRef);
1.1606 - if (classRef[0] != null) {
1.1607 - if (classRef[0].startsWith("[")) {
1.1608 - s = accessClass("java_lang_Class") + "(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('" + classRef[0] + "');";
1.1609 - } else {
1.1610 - addReference(classRef[0]);
1.1611 - s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
1.1612 - }
1.1613 - }
1.1614 - return s;
1.1615 - }
1.1616 -
1.1617 - private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
1.1618 - byte[] arr = m.findAnnotationData(true);
1.1619 - if (arr == null) {
1.1620 - return null;
1.1621 - }
1.1622 - final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
1.1623 - class P extends AnnotationParser {
1.1624 - public P() {
1.1625 - super(false);
1.1626 - }
1.1627 -
1.1628 - int cnt;
1.1629 - String[] args = new String[30];
1.1630 - String body;
1.1631 -
1.1632 - @Override
1.1633 - protected void visitAttr(String type, String attr, String at, String value) {
1.1634 - if (type.equals(jvmType)) {
1.1635 - if ("body".equals(attr)) {
1.1636 - body = value;
1.1637 - } else if ("args".equals(attr)) {
1.1638 - args[cnt++] = value;
1.1639 - } else {
1.1640 - throw new IllegalArgumentException(attr);
1.1641 - }
1.1642 - }
1.1643 - }
1.1644 - }
1.1645 - P p = new P();
1.1646 - p.parse(arr, jc);
1.1647 - if (p.body == null) {
1.1648 - return null;
1.1649 - }
1.1650 - StringBuilder cnt = new StringBuilder();
1.1651 - final String mn = findMethodName(m, cnt);
1.1652 - out.append(prefix).append(mn);
1.1653 - out.append(" = function(");
1.1654 - String space = "";
1.1655 - int index = 0;
1.1656 - for (int i = 0; i < cnt.length(); i++) {
1.1657 - out.append(space);
1.1658 - space = outputArg(out, p.args, index);
1.1659 - index++;
1.1660 - }
1.1661 - out.append(") {").append("\n");
1.1662 - out.append(p.body);
1.1663 - out.append("\n}\n");
1.1664 - return mn;
1.1665 - }
1.1666 - private static String className(ClassData jc) {
1.1667 - //return jc.getName().getInternalName().replace('/', '_');
1.1668 - return jc.getClassName().replace('/', '_');
1.1669 - }
1.1670 -
1.1671 - private static String[] findAnnotation(
1.1672 - byte[] arr, ClassData cd, final String className,
1.1673 - final String... attrNames
1.1674 - ) throws IOException {
1.1675 - if (arr == null) {
1.1676 - return null;
1.1677 - }
1.1678 - final String[] values = new String[attrNames.length];
1.1679 - final boolean[] found = { false };
1.1680 - final String jvmType = "L" + className.replace('.', '/') + ";";
1.1681 - AnnotationParser ap = new AnnotationParser(false) {
1.1682 - @Override
1.1683 - protected void visitAttr(String type, String attr, String at, String value) {
1.1684 - if (type.equals(jvmType)) {
1.1685 - found[0] = true;
1.1686 - for (int i = 0; i < attrNames.length; i++) {
1.1687 - if (attrNames[i].equals(attr)) {
1.1688 - values[i] = value;
1.1689 - }
1.1690 - }
1.1691 - }
1.1692 - }
1.1693 -
1.1694 - };
1.1695 - ap.parse(arr, cd);
1.1696 - return found[0] ? values : null;
1.1697 - }
1.1698 -
1.1699 - private CharSequence initField(FieldData v) {
1.1700 - final String is = v.getInternalSig();
1.1701 - if (is.length() == 1) {
1.1702 - switch (is.charAt(0)) {
1.1703 - case 'S':
1.1704 - case 'J':
1.1705 - case 'B':
1.1706 - case 'Z':
1.1707 - case 'C':
1.1708 - case 'I': return " = 0;";
1.1709 - case 'F':
1.1710 - case 'D': return " = 0.0;";
1.1711 - default:
1.1712 - throw new IllegalStateException(is);
1.1713 - }
1.1714 - }
1.1715 - return " = null;";
1.1716 - }
1.1717 -
1.1718 - private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
1.1719 - AnnotationParser ap = new AnnotationParser(true) {
1.1720 - int anno;
1.1721 - int cnt;
1.1722 -
1.1723 - @Override
1.1724 - protected void visitAnnotationStart(String type) throws IOException {
1.1725 - if (anno++ > 0) {
1.1726 - out.append(",");
1.1727 - }
1.1728 - out.append('"').append(type).append("\" : {\n");
1.1729 - cnt = 0;
1.1730 - }
1.1731 -
1.1732 - @Override
1.1733 - protected void visitAnnotationEnd(String type) throws IOException {
1.1734 - out.append("\n}\n");
1.1735 - }
1.1736 -
1.1737 - @Override
1.1738 - protected void visitAttr(String type, String attr, String attrType, String value)
1.1739 - throws IOException {
1.1740 - if (attr == null) {
1.1741 - return;
1.1742 - }
1.1743 - if (cnt++ > 0) {
1.1744 - out.append(",\n");
1.1745 - }
1.1746 - out.append(attr).append("__").append(attrType).append(" : ").append(value);
1.1747 - }
1.1748 - };
1.1749 - ap.parse(data, cd);
1.1750 - }
1.1751 -
1.1752 - private static String outputArg(Appendable out, String[] args, int indx) throws IOException {
1.1753 - final String name = args[indx];
1.1754 - if (name == null) {
1.1755 - return "";
1.1756 - }
1.1757 - if (name.contains(",")) {
1.1758 - throw new IOException("Wrong parameter with ',': " + name);
1.1759 - }
1.1760 - out.append(name);
1.1761 - return ",";
1.1762 - }
1.1763 -
1.1764 - private static void emit(final Appendable out,
1.1765 - final String format,
1.1766 - final CharSequence... params) throws IOException {
1.1767 - final int length = format.length();
1.1768 -
1.1769 - int processed = 0;
1.1770 - int paramOffset = format.indexOf('@');
1.1771 - while ((paramOffset != -1) && (paramOffset < (length - 1))) {
1.1772 - final char paramChar = format.charAt(paramOffset + 1);
1.1773 - if ((paramChar >= '1') && (paramChar <= '9')) {
1.1774 - final int paramIndex = paramChar - '0' - 1;
1.1775 -
1.1776 - out.append(format, processed, paramOffset);
1.1777 - out.append(params[paramIndex]);
1.1778 -
1.1779 - ++paramOffset;
1.1780 - processed = paramOffset + 1;
1.1781 - }
1.1782 -
1.1783 - paramOffset = format.indexOf('@', paramOffset + 1);
1.1784 - }
1.1785 -
1.1786 - out.append(format, processed, length);
1.1787 - }
1.1788 -
1.1789 - private void generateCatch(TrapData[] traps) throws IOException {
1.1790 - out.append("} catch (e) {\n");
1.1791 - int finallyPC = -1;
1.1792 - for (TrapData e : traps) {
1.1793 - if (e == null) {
1.1794 - break;
1.1795 - }
1.1796 - if (e.catch_cpx != 0) { //not finally
1.1797 - final String classInternalName = jc.getClassName(e.catch_cpx);
1.1798 - addReference(classInternalName);
1.1799 - if ("java/lang/Throwable".equals(classInternalName)) {
1.1800 - out.append("if (e.$instOf_java_lang_Throwable) {");
1.1801 - out.append(" var stA0 = e;");
1.1802 - out.append("} else {");
1.1803 - out.append(" var stA0 = vm.java_lang_Throwable(true);");
1.1804 - out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
1.1805 - out.append("}");
1.1806 - out.append("gt=" + e.handler_pc + "; continue;");
1.1807 - } else {
1.1808 - out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
1.1809 - out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
1.1810 - out.append("}\n");
1.1811 - }
1.1812 - } else {
1.1813 - finallyPC = e.handler_pc;
1.1814 - }
1.1815 - }
1.1816 - if (finallyPC == -1) {
1.1817 - out.append("throw e;");
1.1818 - } else {
1.1819 - out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
1.1820 - }
1.1821 - out.append("\n}");
1.1822 - }
1.1823 -}