Type specific stack variables registers
authorLubomir Nerad <lubomir.nerad@oracle.com>
Fri, 07 Dec 2012 15:02:35 +0100
branchregisters
changeset 281f2352e0b713e
parent 242 8bd4adaf6590
child 282 a98d6c5a545e
Type specific stack variables
javap/src/main/java/org/apidesign/javap/StackMapIterator.java
javap/src/main/java/org/apidesign/javap/StackMapTableData.java
javap/src/main/java/org/apidesign/javap/TypeArray.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/main/java/org/apidesign/vm4brwsr/Main.java
vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java
vm/src/main/java/org/apidesign/vm4brwsr/Variable.java
     1.1 --- a/javap/src/main/java/org/apidesign/javap/StackMapIterator.java	Mon Dec 03 14:44:49 2012 +0100
     1.2 +++ b/javap/src/main/java/org/apidesign/javap/StackMapIterator.java	Fri Dec 07 15:02:35 2012 +0100
     1.3 @@ -29,17 +29,21 @@
     1.4      private static final StackMapTableData INITIAL_FRAME =
     1.5              new StackMapTableData(-1) {
     1.6                  @Override
     1.7 -                int getStackItemsCount() {
     1.8 -                    return 0;
     1.9 +                void applyTo(TypeArray localTypes, TypeArray stackTypes) {
    1.10 +                    localTypes.clear();
    1.11 +                    stackTypes.clear();
    1.12                  }
    1.13  
    1.14                  @Override
    1.15                  public String toString() {
    1.16 -                    return "INITIAL(0)";
    1.17 +                    return toString("INITIAL", 0, null, null);
    1.18                  }
    1.19 +
    1.20              };
    1.21  
    1.22      private final StackMapTableData[] stackMapTable;
    1.23 +    private final TypeArray localTypes;
    1.24 +    private final TypeArray stackTypes;
    1.25  
    1.26      private int nextFrameIndex;
    1.27      private int lastFrameByteCodeOffset;
    1.28 @@ -50,7 +54,10 @@
    1.29          this.stackMapTable = (stackMapTable != null)
    1.30                                   ? stackMapTable
    1.31                                   : new StackMapTableData[0];
    1.32 -        this.lastFrameByteCodeOffset = -1;
    1.33 +
    1.34 +        localTypes = new TypeArray();
    1.35 +        stackTypes = new TypeArray();
    1.36 +        lastFrameByteCodeOffset = -1;
    1.37          advanceBy(0);
    1.38      }
    1.39  
    1.40 @@ -62,8 +69,8 @@
    1.41          return nextFrameIndex;
    1.42      }
    1.43  
    1.44 -    public int getFrameStackItemsCount() {
    1.45 -        return getCurrentFrame().getStackItemsCount();
    1.46 +    public TypeArray getFrameStack() {
    1.47 +        return stackTypes;
    1.48      }
    1.49  
    1.50      public void advanceBy(final int numByteCodes) {
    1.51 @@ -76,8 +83,11 @@
    1.52                      && ((byteCodeOffset - lastFrameByteCodeOffset)
    1.53                              >= (stackMapTable[nextFrameIndex].offsetDelta
    1.54                                      + 1))) {
    1.55 -            lastFrameByteCodeOffset +=
    1.56 -                    stackMapTable[nextFrameIndex].offsetDelta + 1;
    1.57 +            final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
    1.58 +
    1.59 +            lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
    1.60 +            nextFrame.applyTo(localTypes, stackTypes);
    1.61 +
    1.62              ++nextFrameIndex;
    1.63          }
    1.64      }
     2.1 --- a/javap/src/main/java/org/apidesign/javap/StackMapTableData.java	Mon Dec 03 14:44:49 2012 +0100
     2.2 +++ b/javap/src/main/java/org/apidesign/javap/StackMapTableData.java	Fri Dec 07 15:02:35 2012 +0100
     2.3 @@ -40,7 +40,75 @@
     2.4          this.frameType = frameType;
     2.5      }
     2.6  
     2.7 -    abstract int getStackItemsCount();
     2.8 +    abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
     2.9 +
    2.10 +    protected static String toString(
    2.11 +            final String frameType,
    2.12 +            final int offset,
    2.13 +            final int[] localTypes,
    2.14 +            final int[] stackTypes) {
    2.15 +        final StringBuilder sb = new StringBuilder(frameType);
    2.16 +
    2.17 +        sb.append("(off: +").append(offset);
    2.18 +        if (localTypes != null) {
    2.19 +            sb.append(", locals: ");
    2.20 +            appendTypes(sb, localTypes);
    2.21 +        }
    2.22 +        if (stackTypes != null) {
    2.23 +            sb.append(", stack: ");
    2.24 +            appendTypes(sb, stackTypes);
    2.25 +        }
    2.26 +        sb.append(')');
    2.27 +
    2.28 +        return sb.toString();
    2.29 +    }
    2.30 +
    2.31 +    private static void appendTypes(final StringBuilder sb, final int[] types) {
    2.32 +        sb.append('[');
    2.33 +        if (types.length > 0) {
    2.34 +            appendType(sb, types[0]);
    2.35 +            for (int i = 1; i < types.length; ++i) {
    2.36 +                sb.append(", ");
    2.37 +                appendType(sb, types[i]);
    2.38 +            }
    2.39 +        }
    2.40 +        sb.append(']');
    2.41 +    }
    2.42 +
    2.43 +    private static void appendType(final StringBuilder sb, final int type) {
    2.44 +        switch (type & 0xff) {
    2.45 +            case ITEM_Bogus:
    2.46 +                sb.append("_top_");
    2.47 +                break;
    2.48 +            case ITEM_Integer:
    2.49 +                sb.append("_int_");
    2.50 +                break;
    2.51 +            case ITEM_Float:
    2.52 +                sb.append("_float_");
    2.53 +                break;
    2.54 +            case ITEM_Double:
    2.55 +                sb.append("_double_");
    2.56 +                break;
    2.57 +            case ITEM_Long:
    2.58 +                sb.append("_long_");
    2.59 +                break;
    2.60 +            case ITEM_Null:
    2.61 +                sb.append("_null_");
    2.62 +                break;
    2.63 +            case ITEM_InitObject: // UninitializedThis
    2.64 +                sb.append("_init_");
    2.65 +                break;
    2.66 +            case ITEM_Object:
    2.67 +                sb.append("_object_");
    2.68 +                break;
    2.69 +            case ITEM_NewObject: // Uninitialized
    2.70 +                sb.append("_new_");
    2.71 +                break;
    2.72 +            default:
    2.73 +                sb.append("_unknown_");
    2.74 +                break;
    2.75 +        }
    2.76 +    }
    2.77  
    2.78      static class SameFrame extends StackMapTableData {
    2.79          SameFrame(int frameType, int offsetDelta) {
    2.80 @@ -49,16 +117,16 @@
    2.81          }
    2.82  
    2.83          @Override
    2.84 -        int getStackItemsCount() {
    2.85 -            return 0;
    2.86 +        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
    2.87 +            stackTypes.clear();
    2.88          }
    2.89  
    2.90          @Override
    2.91          public String toString() {
    2.92 -            return "SAME"
    2.93 -                       + ((frameType == SAME_FRAME_EXTENDED)
    2.94 -                              ? "_FRAME_EXTENDED" : "")
    2.95 -                       + "(" + offsetDelta + ")";
    2.96 +            return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
    2.97 +                                          ? "_FRAME_EXTENDED" : ""),
    2.98 +                            offsetDelta,
    2.99 +                            null, null);
   2.100          }
   2.101      }
   2.102  
   2.103 @@ -71,16 +139,18 @@
   2.104          }
   2.105  
   2.106          @Override
   2.107 -        int getStackItemsCount() {
   2.108 -            return 1;
   2.109 +        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   2.110 +            stackTypes.setAll(stack);
   2.111          }
   2.112  
   2.113          @Override
   2.114          public String toString() {
   2.115 -            return "SAME_LOCALS_1_STACK_ITEM"
   2.116 -                       + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
   2.117 -                              ? "_EXTENDED" : "")
   2.118 -                       + "(" + offsetDelta + ")";
   2.119 +            return toString(
   2.120 +                       "SAME_LOCALS_1_STACK_ITEM"
   2.121 +                           + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
   2.122 +                                  ? "_EXTENDED" : ""),
   2.123 +                       offsetDelta,
   2.124 +                       null, stack);
   2.125          }
   2.126      }
   2.127  
   2.128 @@ -91,13 +161,15 @@
   2.129          }
   2.130  
   2.131          @Override
   2.132 -        int getStackItemsCount() {
   2.133 -            return 0;
   2.134 +        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   2.135 +            localTypes.setSize(localTypes.getSize()
   2.136 +                                   - (SAME_FRAME_EXTENDED - frameType));
   2.137 +            stackTypes.clear();
   2.138          }
   2.139  
   2.140          @Override
   2.141          public String toString() {
   2.142 -            return "CHOP(" + offsetDelta + ")";
   2.143 +            return toString("CHOP", offsetDelta, null, null);
   2.144          }
   2.145      }
   2.146  
   2.147 @@ -110,13 +182,14 @@
   2.148          }
   2.149  
   2.150          @Override
   2.151 -        int getStackItemsCount() {
   2.152 -            return 0;
   2.153 +        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   2.154 +            localTypes.addAll(locals);
   2.155 +            stackTypes.clear();
   2.156          }
   2.157  
   2.158          @Override
   2.159          public String toString() {
   2.160 -            return "APPEND(" + offsetDelta + ")";
   2.161 +            return toString("APPEND", offsetDelta, locals, null);
   2.162          }
   2.163      }
   2.164  
   2.165 @@ -131,13 +204,14 @@
   2.166          }
   2.167  
   2.168          @Override
   2.169 -        int getStackItemsCount() {
   2.170 -            return stack.length;
   2.171 +        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
   2.172 +            localTypes.setAll(locals);
   2.173 +            stackTypes.setAll(stack);
   2.174          }
   2.175  
   2.176          @Override
   2.177          public String toString() {
   2.178 -            return "FULL(" + offsetDelta + ")";
   2.179 +            return toString("FULL", offsetDelta, locals, stack);
   2.180          }
   2.181      }
   2.182  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/javap/src/main/java/org/apidesign/javap/TypeArray.java	Fri Dec 07 15:02:35 2012 +0100
     3.3 @@ -0,0 +1,100 @@
     3.4 +/*
     3.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package org.apidesign.javap;
    3.30 +
    3.31 +public class TypeArray {
    3.32 +    private static final int CAPACITY_INCREMENT = 16;
    3.33 +
    3.34 +    private int[] types;
    3.35 +    private int size;
    3.36 +
    3.37 +    public void add(final int newType) {
    3.38 +        ensureCapacity(size + 1);
    3.39 +        types[size++] = newType;
    3.40 +    }
    3.41 +
    3.42 +    public void addAll(final int[] newTypes) {
    3.43 +        if (newTypes.length > 0) {
    3.44 +            ensureCapacity(size + newTypes.length);
    3.45 +            arraycopy(newTypes, 0, types, size, newTypes.length);
    3.46 +            size += newTypes.length;
    3.47 +        }
    3.48 +    }
    3.49 +
    3.50 +    public void setAll(final int[] newTypes) {
    3.51 +        if (newTypes.length > 0) {
    3.52 +            ensureCapacity(newTypes.length);
    3.53 +            arraycopy(newTypes, 0, types, 0, newTypes.length);
    3.54 +            size = newTypes.length;
    3.55 +        } else {
    3.56 +            clear();
    3.57 +        }
    3.58 +    }
    3.59 +
    3.60 +    public void setSize(final int newSize) {
    3.61 +        ensureCapacity(newSize);
    3.62 +        size = newSize;
    3.63 +    }
    3.64 +
    3.65 +    public void clear() {
    3.66 +        size = 0;
    3.67 +    }
    3.68 +
    3.69 +    public int getSize() {
    3.70 +        return size;
    3.71 +    }
    3.72 +
    3.73 +    public int get(final int index) {
    3.74 +        return types[index];
    3.75 +    }
    3.76 +
    3.77 +    private void ensureCapacity(final int minCapacity) {
    3.78 +        if ((minCapacity == 0)
    3.79 +                || (types != null) && (minCapacity <= types.length)) {
    3.80 +            return;
    3.81 +        }
    3.82 +
    3.83 +        final int newCapacity =
    3.84 +                ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT)
    3.85 +                    * CAPACITY_INCREMENT;
    3.86 +        final int[] newTypes = new int[newCapacity];
    3.87 +
    3.88 +        if (size > 0) {
    3.89 +            arraycopy(types, 0, newTypes, 0, size);
    3.90 +        }
    3.91 +
    3.92 +        types = newTypes;
    3.93 +    }
    3.94 +
    3.95 +    // no System.arraycopy
    3.96 +    private void arraycopy(final int[] src, final int srcPos,
    3.97 +                           final int[] dest, final int destPos,
    3.98 +                           final int length) {
    3.99 +        for (int i = 0; i < length; ++i) {
   3.100 +            dest[destPos + i] = src[srcPos + i];
   3.101 +        }
   3.102 +    }
   3.103 +}
     4.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Dec 03 14:44:49 2012 +0100
     4.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Dec 07 15:02:35 2012 +0100
     4.3 @@ -241,12 +241,15 @@
     4.4          // so this might generate more stack variables than we need
     4.5          final int maxStack = m.getMaxStack();
     4.6          if (maxStack > 0) {
     4.7 -            out.append("\n  var ").append(mapper.constructVariableName(0));
     4.8 -            for (int i = 1; i < maxStack; ++i) {
     4.9 -                out.append(", ");
    4.10 -                out.append(mapper.constructVariableName(i));
    4.11 +            // TODO: generate only used stack variables
    4.12 +            for (int j = 0; j <= Variable.LAST_TYPE; ++j) {
    4.13 +                out.append("\n  var ").append(Variable.getStackVariable(j, 0));
    4.14 +                for (int i = 1; i < maxStack; ++i) {
    4.15 +                    out.append(", ");
    4.16 +                    out.append(Variable.getStackVariable(j, i));
    4.17 +                }
    4.18 +                out.append(';');
    4.19              }
    4.20 -            out.append(';');
    4.21          }
    4.22  
    4.23          int lastStackFrame = -1;
    4.24 @@ -257,7 +260,7 @@
    4.25              stackMapIterator.advanceTo(i);
    4.26              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
    4.27                  lastStackFrame = stackMapIterator.getFrameIndex();
    4.28 -                mapper.reset(stackMapIterator.getFrameStackItemsCount());
    4.29 +                mapper.syncWithFrameStack(stackMapIterator.getFrameStack());
    4.30                  out.append("    case " + i).append(": ");
    4.31              } else {
    4.32                  out.append("    /* " + i).append(" */ ");
    4.33 @@ -265,162 +268,330 @@
    4.34              final int c = readByte(byteCodes, i);
    4.35              switch (c) {
    4.36                  case opc_aload_0:
    4.37 +                    out.append(mapper.pushA()).append(" = arg0;");
    4.38 +                    break;
    4.39                  case opc_iload_0:
    4.40 +                    out.append(mapper.pushI()).append(" = arg0;");
    4.41 +                    break;
    4.42                  case opc_lload_0:
    4.43 +                    out.append(mapper.pushL()).append(" = arg0;");
    4.44 +                    break;
    4.45                  case opc_fload_0:
    4.46 +                    out.append(mapper.pushF()).append(" = arg0;");
    4.47 +                    break;
    4.48                  case opc_dload_0:
    4.49 -                    out.append(mapper.push()).append(" = arg0;");
    4.50 +                    out.append(mapper.pushD()).append(" = arg0;");
    4.51                      break;
    4.52                  case opc_aload_1:
    4.53 +                    out.append(mapper.pushA()).append(" = arg1;");
    4.54 +                    break;
    4.55                  case opc_iload_1:
    4.56 +                    out.append(mapper.pushI()).append(" = arg1;");
    4.57 +                    break;
    4.58                  case opc_lload_1:
    4.59 +                    out.append(mapper.pushL()).append(" = arg1;");
    4.60 +                    break;
    4.61                  case opc_fload_1:
    4.62 +                    out.append(mapper.pushF()).append(" = arg1;");
    4.63 +                    break;
    4.64                  case opc_dload_1:
    4.65 -                    out.append(mapper.push()).append(" = arg1;");
    4.66 +                    out.append(mapper.pushD()).append(" = arg1;");
    4.67                      break;
    4.68                  case opc_aload_2:
    4.69 +                    out.append(mapper.pushA()).append(" = arg2;");
    4.70 +                    break;
    4.71                  case opc_iload_2:
    4.72 +                    out.append(mapper.pushI()).append(" = arg2;");
    4.73 +                    break;
    4.74                  case opc_lload_2:
    4.75 +                    out.append(mapper.pushL()).append(" = arg2;");
    4.76 +                    break;
    4.77                  case opc_fload_2:
    4.78 +                    out.append(mapper.pushF()).append(" = arg2;");
    4.79 +                    break;
    4.80                  case opc_dload_2:
    4.81 -                    out.append(mapper.push()).append(" = arg2;");
    4.82 +                    out.append(mapper.pushD()).append(" = arg2;");
    4.83                      break;
    4.84                  case opc_aload_3:
    4.85 +                    out.append(mapper.pushA()).append(" = arg3;");
    4.86 +                    break;
    4.87                  case opc_iload_3:
    4.88 +                    out.append(mapper.pushI()).append(" = arg3;");
    4.89 +                    break;
    4.90                  case opc_lload_3:
    4.91 +                    out.append(mapper.pushL()).append(" = arg3;");
    4.92 +                    break;
    4.93                  case opc_fload_3:
    4.94 +                    out.append(mapper.pushF()).append(" = arg3;");
    4.95 +                    break;
    4.96                  case opc_dload_3:
    4.97 -                    out.append(mapper.push()).append(" = arg3;");
    4.98 +                    out.append(mapper.pushD()).append(" = arg3;");
    4.99                      break;
   4.100 -                case opc_iload:
   4.101 -                case opc_lload:
   4.102 -                case opc_fload:
   4.103 -                case opc_dload:
   4.104 +                case opc_iload: {
   4.105 +                    final int indx = readByte(byteCodes, ++i);
   4.106 +                    out.append(mapper.pushI()).append(" = ")
   4.107 +                       .append("arg").append(indx + ";");
   4.108 +                    break;
   4.109 +                }
   4.110 +                case opc_lload: {
   4.111 +                    final int indx = readByte(byteCodes, ++i);
   4.112 +                    out.append(mapper.pushL()).append(" = ")
   4.113 +                       .append("arg").append(indx + ";");
   4.114 +                    break;
   4.115 +                }
   4.116 +                case opc_fload: {
   4.117 +                    final int indx = readByte(byteCodes, ++i);
   4.118 +                    out.append(mapper.pushF()).append(" = ")
   4.119 +                       .append("arg").append(indx + ";");
   4.120 +                    break;
   4.121 +                }
   4.122 +                case opc_dload: {
   4.123 +                    final int indx = readByte(byteCodes, ++i);
   4.124 +                    out.append(mapper.pushD()).append(" = ")
   4.125 +                       .append("arg").append(indx + ";");
   4.126 +                    break;
   4.127 +                }
   4.128                  case opc_aload: {
   4.129                      final int indx = readByte(byteCodes, ++i);
   4.130 -                    out.append(mapper.push())
   4.131 -                       .append(" = arg")
   4.132 -                       .append(indx + ";");
   4.133 +                    out.append(mapper.pushA()).append(" = ")
   4.134 +                       .append("arg").append(indx + ";");
   4.135                      break;
   4.136                  }
   4.137 -                case opc_istore:
   4.138 -                case opc_lstore:
   4.139 -                case opc_fstore:
   4.140 -                case opc_dstore:
   4.141 +                case opc_istore: {
   4.142 +                    final int indx = readByte(byteCodes, ++i);
   4.143 +                    out.append("arg" + indx).append(" = ")
   4.144 +                       .append(mapper.popI()).append(';');
   4.145 +                    break;
   4.146 +                }
   4.147 +                case opc_lstore: {
   4.148 +                    final int indx = readByte(byteCodes, ++i);
   4.149 +                    out.append("arg" + indx).append(" = ")
   4.150 +                       .append(mapper.popL()).append(';');
   4.151 +                    break;
   4.152 +                }
   4.153 +                case opc_fstore: {
   4.154 +                    final int indx = readByte(byteCodes, ++i);
   4.155 +                    out.append("arg" + indx).append(" = ")
   4.156 +                       .append(mapper.popF()).append(';');
   4.157 +                    break;
   4.158 +                }
   4.159 +                case opc_dstore: {
   4.160 +                    final int indx = readByte(byteCodes, ++i);
   4.161 +                    out.append("arg" + indx).append(" = ")
   4.162 +                       .append(mapper.popD()).append(';');
   4.163 +                    break;
   4.164 +                }
   4.165                  case opc_astore: {
   4.166                      final int indx = readByte(byteCodes, ++i);
   4.167 -                    out.append("arg" + indx)
   4.168 -                       .append(" = ")
   4.169 -                       .append(mapper.pop())
   4.170 -                       .append(';');
   4.171 +                    out.append("arg" + indx).append(" = ")
   4.172 +                       .append(mapper.popA()).append(';');
   4.173                      break;
   4.174                  }
   4.175                  case opc_astore_0:
   4.176 +                    out.append("arg0 = ").append(mapper.popA()).append(';');
   4.177 +                    break;
   4.178                  case opc_istore_0:
   4.179 +                    out.append("arg0 = ").append(mapper.popI()).append(';');
   4.180 +                    break;
   4.181                  case opc_lstore_0:
   4.182 +                    out.append("arg0 = ").append(mapper.popL()).append(';');
   4.183 +                    break;
   4.184                  case opc_fstore_0:
   4.185 +                    out.append("arg0 = ").append(mapper.popF()).append(';');
   4.186 +                    break;
   4.187                  case opc_dstore_0:
   4.188 -                    out.append("arg0 = ").append(mapper.pop()).append(';');
   4.189 +                    out.append("arg0 = ").append(mapper.popD()).append(';');
   4.190                      break;
   4.191                  case opc_astore_1:
   4.192 +                    out.append("arg1 = ").append(mapper.popA()).append(';');
   4.193 +                    break;
   4.194                  case opc_istore_1:
   4.195 +                    out.append("arg1 = ").append(mapper.popI()).append(';');
   4.196 +                    break;
   4.197                  case opc_lstore_1:
   4.198 +                    out.append("arg1 = ").append(mapper.popL()).append(';');
   4.199 +                    break;
   4.200                  case opc_fstore_1:
   4.201 +                    out.append("arg1 = ").append(mapper.popF()).append(';');
   4.202 +                    break;
   4.203                  case opc_dstore_1:
   4.204 -                    out.append("arg1 = ").append(mapper.pop()).append(';');
   4.205 +                    out.append("arg1 = ").append(mapper.popD()).append(';');
   4.206                      break;
   4.207                  case opc_astore_2:
   4.208 +                    out.append("arg2 = ").append(mapper.popA()).append(';');
   4.209 +                    break;
   4.210                  case opc_istore_2:
   4.211 +                    out.append("arg2 = ").append(mapper.popI()).append(';');
   4.212 +                    break;
   4.213                  case opc_lstore_2:
   4.214 +                    out.append("arg2 = ").append(mapper.popL()).append(';');
   4.215 +                    break;
   4.216                  case opc_fstore_2:
   4.217 +                    out.append("arg2 = ").append(mapper.popF()).append(';');
   4.218 +                    break;
   4.219                  case opc_dstore_2:
   4.220 -                    out.append("arg2 = ").append(mapper.pop()).append(';');
   4.221 +                    out.append("arg2 = ").append(mapper.popD()).append(';');
   4.222                      break;
   4.223                  case opc_astore_3:
   4.224 +                    out.append("arg3 = ").append(mapper.popA()).append(';');
   4.225 +                    break;
   4.226                  case opc_istore_3:
   4.227 +                    out.append("arg3 = ").append(mapper.popI()).append(';');
   4.228 +                    break;
   4.229                  case opc_lstore_3:
   4.230 +                    out.append("arg3 = ").append(mapper.popL()).append(';');
   4.231 +                    break;
   4.232                  case opc_fstore_3:
   4.233 +                    out.append("arg3 = ").append(mapper.popF()).append(';');
   4.234 +                    break;
   4.235                  case opc_dstore_3:
   4.236 -                    out.append("arg3 = ").append(mapper.pop()).append(';');
   4.237 +                    out.append("arg3 = ").append(mapper.popD()).append(';');
   4.238                      break;
   4.239                  case opc_iadd:
   4.240 +                    out.append(mapper.getI(1)).append(" += ")
   4.241 +                       .append(mapper.popI()).append(';');
   4.242 +                    break;
   4.243                  case opc_ladd:
   4.244 +                    out.append(mapper.getL(1)).append(" += ")
   4.245 +                       .append(mapper.popL()).append(';');
   4.246 +                    break;
   4.247                  case opc_fadd:
   4.248 +                    out.append(mapper.getF(1)).append(" += ")
   4.249 +                       .append(mapper.popF()).append(';');
   4.250 +                    break;
   4.251                  case opc_dadd:
   4.252 -                    out.append(mapper.get(1)).append(" += ")
   4.253 -                       .append(mapper.pop()).append(';');
   4.254 +                    out.append(mapper.getD(1)).append(" += ")
   4.255 +                       .append(mapper.popD()).append(';');
   4.256                      break;
   4.257                  case opc_isub:
   4.258 +                    out.append(mapper.getI(1)).append(" -= ")
   4.259 +                       .append(mapper.popI()).append(';');
   4.260 +                    break;
   4.261                  case opc_lsub:
   4.262 +                    out.append(mapper.getL(1)).append(" -= ")
   4.263 +                       .append(mapper.popL()).append(';');
   4.264 +                    break;
   4.265                  case opc_fsub:
   4.266 +                    out.append(mapper.getF(1)).append(" -= ")
   4.267 +                       .append(mapper.popF()).append(';');
   4.268 +                    break;
   4.269                  case opc_dsub:
   4.270 -                    out.append(mapper.get(1)).append(" -= ")
   4.271 -                       .append(mapper.pop()).append(';');
   4.272 +                    out.append(mapper.getD(1)).append(" -= ")
   4.273 +                       .append(mapper.popD()).append(';');
   4.274                      break;
   4.275                  case opc_imul:
   4.276 +                    out.append(mapper.getI(1)).append(" *= ")
   4.277 +                       .append(mapper.popI()).append(';');
   4.278 +                    break;
   4.279                  case opc_lmul:
   4.280 +                    out.append(mapper.getL(1)).append(" *= ")
   4.281 +                       .append(mapper.popL()).append(';');
   4.282 +                    break;
   4.283                  case opc_fmul:
   4.284 +                    out.append(mapper.getF(1)).append(" *= ")
   4.285 +                       .append(mapper.popF()).append(';');
   4.286 +                    break;
   4.287                  case opc_dmul:
   4.288 -                    out.append(mapper.get(1)).append(" *= ")
   4.289 -                       .append(mapper.pop()).append(';');
   4.290 +                    out.append(mapper.getD(1)).append(" *= ")
   4.291 +                       .append(mapper.popD()).append(';');
   4.292                      break;
   4.293                  case opc_idiv:
   4.294 +                    out.append(mapper.getI(1)).append(" = ")
   4.295 +                       .append("Math.floor(").append(mapper.getI(1))
   4.296 +                       .append(" / ").append(mapper.popI()).append(");");
   4.297 +                    break;
   4.298                  case opc_ldiv:
   4.299 -                    out.append(mapper.get(1))
   4.300 -                       .append(" = Math.floor(")
   4.301 -                       .append(mapper.get(1))
   4.302 -                       .append(" / ")
   4.303 -                       .append(mapper.pop())
   4.304 -                       .append(");");
   4.305 +                    out.append(mapper.getL(1)).append(" = ")
   4.306 +                       .append("Math.floor(").append(mapper.getL(1))
   4.307 +                       .append(" / ").append(mapper.popL()).append(");");
   4.308                      break;
   4.309                  case opc_fdiv:
   4.310 +                    out.append(mapper.getF(1)).append(" /= ")
   4.311 +                       .append(mapper.popF()).append(';');
   4.312 +                    break;
   4.313                  case opc_ddiv:
   4.314 -                    out.append(mapper.get(1)).append(" /= ")
   4.315 -                       .append(mapper.pop()).append(';');
   4.316 +                    out.append(mapper.getD(1)).append(" /= ")
   4.317 +                       .append(mapper.popD()).append(';');
   4.318                      break;
   4.319                  case opc_irem:
   4.320 +                    out.append(mapper.getI(1)).append(" %= ")
   4.321 +                       .append(mapper.popI()).append(';');
   4.322 +                    break;
   4.323                  case opc_lrem:
   4.324 +                    out.append(mapper.getL(1)).append(" %= ")
   4.325 +                       .append(mapper.popL()).append(';');
   4.326 +                    break;
   4.327                  case opc_frem:
   4.328 +                    out.append(mapper.getF(1)).append(" %= ")
   4.329 +                       .append(mapper.popF()).append(';');
   4.330 +                    break;
   4.331                  case opc_drem:
   4.332 -                    out.append(mapper.get(1)).append(" %= ")
   4.333 -                       .append(mapper.pop()).append(';');
   4.334 +                    out.append(mapper.getD(1)).append(" %= ")
   4.335 +                       .append(mapper.popD()).append(';');
   4.336                      break;
   4.337                  case opc_iand:
   4.338 +                    out.append(mapper.getI(1)).append(" &= ")
   4.339 +                       .append(mapper.popI()).append(';');
   4.340 +                    break;
   4.341                  case opc_land:
   4.342 -                    out.append(mapper.get(1)).append(" &= ")
   4.343 -                       .append(mapper.pop()).append(';');
   4.344 +                    out.append(mapper.getL(1)).append(" &= ")
   4.345 +                       .append(mapper.popL()).append(';');
   4.346                      break;
   4.347                  case opc_ior:
   4.348 +                    out.append(mapper.getI(1)).append(" |= ")
   4.349 +                       .append(mapper.popI()).append(';');
   4.350 +                    break;
   4.351                  case opc_lor:
   4.352 -                    out.append(mapper.get(1)).append(" |= ")
   4.353 -                       .append(mapper.pop()).append(';');
   4.354 +                    out.append(mapper.getL(1)).append(" |= ")
   4.355 +                       .append(mapper.popL()).append(';');
   4.356                      break;
   4.357                  case opc_ixor:
   4.358 +                    out.append(mapper.getI(1)).append(" ^= ")
   4.359 +                       .append(mapper.popI()).append(';');
   4.360 +                    break;
   4.361                  case opc_lxor:
   4.362 -                    out.append(mapper.get(1)).append(" ^= ")
   4.363 -                       .append(mapper.pop()).append(';');
   4.364 +                    out.append(mapper.getL(1)).append(" ^= ")
   4.365 +                       .append(mapper.popL()).append(';');
   4.366                      break;
   4.367                  case opc_ineg:
   4.368 +                    out.append(mapper.getI(0)).append(" = -")
   4.369 +                       .append(mapper.getI(0)).append(';');
   4.370 +                    break;
   4.371                  case opc_lneg:
   4.372 +                    out.append(mapper.getL(0)).append(" = -")
   4.373 +                       .append(mapper.getL(0)).append(';');
   4.374 +                    break;
   4.375                  case opc_fneg:
   4.376 +                    out.append(mapper.getF(0)).append(" = -")
   4.377 +                       .append(mapper.getF(0)).append(';');
   4.378 +                    break;
   4.379                  case opc_dneg:
   4.380 -                    out.append(mapper.get(0)).append(" = -")
   4.381 -                       .append(mapper.get(0)).append(';');
   4.382 +                    out.append(mapper.getD(0)).append(" = -")
   4.383 +                       .append(mapper.getD(0)).append(';');
   4.384                      break;
   4.385                  case opc_ishl:
   4.386 +                    out.append(mapper.getI(1)).append(" <<= ")
   4.387 +                       .append(mapper.popI()).append(';');
   4.388 +                    break;
   4.389                  case opc_lshl:
   4.390 -                    out.append(mapper.get(1)).append(" <<= ")
   4.391 -                       .append(mapper.pop()).append(';');
   4.392 +                    out.append(mapper.getL(1)).append(" <<= ")
   4.393 +                       .append(mapper.popI()).append(';');
   4.394                      break;
   4.395                  case opc_ishr:
   4.396 +                    out.append(mapper.getI(1)).append(" >>= ")
   4.397 +                       .append(mapper.popI()).append(';');
   4.398 +                    break;
   4.399                  case opc_lshr:
   4.400 -                    out.append(mapper.get(1)).append(" >>= ")
   4.401 -                       .append(mapper.pop()).append(';');
   4.402 +                    out.append(mapper.getL(1)).append(" >>= ")
   4.403 +                       .append(mapper.popI()).append(';');
   4.404                      break;
   4.405                  case opc_iushr:
   4.406 +                    out.append(mapper.getI(1)).append(" >>>= ")
   4.407 +                       .append(mapper.popI()).append(';');
   4.408 +                    break;
   4.409                  case opc_lushr:
   4.410 -                    out.append(mapper.get(1)).append(" >>>= ")
   4.411 -                       .append(mapper.pop()).append(';');
   4.412 +                    out.append(mapper.getL(1)).append(" >>>= ")
   4.413 +                       .append(mapper.popI()).append(';');
   4.414                      break;
   4.415                  case opc_iinc: {
   4.416                      final int varIndx = readByte(byteCodes, ++i);
   4.417 @@ -436,75 +607,149 @@
   4.418                      out.append("return;");
   4.419                      break;
   4.420                  case opc_ireturn:
   4.421 +                    out.append("return ").append(mapper.popI()).append(';');
   4.422 +                    break;
   4.423                  case opc_lreturn:
   4.424 +                    out.append("return ").append(mapper.popL()).append(';');
   4.425 +                    break;
   4.426                  case opc_freturn:
   4.427 +                    out.append("return ").append(mapper.popF()).append(';');
   4.428 +                    break;
   4.429                  case opc_dreturn:
   4.430 +                    out.append("return ").append(mapper.popD()).append(';');
   4.431 +                    break;
   4.432                  case opc_areturn:
   4.433 -                    out.append("return ").append(mapper.pop()).append(';');
   4.434 +                    out.append("return ").append(mapper.popA()).append(';');
   4.435                      break;
   4.436 -                case opc_i2l:
   4.437 -                case opc_i2f:
   4.438 -                case opc_i2d:
   4.439 -                case opc_l2i:
   4.440 +                case opc_i2l: {
   4.441 +                    final Variable v = mapper.popI();
   4.442 +                    out.append(mapper.pushL()).append(" = ")
   4.443 +                       .append(v).append(';');
   4.444 +                    break;
   4.445 +                }
   4.446 +                case opc_i2f: {
   4.447 +                    final Variable v = mapper.popI();
   4.448 +                    out.append(mapper.pushF()).append(" = ")
   4.449 +                       .append(v).append(';');
   4.450 +                    break;
   4.451 +                }
   4.452 +                case opc_i2d: {
   4.453 +                    final Variable v = mapper.popI();
   4.454 +                    out.append(mapper.pushD()).append(" = ")
   4.455 +                       .append(v).append(';');
   4.456 +                    break;
   4.457 +                }
   4.458 +                case opc_l2i: {
   4.459 +                    final Variable v = mapper.popL();
   4.460 +                    out.append(mapper.pushI()).append(" = ")
   4.461 +                       .append(v).append(';');
   4.462 +                    break;
   4.463 +                }
   4.464                      // max int check?
   4.465 -                case opc_l2f:
   4.466 -                case opc_l2d:
   4.467 -                case opc_f2d:
   4.468 -                case opc_d2f:
   4.469 -                    out.append("/* number conversion */");
   4.470 +                case opc_l2f: {
   4.471 +                    final Variable v = mapper.popL();
   4.472 +                    out.append(mapper.pushF()).append(" = ")
   4.473 +                       .append(v).append(';');
   4.474                      break;
   4.475 -                case opc_f2i:
   4.476 -                case opc_f2l:
   4.477 -                case opc_d2i:
   4.478 -                case opc_d2l:
   4.479 -                    out.append(mapper.get(0))
   4.480 -                       .append(" = Math.floor(")
   4.481 -                       .append(mapper.get(0))
   4.482 -                       .append(");");
   4.483 +                }
   4.484 +                case opc_l2d: {
   4.485 +                    final Variable v = mapper.popL();
   4.486 +                    out.append(mapper.pushD()).append(" = ")
   4.487 +                       .append(v).append(';');
   4.488                      break;
   4.489 +                }
   4.490 +                case opc_f2d: {
   4.491 +                    final Variable v = mapper.popF();
   4.492 +                    out.append(mapper.pushD()).append(" = ")
   4.493 +                       .append(v).append(';');
   4.494 +                    break;
   4.495 +                }
   4.496 +                case opc_d2f: {
   4.497 +                    final Variable v = mapper.popD();
   4.498 +                    out.append(mapper.pushF()).append(" = ")
   4.499 +                       .append(v).append(';');
   4.500 +                    break;
   4.501 +                }
   4.502 +                case opc_f2i: {
   4.503 +                    final Variable v = mapper.popF();
   4.504 +                    out.append(mapper.pushI()).append(" = ")
   4.505 +                       .append("Math.floor(").append(v).append(");");
   4.506 +                    break;
   4.507 +                }
   4.508 +                case opc_f2l: {
   4.509 +                    final Variable v = mapper.popF();
   4.510 +                    out.append(mapper.pushL()).append(" = ")
   4.511 +                       .append("Math.floor(").append(v).append(");");
   4.512 +                    break;
   4.513 +                }
   4.514 +                case opc_d2i: {
   4.515 +                    final Variable v = mapper.popD();
   4.516 +                    out.append(mapper.pushI()).append(" = ")
   4.517 +                       .append("Math.floor(").append(v).append(");");
   4.518 +                    break;
   4.519 +                }
   4.520 +                case opc_d2l: {
   4.521 +                    final Variable v = mapper.popD();
   4.522 +                    out.append(mapper.pushL()).append(" = ")
   4.523 +                       .append("Math.floor(").append(v).append(");");
   4.524 +                    break;
   4.525 +                }
   4.526                  case opc_i2b:
   4.527                  case opc_i2c:
   4.528                  case opc_i2s:
   4.529                      out.append("/* number conversion */");
   4.530                      break;
   4.531                  case opc_aconst_null:
   4.532 -                    out.append(mapper.push()).append(" = null;");
   4.533 +                    out.append(mapper.pushA()).append(" = null;");
   4.534                      break;
   4.535                  case opc_iconst_m1:
   4.536 -                    out.append(mapper.push()).append(" = -1;");
   4.537 +                    out.append(mapper.pushI()).append(" = -1;");
   4.538                      break;
   4.539                  case opc_iconst_0:
   4.540 +                    out.append(mapper.pushI()).append(" = 0;");
   4.541 +                    break;
   4.542                  case opc_dconst_0:
   4.543 +                    out.append(mapper.pushD()).append(" = 0;");
   4.544 +                    break;
   4.545                  case opc_lconst_0:
   4.546 +                    out.append(mapper.pushL()).append(" = 0;");
   4.547 +                    break;
   4.548                  case opc_fconst_0:
   4.549 -                    out.append(mapper.push()).append(" = 0;");
   4.550 +                    out.append(mapper.pushF()).append(" = 0;");
   4.551                      break;
   4.552                  case opc_iconst_1:
   4.553 +                    out.append(mapper.pushI()).append(" = 1;");
   4.554 +                    break;
   4.555                  case opc_lconst_1:
   4.556 +                    out.append(mapper.pushL()).append(" = 1;");
   4.557 +                    break;
   4.558                  case opc_fconst_1:
   4.559 +                    out.append(mapper.pushF()).append(" = 1;");
   4.560 +                    break;
   4.561                  case opc_dconst_1:
   4.562 -                    out.append(mapper.push()).append(" = 1;");
   4.563 +                    out.append(mapper.pushD()).append(" = 1;");
   4.564                      break;
   4.565                  case opc_iconst_2:
   4.566 +                    out.append(mapper.pushI()).append(" = 2;");
   4.567 +                    break;
   4.568                  case opc_fconst_2:
   4.569 -                    out.append(mapper.push()).append(" = 2;");
   4.570 +                    out.append(mapper.pushF()).append(" = 2;");
   4.571                      break;
   4.572                  case opc_iconst_3:
   4.573 -                    out.append(mapper.push()).append(" = 3;");
   4.574 +                    out.append(mapper.pushI()).append(" = 3;");
   4.575                      break;
   4.576                  case opc_iconst_4:
   4.577 -                    out.append(mapper.push()).append(" = 4;");
   4.578 +                    out.append(mapper.pushI()).append(" = 4;");
   4.579                      break;
   4.580                  case opc_iconst_5:
   4.581 -                    out.append(mapper.push()).append(" = 5;");
   4.582 +                    out.append(mapper.pushI()).append(" = 5;");
   4.583                      break;
   4.584                  case opc_ldc: {
   4.585                      int indx = readByte(byteCodes, ++i);
   4.586                      String v = encodeConstant(indx);
   4.587 -                    out.append(mapper.push())
   4.588 -                       .append(" = ")
   4.589 -                       .append(v)
   4.590 -                       .append(';');
   4.591 +                    int type = constantToVariableType(jc.getTag(indx));
   4.592 +                    out.append(mapper.pushT(type)).append(" = ")
   4.593 +                       .append(v).append(';');
   4.594                      break;
   4.595                  }
   4.596                  case opc_ldc_w:
   4.597 @@ -512,44 +757,38 @@
   4.598                      int indx = readIntArg(byteCodes, i);
   4.599                      i += 2;
   4.600                      String v = encodeConstant(indx);
   4.601 -                    out.append(mapper.push())
   4.602 -                       .append(" = ")
   4.603 -                       .append(v)
   4.604 -                       .append(';');
   4.605 +                    int type = constantToVariableType(jc.getTag(indx));
   4.606 +                    out.append(mapper.pushT(type)).append(" = ")
   4.607 +                       .append(v).append(';');
   4.608                      break;
   4.609                  }
   4.610                  case opc_lcmp:
   4.611 +                    generateCmp(mapper.popL(), mapper.popL(), mapper.pushI());
   4.612 +                    break;
   4.613                  case opc_fcmpl:
   4.614                  case opc_fcmpg:
   4.615 +                    generateCmp(mapper.popF(), mapper.popF(), mapper.pushI());
   4.616 +                    break;
   4.617                  case opc_dcmpl:
   4.618 -                case opc_dcmpg: {
   4.619 -                    out.append(mapper.get(1))
   4.620 -                       .append(" = (")
   4.621 -                       .append(mapper.get(1))
   4.622 -                       .append(" == ")
   4.623 -                       .append(mapper.get(0))
   4.624 -                       .append(") ? 0 : ((")
   4.625 -                       .append(mapper.get(1))
   4.626 -                       .append(" < ")
   4.627 -                       .append(mapper.get(0))
   4.628 -                       .append(") ? -1 : 1);");
   4.629 -
   4.630 -                    mapper.pop(1);
   4.631 +                case opc_dcmpg:
   4.632 +                    generateCmp(mapper.popD(), mapper.popD(), mapper.pushI());
   4.633                      break;
   4.634 -                }
   4.635                  case opc_if_acmpeq:
   4.636 -                    i = generateIf(byteCodes, i, mapper, "===");
   4.637 +                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   4.638 +                                   "===");
   4.639                      break;
   4.640                  case opc_if_acmpne:
   4.641 -                    i = generateIf(byteCodes, i, mapper, "!=");
   4.642 +                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   4.643 +                                   "!=");
   4.644                      break;
   4.645                  case opc_if_icmpeq: {
   4.646 -                    i = generateIf(byteCodes, i, mapper, "==");
   4.647 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.648 +                                   "==");
   4.649                      break;
   4.650                  }
   4.651                  case opc_ifeq: {
   4.652                      int indx = i + readIntArg(byteCodes, i);
   4.653 -                    out.append("if (").append(mapper.pop())
   4.654 +                    out.append("if (").append(mapper.popI())
   4.655                                        .append(" == 0) { gt = " + indx);
   4.656                      out.append("; continue; }");
   4.657                      i += 2;
   4.658 @@ -557,7 +796,7 @@
   4.659                  }
   4.660                  case opc_ifne: {
   4.661                      int indx = i + readIntArg(byteCodes, i);
   4.662 -                    out.append("if (").append(mapper.pop())
   4.663 +                    out.append("if (").append(mapper.popI())
   4.664                                        .append(" != 0) { gt = " + indx);
   4.665                      out.append("; continue; }");
   4.666                      i += 2;
   4.667 @@ -565,7 +804,7 @@
   4.668                  }
   4.669                  case opc_iflt: {
   4.670                      int indx = i + readIntArg(byteCodes, i);
   4.671 -                    out.append("if (").append(mapper.pop())
   4.672 +                    out.append("if (").append(mapper.popI())
   4.673                                        .append(" < 0) { gt = " + indx);
   4.674                      out.append("; continue; }");
   4.675                      i += 2;
   4.676 @@ -573,7 +812,7 @@
   4.677                  }
   4.678                  case opc_ifle: {
   4.679                      int indx = i + readIntArg(byteCodes, i);
   4.680 -                    out.append("if (").append(mapper.pop())
   4.681 +                    out.append("if (").append(mapper.popI())
   4.682                                        .append(" <= 0) { gt = " + indx);
   4.683                      out.append("; continue; }");
   4.684                      i += 2;
   4.685 @@ -581,7 +820,7 @@
   4.686                  }
   4.687                  case opc_ifgt: {
   4.688                      int indx = i + readIntArg(byteCodes, i);
   4.689 -                    out.append("if (").append(mapper.pop())
   4.690 +                    out.append("if (").append(mapper.popI())
   4.691                                        .append(" > 0) { gt = " + indx);
   4.692                      out.append("; continue; }");
   4.693                      i += 2;
   4.694 @@ -589,7 +828,7 @@
   4.695                  }
   4.696                  case opc_ifge: {
   4.697                      int indx = i + readIntArg(byteCodes, i);
   4.698 -                    out.append("if (").append(mapper.pop())
   4.699 +                    out.append("if (").append(mapper.popI())
   4.700                                        .append(" >= 0) { gt = " + indx);
   4.701                      out.append("; continue; }");
   4.702                      i += 2;
   4.703 @@ -597,7 +836,7 @@
   4.704                  }
   4.705                  case opc_ifnonnull: {
   4.706                      int indx = i + readIntArg(byteCodes, i);
   4.707 -                    out.append("if (").append(mapper.pop())
   4.708 +                    out.append("if (").append(mapper.popA())
   4.709                                        .append(" !== null) { gt = " + indx);
   4.710                      out.append("; continue; }");
   4.711                      i += 2;
   4.712 @@ -605,26 +844,31 @@
   4.713                  }
   4.714                  case opc_ifnull: {
   4.715                      int indx = i + readIntArg(byteCodes, i);
   4.716 -                    out.append("if (").append(mapper.pop())
   4.717 +                    out.append("if (").append(mapper.popA())
   4.718                                        .append(" === null) { gt = " + indx);
   4.719                      out.append("; continue; }");
   4.720                      i += 2;
   4.721                      break;
   4.722                  }
   4.723                  case opc_if_icmpne:
   4.724 -                    i = generateIf(byteCodes, i, mapper, "!=");
   4.725 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.726 +                                   "!=");
   4.727                      break;
   4.728                  case opc_if_icmplt:
   4.729 -                    i = generateIf(byteCodes, i, mapper, "<");
   4.730 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.731 +                                   "<");
   4.732                      break;
   4.733                  case opc_if_icmple:
   4.734 -                    i = generateIf(byteCodes, i, mapper, "<=");
   4.735 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.736 +                                   "<=");
   4.737                      break;
   4.738                  case opc_if_icmpgt:
   4.739 -                    i = generateIf(byteCodes, i, mapper, ">");
   4.740 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.741 +                                   ">");
   4.742                      break;
   4.743                  case opc_if_icmpge:
   4.744 -                    i = generateIf(byteCodes, i, mapper, ">=");
   4.745 +                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   4.746 +                                   ">=");
   4.747                      break;
   4.748                  case opc_goto: {
   4.749                      int indx = i + readIntArg(byteCodes, i);
   4.750 @@ -638,7 +882,7 @@
   4.751                      table += 4;
   4.752                      int n = readInt4(byteCodes, table);
   4.753                      table += 4;
   4.754 -                    out.append("switch (").append(mapper.pop()).append(") {\n");
   4.755 +                    out.append("switch (").append(mapper.popI()).append(") {\n");
   4.756                      while (n-- > 0) {
   4.757                          int cnstnt = readInt4(byteCodes, table);
   4.758                          table += 4;
   4.759 @@ -658,7 +902,7 @@
   4.760                      table += 4;
   4.761                      int high = readInt4(byteCodes, table);
   4.762                      table += 4;
   4.763 -                    out.append("switch (").append(mapper.pop()).append(") {\n");
   4.764 +                    out.append("switch (").append(mapper.popI()).append(") {\n");
   4.765                      while (low <= high) {
   4.766                          int offset = i + readInt4(byteCodes, table);
   4.767                          table += 4;
   4.768 @@ -685,7 +929,7 @@
   4.769                  case opc_new: {
   4.770                      int indx = readIntArg(byteCodes, i);
   4.771                      String ci = jc.getClassName(indx);
   4.772 -                    out.append(mapper.push()).append(" = ");
   4.773 +                    out.append(mapper.pushA()).append(" = ");
   4.774                      out.append("new ").append(ci.replace('/','_'));
   4.775                      out.append(';');
   4.776                      addReference(ci);
   4.777 @@ -694,28 +938,26 @@
   4.778                  }
   4.779                  case opc_newarray: {
   4.780                      ++i; // skip type of array
   4.781 -                    out.append(mapper.get(0))
   4.782 -                       .append(" = new Array(")
   4.783 -                       .append(mapper.get(0))
   4.784 -                       .append(").fillNulls();");
   4.785 +                    final Variable v = mapper.popI();
   4.786 +                    out.append(mapper.pushA()).append(" = ")
   4.787 +                       .append("new Array(").append(v).append(").fillNulls();");
   4.788                      break;
   4.789                  }
   4.790                  case opc_anewarray: {
   4.791                      i += 2; // skip type of array
   4.792 -                    out.append(mapper.get(0))
   4.793 -                       .append(" = new Array(")
   4.794 -                       .append(mapper.get(0))
   4.795 -                       .append(").fillNulls();");
   4.796 +                    final Variable v = mapper.popI();
   4.797 +                    out.append(mapper.pushA()).append(" = ")
   4.798 +                       .append("new Array(").append(v).append(").fillNulls();");
   4.799                      break;
   4.800                  }
   4.801                  case opc_multianewarray: {
   4.802                      i += 2;
   4.803                      int dim = readByte(byteCodes, ++i);
   4.804 -                    out.append("{ var a0 = new Array(").append(mapper.pop())
   4.805 +                    out.append("{ var a0 = new Array(").append(mapper.popI())
   4.806                         .append(").fillNulls();");
   4.807                      for (int d = 1; d < dim; d++) {
   4.808                          out.append("\n  var l" + d).append(" = ")
   4.809 -                           .append(mapper.pop()).append(';');
   4.810 +                           .append(mapper.popI()).append(';');
   4.811                          out.append("\n  for (var i" + d).append (" = 0; i" + d).
   4.812                              append(" < a" + (d - 1)).
   4.813                              append(".length; i" + d).append("++) {");
   4.814 @@ -727,41 +969,94 @@
   4.815                      for (int d = 1; d < dim; d++) {
   4.816                          out.append("\n  }");
   4.817                      }
   4.818 -                    out.append("\n").append(mapper.push()).append(" = a0; }");
   4.819 +                    out.append("\n").append(mapper.pushA()).append(" = a0; }");
   4.820                      break;
   4.821                  }
   4.822 -                case opc_arraylength:
   4.823 -                    out.append(mapper.get(0)).append(" = ")
   4.824 -                       .append(mapper.get(0)).append(".length;");
   4.825 +                case opc_arraylength: {
   4.826 +                    final Variable v = mapper.popA();
   4.827 +                    out.append(mapper.pushI()).append(" = ")
   4.828 +                       .append(v).append(".length;");
   4.829                      break;
   4.830 +                }
   4.831 +                case opc_lastore: {
   4.832 +                    out.append(mapper.getA(2)).append('[')
   4.833 +                                              .append(mapper.getI(1))
   4.834 +                                              .append(']')
   4.835 +                       .append(" = ").append(mapper.getL(0)).append(';');
   4.836 +                    mapper.pop(3);
   4.837 +                    break;
   4.838 +                }
   4.839 +                case opc_fastore: {
   4.840 +                    out.append(mapper.getA(2)).append('[')
   4.841 +                                              .append(mapper.getI(1))
   4.842 +                                              .append(']')
   4.843 +                       .append(" = ").append(mapper.getF(0)).append(';');
   4.844 +                    mapper.pop(3);
   4.845 +                    break;
   4.846 +                }
   4.847 +                case opc_dastore: {
   4.848 +                    out.append(mapper.getA(2)).append('[')
   4.849 +                                              .append(mapper.getI(1))
   4.850 +                                              .append(']')
   4.851 +                       .append(" = ").append(mapper.getD(0)).append(';');
   4.852 +                    mapper.pop(3);
   4.853 +                    break;
   4.854 +                }
   4.855 +                case opc_aastore: {
   4.856 +                    out.append(mapper.getA(2)).append('[')
   4.857 +                                              .append(mapper.getI(1))
   4.858 +                                              .append(']')
   4.859 +                       .append(" = ").append(mapper.getA(0)).append(';');
   4.860 +                    mapper.pop(3);
   4.861 +                    break;
   4.862 +                }
   4.863                  case opc_iastore:
   4.864 -                case opc_lastore:
   4.865 -                case opc_fastore:
   4.866 -                case opc_dastore:
   4.867 -                case opc_aastore:
   4.868                  case opc_bastore:
   4.869                  case opc_castore:
   4.870                  case opc_sastore: {
   4.871 -                    out.append(mapper.get(2))
   4.872 -                       .append('[').append(mapper.get(1)).append(']')
   4.873 -                       .append(" = ")
   4.874 -                       .append(mapper.get(0))
   4.875 -                       .append(';');
   4.876 +                    out.append(mapper.getA(2)).append('[')
   4.877 +                                              .append(mapper.getI(1))
   4.878 +                                              .append(']')
   4.879 +                       .append(" = ").append(mapper.getI(0)).append(';');
   4.880                      mapper.pop(3);
   4.881                      break;
   4.882                  }
   4.883 +                case opc_laload: {
   4.884 +                    final Variable vidx = mapper.popI();
   4.885 +                    final Variable varr = mapper.popA();
   4.886 +                    out.append(mapper.pushL()).append(" = ")
   4.887 +                       .append(varr).append('[').append(vidx).append("];");
   4.888 +                    break;
   4.889 +                }
   4.890 +                case opc_faload: {
   4.891 +                    final Variable vidx = mapper.popI();
   4.892 +                    final Variable varr = mapper.popA();
   4.893 +                    out.append(mapper.pushF()).append(" = ")
   4.894 +                       .append(varr).append('[').append(vidx).append("];");
   4.895 +                    break;
   4.896 +                }
   4.897 +                case opc_daload: {
   4.898 +                    final Variable vidx = mapper.popI();
   4.899 +                    final Variable varr = mapper.popA();
   4.900 +                    out.append(mapper.pushD()).append(" = ")
   4.901 +                       .append(varr).append('[').append(vidx).append("];");
   4.902 +                    break;
   4.903 +                }
   4.904 +                case opc_aaload: {
   4.905 +                    final Variable vidx = mapper.popI();
   4.906 +                    final Variable varr = mapper.popA();
   4.907 +                    out.append(mapper.pushA()).append(" = ")
   4.908 +                       .append(varr).append('[').append(vidx).append("];");
   4.909 +                    break;
   4.910 +                }
   4.911                  case opc_iaload:
   4.912 -                case opc_laload:
   4.913 -                case opc_faload:
   4.914 -                case opc_daload:
   4.915 -                case opc_aaload:
   4.916                  case opc_baload:
   4.917                  case opc_caload:
   4.918                  case opc_saload: {
   4.919 -                    out.append(mapper.get(1))
   4.920 -                       .append(" = ")
   4.921 -                       .append(mapper.get(1))
   4.922 -                       .append('[').append(mapper.pop()).append("];");
   4.923 +                    final Variable vidx = mapper.popI();
   4.924 +                    final Variable varr = mapper.popA();
   4.925 +                    out.append(mapper.pushI()).append(" = ")
   4.926 +                       .append(varr).append('[').append(vidx).append("];");
   4.927                      break;
   4.928                  }
   4.929                  case opc_pop:
   4.930 @@ -769,38 +1064,80 @@
   4.931                      mapper.pop(1);
   4.932                      out.append("/* pop */");
   4.933                      break;
   4.934 -                case opc_dup:
   4.935 -                    out.append(mapper.push()).append(" = ")
   4.936 -                       .append(mapper.get(1)).append(';');
   4.937 +                case opc_dup: {
   4.938 +                    final Variable v = mapper.get(0);
   4.939 +                    out.append(mapper.pushT(v.getType())).append(" = ")
   4.940 +                       .append(v).append(';');
   4.941                      break;
   4.942 -                case opc_dup_x1:
   4.943 +                }
   4.944 +                case opc_dup2: {
   4.945 +                    if (mapper.get(0).isCategory2()) {
   4.946 +                        final Variable v = mapper.get(0);
   4.947 +                        out.append(mapper.pushT(v.getType())).append(" = ")
   4.948 +                           .append(v).append(';');
   4.949 +                    } else {
   4.950 +                        final Variable v1 = mapper.get(0);
   4.951 +                        final Variable v2 = mapper.get(1);
   4.952 +                        out.append("{ ");
   4.953 +                        out.append(mapper.pushT(v2.getType())).append(" = ")
   4.954 +                           .append(v2).append("; ");
   4.955 +                        out.append(mapper.pushT(v1.getType())).append(" = ")
   4.956 +                           .append(v1).append("; ");
   4.957 +                        out.append('}');
   4.958 +                    }
   4.959 +                    break;
   4.960 +                }
   4.961 +                case opc_dup_x1: {
   4.962 +                    final Variable vi1 = mapper.pop();
   4.963 +                    final Variable vi2 = mapper.pop();
   4.964 +                    final Variable vo3 = mapper.pushT(vi1.getType());
   4.965 +                    final Variable vo2 = mapper.pushT(vi2.getType());
   4.966 +                    final Variable vo1 = mapper.pushT(vi1.getType());
   4.967 +
   4.968                      out.append("{ ");
   4.969 -                    out.append(mapper.push()).append(" = ")
   4.970 -                       .append(mapper.get(1)).append("; ");
   4.971 -                    out.append(mapper.get(1)).append(" = ")
   4.972 -                       .append(mapper.get(2)).append("; ");
   4.973 -                    out.append(mapper.get(2)).append(" = ")
   4.974 -                       .append(mapper.get(0)).append("; ");
   4.975 +                    out.append(vo1).append(" = ").append(vi1).append("; ");
   4.976 +                    out.append(vo2).append(" = ").append(vi2).append("; ");
   4.977 +                    out.append(vo3).append(" = ").append(vo1).append("; ");
   4.978                      out.append('}');
   4.979                      break;
   4.980 -                case opc_dup_x2:
   4.981 -                    out.append("{ ");
   4.982 -                    out.append(mapper.push()).append(" = ")
   4.983 -                       .append(mapper.get(1)).append("; ");
   4.984 -                    out.append(mapper.get(1)).append(" = ")
   4.985 -                       .append(mapper.get(2)).append("; ");
   4.986 -                    out.append(mapper.get(2)).append(" = ")
   4.987 -                       .append(mapper.get(3)).append("; ");
   4.988 -                    out.append(mapper.get(3)).append(" = ")
   4.989 -                       .append(mapper.get(0)).append("; ");
   4.990 -                    out.append('}');
   4.991 +                }
   4.992 +                case opc_dup_x2: {
   4.993 +                    if (mapper.get(1).isCategory2()) {
   4.994 +                        final Variable vi1 = mapper.pop();
   4.995 +                        final Variable vi2 = mapper.pop();
   4.996 +                        final Variable vo3 = mapper.pushT(vi1.getType());
   4.997 +                        final Variable vo2 = mapper.pushT(vi2.getType());
   4.998 +                        final Variable vo1 = mapper.pushT(vi1.getType());
   4.999 +
  4.1000 +                        out.append("{ ");
  4.1001 +                        out.append(vo1).append(" = ").append(vi1).append("; ");
  4.1002 +                        out.append(vo2).append(" = ").append(vi2).append("; ");
  4.1003 +                        out.append(vo3).append(" = ").append(vo1).append("; ");
  4.1004 +                        out.append('}');
  4.1005 +                    } else {
  4.1006 +                        final Variable vi1 = mapper.pop();
  4.1007 +                        final Variable vi2 = mapper.pop();
  4.1008 +                        final Variable vi3 = mapper.pop();
  4.1009 +                        final Variable vo4 = mapper.pushT(vi1.getType());
  4.1010 +                        final Variable vo3 = mapper.pushT(vi3.getType());
  4.1011 +                        final Variable vo2 = mapper.pushT(vi2.getType());
  4.1012 +                        final Variable vo1 = mapper.pushT(vi1.getType());
  4.1013 +
  4.1014 +                        out.append("{ ");
  4.1015 +                        out.append(vo1).append(" = ").append(vi1).append("; ");
  4.1016 +                        out.append(vo2).append(" = ").append(vi2).append("; ");
  4.1017 +                        out.append(vo3).append(" = ").append(vi3).append("; ");
  4.1018 +                        out.append(vo4).append(" = ").append(vo1).append("; ");
  4.1019 +                        out.append('}');
  4.1020 +                    }
  4.1021                      break;
  4.1022 +                }
  4.1023                  case opc_bipush:
  4.1024 -                    out.append(mapper.push()).append(" = ")
  4.1025 +                    out.append(mapper.pushI()).append(" = ")
  4.1026                         .append(Integer.toString(byteCodes[++i])).append(';');
  4.1027                      break;
  4.1028                  case opc_sipush:
  4.1029 -                    out.append(mapper.push()).append(" = ")
  4.1030 +                    out.append(mapper.pushI()).append(" = ")
  4.1031                         .append(Integer.toString(readIntArg(byteCodes, i)))
  4.1032                         .append(';');
  4.1033                      i += 2;
  4.1034 @@ -808,48 +1145,51 @@
  4.1035                  case opc_getfield: {
  4.1036                      int indx = readIntArg(byteCodes, i);
  4.1037                      String[] fi = jc.getFieldInfoName(indx);
  4.1038 -                    out.append(mapper.get(0)).append(" = ")
  4.1039 -                       .append(mapper.get(0)).append(".fld_")
  4.1040 -                       .append(fi[1]).append(';');
  4.1041 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  4.1042 +                    final Variable v = mapper.popA();
  4.1043 +                    out.append(mapper.pushT(type)).append(" = ")
  4.1044 +                       .append(v).append(".fld_").append(fi[1]).append(';');
  4.1045                      i += 2;
  4.1046                      break;
  4.1047                  }
  4.1048                  case opc_getstatic: {
  4.1049                      int indx = readIntArg(byteCodes, i);
  4.1050                      String[] fi = jc.getFieldInfoName(indx);
  4.1051 -                    out.append(mapper.push()).append(" = ")
  4.1052 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  4.1053 +                    out.append(mapper.pushT(type)).append(" = ")
  4.1054                         .append(fi[0].replace('/', '_'))
  4.1055                         .append('.').append(fi[1]).append(';');
  4.1056                      i += 2;
  4.1057                      addReference(fi[0]);
  4.1058                      break;
  4.1059                  }
  4.1060 -                case opc_putstatic: {
  4.1061 -                    int indx = readIntArg(byteCodes, i);
  4.1062 -                    String[] fi = jc.getFieldInfoName(indx);
  4.1063 -                    out.append(fi[0].replace('/', '_'));
  4.1064 -                    out.append('.').append(fi[1]).append(" = ")
  4.1065 -                       .append(mapper.pop()).append(';');
  4.1066 -                    i += 2;
  4.1067 -                    addReference(fi[0]);
  4.1068 -                    break;
  4.1069 -                }
  4.1070                  case opc_putfield: {
  4.1071                      int indx = readIntArg(byteCodes, i);
  4.1072                      String[] fi = jc.getFieldInfoName(indx);
  4.1073 -                    out.append(mapper.get(1)).append(".fld_").append(fi[1])
  4.1074 -                       .append(" = ")
  4.1075 -                       .append(mapper.get(0)).append(';');
  4.1076 -                    mapper.pop(2);
  4.1077 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  4.1078 +                    final Variable v = mapper.popT(type);
  4.1079 +                    out.append(mapper.popA()).append(".fld_").append(fi[1])
  4.1080 +                       .append(" = ").append(v).append(';');
  4.1081                      i += 2;
  4.1082                      break;
  4.1083                  }
  4.1084 +                case opc_putstatic: {
  4.1085 +                    int indx = readIntArg(byteCodes, i);
  4.1086 +                    String[] fi = jc.getFieldInfoName(indx);
  4.1087 +                    final int type = fieldToVariableType(fi[2].charAt(0));
  4.1088 +                    out.append(fi[0].replace('/', '_'));
  4.1089 +                    out.append('.').append(fi[1]).append(" = ")
  4.1090 +                       .append(mapper.popT(type)).append(';');
  4.1091 +                    i += 2;
  4.1092 +                    addReference(fi[0]);
  4.1093 +                    break;
  4.1094 +                }
  4.1095                  case opc_checkcast: {
  4.1096                      int indx = readIntArg(byteCodes, i);
  4.1097                      final String type = jc.getClassName(indx);
  4.1098                      if (!type.startsWith("[")) {
  4.1099                          // no way to check arrays right now
  4.1100 -                        out.append("if (").append(mapper.get(0))
  4.1101 +                        out.append("if (").append(mapper.getA(0))
  4.1102                             .append(".$instOf_").append(type.replace('/', '_'))
  4.1103                             .append(" != 1) throw {};"); // XXX proper exception
  4.1104                      }
  4.1105 @@ -859,33 +1199,36 @@
  4.1106                  case opc_instanceof: {
  4.1107                      int indx = readIntArg(byteCodes, i);
  4.1108                      final String type = jc.getClassName(indx);
  4.1109 -                    out.append(mapper.get(0)).append(" = ")
  4.1110 -                       .append(mapper.get(0)).append(".$instOf_")
  4.1111 -                       .append(type.replace('/', '_'))
  4.1112 +                    final Variable v = mapper.popA();
  4.1113 +                    out.append(mapper.pushI()).append(" = ")
  4.1114 +                       .append(v).append(".$instOf_")
  4.1115 +                                 .append(type.replace('/', '_'))
  4.1116                         .append(" ? 1 : 0;");
  4.1117                      i += 2;
  4.1118                      break;
  4.1119                  }
  4.1120                  case opc_athrow: {
  4.1121 +                    final Variable v = mapper.popA();
  4.1122 +                    mapper.clear();
  4.1123 +
  4.1124                      out.append("{ ");
  4.1125 -                    out.append(mapper.bottom()).append(" = ")
  4.1126 -                       .append(mapper.top()).append("; ");
  4.1127 -                    out.append("throw ").append(mapper.bottom()).append("; ");
  4.1128 +                    out.append(mapper.pushA()).append(" = ")
  4.1129 +                       .append(v).append("; ");
  4.1130 +                    out.append("throw ").append(v).append("; ");
  4.1131                      out.append('}');
  4.1132  
  4.1133 -                    mapper.reset(1);
  4.1134                      break;
  4.1135                  }
  4.1136  
  4.1137                  case opc_monitorenter: {
  4.1138                      out.append("/* monitor enter */");
  4.1139 -                    mapper.pop(1);
  4.1140 +                    mapper.popA();
  4.1141                      break;
  4.1142                  }
  4.1143  
  4.1144                  case opc_monitorexit: {
  4.1145                      out.append("/* monitor exit */");
  4.1146 -                    mapper.pop(1);
  4.1147 +                    mapper.popA();
  4.1148                      break;
  4.1149                  }
  4.1150  
  4.1151 @@ -903,22 +1246,28 @@
  4.1152              out.append("\n");
  4.1153          }
  4.1154          out.append("  }\n");
  4.1155 -
  4.1156 -        if (mapper.getMaxStackSize() > maxStack) {
  4.1157 -            throw new IllegalStateException("Incorrect stack usage");
  4.1158 -        }
  4.1159      }
  4.1160  
  4.1161 -    private int generateIf(byte[] byteCodes, int i, final StackToVariableMapper mapper, final String test) throws IOException {
  4.1162 +    private int generateIf(byte[] byteCodes, int i,
  4.1163 +                           final Variable v2, final Variable v1,
  4.1164 +                           final String test) throws IOException {
  4.1165          int indx = i + readIntArg(byteCodes, i);
  4.1166 -        out.append("if (").append(mapper.get(1))
  4.1167 +        out.append("if (").append(v1)
  4.1168             .append(' ').append(test).append(' ')
  4.1169 -           .append(mapper.get(0)).append(") { gt = " + indx)
  4.1170 +           .append(v2).append(") { gt = " + indx)
  4.1171             .append("; continue; }");
  4.1172 -        mapper.pop(2);
  4.1173          return i + 2;
  4.1174      }
  4.1175  
  4.1176 +    private void generateCmp(Variable v2, Variable v1, Variable vr)
  4.1177 +            throws IOException {
  4.1178 +        out.append(vr).append(" = ")
  4.1179 +           .append('(').append(v1).append(" == ").append(v2).append(')')
  4.1180 +           .append(" ? 0")
  4.1181 +           .append(" : ((").append(v1).append(" < ").append(v2).append(')')
  4.1182 +           .append(" ? -1 : 1);");
  4.1183 +    }
  4.1184 +
  4.1185      private int readIntArg(byte[] byteCodes, int offsetInstruction) {
  4.1186          final int indxHi = byteCodes[offsetInstruction + 1] << 8;
  4.1187          final int indxLo = byteCodes[offsetInstruction + 2];
  4.1188 @@ -935,7 +1284,7 @@
  4.1189          return byteCodes[offsetInstruction] & 0xff;
  4.1190      }
  4.1191      
  4.1192 -    private static void countArgs(String descriptor, boolean[] hasReturnType, StringBuilder sig, StringBuilder cnt) {
  4.1193 +    private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
  4.1194          int i = 0;
  4.1195          Boolean count = null;
  4.1196          boolean array = false;
  4.1197 @@ -971,17 +1320,19 @@
  4.1198                              cnt.append('0');
  4.1199                          }
  4.1200                      } else {
  4.1201 -                        hasReturnType[0] = true;
  4.1202                          sig.insert(firstPos, ch);
  4.1203                          if (array) {
  4.1204 +                            returnType[0] = '[';
  4.1205                              sig.insert(firstPos, 'A');
  4.1206 +                        } else {
  4.1207 +                            returnType[0] = ch;
  4.1208                          }
  4.1209                      }
  4.1210                      array = false;
  4.1211                      continue;
  4.1212                  case 'V': 
  4.1213                      assert !count;
  4.1214 -                    hasReturnType[0] = false;
  4.1215 +                    returnType[0] = 'V';
  4.1216                      sig.insert(firstPos, 'V');
  4.1217                      continue;
  4.1218                  case 'L':
  4.1219 @@ -999,7 +1350,7 @@
  4.1220                          if (array) {
  4.1221                              sig.insert(firstPos, 'A');
  4.1222                          }
  4.1223 -                        hasReturnType[0] = true;
  4.1224 +                        returnType[0] = 'L';
  4.1225                      }
  4.1226                      i = next + 1;
  4.1227                      continue;
  4.1228 @@ -1022,12 +1373,11 @@
  4.1229              name.append(m.getName());
  4.1230          } 
  4.1231          
  4.1232 -        boolean hasReturn[] = { false };
  4.1233 -        countArgs(findDescriptor(m.getInternalSig()), hasReturn, name, cnt);
  4.1234 +        countArgs(findDescriptor(m.getInternalSig()), new char[1], name, cnt);
  4.1235          return name.toString();
  4.1236      }
  4.1237  
  4.1238 -    private String findMethodName(String[] mi, StringBuilder cnt, boolean[] hasReturn) {
  4.1239 +    private String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) {
  4.1240          StringBuilder name = new StringBuilder();
  4.1241          String descr = mi[2];//mi.getDescriptor();
  4.1242          String nm= mi[1];
  4.1243 @@ -1036,7 +1386,7 @@
  4.1244          } else {
  4.1245              name.append(nm);
  4.1246          }
  4.1247 -        countArgs(findDescriptor(descr), hasReturn, name, cnt);
  4.1248 +        countArgs(findDescriptor(descr), returnType, name, cnt);
  4.1249          return name.toString();
  4.1250      }
  4.1251  
  4.1252 @@ -1044,15 +1394,20 @@
  4.1253      throws IOException {
  4.1254          int methodIndex = readIntArg(byteCodes, i);
  4.1255          String[] mi = jc.getFieldInfoName(methodIndex);
  4.1256 -        boolean[] hasReturn = { false };
  4.1257 +        char[] returnType = { 'V' };
  4.1258          StringBuilder cnt = new StringBuilder();
  4.1259 -        String mn = findMethodName(mi, cnt, hasReturn);
  4.1260 +        String mn = findMethodName(mi, cnt, returnType);
  4.1261  
  4.1262          final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
  4.1263 +        final Variable[] vars = new Variable[numArguments];
  4.1264  
  4.1265 -        if (hasReturn[0]) {
  4.1266 -            out.append((numArguments > 0) ? mapper.get(numArguments - 1)
  4.1267 -                                          : mapper.push()).append(" = ");
  4.1268 +        for (int j = numArguments - 1; j >= 0; --j) {
  4.1269 +            vars[j] = mapper.pop();
  4.1270 +        }
  4.1271 +
  4.1272 +        if (returnType[0] != 'V') {
  4.1273 +            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  4.1274 +               .append(" = ");
  4.1275          }
  4.1276  
  4.1277          final String in = mi[0];
  4.1278 @@ -1061,16 +1416,13 @@
  4.1279          out.append(mn);
  4.1280          out.append('(');
  4.1281          if (numArguments > 0) {
  4.1282 -            out.append(mapper.get(numArguments - 1));
  4.1283 -            for (int j = numArguments - 2; j >= 0; --j) {
  4.1284 +            out.append(vars[0]);
  4.1285 +            for (int j = 1; j < numArguments; ++j) {
  4.1286                  out.append(", ");
  4.1287 -                out.append(mapper.get(j));
  4.1288 +                out.append(vars[j]);
  4.1289              }
  4.1290          }
  4.1291          out.append(");");
  4.1292 -        if (numArguments > 0) {
  4.1293 -            mapper.pop(hasReturn[0] ? numArguments - 1 : numArguments);
  4.1294 -        }
  4.1295          i += 2;
  4.1296          addReference(in);
  4.1297          return i;
  4.1298 @@ -1079,26 +1431,31 @@
  4.1299      throws IOException {
  4.1300          int methodIndex = readIntArg(byteCodes, i);
  4.1301          String[] mi = jc.getFieldInfoName(methodIndex);
  4.1302 -        boolean[] hasReturn = { false };
  4.1303 +        char[] returnType = { 'V' };
  4.1304          StringBuilder cnt = new StringBuilder();
  4.1305 -        String mn = findMethodName(mi, cnt, hasReturn);
  4.1306 +        String mn = findMethodName(mi, cnt, returnType);
  4.1307  
  4.1308 -        final int numArguments = cnt.length();
  4.1309 +        final int numArguments = cnt.length() + 1;
  4.1310 +        final Variable[] vars = new Variable[numArguments];
  4.1311  
  4.1312 -        if (hasReturn[0]) {
  4.1313 -            out.append(mapper.get(numArguments)).append(" = ");
  4.1314 +        for (int j = numArguments - 1; j >= 0; --j) {
  4.1315 +            vars[j] = mapper.pop();
  4.1316          }
  4.1317  
  4.1318 -        out.append(mapper.get(numArguments)).append('.');
  4.1319 +        if (returnType[0] != 'V') {
  4.1320 +            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  4.1321 +               .append(" = ");
  4.1322 +        }
  4.1323 +
  4.1324 +        out.append(vars[0]).append('.');
  4.1325          out.append(mn);
  4.1326          out.append('(');
  4.1327 -        out.append(mapper.get(numArguments));
  4.1328 -        for (int j = numArguments - 1; j >= 0; --j) {
  4.1329 +        out.append(vars[0]);
  4.1330 +        for (int j = 1; j < numArguments; ++j) {
  4.1331              out.append(", ");
  4.1332 -            out.append(mapper.get(j));
  4.1333 +            out.append(vars[j]);
  4.1334          }
  4.1335          out.append(");");
  4.1336 -        mapper.pop(hasReturn[0] ? numArguments : numArguments + 1);
  4.1337          i += 2;
  4.1338          return i;
  4.1339      }
  4.1340 @@ -1236,4 +1593,54 @@
  4.1341          }
  4.1342          return " = null;";
  4.1343      }
  4.1344 +
  4.1345 +    private static int constantToVariableType(final byte constantTag) {
  4.1346 +        switch (constantTag) {
  4.1347 +            case CONSTANT_INTEGER:
  4.1348 +                return Variable.TYPE_INT;
  4.1349 +            case CONSTANT_FLOAT:
  4.1350 +                return Variable.TYPE_FLOAT;
  4.1351 +            case CONSTANT_LONG:
  4.1352 +                return Variable.TYPE_LONG;
  4.1353 +            case CONSTANT_DOUBLE:
  4.1354 +                return Variable.TYPE_DOUBLE;
  4.1355 +
  4.1356 +            case CONSTANT_CLASS:
  4.1357 +            case CONSTANT_UTF8:
  4.1358 +            case CONSTANT_UNICODE:
  4.1359 +            case CONSTANT_STRING:
  4.1360 +                return Variable.TYPE_REF;
  4.1361 +
  4.1362 +            case CONSTANT_FIELD:
  4.1363 +            case CONSTANT_METHOD:
  4.1364 +            case CONSTANT_INTERFACEMETHOD:
  4.1365 +            case CONSTANT_NAMEANDTYPE:
  4.1366 +                /* unclear how to handle for now */
  4.1367 +            default:
  4.1368 +                throw new IllegalStateException("Unhandled constant tag");
  4.1369 +        }
  4.1370 +    }
  4.1371 +
  4.1372 +    private static int fieldToVariableType(final char fieldType) {
  4.1373 +        switch (fieldType) {
  4.1374 +            case 'B':
  4.1375 +            case 'C':
  4.1376 +            case 'S':
  4.1377 +            case 'Z':
  4.1378 +            case 'I':
  4.1379 +                return Variable.TYPE_INT;
  4.1380 +            case 'J':
  4.1381 +                return Variable.TYPE_LONG;
  4.1382 +            case 'F':
  4.1383 +                return Variable.TYPE_FLOAT;
  4.1384 +            case 'D':
  4.1385 +                return Variable.TYPE_DOUBLE;
  4.1386 +            case 'L':
  4.1387 +            case '[':
  4.1388 +                return Variable.TYPE_REF;
  4.1389 +
  4.1390 +            default:
  4.1391 +                throw new IllegalStateException("Unhandled field type");
  4.1392 +        }
  4.1393 +    }
  4.1394  }
     5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Mon Dec 03 14:44:49 2012 +0100
     5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Fri Dec 07 15:02:35 2012 +0100
     5.3 @@ -39,7 +39,10 @@
     5.4          Writer w = new BufferedWriter(new FileWriter(args[0]));
     5.5          StringArray classes = StringArray.asList(args);
     5.6          classes.delete(0);
     5.7 -        GenJS.compile(w, classes);
     5.8 -        w.close();
     5.9 +        try {
    5.10 +            GenJS.compile(w, classes);
    5.11 +        } finally {
    5.12 +            w.close();
    5.13 +        }
    5.14      }
    5.15  }
     6.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java	Mon Dec 03 14:44:49 2012 +0100
     6.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java	Fri Dec 07 15:02:35 2012 +0100
     6.3 @@ -17,77 +17,214 @@
     6.4   */
     6.5  package org.apidesign.vm4brwsr;
     6.6  
     6.7 +import org.apidesign.javap.TypeArray;
     6.8 +
     6.9 +import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
    6.10 +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
    6.11 +import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
    6.12 +import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
    6.13 +import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
    6.14 +import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
    6.15 +import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
    6.16 +import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
    6.17 +import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
    6.18 +
    6.19  public final class StackToVariableMapper {
    6.20 -    private static final String VAR_NAME_PREFIX = "stack";
    6.21 -
    6.22 -    private int stackSize;
    6.23 -    private StringBuilder varNameBuilder;
    6.24 -
    6.25 -    private int maxStackSize;
    6.26 +    private final TypeArray stackTypeIndexPairs;
    6.27 +    private int[] typeCounters;
    6.28 +    private int[] typeMaxCounters;
    6.29  
    6.30      public StackToVariableMapper() {
    6.31 -        varNameBuilder = new StringBuilder(VAR_NAME_PREFIX);
    6.32 +        stackTypeIndexPairs = new TypeArray();
    6.33 +        typeCounters = new int[Variable.LAST_TYPE + 1];
    6.34 +        typeMaxCounters = new int[Variable.LAST_TYPE + 1];
    6.35      }
    6.36  
    6.37 -    public void reset(final int newStackSize) {
    6.38 -        stackSize = newStackSize;
    6.39 -        if (maxStackSize < stackSize) {
    6.40 -            maxStackSize = stackSize;
    6.41 +    public void clear() {
    6.42 +        for (int type = 0; type <= Variable.LAST_TYPE; ++type) {
    6.43 +            typeCounters[type] = 0;
    6.44 +        }
    6.45 +        stackTypeIndexPairs.clear();
    6.46 +    }
    6.47 +
    6.48 +    public void syncWithFrameStack(final TypeArray frameStack) {
    6.49 +        clear();
    6.50 +
    6.51 +        final int size = frameStack.getSize();
    6.52 +        for (int i = 0; i < size; ++i) {
    6.53 +            final int frameStackValue = frameStack.get(i);
    6.54 +            switch (frameStackValue & 0xff) {
    6.55 +                case ITEM_Integer:
    6.56 +                    pushTypeImpl(Variable.TYPE_INT);
    6.57 +                    break;
    6.58 +                case ITEM_Float:
    6.59 +                    pushTypeImpl(Variable.TYPE_FLOAT);
    6.60 +                    break;
    6.61 +                case ITEM_Double:
    6.62 +                    pushTypeImpl(Variable.TYPE_DOUBLE);
    6.63 +                    break;
    6.64 +                case ITEM_Long:
    6.65 +                    pushTypeImpl(Variable.TYPE_LONG);
    6.66 +                    break;
    6.67 +                case ITEM_Object:
    6.68 +                    pushTypeImpl(Variable.TYPE_REF);
    6.69 +                    break;
    6.70 +
    6.71 +                case ITEM_Bogus:
    6.72 +                case ITEM_Null:
    6.73 +                case ITEM_InitObject:
    6.74 +                case ITEM_NewObject:
    6.75 +                    /* unclear how to handle for now */
    6.76 +                default:
    6.77 +                    throw new IllegalStateException(
    6.78 +                                  "Unhandled frame stack type");
    6.79 +            }
    6.80          }
    6.81      }
    6.82  
    6.83 -    public void push(final int numOfElements) {
    6.84 -        stackSize += numOfElements;
    6.85 -        if (maxStackSize < stackSize) {
    6.86 -            maxStackSize = stackSize;
    6.87 +    public Variable pushI() {
    6.88 +        return pushT(Variable.TYPE_INT);
    6.89 +    }
    6.90 +
    6.91 +    public Variable pushL() {
    6.92 +        return pushT(Variable.TYPE_LONG);
    6.93 +    }
    6.94 +
    6.95 +    public Variable pushF() {
    6.96 +        return pushT(Variable.TYPE_FLOAT);
    6.97 +    }
    6.98 +
    6.99 +    public Variable pushD() {
   6.100 +        return pushT(Variable.TYPE_DOUBLE);
   6.101 +    }
   6.102 +
   6.103 +    public Variable pushA() {
   6.104 +        return pushT(Variable.TYPE_REF);
   6.105 +    }
   6.106 +
   6.107 +    public Variable pushT(final int type) {
   6.108 +        return getVariable(pushTypeImpl(type));
   6.109 +    }
   6.110 +
   6.111 +    public Variable popI() {
   6.112 +        return popT(Variable.TYPE_INT);
   6.113 +    }
   6.114 +
   6.115 +    public Variable popL() {
   6.116 +        return popT(Variable.TYPE_LONG);
   6.117 +    }
   6.118 +
   6.119 +    public Variable popF() {
   6.120 +        return popT(Variable.TYPE_FLOAT);
   6.121 +    }
   6.122 +
   6.123 +    public Variable popD() {
   6.124 +        return popT(Variable.TYPE_DOUBLE);
   6.125 +    }
   6.126 +
   6.127 +    public Variable popA() {
   6.128 +        return popT(Variable.TYPE_REF);
   6.129 +    }
   6.130 +
   6.131 +    public Variable popT(final int type) {
   6.132 +        final Variable variable = getT(0, type);
   6.133 +        popImpl(1);
   6.134 +        return variable;
   6.135 +    }
   6.136 +
   6.137 +    public Variable pop() {
   6.138 +        final Variable variable = get(0);
   6.139 +        popImpl(1);
   6.140 +        return variable;
   6.141 +    }
   6.142 +
   6.143 +    public void pop(final int count) {
   6.144 +        final int stackSize = stackTypeIndexPairs.getSize();
   6.145 +        if (count > stackSize) {
   6.146 +            throw new IllegalStateException("Stack underflow");
   6.147 +        }
   6.148 +        popImpl(count);
   6.149 +    }
   6.150 +
   6.151 +    public Variable getI(final int indexFromTop) {
   6.152 +        return getT(indexFromTop, Variable.TYPE_INT);
   6.153 +    }
   6.154 +
   6.155 +    public Variable getL(final int indexFromTop) {
   6.156 +        return getT(indexFromTop, Variable.TYPE_LONG);
   6.157 +    }
   6.158 +
   6.159 +    public Variable getF(final int indexFromTop) {
   6.160 +        return getT(indexFromTop, Variable.TYPE_FLOAT);
   6.161 +    }
   6.162 +
   6.163 +    public Variable getD(final int indexFromTop) {
   6.164 +        return getT(indexFromTop, Variable.TYPE_DOUBLE);
   6.165 +    }
   6.166 +
   6.167 +    public Variable getA(final int indexFromTop) {
   6.168 +        return getT(indexFromTop, Variable.TYPE_REF);
   6.169 +    }
   6.170 +
   6.171 +    public Variable getT(final int indexFromTop, final int type) {
   6.172 +        final int stackSize = stackTypeIndexPairs.getSize();
   6.173 +        if (indexFromTop >= stackSize) {
   6.174 +            throw new IllegalStateException("Stack underflow");
   6.175 +        }
   6.176 +        final int stackValue =
   6.177 +                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   6.178 +        if ((stackValue & 0xff) != type) {
   6.179 +            throw new IllegalStateException("Type mismatch");
   6.180 +        }
   6.181 +
   6.182 +        return getVariable(stackValue);
   6.183 +    }
   6.184 +
   6.185 +    public Variable get(final int indexFromTop) {
   6.186 +        final int stackSize = stackTypeIndexPairs.getSize();
   6.187 +        if (indexFromTop >= stackSize) {
   6.188 +            throw new IllegalStateException("Stack underflow");
   6.189 +        }
   6.190 +        final int stackValue =
   6.191 +                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   6.192 +
   6.193 +        return getVariable(stackValue);
   6.194 +    }
   6.195 +
   6.196 +    private int pushTypeImpl(final int type) {
   6.197 +        final int count = typeCounters[type];
   6.198 +        final int value = (count << 8) | (type & 0xff);
   6.199 +        incCounter(type);
   6.200 +        stackTypeIndexPairs.add(value);
   6.201 +
   6.202 +        return value;
   6.203 +    }
   6.204 +
   6.205 +    private void popImpl(final int count) {
   6.206 +        final int stackSize = stackTypeIndexPairs.getSize();
   6.207 +        for (int i = stackSize - count; i < stackSize; ++i) {
   6.208 +            final int value = stackTypeIndexPairs.get(i);
   6.209 +            decCounter(value & 0xff);
   6.210 +        }
   6.211 +
   6.212 +        stackTypeIndexPairs.setSize(stackSize - count);
   6.213 +    }
   6.214 +
   6.215 +    private void incCounter(final int type) {
   6.216 +        final int newValue = ++typeCounters[type];
   6.217 +        if (typeMaxCounters[type] < newValue) {
   6.218 +            typeMaxCounters[type] = newValue;
   6.219          }
   6.220      }
   6.221  
   6.222 -    public String push() {
   6.223 -        push(1);
   6.224 -        return get(0);
   6.225 +    private void decCounter(final int type) {
   6.226 +        --typeCounters[type];
   6.227      }
   6.228  
   6.229 -    public void pop(final int numOfElements) {
   6.230 -        if (numOfElements > stackSize) {
   6.231 -            throw new IllegalStateException("Stack underflow");
   6.232 -        }
   6.233 -        stackSize -= numOfElements;
   6.234 -    }
   6.235 +    public Variable getVariable(final int typeAndIndex) {
   6.236 +        final int type = typeAndIndex & 0xff;
   6.237 +        final int index = typeAndIndex >> 8;
   6.238  
   6.239 -    public String pop() {
   6.240 -        final String variableName = get(0);
   6.241 -        pop(1);
   6.242 -        return variableName;
   6.243 -    }
   6.244 -
   6.245 -    public String get(final int indexFromTop) {
   6.246 -        if (indexFromTop >= stackSize) {
   6.247 -            throw new IllegalStateException("Stack underflow");
   6.248 -        }
   6.249 -
   6.250 -        return constructVariableName(stackSize - indexFromTop - 1);
   6.251 -    }
   6.252 -
   6.253 -    public String top() {
   6.254 -        return get(0);
   6.255 -    }
   6.256 -
   6.257 -    public String bottom() {
   6.258 -        if (stackSize == 0) {
   6.259 -            throw new IllegalStateException("Stack underflow");
   6.260 -        }
   6.261 -
   6.262 -        return constructVariableName(0);
   6.263 -    }
   6.264 -
   6.265 -    public int getMaxStackSize() {
   6.266 -        return maxStackSize;
   6.267 -    }
   6.268 -
   6.269 -    public String constructVariableName(final int index) {
   6.270 -        varNameBuilder.setLength(VAR_NAME_PREFIX.length());
   6.271 -        varNameBuilder.append(index);
   6.272 -        return varNameBuilder.toString();
   6.273 +        return Variable.getStackVariable(type, index);
   6.274      }
   6.275  }
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Variable.java	Fri Dec 07 15:02:35 2012 +0100
     7.3 @@ -0,0 +1,101 @@
     7.4 +/**
     7.5 + * Back 2 Browser Bytecode Translator
     7.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU General Public License
    7.18 + * along with this program. Look for COPYING file in the top folder.
    7.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 + */
    7.21 +package org.apidesign.vm4brwsr;
    7.22 +
    7.23 +public final class Variable implements CharSequence {
    7.24 +    public static final int TYPE_INT = 0;
    7.25 +    public static final int TYPE_LONG = 1;
    7.26 +    public static final int TYPE_FLOAT = 2;
    7.27 +    public static final int TYPE_DOUBLE = 3;
    7.28 +    public static final int TYPE_REF = 4;
    7.29 +
    7.30 +    public static final int LAST_TYPE = TYPE_REF;
    7.31 +
    7.32 +    private static final String STACK_VAR_PREFIX = "st";
    7.33 +
    7.34 +    private final String name;
    7.35 +    private final int type;
    7.36 +    private final int index;
    7.37 +
    7.38 +    private static final char[] TYPE_IDS = { 'I', 'L', 'F', 'D', 'A' };
    7.39 +
    7.40 +    private Variable(final String prefix, final int type, final int index) {
    7.41 +        this.name = prefix + TYPE_IDS[type] + index;
    7.42 +        this.type = type;
    7.43 +        this.index = index;
    7.44 +    }
    7.45 +
    7.46 +    public static Variable getStackVariable(
    7.47 +            final int type, final int index) {
    7.48 +        // TODO: precreate frequently used variables
    7.49 +        return new Variable(STACK_VAR_PREFIX, type, index);
    7.50 +    }
    7.51 +
    7.52 +    public String getName() {
    7.53 +        return name;
    7.54 +    }
    7.55 +
    7.56 +    public int getType() {
    7.57 +        return type;
    7.58 +    }
    7.59 +
    7.60 +    public int getIndex() {
    7.61 +        return index;
    7.62 +    }
    7.63 +
    7.64 +    public boolean isCategory2() {
    7.65 +        return (type == TYPE_LONG) || (type == TYPE_DOUBLE);
    7.66 +    }
    7.67 +
    7.68 +    @Override
    7.69 +    public int length() {
    7.70 +        return name.length();
    7.71 +    }
    7.72 +
    7.73 +    @Override
    7.74 +    public char charAt(final int index) {
    7.75 +        return name.charAt(index);
    7.76 +    }
    7.77 +
    7.78 +    @Override
    7.79 +    public CharSequence subSequence(final int start, final int end) {
    7.80 +        return name.subSequence(start, end);
    7.81 +    }
    7.82 +
    7.83 +    @Override
    7.84 +    public int hashCode() {
    7.85 +        return name.hashCode();
    7.86 +    }
    7.87 +
    7.88 +    @Override
    7.89 +    public boolean equals(final Object other) {
    7.90 +        if (this == other) {
    7.91 +            return true;
    7.92 +        }
    7.93 +        if (!(other instanceof Variable)) {
    7.94 +            return false;
    7.95 +        }
    7.96 +
    7.97 +        return name.equals(((Variable) other).name);
    7.98 +    }
    7.99 +
   7.100 +    @Override
   7.101 +    public String toString() {
   7.102 +        return name;
   7.103 +    }
   7.104 +}