vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Jan 2013 08:47:05 +0100
changeset 592 5e13b1ac2886
parent 587 a7a45e5e5e77
child 593 b42911b78a16
child 639 960ecf7cea5d
child 652 f095ea52f417
permissions -rw-r--r--
In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
jaroslav@106
     1
/**
jaroslav@106
     2
 * Back 2 Browser Bytecode Translator
jaroslav@106
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@106
     4
 *
jaroslav@106
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@106
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@106
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@106
     8
 *
jaroslav@106
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@106
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@106
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@106
    12
 * GNU General Public License for more details.
jaroslav@106
    13
 *
jaroslav@106
    14
 * You should have received a copy of the GNU General Public License
jaroslav@106
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@106
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@106
    17
 */
jaroslav@22
    18
package org.apidesign.vm4brwsr;
jaroslav@0
    19
jaroslav@0
    20
import java.io.IOException;
jaroslav@0
    21
import java.io.InputStream;
jaroslav@457
    22
import org.apidesign.bck2brwsr.core.JavaScriptBody;
jtulach@167
    23
import org.apidesign.javap.AnnotationParser;
jtulach@167
    24
import org.apidesign.javap.ClassData;
jtulach@167
    25
import org.apidesign.javap.FieldData;
jtulach@167
    26
import org.apidesign.javap.MethodData;
lubomir@221
    27
import org.apidesign.javap.StackMapIterator;
jtulach@167
    28
import static org.apidesign.javap.RuntimeConstants.*;
tzezula@287
    29
import org.apidesign.javap.TrapData;
jaroslav@288
    30
import org.apidesign.javap.TrapDataIterator;
jaroslav@0
    31
jaroslav@0
    32
/** Translator of the code inside class files to JavaScript.
jaroslav@0
    33
 *
jaroslav@0
    34
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@0
    35
 */
jaroslav@298
    36
abstract class ByteCodeToJavaScript {
jtulach@162
    37
    private ClassData jc;
jaroslav@272
    38
    final Appendable out;
jaroslav@0
    39
jtulach@162
    40
    protected ByteCodeToJavaScript(Appendable out) {
jaroslav@0
    41
        this.out = out;
jaroslav@0
    42
    }
jtulach@162
    43
    
jtulach@162
    44
    /* Collects additional required resources.
jtulach@162
    45
     * 
jtulach@162
    46
     * @param internalClassName classes that were referenced and should be loaded in order the
jtulach@162
    47
     *   generated JavaScript code works properly. The names are in internal 
jtulach@162
    48
     *   JVM form so String is <code>java/lang/String</code>. 
jtulach@162
    49
     */
jtulach@162
    50
    protected abstract boolean requireReference(String internalClassName);
jtulach@162
    51
    
jtulach@162
    52
    /*
jtulach@162
    53
     * @param resourcePath name of resources to read
jtulach@162
    54
     */
jaroslav@503
    55
    protected abstract void requireScript(String resourcePath) throws IOException;
jaroslav@213
    56
    
jaroslav@213
    57
    /** Allows subclasses to redefine what field a function representing a
jaroslav@213
    58
     * class gets assigned. By default it returns the suggested name followed
jaroslav@213
    59
     * by <code>" = "</code>;
jaroslav@213
    60
     * 
jaroslav@213
    61
     * @param className suggested name of the class
jaroslav@213
    62
     */
jaroslav@274
    63
    /* protected */ String assignClass(String className) {
jaroslav@213
    64
        return className + " = ";
jaroslav@213
    65
    }
jaroslav@274
    66
    /* protected */ String accessClass(String classOperation) {
jaroslav@274
    67
        return classOperation;
jaroslav@274
    68
    }
jaroslav@399
    69
    
jaroslav@399
    70
    /** Prints out a debug message. 
jaroslav@399
    71
     * 
jaroslav@399
    72
     * @param msg the message
jaroslav@399
    73
     * @return true if the message has been printed
jaroslav@399
    74
     * @throws IOException 
jaroslav@399
    75
     */
jaroslav@399
    76
    boolean debug(String msg) throws IOException {
jaroslav@399
    77
        out.append(msg);
jaroslav@399
    78
        return true;
jaroslav@399
    79
    }
jaroslav@18
    80
jaroslav@18
    81
    /**
jaroslav@18
    82
     * Converts a given class file to a JavaScript version.
jaroslav@18
    83
     *
jaroslav@0
    84
     * @param classFile input stream with code of the .class file
jaroslav@97
    85
     * @return the initialization code for this class, if any. Otherwise <code>null</code>
jaroslav@91
    86
     * 
jaroslav@0
    87
     * @throws IOException if something goes wrong during read or write or translating
jaroslav@0
    88
     */
jaroslav@18
    89
    
jtulach@162
    90
    public String compile(InputStream classFile) throws IOException {
jtulach@162
    91
        this.jc = new ClassData(classFile);
jaroslav@324
    92
        if (jc.getMajor_version() < 50) {
jaroslav@324
    93
            throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "."
jaroslav@324
    94
                + jc.getMinor_version() + " - recompile with -target 1.6 (at least)."
jaroslav@324
    95
            );
jaroslav@324
    96
        }
jaroslav@152
    97
        byte[] arrData = jc.findAnnotationData(true);
jaroslav@170
    98
        String[] arr = findAnnotation(arrData, jc, 
jaroslav@170
    99
            "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
jaroslav@170
   100
            "resource", "processByteCode"
jaroslav@170
   101
        );
jaroslav@152
   102
        if (arr != null) {
jtulach@162
   103
            requireScript(arr[0]);
jaroslav@152
   104
            if ("0".equals(arr[1])) {
jaroslav@97
   105
                return null;
jaroslav@91
   106
            }
jaroslav@91
   107
        }
jaroslav@239
   108
        String[] proto = findAnnotation(arrData, jc, 
jaroslav@239
   109
            "org.apidesign.bck2brwsr.core.JavaScriptPrototype", 
jaroslav@239
   110
            "container", "prototype"
jaroslav@239
   111
        );
jtulach@162
   112
        StringArray toInitilize = new StringArray();
jaroslav@151
   113
        final String className = className(jc);
jaroslav@213
   114
        out.append("\n\n").append(assignClass(className));
jaroslav@213
   115
        out.append("function CLS() {");
jaroslav@213
   116
        out.append("\n  if (!CLS.prototype.$instOf_").append(className).append(") {");
jaroslav@239
   117
        if (proto == null) {
jaroslav@239
   118
            String sc = jc.getSuperClassName(); // with _
jaroslav@230
   119
            out.append("\n    var pp = ").
jaroslav@274
   120
                append(accessClass(sc.replace('/', '_'))).append("(true);");
jaroslav@230
   121
            out.append("\n    var p = CLS.prototype = pp;");
jaroslav@239
   122
            out.append("\n    var c = p;");
jaroslav@230
   123
            out.append("\n    var sprcls = pp.constructor.$class;");
jtulach@130
   124
        } else {
jaroslav@240
   125
            out.append("\n    var p = CLS.prototype = ").append(proto[1]).append(";");
jaroslav@316
   126
            if (proto[0] == null) {
jaroslav@316
   127
                proto[0] = "p";
jaroslav@316
   128
            }
jaroslav@239
   129
            out.append("\n    var c = ").append(proto[0]).append(";");
jaroslav@230
   130
            out.append("\n    var sprcls = null;");
jaroslav@13
   131
        }
jaroslav@592
   132
        for (FieldData v : jc.getFields()) {
jaroslav@592
   133
            if (v.isStatic()) {
jaroslav@592
   134
                out.append("\n  CLS.").append(v.getName()).append(initField(v));
jaroslav@592
   135
            } else {
jaroslav@592
   136
                out.append("\n  c._").append(v.getName()).append(" = function (v) {")
jaroslav@592
   137
                   .append("  if (arguments.length == 1) this.fld_").
jaroslav@592
   138
                    append(className).append('_').append(v.getName())
jaroslav@592
   139
                   .append(" = v; return this.fld_").
jaroslav@592
   140
                    append(className).append('_').append(v.getName())
jaroslav@592
   141
                   .append("; };");
jaroslav@592
   142
            }
jaroslav@592
   143
        }
jaroslav@151
   144
        for (MethodData m : jc.getMethods()) {
jaroslav@240
   145
            byte[] onlyArr = m.findAnnotationData(true);
jaroslav@240
   146
            String[] only = findAnnotation(onlyArr, jc, 
jaroslav@240
   147
                "org.apidesign.bck2brwsr.core.JavaScriptOnly", 
jaroslav@240
   148
                "name", "value"
jaroslav@240
   149
            );
jaroslav@240
   150
            if (only != null) {
jaroslav@240
   151
                if (only[0] != null && only[1] != null) {
jaroslav@240
   152
                    out.append("\n    p.").append(only[0]).append(" = ")
jaroslav@240
   153
                        .append(only[1]).append(";");
jaroslav@240
   154
                }
jaroslav@240
   155
                continue;
jaroslav@240
   156
            }
jaroslav@397
   157
            String prefix;
jaroslav@266
   158
            String mn;
jaroslav@203
   159
            if (m.isStatic()) {
jaroslav@397
   160
                prefix = "\n    c.";
jaroslav@397
   161
                mn = generateStaticMethod(prefix, m, toInitilize);
jaroslav@203
   162
            } else {
jaroslav@397
   163
                if (m.isConstructor()) {
jaroslav@397
   164
                    prefix = "\n    CLS.";
jaroslav@397
   165
                    mn = generateInstanceMethod(prefix, m);
jaroslav@397
   166
                } else {
jaroslav@397
   167
                    prefix = "\n    c.";
jaroslav@397
   168
                    mn = generateInstanceMethod(prefix, m);
jaroslav@397
   169
                }
jaroslav@266
   170
            }
jaroslav@266
   171
            byte[] runAnno = m.findAnnotationData(false);
jaroslav@266
   172
            if (runAnno != null) {
jaroslav@397
   173
                out.append(prefix).append(mn).append(".anno = {");
jaroslav@266
   174
                generateAnno(jc, out, runAnno);
jaroslav@266
   175
                out.append("\n    };");
jaroslav@38
   176
            }
jaroslav@397
   177
            out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
jaroslav@38
   178
        }
jaroslav@239
   179
        out.append("\n    c.constructor = CLS;");
jaroslav@239
   180
        out.append("\n    c.$instOf_").append(className).append(" = true;");
jaroslav@151
   181
        for (String superInterface : jc.getSuperInterfaces()) {
jaroslav@239
   182
            out.append("\n    c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
jaroslav@40
   183
        }
jaroslav@274
   184
        out.append("\n    CLS.$class = ");
jaroslav@274
   185
        out.append(accessClass("java_lang_Class(true);"));
jaroslav@225
   186
        out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
jaroslav@230
   187
        out.append("\n    CLS.$class.superclass = sprcls;");
jaroslav@355
   188
        out.append("\n    CLS.$class.access = ").append(jc.getAccessFlags()+";");
jaroslav@231
   189
        out.append("\n    CLS.$class.cnstr = CLS;");
jaroslav@235
   190
        byte[] classAnno = jc.findAnnotationData(false);
jaroslav@235
   191
        if (classAnno != null) {
jaroslav@235
   192
            out.append("\n    CLS.$class.anno = {");
jaroslav@235
   193
            generateAnno(jc, out, classAnno);
jaroslav@235
   194
            out.append("\n    };");
jaroslav@235
   195
        }
jaroslav@204
   196
        out.append("\n  }");
jaroslav@205
   197
        out.append("\n  if (arguments.length === 0) {");
jaroslav@226
   198
        out.append("\n    if (!(this instanceof CLS)) {");
jaroslav@226
   199
        out.append("\n      return new CLS();");
jaroslav@226
   200
        out.append("\n    }");
jaroslav@205
   201
        for (FieldData v : jc.getFields()) {
jaroslav@240
   202
            byte[] onlyArr = v.findAnnotationData(true);
jaroslav@240
   203
            String[] only = findAnnotation(onlyArr, jc, 
jaroslav@240
   204
                "org.apidesign.bck2brwsr.core.JavaScriptOnly", 
jaroslav@240
   205
                "name", "value"
jaroslav@240
   206
            );
jaroslav@240
   207
            if (only != null) {
jaroslav@240
   208
                if (only[0] != null && only[1] != null) {
jaroslav@240
   209
                    out.append("\n    p.").append(only[0]).append(" = ")
jaroslav@240
   210
                        .append(only[1]).append(";");
jaroslav@240
   211
                }
jaroslav@240
   212
                continue;
jaroslav@240
   213
            }
jaroslav@205
   214
            if (!v.isStatic()) {
jaroslav@205
   215
                out.append("\n    this.fld_").
jaroslav@592
   216
                    append(className).append('_').
jaroslav@205
   217
                    append(v.getName()).append(initField(v));
jaroslav@205
   218
            }
jaroslav@205
   219
        }
jaroslav@205
   220
        out.append("\n    return this;");
jaroslav@205
   221
        out.append("\n  }");
jaroslav@224
   222
        out.append("\n  return arguments[0] ? new CLS() : CLS.prototype;");
jaroslav@509
   223
        out.append("\n};");
jaroslav@97
   224
        StringBuilder sb = new StringBuilder();
jtulach@162
   225
        for (String init : toInitilize.toArray()) {
jaroslav@97
   226
            sb.append("\n").append(init).append("();");
jaroslav@21
   227
        }
jaroslav@97
   228
        return sb.toString();
jaroslav@0
   229
    }
jaroslav@266
   230
    private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
jaroslav@266
   231
        String jsb = javaScriptBody(prefix, m, true);
jaroslav@266
   232
        if (jsb != null) {
jaroslav@266
   233
            return jsb;
jaroslav@94
   234
        }
lubomir@307
   235
        final String mn = findMethodName(m, new StringBuilder());
jaroslav@248
   236
        if (mn.equals("class__V")) {
jaroslav@274
   237
            toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
jaroslav@21
   238
        }
lubomir@307
   239
        generateMethod(prefix, mn, m);
jaroslav@266
   240
        return mn;
jaroslav@10
   241
    }
lubomir@307
   242
jaroslav@266
   243
    private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
jaroslav@266
   244
        String jsb = javaScriptBody(prefix, m, false);
jaroslav@266
   245
        if (jsb != null) {
jaroslav@266
   246
            return jsb;
jaroslav@94
   247
        }
lubomir@307
   248
        final String mn = findMethodName(m, new StringBuilder());
lubomir@307
   249
        generateMethod(prefix, mn, m);
jaroslav@266
   250
        return mn;
jaroslav@0
   251
    }
jaroslav@0
   252
lubomir@307
   253
    private void generateMethod(String prefix, String name, MethodData m)
lubomir@307
   254
            throws IOException {
lubomir@307
   255
        final StackMapIterator stackMapIterator = m.createStackMapIterator();
jaroslav@376
   256
        TrapDataIterator trap = m.getTrapDataIterator();
lubomir@307
   257
        final LocalsMapper lmapper =
lubomir@307
   258
                new LocalsMapper(stackMapIterator.getArguments());
lubomir@307
   259
lubomir@307
   260
        out.append(prefix).append(name).append(" = function(");
jaroslav@442
   261
        lmapper.outputArguments(out, m.isStatic());
lubomir@307
   262
        out.append(") {").append("\n");
lubomir@307
   263
lubomir@221
   264
        final byte[] byteCodes = m.getCode();
lubomir@307
   265
        if (byteCodes == null) {
lubomir@307
   266
            out.append("  throw 'no code found for ")
jaroslav@424
   267
               .append(jc.getClassName()).append('.')
jaroslav@424
   268
               .append(m.getName()).append("';\n");
lubomir@307
   269
            out.append("};");
lubomir@307
   270
            return;
lubomir@307
   271
        }
lubomir@307
   272
lubomir@307
   273
        final StackMapper smapper = new StackMapper();
lubomir@307
   274
jaroslav@442
   275
        if (!m.isStatic()) {
jaroslav@442
   276
            out.append("  var ").append(" lcA0 = this;\n");
jaroslav@442
   277
        }
lubomir@221
   278
lubomir@221
   279
        int lastStackFrame = -1;
jaroslav@398
   280
        TrapData[] previousTrap = null;
lubomir@585
   281
        boolean wide = false;
jaroslav@398
   282
        
jaroslav@10
   283
        out.append("\n  var gt = 0;\n  for(;;) switch(gt) {\n");
jaroslav@0
   284
        for (int i = 0; i < byteCodes.length; i++) {
jaroslav@272
   285
            int prev = i;
lubomir@221
   286
            stackMapIterator.advanceTo(i);
jaroslav@398
   287
            boolean changeInCatch = trap.advanceTo(i);
jaroslav@398
   288
            if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
jaroslav@398
   289
                if (previousTrap != null) {
jaroslav@398
   290
                    generateCatch(previousTrap);
jaroslav@398
   291
                    previousTrap = null;
jaroslav@398
   292
                }
jaroslav@398
   293
            }
lubomir@221
   294
            if (lastStackFrame != stackMapIterator.getFrameIndex()) {
lubomir@221
   295
                lastStackFrame = stackMapIterator.getFrameIndex();
lubomir@307
   296
                lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
lubomir@307
   297
                smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
jaroslav@376
   298
                out.append("    case " + i).append(": ");            
jaroslav@398
   299
                changeInCatch = true;
lubomir@221
   300
            } else {
jaroslav@399
   301
                debug("    /* " + i + " */ ");
lubomir@221
   302
            }
jaroslav@398
   303
            if (changeInCatch && trap.useTry()) {
tzezula@285
   304
                out.append("try {");
jaroslav@398
   305
                previousTrap = trap.current();
tzezula@285
   306
            }
lubomir@585
   307
            final int c = readUByte(byteCodes, i);
jaroslav@0
   308
            switch (c) {
jaroslav@151
   309
                case opc_aload_0:
lubomir@474
   310
                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
lubomir@281
   311
                    break;
jaroslav@151
   312
                case opc_iload_0:
lubomir@474
   313
                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0));
lubomir@281
   314
                    break;
jaroslav@151
   315
                case opc_lload_0:
lubomir@474
   316
                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0));
lubomir@281
   317
                    break;
jaroslav@151
   318
                case opc_fload_0:
lubomir@474
   319
                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0));
lubomir@281
   320
                    break;
jaroslav@151
   321
                case opc_dload_0:
lubomir@474
   322
                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0));
jaroslav@0
   323
                    break;
jaroslav@151
   324
                case opc_aload_1:
lubomir@474
   325
                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1));
lubomir@281
   326
                    break;
jaroslav@151
   327
                case opc_iload_1:
lubomir@474
   328
                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1));
lubomir@281
   329
                    break;
jaroslav@151
   330
                case opc_lload_1:
lubomir@474
   331
                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1));
lubomir@281
   332
                    break;
jaroslav@151
   333
                case opc_fload_1:
lubomir@474
   334
                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1));
lubomir@281
   335
                    break;
jaroslav@151
   336
                case opc_dload_1:
lubomir@474
   337
                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1));
jaroslav@0
   338
                    break;
jaroslav@151
   339
                case opc_aload_2:
lubomir@474
   340
                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2));
lubomir@281
   341
                    break;
jaroslav@151
   342
                case opc_iload_2:
lubomir@474
   343
                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2));
lubomir@281
   344
                    break;
jaroslav@151
   345
                case opc_lload_2:
lubomir@474
   346
                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2));
lubomir@281
   347
                    break;
jaroslav@151
   348
                case opc_fload_2:
lubomir@474
   349
                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2));
lubomir@281
   350
                    break;
jaroslav@151
   351
                case opc_dload_2:
lubomir@474
   352
                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2));
jaroslav@2
   353
                    break;
jaroslav@151
   354
                case opc_aload_3:
lubomir@474
   355
                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3));
lubomir@281
   356
                    break;
jaroslav@151
   357
                case opc_iload_3:
lubomir@474
   358
                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3));
lubomir@281
   359
                    break;
jaroslav@151
   360
                case opc_lload_3:
lubomir@474
   361
                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3));
lubomir@281
   362
                    break;
jaroslav@151
   363
                case opc_fload_3:
lubomir@474
   364
                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3));
lubomir@281
   365
                    break;
jaroslav@151
   366
                case opc_dload_3:
lubomir@474
   367
                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
jaroslav@3
   368
                    break;
lubomir@281
   369
                case opc_iload: {
lubomir@585
   370
                    ++i;
lubomir@585
   371
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   372
                                          : readUByte(byteCodes, i);
lubomir@585
   373
                    wide = false;
lubomir@474
   374
                    emit(out, "var @1 = @2;",
lubomir@474
   375
                         smapper.pushI(), lmapper.getI(indx));
lubomir@281
   376
                    break;
lubomir@281
   377
                }
lubomir@281
   378
                case opc_lload: {
lubomir@585
   379
                    ++i;
lubomir@585
   380
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   381
                                          : readUByte(byteCodes, i);
lubomir@585
   382
                    wide = false;
lubomir@474
   383
                    emit(out, "var @1 = @2;",
lubomir@474
   384
                         smapper.pushL(), lmapper.getL(indx));
lubomir@281
   385
                    break;
lubomir@281
   386
                }
lubomir@281
   387
                case opc_fload: {
lubomir@585
   388
                    ++i;
lubomir@585
   389
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   390
                                          : readUByte(byteCodes, i);
lubomir@585
   391
                    wide = false;
lubomir@474
   392
                    emit(out, "var @1 = @2;",
lubomir@474
   393
                         smapper.pushF(), lmapper.getF(indx));
lubomir@281
   394
                    break;
lubomir@281
   395
                }
lubomir@281
   396
                case opc_dload: {
lubomir@585
   397
                    ++i;
lubomir@585
   398
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   399
                                          : readUByte(byteCodes, i);
lubomir@585
   400
                    wide = false;
lubomir@474
   401
                    emit(out, "var @1 = @2;",
lubomir@474
   402
                         smapper.pushD(), lmapper.getD(indx));
lubomir@281
   403
                    break;
lubomir@281
   404
                }
jaroslav@151
   405
                case opc_aload: {
lubomir@585
   406
                    ++i;
lubomir@585
   407
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   408
                                          : readUByte(byteCodes, i);
lubomir@585
   409
                    wide = false;
lubomir@474
   410
                    emit(out, "var @1 = @2;",
lubomir@474
   411
                         smapper.pushA(), lmapper.getA(indx));
jaroslav@3
   412
                    break;
jaroslav@3
   413
                }
lubomir@281
   414
                case opc_istore: {
lubomir@585
   415
                    ++i;
lubomir@585
   416
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   417
                                          : readUByte(byteCodes, i);
lubomir@585
   418
                    wide = false;
lubomir@474
   419
                    emit(out, "var @1 = @2;",
lubomir@474
   420
                         lmapper.setI(indx), smapper.popI());
lubomir@281
   421
                    break;
lubomir@281
   422
                }
lubomir@281
   423
                case opc_lstore: {
lubomir@585
   424
                    ++i;
lubomir@585
   425
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   426
                                          : readUByte(byteCodes, i);
lubomir@585
   427
                    wide = false;
lubomir@474
   428
                    emit(out, "var @1 = @2;",
lubomir@474
   429
                         lmapper.setL(indx), smapper.popL());
lubomir@281
   430
                    break;
lubomir@281
   431
                }
lubomir@281
   432
                case opc_fstore: {
lubomir@585
   433
                    ++i;
lubomir@585
   434
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   435
                                          : readUByte(byteCodes, i);
lubomir@585
   436
                    wide = false;
lubomir@474
   437
                    emit(out, "var @1 = @2;",
lubomir@474
   438
                         lmapper.setF(indx), smapper.popF());
lubomir@281
   439
                    break;
lubomir@281
   440
                }
lubomir@281
   441
                case opc_dstore: {
lubomir@585
   442
                    ++i;
lubomir@585
   443
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   444
                                          : readUByte(byteCodes, i);
lubomir@585
   445
                    wide = false;
lubomir@474
   446
                    emit(out, "var @1 = @2;",
lubomir@474
   447
                         lmapper.setD(indx), smapper.popD());
lubomir@281
   448
                    break;
lubomir@281
   449
                }
jaroslav@151
   450
                case opc_astore: {
lubomir@585
   451
                    ++i;
lubomir@585
   452
                    final int indx = wide ? readUShort(byteCodes, i++)
lubomir@585
   453
                                          : readUByte(byteCodes, i);
lubomir@585
   454
                    wide = false;
lubomir@474
   455
                    emit(out, "var @1 = @2;",
lubomir@474
   456
                         lmapper.setA(indx), smapper.popA());
jaroslav@31
   457
                    break;
jaroslav@31
   458
                }
jaroslav@151
   459
                case opc_astore_0:
lubomir@474
   460
                    emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA());
lubomir@281
   461
                    break;
jaroslav@151
   462
                case opc_istore_0:
lubomir@474
   463
                    emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI());
lubomir@281
   464
                    break;
jaroslav@151
   465
                case opc_lstore_0:
lubomir@474
   466
                    emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL());
lubomir@281
   467
                    break;
jaroslav@151
   468
                case opc_fstore_0:
lubomir@474
   469
                    emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF());
lubomir@281
   470
                    break;
jaroslav@151
   471
                case opc_dstore_0:
lubomir@474
   472
                    emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD());
jaroslav@5
   473
                    break;
jaroslav@151
   474
                case opc_astore_1:
lubomir@474
   475
                    emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA());
lubomir@281
   476
                    break;
jaroslav@151
   477
                case opc_istore_1:
lubomir@474
   478
                    emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI());
lubomir@281
   479
                    break;
jaroslav@151
   480
                case opc_lstore_1:
lubomir@474
   481
                    emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL());
lubomir@281
   482
                    break;
jaroslav@151
   483
                case opc_fstore_1:
lubomir@474
   484
                    emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF());
lubomir@281
   485
                    break;
jaroslav@151
   486
                case opc_dstore_1:
lubomir@474
   487
                    emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD());
jaroslav@5
   488
                    break;
jaroslav@151
   489
                case opc_astore_2:
lubomir@474
   490
                    emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA());
lubomir@281
   491
                    break;
jaroslav@151
   492
                case opc_istore_2:
lubomir@474
   493
                    emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI());
lubomir@281
   494
                    break;
jaroslav@151
   495
                case opc_lstore_2:
lubomir@474
   496
                    emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL());
lubomir@281
   497
                    break;
jaroslav@151
   498
                case opc_fstore_2:
lubomir@474
   499
                    emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF());
lubomir@281
   500
                    break;
jaroslav@151
   501
                case opc_dstore_2:
lubomir@474
   502
                    emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD());
jaroslav@5
   503
                    break;
jaroslav@151
   504
                case opc_astore_3:
lubomir@474
   505
                    emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA());
lubomir@281
   506
                    break;
jaroslav@151
   507
                case opc_istore_3:
lubomir@474
   508
                    emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI());
lubomir@281
   509
                    break;
jaroslav@151
   510
                case opc_lstore_3:
lubomir@474
   511
                    emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL());
lubomir@281
   512
                    break;
jaroslav@151
   513
                case opc_fstore_3:
lubomir@474
   514
                    emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF());
lubomir@281
   515
                    break;
jaroslav@151
   516
                case opc_dstore_3:
lubomir@474
   517
                    emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
jaroslav@5
   518
                    break;
jaroslav@151
   519
                case opc_iadd:
Martin@445
   520
                    emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
lubomir@281
   521
                    break;
jaroslav@151
   522
                case opc_ladd:
lubomir@307
   523
                    emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
lubomir@281
   524
                    break;
jaroslav@151
   525
                case opc_fadd:
lubomir@307
   526
                    emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
lubomir@281
   527
                    break;
jaroslav@151
   528
                case opc_dadd:
lubomir@307
   529
                    emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
jaroslav@0
   530
                    break;
jaroslav@151
   531
                case opc_isub:
Martin@445
   532
                    emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
lubomir@281
   533
                    break;
jaroslav@151
   534
                case opc_lsub:
lubomir@307
   535
                    emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
lubomir@281
   536
                    break;
jaroslav@151
   537
                case opc_fsub:
lubomir@307
   538
                    emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
lubomir@281
   539
                    break;
jaroslav@151
   540
                case opc_dsub:
lubomir@307
   541
                    emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
jaroslav@2
   542
                    break;
jaroslav@151
   543
                case opc_imul:
Martin@445
   544
                    emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
lubomir@281
   545
                    break;
jaroslav@151
   546
                case opc_lmul:
lubomir@307
   547
                    emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
lubomir@281
   548
                    break;
jaroslav@151
   549
                case opc_fmul:
lubomir@307
   550
                    emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
lubomir@281
   551
                    break;
jaroslav@151
   552
                case opc_dmul:
lubomir@307
   553
                    emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
jaroslav@1
   554
                    break;
jaroslav@151
   555
                case opc_idiv:
lubomir@283
   556
                    emit(out, "@1 = Math.floor(@1 / @2);",
lubomir@307
   557
                         smapper.getI(1), smapper.popI());
lubomir@281
   558
                    break;
jaroslav@151
   559
                case opc_ldiv:
lubomir@283
   560
                    emit(out, "@1 = Math.floor(@1 / @2);",
lubomir@307
   561
                         smapper.getL(1), smapper.popL());
jaroslav@3
   562
                    break;
jaroslav@151
   563
                case opc_fdiv:
lubomir@307
   564
                    emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
lubomir@281
   565
                    break;
jaroslav@151
   566
                case opc_ddiv:
lubomir@307
   567
                    emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
jaroslav@3
   568
                    break;
jaroslav@178
   569
                case opc_irem:
lubomir@307
   570
                    emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   571
                    break;
jaroslav@178
   572
                case opc_lrem:
lubomir@307
   573
                    emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
lubomir@281
   574
                    break;
jaroslav@178
   575
                case opc_frem:
lubomir@307
   576
                    emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
lubomir@281
   577
                    break;
jaroslav@178
   578
                case opc_drem:
lubomir@307
   579
                    emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
jaroslav@178
   580
                    break;
jaroslav@151
   581
                case opc_iand:
lubomir@307
   582
                    emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   583
                    break;
jaroslav@151
   584
                case opc_land:
lubomir@307
   585
                    emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
jaroslav@7
   586
                    break;
jaroslav@151
   587
                case opc_ior:
lubomir@307
   588
                    emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   589
                    break;
jaroslav@151
   590
                case opc_lor:
lubomir@307
   591
                    emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL());
jaroslav@7
   592
                    break;
jaroslav@151
   593
                case opc_ixor:
lubomir@307
   594
                    emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   595
                    break;
jaroslav@151
   596
                case opc_lxor:
lubomir@307
   597
                    emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL());
jaroslav@6
   598
                    break;
jaroslav@151
   599
                case opc_ineg:
lubomir@307
   600
                    emit(out, "@1 = -@1;", smapper.getI(0));
lubomir@281
   601
                    break;
jaroslav@151
   602
                case opc_lneg:
lubomir@307
   603
                    emit(out, "@1 = -@1;", smapper.getL(0));
lubomir@281
   604
                    break;
jaroslav@151
   605
                case opc_fneg:
lubomir@307
   606
                    emit(out, "@1 = -@1;", smapper.getF(0));
lubomir@281
   607
                    break;
jaroslav@151
   608
                case opc_dneg:
lubomir@307
   609
                    emit(out, "@1 = -@1;", smapper.getD(0));
jaroslav@93
   610
                    break;
jaroslav@151
   611
                case opc_ishl:
lubomir@307
   612
                    emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   613
                    break;
jaroslav@151
   614
                case opc_lshl:
lubomir@307
   615
                    emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI());
jaroslav@93
   616
                    break;
jaroslav@151
   617
                case opc_ishr:
lubomir@307
   618
                    emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   619
                    break;
jaroslav@151
   620
                case opc_lshr:
lubomir@307
   621
                    emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
jaroslav@93
   622
                    break;
jaroslav@151
   623
                case opc_iushr:
lubomir@307
   624
                    emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
lubomir@281
   625
                    break;
jaroslav@151
   626
                case opc_lushr:
lubomir@307
   627
                    emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
jaroslav@93
   628
                    break;
jaroslav@151
   629
                case opc_iinc: {
lubomir@585
   630
                    ++i;
lubomir@585
   631
                    final int varIndx = wide ? readUShort(byteCodes, i++)
lubomir@585
   632
                                             : readUByte(byteCodes, i);
lubomir@585
   633
                    ++i;
lubomir@585
   634
                    final int incrBy = wide ? readIntArg(byteCodes, i++)
lubomir@585
   635
                                            : byteCodes[i];
lubomir@585
   636
                    wide = false;
jaroslav@5
   637
                    if (incrBy == 1) {
lubomir@307
   638
                        emit(out, "@1++;", lmapper.getI(varIndx));
jaroslav@5
   639
                    } else {
lubomir@307
   640
                        emit(out, "@1 += @2;",
lubomir@307
   641
                             lmapper.getI(varIndx),
lubomir@283
   642
                             Integer.toString(incrBy));
jaroslav@5
   643
                    }
jaroslav@5
   644
                    break;
jaroslav@5
   645
                }
jaroslav@151
   646
                case opc_return:
lubomir@283
   647
                    emit(out, "return;");
jaroslav@10
   648
                    break;
jaroslav@151
   649
                case opc_ireturn:
lubomir@307
   650
                    emit(out, "return @1;", smapper.popI());
lubomir@281
   651
                    break;
jaroslav@151
   652
                case opc_lreturn:
lubomir@307
   653
                    emit(out, "return @1;", smapper.popL());
lubomir@281
   654
                    break;
jaroslav@151
   655
                case opc_freturn:
lubomir@307
   656
                    emit(out, "return @1;", smapper.popF());
lubomir@281
   657
                    break;
jaroslav@151
   658
                case opc_dreturn:
lubomir@307
   659
                    emit(out, "return @1;", smapper.popD());
lubomir@281
   660
                    break;
jaroslav@151
   661
                case opc_areturn:
lubomir@307
   662
                    emit(out, "return @1;", smapper.popA());
jaroslav@1
   663
                    break;
jaroslav@151
   664
                case opc_i2l:
lubomir@474
   665
                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL());
lubomir@281
   666
                    break;
jaroslav@151
   667
                case opc_i2f:
lubomir@474
   668
                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF());
lubomir@281
   669
                    break;
jaroslav@151
   670
                case opc_i2d:
lubomir@474
   671
                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
lubomir@281
   672
                    break;
jaroslav@151
   673
                case opc_l2i:
lubomir@474
   674
                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushI());
lubomir@281
   675
                    break;
jaroslav@3
   676
                    // max int check?
jaroslav@151
   677
                case opc_l2f:
lubomir@474
   678
                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushF());
jaroslav@272
   679
                    break;
jaroslav@151
   680
                case opc_l2d:
lubomir@474
   681
                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushD());
jaroslav@272
   682
                    break;
jaroslav@151
   683
                case opc_f2d:
lubomir@474
   684
                    emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
lubomir@281
   685
                    break;
jaroslav@151
   686
                case opc_d2f:
lubomir@474
   687
                    emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
jaroslav@3
   688
                    break;
jaroslav@151
   689
                case opc_f2i:
lubomir@474
   690
                    emit(out, "var @2 = Math.floor(@1);",
lubomir@307
   691
                         smapper.popF(), smapper.pushI());
lubomir@281
   692
                    break;
jaroslav@151
   693
                case opc_f2l:
lubomir@474
   694
                    emit(out, "var @2 = Math.floor(@1);",
lubomir@307
   695
                         smapper.popF(), smapper.pushL());
lubomir@281
   696
                    break;
jaroslav@151
   697
                case opc_d2i:
lubomir@474
   698
                    emit(out, "var @2 = Math.floor(@1);",
lubomir@307
   699
                         smapper.popD(), smapper.pushI());
lubomir@281
   700
                    break;
jaroslav@151
   701
                case opc_d2l:
lubomir@474
   702
                    emit(out, "var @2 = Math.floor(@1);",
lubomir@307
   703
                         smapper.popD(), smapper.pushL());
jaroslav@3
   704
                    break;
jaroslav@151
   705
                case opc_i2b:
lubomir@474
   706
                    emit(out, "var @1 = @1.toInt8();", smapper.getI(0));
Martin@440
   707
                    break;
jaroslav@151
   708
                case opc_i2c:
Martin@439
   709
                    out.append("{ /* number conversion */ }");
Martin@439
   710
                    break;
jaroslav@151
   711
                case opc_i2s:
lubomir@474
   712
                    emit(out, "var @1 = @1.toInt16();", smapper.getI(0));
jaroslav@2
   713
                    break;
jaroslav@151
   714
                case opc_aconst_null:
lubomir@474
   715
                    emit(out, "var @1 = null;", smapper.pushA());
jaroslav@46
   716
                    break;
jaroslav@151
   717
                case opc_iconst_m1:
lubomir@474
   718
                    emit(out, "var @1 = -1;", smapper.pushI());
jaroslav@48
   719
                    break;
jaroslav@151
   720
                case opc_iconst_0:
lubomir@474
   721
                    emit(out, "var @1 = 0;", smapper.pushI());
lubomir@281
   722
                    break;
jaroslav@151
   723
                case opc_dconst_0:
lubomir@474
   724
                    emit(out, "var @1 = 0;", smapper.pushD());
lubomir@281
   725
                    break;
jaroslav@151
   726
                case opc_lconst_0:
lubomir@474
   727
                    emit(out, "var @1 = 0;", smapper.pushL());
lubomir@281
   728
                    break;
jaroslav@151
   729
                case opc_fconst_0:
lubomir@474
   730
                    emit(out, "var @1 = 0;", smapper.pushF());
jaroslav@4
   731
                    break;
jaroslav@151
   732
                case opc_iconst_1:
lubomir@474
   733
                    emit(out, "var @1 = 1;", smapper.pushI());
lubomir@281
   734
                    break;
jaroslav@151
   735
                case opc_lconst_1:
lubomir@474
   736
                    emit(out, "var @1 = 1;", smapper.pushL());
lubomir@281
   737
                    break;
jaroslav@151
   738
                case opc_fconst_1:
lubomir@474
   739
                    emit(out, "var @1 = 1;", smapper.pushF());
lubomir@281
   740
                    break;
jaroslav@151
   741
                case opc_dconst_1:
lubomir@474
   742
                    emit(out, "var @1 = 1;", smapper.pushD());
jaroslav@4
   743
                    break;
jaroslav@151
   744
                case opc_iconst_2:
lubomir@474
   745
                    emit(out, "var @1 = 2;", smapper.pushI());
lubomir@281
   746
                    break;
jaroslav@151
   747
                case opc_fconst_2:
lubomir@474
   748
                    emit(out, "var @1 = 2;", smapper.pushF());
jaroslav@4
   749
                    break;
jaroslav@151
   750
                case opc_iconst_3:
lubomir@474
   751
                    emit(out, "var @1 = 3;", smapper.pushI());
jaroslav@4
   752
                    break;
jaroslav@151
   753
                case opc_iconst_4:
lubomir@474
   754
                    emit(out, "var @1 = 4;", smapper.pushI());
jaroslav@4
   755
                    break;
jaroslav@151
   756
                case opc_iconst_5:
lubomir@474
   757
                    emit(out, "var @1 = 5;", smapper.pushI());
jaroslav@4
   758
                    break;
jaroslav@151
   759
                case opc_ldc: {
lubomir@585
   760
                    int indx = readUByte(byteCodes, ++i);
jaroslav@151
   761
                    String v = encodeConstant(indx);
lubomir@307
   762
                    int type = VarType.fromConstantType(jc.getTag(indx));
lubomir@474
   763
                    emit(out, "var @1 = @2;", smapper.pushT(type), v);
jaroslav@20
   764
                    break;
jaroslav@20
   765
                }
jaroslav@151
   766
                case opc_ldc_w:
jaroslav@151
   767
                case opc_ldc2_w: {
jaroslav@8
   768
                    int indx = readIntArg(byteCodes, i);
jaroslav@8
   769
                    i += 2;
jaroslav@151
   770
                    String v = encodeConstant(indx);
lubomir@307
   771
                    int type = VarType.fromConstantType(jc.getTag(indx));
lubomir@474
   772
                    emit(out, "var @1 = @2;", smapper.pushT(type), v);
jaroslav@8
   773
                    break;
jaroslav@8
   774
                }
jaroslav@151
   775
                case opc_lcmp:
lubomir@474
   776
                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
lubomir@307
   777
                         smapper.popL(), smapper.popL(), smapper.pushI());
lubomir@281
   778
                    break;
jaroslav@151
   779
                case opc_fcmpl:
jaroslav@151
   780
                case opc_fcmpg:
lubomir@474
   781
                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
lubomir@307
   782
                         smapper.popF(), smapper.popF(), smapper.pushI());
lubomir@281
   783
                    break;
jaroslav@151
   784
                case opc_dcmpl:
lubomir@281
   785
                case opc_dcmpg:
lubomir@474
   786
                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
lubomir@307
   787
                         smapper.popD(), smapper.popD(), smapper.pushI());
jaroslav@20
   788
                    break;
jaroslav@151
   789
                case opc_if_acmpeq:
lubomir@307
   790
                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
lubomir@281
   791
                                   "===");
jaroslav@104
   792
                    break;
jaroslav@151
   793
                case opc_if_acmpne:
lubomir@307
   794
                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
lubomir@281
   795
                                   "!=");
jaroslav@104
   796
                    break;
lubomir@283
   797
                case opc_if_icmpeq:
lubomir@307
   798
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   799
                                   "==");
jaroslav@4
   800
                    break;
jaroslav@151
   801
                case opc_ifeq: {
jaroslav@7
   802
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   803
                    emit(out, "if (@1 == 0) { gt = @2; continue; }",
lubomir@307
   804
                         smapper.popI(), Integer.toString(indx));
jaroslav@7
   805
                    i += 2;
jaroslav@7
   806
                    break;
jaroslav@7
   807
                }
jaroslav@151
   808
                case opc_ifne: {
jaroslav@20
   809
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   810
                    emit(out, "if (@1 != 0) { gt = @2; continue; }",
lubomir@307
   811
                         smapper.popI(), Integer.toString(indx));
jaroslav@20
   812
                    i += 2;
jaroslav@20
   813
                    break;
jaroslav@20
   814
                }
jaroslav@151
   815
                case opc_iflt: {
jaroslav@20
   816
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   817
                    emit(out, "if (@1 < 0) { gt = @2; continue; }",
lubomir@307
   818
                         smapper.popI(), Integer.toString(indx));
jaroslav@20
   819
                    i += 2;
jaroslav@20
   820
                    break;
jaroslav@20
   821
                }
jaroslav@151
   822
                case opc_ifle: {
jaroslav@20
   823
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   824
                    emit(out, "if (@1 <= 0) { gt = @2; continue; }",
lubomir@307
   825
                         smapper.popI(), Integer.toString(indx));
jaroslav@20
   826
                    i += 2;
jaroslav@20
   827
                    break;
jaroslav@20
   828
                }
jaroslav@151
   829
                case opc_ifgt: {
jaroslav@20
   830
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   831
                    emit(out, "if (@1 > 0) { gt = @2; continue; }",
lubomir@307
   832
                         smapper.popI(), Integer.toString(indx));
jaroslav@20
   833
                    i += 2;
jaroslav@20
   834
                    break;
jaroslav@20
   835
                }
jaroslav@151
   836
                case opc_ifge: {
jaroslav@20
   837
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   838
                    emit(out, "if (@1 >= 0) { gt = @2; continue; }",
lubomir@307
   839
                         smapper.popI(), Integer.toString(indx));
jaroslav@20
   840
                    i += 2;
jaroslav@20
   841
                    break;
jaroslav@20
   842
                }
jaroslav@151
   843
                case opc_ifnonnull: {
jaroslav@16
   844
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   845
                    emit(out, "if (@1 !== null) { gt = @2; continue; }",
lubomir@307
   846
                         smapper.popA(), Integer.toString(indx));
jaroslav@16
   847
                    i += 2;
jaroslav@16
   848
                    break;
jaroslav@16
   849
                }
jaroslav@151
   850
                case opc_ifnull: {
jaroslav@16
   851
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   852
                    emit(out, "if (@1 === null) { gt = @2; continue; }",
lubomir@307
   853
                         smapper.popA(), Integer.toString(indx));
jaroslav@16
   854
                    i += 2;
jaroslav@16
   855
                    break;
jaroslav@16
   856
                }
jaroslav@151
   857
                case opc_if_icmpne:
lubomir@307
   858
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   859
                                   "!=");
jaroslav@4
   860
                    break;
jaroslav@151
   861
                case opc_if_icmplt:
lubomir@307
   862
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   863
                                   "<");
jaroslav@4
   864
                    break;
jaroslav@151
   865
                case opc_if_icmple:
lubomir@307
   866
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   867
                                   "<=");
jaroslav@4
   868
                    break;
jaroslav@151
   869
                case opc_if_icmpgt:
lubomir@307
   870
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   871
                                   ">");
jaroslav@4
   872
                    break;
jaroslav@151
   873
                case opc_if_icmpge:
lubomir@307
   874
                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
lubomir@281
   875
                                   ">=");
jaroslav@4
   876
                    break;
jaroslav@151
   877
                case opc_goto: {
jaroslav@5
   878
                    int indx = i + readIntArg(byteCodes, i);
lubomir@283
   879
                    emit(out, "gt = @1; continue;", Integer.toString(indx));
jaroslav@5
   880
                    i += 2;
jaroslav@5
   881
                    break;
jaroslav@5
   882
                }
jaroslav@151
   883
                case opc_lookupswitch: {
jtulach@128
   884
                    int table = i / 4 * 4 + 4;
jaroslav@115
   885
                    int dflt = i + readInt4(byteCodes, table);
jaroslav@115
   886
                    table += 4;
jaroslav@115
   887
                    int n = readInt4(byteCodes, table);
jaroslav@115
   888
                    table += 4;
lubomir@307
   889
                    out.append("switch (").append(smapper.popI()).append(") {\n");
jaroslav@115
   890
                    while (n-- > 0) {
jaroslav@115
   891
                        int cnstnt = readInt4(byteCodes, table);
jaroslav@115
   892
                        table += 4;
jaroslav@115
   893
                        int offset = i + readInt4(byteCodes, table);
jaroslav@115
   894
                        table += 4;
jaroslav@115
   895
                        out.append("  case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
jaroslav@115
   896
                    }
jaroslav@115
   897
                    out.append("  default: gt = " + dflt).append("; continue;\n}");
jaroslav@115
   898
                    i = table - 1;
jaroslav@115
   899
                    break;
jaroslav@115
   900
                }
jaroslav@151
   901
                case opc_tableswitch: {
jtulach@128
   902
                    int table = i / 4 * 4 + 4;
jaroslav@115
   903
                    int dflt = i + readInt4(byteCodes, table);
jaroslav@115
   904
                    table += 4;
jaroslav@115
   905
                    int low = readInt4(byteCodes, table);
jaroslav@115
   906
                    table += 4;
jaroslav@115
   907
                    int high = readInt4(byteCodes, table);
jaroslav@115
   908
                    table += 4;
lubomir@307
   909
                    out.append("switch (").append(smapper.popI()).append(") {\n");
jaroslav@115
   910
                    while (low <= high) {
jaroslav@115
   911
                        int offset = i + readInt4(byteCodes, table);
jaroslav@115
   912
                        table += 4;
jaroslav@115
   913
                        out.append("  case " + low).append(": gt = " + offset).append("; continue;\n");
jaroslav@115
   914
                        low++;
jaroslav@115
   915
                    }
jaroslav@115
   916
                    out.append("  default: gt = " + dflt).append("; continue;\n}");
jaroslav@115
   917
                    i = table - 1;
jaroslav@115
   918
                    break;
jaroslav@115
   919
                }
jaroslav@151
   920
                case opc_invokeinterface: {
lubomir@307
   921
                    i = invokeVirtualMethod(byteCodes, i, smapper) + 2;
jaroslav@46
   922
                    break;
jaroslav@46
   923
                }
jaroslav@151
   924
                case opc_invokevirtual:
lubomir@307
   925
                    i = invokeVirtualMethod(byteCodes, i, smapper);
jaroslav@12
   926
                    break;
jaroslav@151
   927
                case opc_invokespecial:
lubomir@307
   928
                    i = invokeStaticMethod(byteCodes, i, smapper, false);
jaroslav@4
   929
                    break;
jaroslav@151
   930
                case opc_invokestatic:
lubomir@307
   931
                    i = invokeStaticMethod(byteCodes, i, smapper, true);
jaroslav@10
   932
                    break;
jaroslav@151
   933
                case opc_new: {
jaroslav@8
   934
                    int indx = readIntArg(byteCodes, i);
jaroslav@151
   935
                    String ci = jc.getClassName(indx);
lubomir@474
   936
                    emit(out, "var @1 = new @2;",
lubomir@317
   937
                         smapper.pushA(), accessClass(ci.replace('/', '_')));
jaroslav@151
   938
                    addReference(ci);
jaroslav@8
   939
                    i += 2;
jaroslav@8
   940
                    break;
jaroslav@8
   941
                }
lubomir@283
   942
                case opc_newarray:
lubomir@585
   943
                    int atype = readUByte(byteCodes, ++i);
jaroslav@448
   944
                    String jvmType;
jaroslav@448
   945
                    switch (atype) {
jaroslav@448
   946
                        case 4: jvmType = "[Z"; break;
jaroslav@448
   947
                        case 5: jvmType = "[C"; break;
jaroslav@448
   948
                        case 6: jvmType = "[F"; break;
jaroslav@448
   949
                        case 7: jvmType = "[D"; break;
jaroslav@448
   950
                        case 8: jvmType = "[B"; break;
jaroslav@448
   951
                        case 9: jvmType = "[S"; break;
jaroslav@448
   952
                        case 10: jvmType = "[I"; break;
jaroslav@448
   953
                        case 11: jvmType = "[J"; break;
jaroslav@448
   954
                        default: throw new IllegalStateException("Array type: " + atype);
jaroslav@448
   955
                    }
jaroslav@488
   956
                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
jaroslav@448
   957
                         smapper.popI(), smapper.pushA(), jvmType);
jaroslav@21
   958
                    break;
jaroslav@448
   959
                case opc_anewarray: {
jaroslav@448
   960
                    int type = readIntArg(byteCodes, i);
jaroslav@448
   961
                    i += 2;
jaroslav@448
   962
                    String typeName = jc.getClassName(type);
jaroslav@448
   963
                    if (typeName.startsWith("[")) {
jaroslav@448
   964
                        typeName = "[" + typeName;
jaroslav@448
   965
                    } else {
jaroslav@448
   966
                        typeName = "[L" + typeName + ";";
jaroslav@448
   967
                    }
jaroslav@488
   968
                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
jaroslav@448
   969
                         smapper.popI(), smapper.pushA(), typeName);
jaroslav@21
   970
                    break;
jaroslav@448
   971
                }
jaroslav@151
   972
                case opc_multianewarray: {
jaroslav@448
   973
                    int type = readIntArg(byteCodes, i);
jtulach@128
   974
                    i += 2;
jaroslav@448
   975
                    String typeName = jc.getClassName(type);
lubomir@585
   976
                    int dim = readUByte(byteCodes, ++i);
jaroslav@481
   977
                    StringBuilder dims = new StringBuilder();
jaroslav@481
   978
                    dims.append('[');
jaroslav@481
   979
                    for (int d = 0; d < dim; d++) {
jaroslav@481
   980
                        if (d != 0) {
jaroslav@481
   981
                            dims.append(",");
jaroslav@481
   982
                        }
jaroslav@481
   983
                        dims.append(smapper.popI());
jtulach@128
   984
                    }
jaroslav@481
   985
                    dims.append(']');
jaroslav@488
   986
                    emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
jaroslav@481
   987
                         dims.toString(), smapper.pushA(), typeName);
jtulach@128
   988
                    break;
jtulach@128
   989
                }
jaroslav@151
   990
                case opc_arraylength:
lubomir@474
   991
                    emit(out, "var @2 = @1.length;",
lubomir@474
   992
                         smapper.popA(), smapper.pushI());
jaroslav@272
   993
                    break;
lubomir@283
   994
                case opc_lastore:
jaroslav@459
   995
                    emit(out, "@3.at(@2, @1);",
lubomir@307
   996
                         smapper.popL(), smapper.popI(), smapper.popA());
lubomir@281
   997
                    break;
lubomir@283
   998
                case opc_fastore:
jaroslav@459
   999
                    emit(out, "@3.at(@2, @1);",
lubomir@307
  1000
                         smapper.popF(), smapper.popI(), smapper.popA());
lubomir@281
  1001
                    break;
lubomir@283
  1002
                case opc_dastore:
jaroslav@459
  1003
                    emit(out, "@3.at(@2, @1);",
lubomir@307
  1004
                         smapper.popD(), smapper.popI(), smapper.popA());
lubomir@281
  1005
                    break;
lubomir@283
  1006
                case opc_aastore:
jaroslav@459
  1007
                    emit(out, "@3.at(@2, @1);",
lubomir@307
  1008
                         smapper.popA(), smapper.popI(), smapper.popA());
jaroslav@21
  1009
                    break;
jaroslav@151
  1010
                case opc_iastore:
jaroslav@151
  1011
                case opc_bastore:
jaroslav@151
  1012
                case opc_castore:
lubomir@283
  1013
                case opc_sastore:
jaroslav@459
  1014
                    emit(out, "@3.at(@2, @1);",
lubomir@307
  1015
                         smapper.popI(), smapper.popI(), smapper.popA());
jaroslav@240
  1016
                    break;
lubomir@283
  1017
                case opc_laload:
lubomir@474
  1018
                    emit(out, "var @3 = @2.at(@1);",
lubomir@307
  1019
                         smapper.popI(), smapper.popA(), smapper.pushL());
lubomir@281
  1020
                    break;
lubomir@283
  1021
                case opc_faload:
lubomir@474
  1022
                    emit(out, "var @3 = @2.at(@1);",
lubomir@307
  1023
                         smapper.popI(), smapper.popA(), smapper.pushF());
lubomir@281
  1024
                    break;
lubomir@283
  1025
                case opc_daload:
lubomir@474
  1026
                    emit(out, "var @3 = @2.at(@1);",
lubomir@307
  1027
                         smapper.popI(), smapper.popA(), smapper.pushD());
lubomir@281
  1028
                    break;
lubomir@283
  1029
                case opc_aaload:
lubomir@474
  1030
                    emit(out, "var @3 = @2.at(@1);",
lubomir@307
  1031
                         smapper.popI(), smapper.popA(), smapper.pushA());
jaroslav@272
  1032
                    break;
jaroslav@272
  1033
                case opc_iaload:
jaroslav@272
  1034
                case opc_baload:
jaroslav@272
  1035
                case opc_caload:
lubomir@283
  1036
                case opc_saload:
lubomir@474
  1037
                    emit(out, "var @3 = @2.at(@1);",
lubomir@307
  1038
                         smapper.popI(), smapper.popA(), smapper.pushI());
jaroslav@272
  1039
                    break;
lubomir@221
  1040
                case opc_pop:
jaroslav@272
  1041
                case opc_pop2:
lubomir@307
  1042
                    smapper.pop(1);
jaroslav@399
  1043
                    debug("/* pop */");
jaroslav@272
  1044
                    break;
lubomir@281
  1045
                case opc_dup: {
lubomir@307
  1046
                    final Variable v = smapper.get(0);
lubomir@474
  1047
                    emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v);
jaroslav@21
  1048
                    break;
jaroslav@21
  1049
                }
lubomir@281
  1050
                case opc_dup2: {
lubomir@585
  1051
                    final Variable vi1 = smapper.get(0);
lubomir@585
  1052
lubomir@585
  1053
                    if (vi1.isCategory2()) {
lubomir@474
  1054
                        emit(out, "var @1 = @2;",
lubomir@585
  1055
                             smapper.pushT(vi1.getType()), vi1);
lubomir@281
  1056
                    } else {
lubomir@585
  1057
                        final Variable vi2 = smapper.get(1);
lubomir@474
  1058
                        emit(out, "var @1 = @2, @3 = @4;",
lubomir@585
  1059
                             smapper.pushT(vi2.getType()), vi2,
lubomir@585
  1060
                             smapper.pushT(vi1.getType()), vi1);
lubomir@281
  1061
                    }
jaroslav@21
  1062
                    break;
jaroslav@21
  1063
                }
lubomir@281
  1064
                case opc_dup_x1: {
lubomir@307
  1065
                    final Variable vi1 = smapper.pop();
lubomir@307
  1066
                    final Variable vi2 = smapper.pop();
lubomir@307
  1067
                    final Variable vo3 = smapper.pushT(vi1.getType());
lubomir@307
  1068
                    final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@307
  1069
                    final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@281
  1070
lubomir@474
  1071
                    emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
lubomir@283
  1072
                         vo1, vi1, vo2, vi2, vo3, vo1);
jaroslav@93
  1073
                    break;
lubomir@281
  1074
                }
lubomir@585
  1075
                case opc_dup2_x1: {
lubomir@585
  1076
                    final Variable vi1 = smapper.pop();
lubomir@585
  1077
                    final Variable vi2 = smapper.pop();
lubomir@585
  1078
lubomir@585
  1079
                    if (vi1.isCategory2()) {
lubomir@307
  1080
                        final Variable vo3 = smapper.pushT(vi1.getType());
lubomir@307
  1081
                        final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@307
  1082
                        final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@281
  1083
lubomir@474
  1084
                        emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
lubomir@283
  1085
                             vo1, vi1, vo2, vi2, vo3, vo1);
lubomir@281
  1086
                    } else {
lubomir@585
  1087
                        final Variable vi3 = smapper.pop();
lubomir@585
  1088
                        final Variable vo5 = smapper.pushT(vi2.getType());
lubomir@585
  1089
                        final Variable vo4 = smapper.pushT(vi1.getType());
lubomir@585
  1090
                        final Variable vo3 = smapper.pushT(vi3.getType());
lubomir@585
  1091
                        final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1092
                        final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1093
lubomir@585
  1094
                        emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
lubomir@585
  1095
                             vo1, vi1, vo2, vi2, vo3, vi3);
lubomir@585
  1096
                        emit(out, " @1 = @2, @3 = @4;",
lubomir@585
  1097
                             vo4, vo1, vo5, vo2);
lubomir@585
  1098
                    }
lubomir@585
  1099
                    break;
lubomir@585
  1100
                }
lubomir@585
  1101
                case opc_dup_x2: {
lubomir@585
  1102
                    final Variable vi1 = smapper.pop();
lubomir@585
  1103
                    final Variable vi2 = smapper.pop();
lubomir@585
  1104
lubomir@585
  1105
                    if (vi2.isCategory2()) {
lubomir@585
  1106
                        final Variable vo3 = smapper.pushT(vi1.getType());
lubomir@585
  1107
                        final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1108
                        final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1109
lubomir@585
  1110
                        emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
lubomir@585
  1111
                             vo1, vi1, vo2, vi2, vo3, vo1);
lubomir@585
  1112
                    } else {
lubomir@307
  1113
                        final Variable vi3 = smapper.pop();
lubomir@307
  1114
                        final Variable vo4 = smapper.pushT(vi1.getType());
lubomir@307
  1115
                        final Variable vo3 = smapper.pushT(vi3.getType());
lubomir@307
  1116
                        final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@307
  1117
                        final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@281
  1118
lubomir@474
  1119
                        emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
lubomir@283
  1120
                             vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
lubomir@281
  1121
                    }
jaroslav@8
  1122
                    break;
lubomir@281
  1123
                }
lubomir@585
  1124
                case opc_dup2_x2: {
lubomir@585
  1125
                    final Variable vi1 = smapper.pop();
lubomir@585
  1126
                    final Variable vi2 = smapper.pop();
lubomir@585
  1127
lubomir@585
  1128
                    if (vi1.isCategory2()) {
lubomir@585
  1129
                        if (vi2.isCategory2()) {
lubomir@585
  1130
                            final Variable vo3 = smapper.pushT(vi1.getType());
lubomir@585
  1131
                            final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1132
                            final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1133
lubomir@585
  1134
                            emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
lubomir@585
  1135
                                 vo1, vi1, vo2, vi2, vo3, vo1);
lubomir@585
  1136
                        } else {
lubomir@585
  1137
                            final Variable vi3 = smapper.pop();
lubomir@585
  1138
                            final Variable vo4 = smapper.pushT(vi1.getType());
lubomir@585
  1139
                            final Variable vo3 = smapper.pushT(vi3.getType());
lubomir@585
  1140
                            final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1141
                            final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1142
lubomir@585
  1143
                            emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
lubomir@585
  1144
                                 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
lubomir@585
  1145
                        }
lubomir@585
  1146
                    } else {
lubomir@585
  1147
                        final Variable vi3 = smapper.pop();
lubomir@585
  1148
lubomir@585
  1149
                        if (vi3.isCategory2()) {
lubomir@585
  1150
                            final Variable vo5 = smapper.pushT(vi2.getType());
lubomir@585
  1151
                            final Variable vo4 = smapper.pushT(vi1.getType());
lubomir@585
  1152
                            final Variable vo3 = smapper.pushT(vi3.getType());
lubomir@585
  1153
                            final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1154
                            final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1155
lubomir@585
  1156
                            emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
lubomir@585
  1157
                                 vo1, vi1, vo2, vi2, vo3, vi3);
lubomir@585
  1158
                            emit(out, " @1 = @2, @3 = @4;",
lubomir@585
  1159
                                 vo4, vo1, vo5, vo2);
lubomir@585
  1160
                        } else {
lubomir@585
  1161
                            final Variable vi4 = smapper.pop();
lubomir@585
  1162
                            final Variable vo6 = smapper.pushT(vi2.getType());
lubomir@585
  1163
                            final Variable vo5 = smapper.pushT(vi1.getType());
lubomir@585
  1164
                            final Variable vo4 = smapper.pushT(vi4.getType());
lubomir@585
  1165
                            final Variable vo3 = smapper.pushT(vi3.getType());
lubomir@585
  1166
                            final Variable vo2 = smapper.pushT(vi2.getType());
lubomir@585
  1167
                            final Variable vo1 = smapper.pushT(vi1.getType());
lubomir@585
  1168
                            
lubomir@585
  1169
                            emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
lubomir@585
  1170
                                 vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
lubomir@585
  1171
                            emit(out, " @1 = @2, @3 = @4;",
lubomir@585
  1172
                                 vo5, vo1, vo6, vo2);
lubomir@585
  1173
                        }
lubomir@585
  1174
                    }
lubomir@585
  1175
                    break;
lubomir@585
  1176
                }
lubomir@585
  1177
                case opc_swap: {
lubomir@585
  1178
                    final Variable vi1 = smapper.get(0);
lubomir@585
  1179
                    final Variable vi2 = smapper.get(1);
lubomir@585
  1180
lubomir@585
  1181
                    if (vi1.getType() == vi2.getType()) {
lubomir@585
  1182
                        final Variable tmp = smapper.pushT(vi1.getType());
lubomir@585
  1183
lubomir@585
  1184
                        emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
lubomir@585
  1185
                             tmp, vi1, vi2);
lubomir@585
  1186
                        smapper.pop(1);
lubomir@585
  1187
                    } else {
lubomir@585
  1188
                        smapper.pop(2);
lubomir@585
  1189
                        smapper.pushT(vi1.getType());
lubomir@585
  1190
                        smapper.pushT(vi2.getType());
lubomir@585
  1191
                    }
lubomir@585
  1192
                    break;
lubomir@585
  1193
                }
jaroslav@151
  1194
                case opc_bipush:
lubomir@474
  1195
                    emit(out, "var @1 = @2;",
lubomir@307
  1196
                         smapper.pushI(), Integer.toString(byteCodes[++i]));
jaroslav@8
  1197
                    break;
jaroslav@151
  1198
                case opc_sipush:
lubomir@474
  1199
                    emit(out, "var @1 = @2;",
lubomir@307
  1200
                         smapper.pushI(),
lubomir@283
  1201
                         Integer.toString(readIntArg(byteCodes, i)));
jaroslav@31
  1202
                    i += 2;
jaroslav@31
  1203
                    break;
jaroslav@151
  1204
                case opc_getfield: {
jaroslav@8
  1205
                    int indx = readIntArg(byteCodes, i);
jaroslav@151
  1206
                    String[] fi = jc.getFieldInfoName(indx);
lubomir@307
  1207
                    final int type = VarType.fromFieldType(fi[2].charAt(0));
jaroslav@592
  1208
                    final String mangleClass = mangleSig(fi[0]);
jaroslav@592
  1209
                    final String mangleClassAccess = accessClass(mangleClass);
jaroslav@592
  1210
                    emit(out, "var @2 = @4(false)._@3.call(@1);",
jaroslav@592
  1211
                         smapper.popA(),
jaroslav@592
  1212
                         smapper.pushT(type), fi[1], mangleClassAccess
jaroslav@592
  1213
                    );
jaroslav@592
  1214
                    i += 2;
jaroslav@592
  1215
                    break;
jaroslav@592
  1216
                }
jaroslav@592
  1217
                case opc_putfield: {
jaroslav@592
  1218
                    int indx = readIntArg(byteCodes, i);
jaroslav@592
  1219
                    String[] fi = jc.getFieldInfoName(indx);
jaroslav@592
  1220
                    final int type = VarType.fromFieldType(fi[2].charAt(0));
jaroslav@592
  1221
                    final String mangleClass = mangleSig(fi[0]);
jaroslav@592
  1222
                    final String mangleClassAccess = accessClass(mangleClass);
jaroslav@592
  1223
                    emit(out, "@4(false)._@3.call(@2, @1);",
jaroslav@592
  1224
                         smapper.popT(type),
jaroslav@592
  1225
                         smapper.popA(), fi[1], 
jaroslav@592
  1226
                         mangleClassAccess
jaroslav@592
  1227
                    );
jaroslav@8
  1228
                    i += 2;
jaroslav@8
  1229
                    break;
jaroslav@8
  1230
                }
jaroslav@151
  1231
                case opc_getstatic: {
jaroslav@9
  1232
                    int indx = readIntArg(byteCodes, i);
jaroslav@151
  1233
                    String[] fi = jc.getFieldInfoName(indx);
lubomir@307
  1234
                    final int type = VarType.fromFieldType(fi[2].charAt(0));
lubomir@474
  1235
                    emit(out, "var @1 = @2(false).constructor.@3;",
lubomir@317
  1236
                         smapper.pushT(type),
lubomir@317
  1237
                         accessClass(fi[0].replace('/', '_')), fi[1]);
jaroslav@9
  1238
                    i += 2;
jaroslav@151
  1239
                    addReference(fi[0]);
jaroslav@9
  1240
                    break;
jaroslav@9
  1241
                }
lubomir@281
  1242
                case opc_putstatic: {
lubomir@281
  1243
                    int indx = readIntArg(byteCodes, i);
lubomir@281
  1244
                    String[] fi = jc.getFieldInfoName(indx);
lubomir@307
  1245
                    final int type = VarType.fromFieldType(fi[2].charAt(0));
jaroslav@358
  1246
                    emit(out, "@1(false).constructor.@2 = @3;",
lubomir@317
  1247
                         accessClass(fi[0].replace('/', '_')), fi[1],
lubomir@317
  1248
                         smapper.popT(type));
lubomir@281
  1249
                    i += 2;
lubomir@281
  1250
                    addReference(fi[0]);
lubomir@281
  1251
                    break;
lubomir@281
  1252
                }
jaroslav@151
  1253
                case opc_checkcast: {
jaroslav@30
  1254
                    int indx = readIntArg(byteCodes, i);
jaroslav@151
  1255
                    final String type = jc.getClassName(indx);
jaroslav@42
  1256
                    if (!type.startsWith("[")) {
lubomir@317
  1257
                        emit(out,
lubomir@317
  1258
                             "if (@1 !== null && !@1.$instOf_@2) throw {};",
lubomir@307
  1259
                             smapper.getA(0), type.replace('/', '_'));
jaroslav@571
  1260
                    } else {
jaroslav@571
  1261
                        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);",
jaroslav@571
  1262
                             smapper.getA(0), type
jaroslav@571
  1263
                        );
jaroslav@42
  1264
                    }
jaroslav@30
  1265
                    i += 2;
jaroslav@30
  1266
                    break;
jaroslav@30
  1267
                }
jaroslav@151
  1268
                case opc_instanceof: {
jaroslav@17
  1269
                    int indx = readIntArg(byteCodes, i);
jaroslav@151
  1270
                    final String type = jc.getClassName(indx);
jaroslav@571
  1271
                    if (!type.startsWith("[")) {
jaroslav@571
  1272
                        emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
jaroslav@571
  1273
                             smapper.popA(), smapper.pushI(),
jaroslav@571
  1274
                             type.replace('/', '_'));
jaroslav@571
  1275
                    } else {
jaroslav@571
  1276
                        emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
jaroslav@571
  1277
                            smapper.popA(), smapper.pushI(),
jaroslav@571
  1278
                            type
jaroslav@571
  1279
                        );
jaroslav@571
  1280
                    }
jaroslav@17
  1281
                    i += 2;
jaroslav@30
  1282
                    break;
jaroslav@17
  1283
                }
jaroslav@151
  1284
                case opc_athrow: {
lubomir@307
  1285
                    final Variable v = smapper.popA();
lubomir@307
  1286
                    smapper.clear();
lubomir@281
  1287
lubomir@474
  1288
                    emit(out, "{ var @1 = @2; throw @2; }",
lubomir@307
  1289
                         smapper.pushA(), v);
jaroslav@104
  1290
                    break;
jaroslav@104
  1291
                }
lubomir@221
  1292
lubomir@221
  1293
                case opc_monitorenter: {
lubomir@221
  1294
                    out.append("/* monitor enter */");
lubomir@307
  1295
                    smapper.popA();
lubomir@221
  1296
                    break;
lubomir@221
  1297
                }
lubomir@221
  1298
lubomir@221
  1299
                case opc_monitorexit: {
lubomir@221
  1300
                    out.append("/* monitor exit */");
lubomir@307
  1301
                    smapper.popA();
lubomir@221
  1302
                    break;
lubomir@221
  1303
                }
lubomir@221
  1304
lubomir@585
  1305
                case opc_wide:
lubomir@585
  1306
                    wide = true;
lubomir@585
  1307
                    break;
lubomir@585
  1308
jaroslav@104
  1309
                default: {
lubomir@585
  1310
                    wide = false;
lubomir@283
  1311
                    emit(out, "throw 'unknown bytecode @1';",
lubomir@283
  1312
                         Integer.toString(c));
jaroslav@104
  1313
                }
jaroslav@0
  1314
            }
jaroslav@399
  1315
            if (debug(" //")) {
jaroslav@399
  1316
                for (int j = prev; j <= i; j++) {
jaroslav@399
  1317
                    out.append(" ");
lubomir@585
  1318
                    final int cc = readUByte(byteCodes, j);
jaroslav@399
  1319
                    out.append(Integer.toString(cc));
tzezula@285
  1320
                }
jaroslav@0
  1321
            }
tzezula@285
  1322
            out.append("\n");            
jaroslav@0
  1323
        }
jaroslav@398
  1324
        if (previousTrap != null) {
jaroslav@398
  1325
            generateCatch(previousTrap);
jaroslav@398
  1326
        }
jaroslav@10
  1327
        out.append("  }\n");
lubomir@307
  1328
        out.append("};");
jaroslav@4
  1329
    }
jaroslav@4
  1330
lubomir@281
  1331
    private int generateIf(byte[] byteCodes, int i,
lubomir@281
  1332
                           final Variable v2, final Variable v1,
lubomir@281
  1333
                           final String test) throws IOException {
jaroslav@4
  1334
        int indx = i + readIntArg(byteCodes, i);
lubomir@281
  1335
        out.append("if (").append(v1)
lubomir@221
  1336
           .append(' ').append(test).append(' ')
lubomir@281
  1337
           .append(v2).append(") { gt = " + indx)
lubomir@221
  1338
           .append("; continue; }");
jaroslav@4
  1339
        return i + 2;
jaroslav@4
  1340
    }
jaroslav@4
  1341
jaroslav@4
  1342
    private int readIntArg(byte[] byteCodes, int offsetInstruction) {
jaroslav@5
  1343
        final int indxHi = byteCodes[offsetInstruction + 1] << 8;
jaroslav@5
  1344
        final int indxLo = byteCodes[offsetInstruction + 2];
jaroslav@5
  1345
        return (indxHi & 0xffffff00) | (indxLo & 0xff);
jaroslav@4
  1346
    }
jaroslav@115
  1347
    private int readInt4(byte[] byteCodes, int offsetInstruction) {
jaroslav@115
  1348
        final int d = byteCodes[offsetInstruction + 0] << 24;
jaroslav@115
  1349
        final int c = byteCodes[offsetInstruction + 1] << 16;
jaroslav@115
  1350
        final int b = byteCodes[offsetInstruction + 2] << 8;
jaroslav@115
  1351
        final int a = byteCodes[offsetInstruction + 3];
jaroslav@115
  1352
        return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
jaroslav@115
  1353
    }
lubomir@585
  1354
    private int readUByte(byte[] byteCodes, int offsetInstruction) {
lubomir@221
  1355
        return byteCodes[offsetInstruction] & 0xff;
jtulach@128
  1356
    }
lubomir@585
  1357
lubomir@585
  1358
    private int readUShort(byte[] byteCodes, int offsetInstruction) {
lubomir@585
  1359
        return ((byteCodes[offsetInstruction] & 0xff) << 8)
lubomir@585
  1360
                    | (byteCodes[offsetInstruction + 1] & 0xff);
lubomir@585
  1361
    }
lubomir@585
  1362
lubomir@281
  1363
    private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
jaroslav@4
  1364
        int i = 0;
jaroslav@4
  1365
        Boolean count = null;
jaroslav@32
  1366
        boolean array = false;
jaroslav@248
  1367
        sig.append("__");
jaroslav@10
  1368
        int firstPos = sig.length();
jaroslav@4
  1369
        while (i < descriptor.length()) {
jaroslav@4
  1370
            char ch = descriptor.charAt(i++);
jaroslav@4
  1371
            switch (ch) {
jaroslav@4
  1372
                case '(':
jaroslav@4
  1373
                    count = true;
jaroslav@4
  1374
                    continue;
jaroslav@4
  1375
                case ')':
jaroslav@4
  1376
                    count = false;
jaroslav@4
  1377
                    continue;
jaroslav@4
  1378
                case 'B': 
jaroslav@4
  1379
                case 'C': 
jaroslav@4
  1380
                case 'D': 
jaroslav@4
  1381
                case 'F': 
jaroslav@4
  1382
                case 'I': 
jaroslav@4
  1383
                case 'J': 
jaroslav@4
  1384
                case 'S': 
jaroslav@4
  1385
                case 'Z': 
jaroslav@4
  1386
                    if (count) {
jaroslav@32
  1387
                        if (array) {
jaroslav@248
  1388
                            sig.append("_3");
jaroslav@32
  1389
                        }
jaroslav@4
  1390
                        sig.append(ch);
jtulach@156
  1391
                        if (ch == 'J' || ch == 'D') {
jtulach@156
  1392
                            cnt.append('1');
jtulach@156
  1393
                        } else {
jtulach@156
  1394
                            cnt.append('0');
jtulach@156
  1395
                        }
jaroslav@4
  1396
                    } else {
jaroslav@10
  1397
                        sig.insert(firstPos, ch);
jaroslav@32
  1398
                        if (array) {
lubomir@281
  1399
                            returnType[0] = '[';
jaroslav@248
  1400
                            sig.insert(firstPos, "_3");
lubomir@281
  1401
                        } else {
lubomir@281
  1402
                            returnType[0] = ch;
jaroslav@32
  1403
                        }
jaroslav@4
  1404
                    }
jaroslav@93
  1405
                    array = false;
jaroslav@4
  1406
                    continue;
jaroslav@4
  1407
                case 'V': 
jaroslav@4
  1408
                    assert !count;
lubomir@281
  1409
                    returnType[0] = 'V';
jaroslav@10
  1410
                    sig.insert(firstPos, 'V');
jaroslav@4
  1411
                    continue;
jaroslav@4
  1412
                case 'L':
jaroslav@16
  1413
                    int next = descriptor.indexOf(';', i);
jaroslav@248
  1414
                    String realSig = mangleSig(descriptor, i - 1, next + 1);
jaroslav@4
  1415
                    if (count) {
jaroslav@32
  1416
                        if (array) {
jaroslav@248
  1417
                            sig.append("_3");
jaroslav@32
  1418
                        }
jaroslav@248
  1419
                        sig.append(realSig);
jtulach@156
  1420
                        cnt.append('0');
jaroslav@4
  1421
                    } else {
jaroslav@248
  1422
                        sig.insert(firstPos, realSig);
jaroslav@32
  1423
                        if (array) {
jaroslav@248
  1424
                            sig.insert(firstPos, "_3");
jaroslav@32
  1425
                        }
lubomir@281
  1426
                        returnType[0] = 'L';
jaroslav@4
  1427
                    }
jaroslav@16
  1428
                    i = next + 1;
lubomir@407
  1429
                    array = false;
jaroslav@4
  1430
                    continue;
jaroslav@4
  1431
                case '[':
jaroslav@248
  1432
                    array = true;
jaroslav@4
  1433
                    continue;
jaroslav@4
  1434
                default:
jaroslav@248
  1435
                    throw new IllegalStateException("Invalid char: " + ch);
jaroslav@4
  1436
            }
jaroslav@4
  1437
        }
jaroslav@0
  1438
    }
jaroslav@248
  1439
    
jaroslav@592
  1440
    static String mangleSig(String sig) {
jaroslav@592
  1441
        return mangleSig(sig, 0, sig.length());
jaroslav@592
  1442
    }
jaroslav@592
  1443
    
jaroslav@248
  1444
    private static String mangleSig(String txt, int first, int last) {
jaroslav@248
  1445
        StringBuilder sb = new StringBuilder();
jaroslav@248
  1446
        for (int i = first; i < last; i++) {
jaroslav@248
  1447
            final char ch = txt.charAt(i);
jaroslav@248
  1448
            switch (ch) {
jaroslav@248
  1449
                case '/': sb.append('_'); break;
jaroslav@248
  1450
                case '_': sb.append("_1"); break;
jaroslav@248
  1451
                case ';': sb.append("_2"); break;
jaroslav@248
  1452
                case '[': sb.append("_3"); break;
jaroslav@248
  1453
                default: sb.append(ch); break;
jaroslav@248
  1454
            }
jaroslav@248
  1455
        }
jaroslav@248
  1456
        return sb.toString();
jaroslav@248
  1457
    }
jaroslav@9
  1458
jaroslav@248
  1459
    private static String findMethodName(MethodData m, StringBuilder cnt) {
jaroslav@42
  1460
        StringBuilder name = new StringBuilder();
jaroslav@10
  1461
        if ("<init>".equals(m.getName())) { // NOI18N
jaroslav@42
  1462
            name.append("cons"); // NOI18N
jaroslav@19
  1463
        } else if ("<clinit>".equals(m.getName())) { // NOI18N
jaroslav@42
  1464
            name.append("class"); // NOI18N
jaroslav@10
  1465
        } else {
jaroslav@42
  1466
            name.append(m.getName());
jaroslav@10
  1467
        } 
jaroslav@42
  1468
        
lubomir@282
  1469
        countArgs(m.getInternalSig(), new char[1], name, cnt);
jaroslav@42
  1470
        return name.toString();
jaroslav@10
  1471
    }
jaroslav@10
  1472
lubomir@282
  1473
    static String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) {
jaroslav@10
  1474
        StringBuilder name = new StringBuilder();
jaroslav@151
  1475
        String descr = mi[2];//mi.getDescriptor();
jaroslav@151
  1476
        String nm= mi[1];
jaroslav@151
  1477
        if ("<init>".equals(nm)) { // NOI18N
jaroslav@10
  1478
            name.append("cons"); // NOI18N
jaroslav@10
  1479
        } else {
jaroslav@151
  1480
            name.append(nm);
jaroslav@10
  1481
        }
lubomir@282
  1482
        countArgs(descr, returnType, name, cnt);
jaroslav@10
  1483
        return name.toString();
jaroslav@10
  1484
    }
jaroslav@10
  1485
lubomir@307
  1486
    private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
jaroslav@10
  1487
    throws IOException {
jaroslav@10
  1488
        int methodIndex = readIntArg(byteCodes, i);
jaroslav@151
  1489
        String[] mi = jc.getFieldInfoName(methodIndex);
lubomir@281
  1490
        char[] returnType = { 'V' };
jtulach@156
  1491
        StringBuilder cnt = new StringBuilder();
lubomir@281
  1492
        String mn = findMethodName(mi, cnt, returnType);
lubomir@221
  1493
lubomir@221
  1494
        final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
lubomir@281
  1495
        final Variable[] vars = new Variable[numArguments];
lubomir@221
  1496
lubomir@281
  1497
        for (int j = numArguments - 1; j >= 0; --j) {
lubomir@281
  1498
            vars[j] = mapper.pop();
jaroslav@11
  1499
        }
lubomir@281
  1500
lubomir@281
  1501
        if (returnType[0] != 'V') {
lubomir@474
  1502
            out.append("var ")
lubomir@474
  1503
               .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
lubomir@281
  1504
               .append(" = ");
jaroslav@10
  1505
        }
lubomir@221
  1506
jaroslav@151
  1507
        final String in = mi[0];
jaroslav@274
  1508
        out.append(accessClass(in.replace('/', '_')));
jaroslav@224
  1509
        out.append("(false).");
jaroslav@397
  1510
        if (mn.startsWith("cons_")) {
jaroslav@397
  1511
            out.append("constructor.");
jaroslav@397
  1512
        }
jaroslav@10
  1513
        out.append(mn);
jaroslav@442
  1514
        if (isStatic) {
jaroslav@442
  1515
            out.append('(');
jaroslav@442
  1516
        } else {
jaroslav@442
  1517
            out.append(".call(");
jaroslav@442
  1518
        }
lubomir@221
  1519
        if (numArguments > 0) {
lubomir@281
  1520
            out.append(vars[0]);
lubomir@281
  1521
            for (int j = 1; j < numArguments; ++j) {
lubomir@221
  1522
                out.append(", ");
lubomir@281
  1523
                out.append(vars[j]);
lubomir@221
  1524
            }
jaroslav@10
  1525
        }
lubomir@221
  1526
        out.append(");");
jaroslav@10
  1527
        i += 2;
jaroslav@18
  1528
        addReference(in);
jaroslav@10
  1529
        return i;
jaroslav@10
  1530
    }
lubomir@307
  1531
    private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
jaroslav@12
  1532
    throws IOException {
jaroslav@12
  1533
        int methodIndex = readIntArg(byteCodes, i);
jaroslav@151
  1534
        String[] mi = jc.getFieldInfoName(methodIndex);
lubomir@281
  1535
        char[] returnType = { 'V' };
jtulach@156
  1536
        StringBuilder cnt = new StringBuilder();
lubomir@281
  1537
        String mn = findMethodName(mi, cnt, returnType);
lubomir@221
  1538
lubomir@281
  1539
        final int numArguments = cnt.length() + 1;
lubomir@281
  1540
        final Variable[] vars = new Variable[numArguments];
lubomir@221
  1541
lubomir@281
  1542
        for (int j = numArguments - 1; j >= 0; --j) {
lubomir@281
  1543
            vars[j] = mapper.pop();
jaroslav@12
  1544
        }
lubomir@221
  1545
lubomir@281
  1546
        if (returnType[0] != 'V') {
lubomir@474
  1547
            out.append("var ")
lubomir@474
  1548
               .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
lubomir@281
  1549
               .append(" = ");
jaroslav@12
  1550
        }
lubomir@281
  1551
lubomir@281
  1552
        out.append(vars[0]).append('.');
jaroslav@12
  1553
        out.append(mn);
jaroslav@12
  1554
        out.append('(');
jaroslav@442
  1555
        String sep = "";
lubomir@281
  1556
        for (int j = 1; j < numArguments; ++j) {
jaroslav@442
  1557
            out.append(sep);
lubomir@281
  1558
            out.append(vars[j]);
jaroslav@442
  1559
            sep = ", ";
jaroslav@12
  1560
        }
lubomir@221
  1561
        out.append(");");
jaroslav@12
  1562
        i += 2;
jaroslav@12
  1563
        return i;
jaroslav@12
  1564
    }
lubomir@221
  1565
jaroslav@103
  1566
    private void addReference(String cn) throws IOException {
jtulach@162
  1567
        if (requireReference(cn)) {
jaroslav@399
  1568
            debug(" /* needs " + cn + " */");
jaroslav@18
  1569
        }
jaroslav@18
  1570
    }
jaroslav@16
  1571
jaroslav@33
  1572
    private void outType(String d, StringBuilder out) {
jaroslav@33
  1573
        int arr = 0;
jaroslav@33
  1574
        while (d.charAt(0) == '[') {
jaroslav@33
  1575
            out.append('A');
jaroslav@33
  1576
            d = d.substring(1);
jaroslav@33
  1577
        }
jaroslav@16
  1578
        if (d.charAt(0) == 'L') {
jaroslav@16
  1579
            assert d.charAt(d.length() - 1) == ';';
jaroslav@16
  1580
            out.append(d.replace('/', '_').substring(0, d.length() - 1));
jaroslav@16
  1581
        } else {
jaroslav@16
  1582
            out.append(d);
jaroslav@16
  1583
        }
jaroslav@16
  1584
    }
jaroslav@21
  1585
jaroslav@230
  1586
    private String encodeConstant(int entryIndex) throws IOException {
jaroslav@230
  1587
        String[] classRef = { null };
jaroslav@230
  1588
        String s = jc.stringValue(entryIndex, classRef);
jaroslav@230
  1589
        if (classRef[0] != null) {
jaroslav@567
  1590
            if (classRef[0].startsWith("[")) {
jaroslav@567
  1591
                s = accessClass("java_lang_Class") + "(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('" + classRef[0] + "');";
jaroslav@567
  1592
            } else {
jaroslav@567
  1593
                addReference(classRef[0]);
jaroslav@567
  1594
                s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
jaroslav@567
  1595
            }
jaroslav@230
  1596
        }
jaroslav@151
  1597
        return s;
jaroslav@21
  1598
    }
jaroslav@32
  1599
jaroslav@266
  1600
    private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
jaroslav@152
  1601
        byte[] arr = m.findAnnotationData(true);
jaroslav@152
  1602
        if (arr == null) {
jaroslav@266
  1603
            return null;
jaroslav@152
  1604
        }
jaroslav@200
  1605
        final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
jaroslav@152
  1606
        class P extends AnnotationParser {
jaroslav@237
  1607
            public P() {
jaroslav@237
  1608
                super(false);
jaroslav@237
  1609
            }
jaroslav@237
  1610
            
jaroslav@152
  1611
            int cnt;
jaroslav@152
  1612
            String[] args = new String[30];
jaroslav@152
  1613
            String body;
jaroslav@94
  1614
            
jaroslav@152
  1615
            @Override
jaroslav@236
  1616
            protected void visitAttr(String type, String attr, String at, String value) {
jaroslav@152
  1617
                if (type.equals(jvmType)) {
jaroslav@152
  1618
                    if ("body".equals(attr)) {
jaroslav@152
  1619
                        body = value;
jaroslav@152
  1620
                    } else if ("args".equals(attr)) {
jaroslav@152
  1621
                        args[cnt++] = value;
jaroslav@152
  1622
                    } else {
jaroslav@152
  1623
                        throw new IllegalArgumentException(attr);
jaroslav@152
  1624
                    }
jaroslav@152
  1625
                }
jaroslav@94
  1626
            }
jaroslav@94
  1627
        }
jaroslav@152
  1628
        P p = new P();
jaroslav@152
  1629
        p.parse(arr, jc);
jaroslav@152
  1630
        if (p.body == null) {
jaroslav@266
  1631
            return null;
jaroslav@152
  1632
        }
jtulach@156
  1633
        StringBuilder cnt = new StringBuilder();
jaroslav@266
  1634
        final String mn = findMethodName(m, cnt);
jaroslav@266
  1635
        out.append(prefix).append(mn);
jaroslav@203
  1636
        out.append(" = function(");
jaroslav@442
  1637
        String space = "";
jaroslav@443
  1638
        int index = 0;
jtulach@156
  1639
        for (int i = 0; i < cnt.length(); i++) {
jaroslav@152
  1640
            out.append(space);
jaroslav@316
  1641
            space = outputArg(out, p.args, index);
jaroslav@152
  1642
            index++;
jaroslav@152
  1643
        }
jaroslav@152
  1644
        out.append(") {").append("\n");
jaroslav@152
  1645
        out.append(p.body);
jaroslav@152
  1646
        out.append("\n}\n");
jaroslav@266
  1647
        return mn;
jaroslav@151
  1648
    }
jaroslav@151
  1649
    private static String className(ClassData jc) {
jaroslav@151
  1650
        //return jc.getName().getInternalName().replace('/', '_');
jaroslav@151
  1651
        return jc.getClassName().replace('/', '_');
jaroslav@94
  1652
    }
jaroslav@152
  1653
    
jaroslav@152
  1654
    private static String[] findAnnotation(
jaroslav@152
  1655
        byte[] arr, ClassData cd, final String className, 
jaroslav@152
  1656
        final String... attrNames
jaroslav@152
  1657
    ) throws IOException {
jaroslav@152
  1658
        if (arr == null) {
jaroslav@152
  1659
            return null;
jaroslav@152
  1660
        }
jaroslav@152
  1661
        final String[] values = new String[attrNames.length];
jaroslav@152
  1662
        final boolean[] found = { false };
jaroslav@152
  1663
        final String jvmType = "L" + className.replace('.', '/') + ";";
jaroslav@237
  1664
        AnnotationParser ap = new AnnotationParser(false) {
jaroslav@152
  1665
            @Override
jaroslav@236
  1666
            protected void visitAttr(String type, String attr, String at, String value) {
jaroslav@152
  1667
                if (type.equals(jvmType)) {
jaroslav@152
  1668
                    found[0] = true;
jaroslav@152
  1669
                    for (int i = 0; i < attrNames.length; i++) {
jaroslav@152
  1670
                        if (attrNames[i].equals(attr)) {
jaroslav@152
  1671
                            values[i] = value;
jaroslav@152
  1672
                        }
jaroslav@152
  1673
                    }
jaroslav@152
  1674
                }
jaroslav@152
  1675
            }
jaroslav@152
  1676
            
jaroslav@152
  1677
        };
jaroslav@152
  1678
        ap.parse(arr, cd);
jaroslav@152
  1679
        return found[0] ? values : null;
jaroslav@152
  1680
    }
jaroslav@173
  1681
jaroslav@173
  1682
    private CharSequence initField(FieldData v) {
jaroslav@173
  1683
        final String is = v.getInternalSig();
jaroslav@173
  1684
        if (is.length() == 1) {
jaroslav@173
  1685
            switch (is.charAt(0)) {
jaroslav@173
  1686
                case 'S':
jaroslav@173
  1687
                case 'J':
jaroslav@173
  1688
                case 'B':
jaroslav@173
  1689
                case 'Z':
jaroslav@173
  1690
                case 'C':
jaroslav@173
  1691
                case 'I': return " = 0;";
jaroslav@173
  1692
                case 'F': 
jaroslav@180
  1693
                case 'D': return " = 0.0;";
jaroslav@173
  1694
                default:
jaroslav@173
  1695
                    throw new IllegalStateException(is);
jaroslav@173
  1696
            }
jaroslav@173
  1697
        }
jaroslav@173
  1698
        return " = null;";
jaroslav@173
  1699
    }
jaroslav@235
  1700
jaroslav@235
  1701
    private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
jaroslav@237
  1702
        AnnotationParser ap = new AnnotationParser(true) {
jaroslav@237
  1703
            int anno;
jaroslav@235
  1704
            int cnt;
jaroslav@235
  1705
            
jaroslav@235
  1706
            @Override
jaroslav@235
  1707
            protected void visitAnnotationStart(String type) throws IOException {
jaroslav@237
  1708
                if (anno++ > 0) {
jaroslav@237
  1709
                    out.append(",");
jaroslav@237
  1710
                }
jaroslav@235
  1711
                out.append('"').append(type).append("\" : {\n");
jaroslav@235
  1712
                cnt = 0;
jaroslav@235
  1713
            }
jaroslav@235
  1714
jaroslav@235
  1715
            @Override
jaroslav@235
  1716
            protected void visitAnnotationEnd(String type) throws IOException {
jaroslav@235
  1717
                out.append("\n}\n");
jaroslav@235
  1718
            }
jaroslav@235
  1719
            
jaroslav@235
  1720
            @Override
jaroslav@236
  1721
            protected void visitAttr(String type, String attr, String attrType, String value) 
jaroslav@235
  1722
            throws IOException {
jaroslav@266
  1723
                if (attr == null) {
jaroslav@266
  1724
                    return;
jaroslav@266
  1725
                }
jaroslav@235
  1726
                if (cnt++ > 0) {
jaroslav@235
  1727
                    out.append(",\n");
jaroslav@235
  1728
                }
jaroslav@250
  1729
                out.append(attr).append("__").append(attrType).append(" : ").append(value);
jaroslav@235
  1730
            }
jaroslav@235
  1731
        };
jaroslav@235
  1732
        ap.parse(data, cd);
jaroslav@235
  1733
    }
jaroslav@316
  1734
jaroslav@316
  1735
    private static String outputArg(Appendable out, String[] args, int indx) throws IOException {
jaroslav@316
  1736
        final String name = args[indx];
jaroslav@316
  1737
        if (name == null) {
jaroslav@316
  1738
            return "";
jaroslav@316
  1739
        }
jaroslav@316
  1740
        if (name.contains(",")) {
jaroslav@316
  1741
            throw new IOException("Wrong parameter with ',': " + name);
jaroslav@316
  1742
        }
jaroslav@316
  1743
        out.append(name);
jaroslav@316
  1744
        return ",";
jaroslav@316
  1745
    }
lubomir@317
  1746
lubomir@283
  1747
    private static void emit(final Appendable out,
lubomir@283
  1748
                             final String format,
lubomir@283
  1749
                             final CharSequence... params) throws IOException {
lubomir@283
  1750
        final int length = format.length();
lubomir@283
  1751
lubomir@283
  1752
        int processed = 0;
lubomir@283
  1753
        int paramOffset = format.indexOf('@');
lubomir@283
  1754
        while ((paramOffset != -1) && (paramOffset < (length - 1))) {
lubomir@283
  1755
            final char paramChar = format.charAt(paramOffset + 1);
lubomir@283
  1756
            if ((paramChar >= '1') && (paramChar <= '9')) {
lubomir@283
  1757
                final int paramIndex = paramChar - '0' - 1;
lubomir@283
  1758
lubomir@283
  1759
                out.append(format, processed, paramOffset);
lubomir@283
  1760
                out.append(params[paramIndex]);
lubomir@283
  1761
lubomir@283
  1762
                ++paramOffset;
lubomir@283
  1763
                processed = paramOffset + 1;
lubomir@283
  1764
            }
lubomir@283
  1765
lubomir@283
  1766
            paramOffset = format.indexOf('@', paramOffset + 1);
lubomir@283
  1767
        }
lubomir@283
  1768
lubomir@283
  1769
        out.append(format, processed, length);
lubomir@283
  1770
    }
jaroslav@398
  1771
jaroslav@398
  1772
    private void generateCatch(TrapData[] traps) throws IOException {
jaroslav@400
  1773
        out.append("} catch (e) {\n");
jaroslav@401
  1774
        int finallyPC = -1;
jaroslav@398
  1775
        for (TrapData e : traps) {
jaroslav@398
  1776
            if (e == null) {
jaroslav@398
  1777
                break;
jaroslav@398
  1778
            }
jaroslav@398
  1779
            if (e.catch_cpx != 0) { //not finally
jaroslav@398
  1780
                final String classInternalName = jc.getClassName(e.catch_cpx);
jaroslav@398
  1781
                addReference(classInternalName);
jaroslav@423
  1782
                if ("java/lang/Throwable".equals(classInternalName)) {
jaroslav@423
  1783
                    out.append("if (e.$instOf_java_lang_Throwable) {");
lubomir@474
  1784
                    out.append("  var stA0 = e;");
jaroslav@423
  1785
                    out.append("} else {");
lubomir@474
  1786
                    out.append("  var stA0 = vm.java_lang_Throwable(true);");
jaroslav@442
  1787
                    out.append("  vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
jaroslav@423
  1788
                    out.append("}");
jaroslav@423
  1789
                    out.append("gt=" + e.handler_pc + "; continue;");
jaroslav@423
  1790
                } else {
jaroslav@423
  1791
                    out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
lubomir@474
  1792
                    out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
jaroslav@423
  1793
                    out.append("}\n");
jaroslav@423
  1794
                }
jaroslav@398
  1795
            } else {
jaroslav@401
  1796
                finallyPC = e.handler_pc;
jaroslav@398
  1797
            }
jaroslav@398
  1798
        }
jaroslav@401
  1799
        if (finallyPC == -1) {
jaroslav@401
  1800
            out.append("throw e;");
jaroslav@401
  1801
        } else {
lubomir@474
  1802
            out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
jaroslav@401
  1803
        }
jaroslav@400
  1804
        out.append("\n}");
jaroslav@398
  1805
    }
jaroslav@0
  1806
}