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