Type specific local variables registers
authorLubomir Nerad <lubomir.nerad@oracle.com>
Wed, 12 Dec 2012 11:04:02 +0100
branchregisters
changeset 307eaf4e8387065
parent 283 51043a802035
child 310 ec7d8bc17725
Type specific local variables
javap/src/main/java/org/apidesign/javap/MethodData.java
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/LocalsMapper.java
vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java
vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java
vm/src/main/java/org/apidesign/vm4brwsr/VarType.java
vm/src/main/java/org/apidesign/vm4brwsr/Variable.java
     1.1 --- a/javap/src/main/java/org/apidesign/javap/MethodData.java	Fri Dec 07 19:16:21 2012 +0100
     1.2 +++ b/javap/src/main/java/org/apidesign/javap/MethodData.java	Wed Dec 12 11:04:02 2012 +0100
     1.3 @@ -318,7 +318,7 @@
     1.4      }
     1.5  
     1.6      public StackMapIterator createStackMapIterator() {
     1.7 -        return new StackMapIterator(stackMapTable);
     1.8 +        return new StackMapIterator(this);
     1.9      }
    1.10  
    1.11      /**
     2.1 --- a/javap/src/main/java/org/apidesign/javap/StackMapIterator.java	Fri Dec 07 19:16:21 2012 +0100
     2.2 +++ b/javap/src/main/java/org/apidesign/javap/StackMapIterator.java	Wed Dec 12 11:04:02 2012 +0100
     2.3 @@ -25,23 +25,15 @@
     2.4  
     2.5  package org.apidesign.javap;
     2.6  
     2.7 +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
     2.8 +import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
     2.9 +import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
    2.10 +import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
    2.11 +import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
    2.12 +
    2.13  public final class StackMapIterator {
    2.14 -    private static final StackMapTableData INITIAL_FRAME =
    2.15 -            new StackMapTableData(-1) {
    2.16 -                @Override
    2.17 -                void applyTo(TypeArray localTypes, TypeArray stackTypes) {
    2.18 -                    localTypes.clear();
    2.19 -                    stackTypes.clear();
    2.20 -                }
    2.21 -
    2.22 -                @Override
    2.23 -                public String toString() {
    2.24 -                    return toString("INITIAL", 0, null, null);
    2.25 -                }
    2.26 -
    2.27 -            };
    2.28 -
    2.29      private final StackMapTableData[] stackMapTable;
    2.30 +    private final TypeArray argTypes;
    2.31      private final TypeArray localTypes;
    2.32      private final TypeArray stackTypes;
    2.33  
    2.34 @@ -50,19 +42,33 @@
    2.35  
    2.36      private int byteCodeOffset;
    2.37  
    2.38 -    StackMapIterator(final StackMapTableData[] stackMapTable) {
    2.39 +    StackMapIterator(final MethodData methodData) {
    2.40 +        this(methodData.getStackMapTable(),
    2.41 +             methodData.getInternalSig(),
    2.42 +             methodData.isStatic());
    2.43 +    }
    2.44 +
    2.45 +    StackMapIterator(final StackMapTableData[] stackMapTable,
    2.46 +                     final String methodSignature,
    2.47 +                     final boolean isStaticMethod) {
    2.48          this.stackMapTable = (stackMapTable != null)
    2.49                                   ? stackMapTable
    2.50                                   : new StackMapTableData[0];
    2.51  
    2.52 +        argTypes = getArgTypes(methodSignature, isStaticMethod);
    2.53          localTypes = new TypeArray();
    2.54          stackTypes = new TypeArray();
    2.55 +
    2.56 +        localTypes.addAll(argTypes);
    2.57 +
    2.58          lastFrameByteCodeOffset = -1;
    2.59          advanceBy(0);
    2.60      }
    2.61  
    2.62      public String getFrameAsString() {
    2.63 -        return getCurrentFrame().toString();
    2.64 +        return (nextFrameIndex == 0)
    2.65 +                   ? StackMapTableData.toString("INITIAL", 0, null, null)
    2.66 +                   : stackMapTable[nextFrameIndex - 1].toString();
    2.67      }
    2.68  
    2.69      public int getFrameIndex() {
    2.70 @@ -73,6 +79,14 @@
    2.71          return stackTypes;
    2.72      }
    2.73  
    2.74 +    public TypeArray getFrameLocals() {
    2.75 +        return localTypes;
    2.76 +    }
    2.77 +
    2.78 +    public TypeArray getArguments() {
    2.79 +        return argTypes;
    2.80 +    }
    2.81 +
    2.82      public void advanceBy(final int numByteCodes) {
    2.83          if (numByteCodes < 0) {
    2.84              throw new IllegalStateException("Forward only iterator");
    2.85 @@ -96,9 +110,70 @@
    2.86          advanceBy(nextByteCodeOffset - byteCodeOffset);
    2.87      }
    2.88  
    2.89 -    private StackMapTableData getCurrentFrame() {
    2.90 -        return (nextFrameIndex == 0)
    2.91 -                ? INITIAL_FRAME
    2.92 -                : stackMapTable[nextFrameIndex - 1];
    2.93 +    private static TypeArray getArgTypes(final String methodSignature,
    2.94 +                                         final boolean isStaticMethod) {
    2.95 +        final TypeArray argTypes = new TypeArray();
    2.96 +
    2.97 +        if (!isStaticMethod) {
    2.98 +            argTypes.add(ITEM_Object);
    2.99 +        }
   2.100 +
   2.101 +        if (methodSignature.charAt(0) != '(') {
   2.102 +            throw new IllegalArgumentException("Invalid method signature");
   2.103 +        }
   2.104 +
   2.105 +        final int length = methodSignature.length();
   2.106 +        int skipType = 0;
   2.107 +        int argType;
   2.108 +        for (int i = 1; i < length; ++i) {
   2.109 +            switch (methodSignature.charAt(i)) {
   2.110 +                case 'B':
   2.111 +                case 'C':
   2.112 +                case 'S':
   2.113 +                case 'Z':
   2.114 +                case 'I':
   2.115 +                    argType = ITEM_Integer;
   2.116 +                    break;
   2.117 +                case 'J':
   2.118 +                    argType = ITEM_Long;
   2.119 +                    break;
   2.120 +                case 'F':
   2.121 +                    argType = ITEM_Float;
   2.122 +                    break;
   2.123 +                case 'D':
   2.124 +                    argType = ITEM_Double;
   2.125 +                    break;
   2.126 +                case 'L': {
   2.127 +                    i = methodSignature.indexOf(';', i + 1);
   2.128 +                    if (i == -1) {
   2.129 +                        throw new IllegalArgumentException(
   2.130 +                                      "Invalid method signature");
   2.131 +                    }
   2.132 +                    argType = ITEM_Object;
   2.133 +                    break;
   2.134 +                }
   2.135 +                case ')':
   2.136 +                    // not interested in the return value type
   2.137 +                    return argTypes;
   2.138 +                case '[':
   2.139 +                    if (skipType == 0) {
   2.140 +                        argTypes.add(ITEM_Object);
   2.141 +                    }
   2.142 +                    ++skipType;
   2.143 +                    continue;
   2.144 +
   2.145 +                default:
   2.146 +                    throw new IllegalArgumentException(
   2.147 +                                  "Invalid method signature");
   2.148 +            }
   2.149 +
   2.150 +            if (skipType == 0) {
   2.151 +                argTypes.add(argType);
   2.152 +            } else {
   2.153 +                --skipType;
   2.154 +            }
   2.155 +        }
   2.156 +
   2.157 +        return argTypes;
   2.158      }
   2.159  }
     3.1 --- a/javap/src/main/java/org/apidesign/javap/StackMapTableData.java	Fri Dec 07 19:16:21 2012 +0100
     3.2 +++ b/javap/src/main/java/org/apidesign/javap/StackMapTableData.java	Wed Dec 12 11:04:02 2012 +0100
     3.3 @@ -66,50 +66,15 @@
     3.4      private static void appendTypes(final StringBuilder sb, final int[] types) {
     3.5          sb.append('[');
     3.6          if (types.length > 0) {
     3.7 -            appendType(sb, types[0]);
     3.8 +            sb.append(TypeArray.typeString(types[0]));
     3.9              for (int i = 1; i < types.length; ++i) {
    3.10                  sb.append(", ");
    3.11 -                appendType(sb, types[i]);
    3.12 +                sb.append(TypeArray.typeString(types[i]));
    3.13              }
    3.14          }
    3.15          sb.append(']');
    3.16      }
    3.17  
    3.18 -    private static void appendType(final StringBuilder sb, final int type) {
    3.19 -        switch (type & 0xff) {
    3.20 -            case ITEM_Bogus:
    3.21 -                sb.append("_top_");
    3.22 -                break;
    3.23 -            case ITEM_Integer:
    3.24 -                sb.append("_int_");
    3.25 -                break;
    3.26 -            case ITEM_Float:
    3.27 -                sb.append("_float_");
    3.28 -                break;
    3.29 -            case ITEM_Double:
    3.30 -                sb.append("_double_");
    3.31 -                break;
    3.32 -            case ITEM_Long:
    3.33 -                sb.append("_long_");
    3.34 -                break;
    3.35 -            case ITEM_Null:
    3.36 -                sb.append("_null_");
    3.37 -                break;
    3.38 -            case ITEM_InitObject: // UninitializedThis
    3.39 -                sb.append("_init_");
    3.40 -                break;
    3.41 -            case ITEM_Object:
    3.42 -                sb.append("_object_");
    3.43 -                break;
    3.44 -            case ITEM_NewObject: // Uninitialized
    3.45 -                sb.append("_new_");
    3.46 -                break;
    3.47 -            default:
    3.48 -                sb.append("_unknown_");
    3.49 -                break;
    3.50 -        }
    3.51 -    }
    3.52 -
    3.53      static class SameFrame extends StackMapTableData {
    3.54          SameFrame(int frameType, int offsetDelta) {
    3.55              super(frameType);
     4.1 --- a/javap/src/main/java/org/apidesign/javap/TypeArray.java	Fri Dec 07 19:16:21 2012 +0100
     4.2 +++ b/javap/src/main/java/org/apidesign/javap/TypeArray.java	Wed Dec 12 11:04:02 2012 +0100
     4.3 @@ -25,38 +25,85 @@
     4.4  
     4.5  package org.apidesign.javap;
     4.6  
     4.7 -public class TypeArray {
     4.8 +import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
     4.9 +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
    4.10 +import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
    4.11 +import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
    4.12 +import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
    4.13 +import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
    4.14 +import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
    4.15 +import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
    4.16 +import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
    4.17 +
    4.18 +public final class TypeArray {
    4.19      private static final int CAPACITY_INCREMENT = 16;
    4.20  
    4.21      private int[] types;
    4.22      private int size;
    4.23  
    4.24 +    public TypeArray() {
    4.25 +    }
    4.26 +    
    4.27 +    public TypeArray(final TypeArray initialTypes) {
    4.28 +        setAll(initialTypes);
    4.29 +    }
    4.30 +
    4.31      public void add(final int newType) {
    4.32          ensureCapacity(size + 1);
    4.33          types[size++] = newType;
    4.34      }
    4.35  
    4.36 +    public void addAll(final TypeArray newTypes) {
    4.37 +        addAll(newTypes.types, 0, newTypes.size);
    4.38 +    }
    4.39 +
    4.40      public void addAll(final int[] newTypes) {
    4.41 -        if (newTypes.length > 0) {
    4.42 -            ensureCapacity(size + newTypes.length);
    4.43 -            arraycopy(newTypes, 0, types, size, newTypes.length);
    4.44 -            size += newTypes.length;
    4.45 +        addAll(newTypes, 0, newTypes.length);
    4.46 +    }
    4.47 +
    4.48 +    public void addAll(final int[] newTypes,
    4.49 +                       final int offset,
    4.50 +                       final int count) {
    4.51 +        if (count > 0) {
    4.52 +            ensureCapacity(size + count);
    4.53 +            arraycopy(newTypes, offset, types, size, count);
    4.54 +            size += count;
    4.55          }
    4.56      }
    4.57  
    4.58 +    public void set(final int index, final int newType) {
    4.59 +        types[index] = newType;
    4.60 +    }
    4.61 +
    4.62 +    public void setAll(final TypeArray newTypes) {
    4.63 +        setAll(newTypes.types, 0, newTypes.size);
    4.64 +    }
    4.65 +
    4.66      public void setAll(final int[] newTypes) {
    4.67 -        if (newTypes.length > 0) {
    4.68 -            ensureCapacity(newTypes.length);
    4.69 -            arraycopy(newTypes, 0, types, 0, newTypes.length);
    4.70 -            size = newTypes.length;
    4.71 +        setAll(newTypes, 0, newTypes.length);
    4.72 +    }
    4.73 +
    4.74 +    public void setAll(final int[] newTypes,
    4.75 +                       final int offset,
    4.76 +                       final int count) {
    4.77 +        if (count > 0) {
    4.78 +            ensureCapacity(count);
    4.79 +            arraycopy(newTypes, offset, types, 0, count);
    4.80 +            size = count;
    4.81          } else {
    4.82              clear();
    4.83          }
    4.84      }
    4.85  
    4.86      public void setSize(final int newSize) {
    4.87 -        ensureCapacity(newSize);
    4.88 -        size = newSize;
    4.89 +        if (size != newSize) {
    4.90 +            ensureCapacity(newSize);
    4.91 +
    4.92 +            for (int i = size; i < newSize; ++i) {
    4.93 +                types[i] = 0;
    4.94 +            }
    4.95 +            size = newSize;
    4.96 +        }
    4.97      }
    4.98  
    4.99      public void clear() {
   4.100 @@ -71,6 +118,45 @@
   4.101          return types[index];
   4.102      }
   4.103  
   4.104 +    public static String typeString(final int type) {
   4.105 +        switch (type & 0xff) {
   4.106 +            case ITEM_Bogus:
   4.107 +                return "_top_";
   4.108 +            case ITEM_Integer:
   4.109 +                return "_int_";
   4.110 +            case ITEM_Float:
   4.111 +                return "_float_";
   4.112 +            case ITEM_Double:
   4.113 +                return "_double_";
   4.114 +            case ITEM_Long:
   4.115 +                return "_long_";
   4.116 +            case ITEM_Null:
   4.117 +                return "_null_";
   4.118 +            case ITEM_InitObject: // UninitializedThis
   4.119 +                return "_init_";
   4.120 +            case ITEM_Object:
   4.121 +                return "_object_";
   4.122 +            case ITEM_NewObject: // Uninitialized
   4.123 +                return "_new_";
   4.124 +            default:
   4.125 +                throw new IllegalArgumentException("Unknown type");
   4.126 +        }
   4.127 +    }
   4.128 +
   4.129 +    @Override
   4.130 +    public String toString() {
   4.131 +        final StringBuilder sb = new StringBuilder("[");
   4.132 +        if (size > 0) {
   4.133 +            sb.append(typeString(types[0]));
   4.134 +            for (int i = 1; i < size; ++i) {
   4.135 +                sb.append(", ");
   4.136 +                sb.append(typeString(types[i]));
   4.137 +            }
   4.138 +        }
   4.139 +
   4.140 +        return sb.append(']').toString();
   4.141 +    }
   4.142 +
   4.143      private void ensureCapacity(final int minCapacity) {
   4.144          if ((minCapacity == 0)
   4.145                  || (types != null) && (minCapacity <= types.length)) {
     5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Dec 07 19:16:21 2012 +0100
     5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Dec 12 11:04:02 2012 +0100
     5.3 @@ -188,85 +188,63 @@
     5.4          if (jsb != null) {
     5.5              return jsb;
     5.6          }
     5.7 -        StringBuilder argsCnt = new StringBuilder();
     5.8 -        final String mn = findMethodName(m, argsCnt);
     5.9 -        out.append(prefix).append(mn).append(" = function");
    5.10 +        final String mn = findMethodName(m, new StringBuilder());
    5.11          if (mn.equals("class__V")) {
    5.12              toInitilize.add(className(jc) + "(false)." + mn);
    5.13          }
    5.14 -        out.append('(');
    5.15 -        String space = "";
    5.16 -        for (int index = 0, i = 0; i < argsCnt.length(); i++) {
    5.17 -            out.append(space);
    5.18 -            out.append("arg").append(String.valueOf(index));
    5.19 -            space = ",";
    5.20 -            final String desc = null;// XXX findDescriptor(args.get(i).getDescriptor());
    5.21 -            if (argsCnt.charAt(i) == '1') {
    5.22 -                index += 2;
    5.23 -            } else {
    5.24 -                index++;
    5.25 -            }
    5.26 -        }
    5.27 -        out.append(") {").append("\n");
    5.28 -        if (m.getCode() != null) {
    5.29 -            int len = m.getMaxLocals();
    5.30 -            for (int i = argsCnt.length(); i < len; i++) {
    5.31 -                out.append("  var ");
    5.32 -                out.append("arg").append(String.valueOf(i)).append(";\n");
    5.33 -            }
    5.34 -            produceCode(m);
    5.35 -        } else {
    5.36 -            out.append("  throw 'no code found for ").append(m.getInternalSig()).append("';\n");
    5.37 -        }
    5.38 -        out.append("};");
    5.39 +        generateMethod(prefix, mn, m);
    5.40          return mn;
    5.41      }
    5.42 -    
    5.43 +
    5.44      private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
    5.45          String jsb = javaScriptBody(prefix, m, false);
    5.46          if (jsb != null) {
    5.47              return jsb;
    5.48          }
    5.49 -        StringBuilder argsCnt = new StringBuilder();
    5.50 -        final String mn = findMethodName(m, argsCnt);
    5.51 -        out.append(prefix).append(mn).append(" = function");
    5.52 -        out.append("(arg0");
    5.53 -        String space = ",";
    5.54 -        for (int index = 1, i = 0; i < argsCnt.length(); i++) {
    5.55 -            out.append(space);
    5.56 -            out.append("arg").append(String.valueOf(index));
    5.57 -            if (argsCnt.charAt(i) == '1') {
    5.58 -                index += 2;
    5.59 -            } else {
    5.60 -                index++;
    5.61 -            }
    5.62 -        }
    5.63 -        out.append(") {").append("\n");
    5.64 -        if (m.getCode() != null) {
    5.65 -            int len = m.getMaxLocals();
    5.66 -            for (int i = argsCnt.length(); i < len; i++) {
    5.67 -                out.append("  var ");
    5.68 -                out.append("arg").append(String.valueOf(i + 1)).append(";\n");
    5.69 -            }
    5.70 -            produceCode(m);
    5.71 -        } else {
    5.72 -            out.append("  throw 'no code found for ").append(m.getInternalSig()).append("';\n");
    5.73 -        }
    5.74 -        out.append("};");
    5.75 +        final String mn = findMethodName(m, new StringBuilder());
    5.76 +        generateMethod(prefix, mn, m);
    5.77          return mn;
    5.78      }
    5.79  
    5.80 -    private void produceCode(MethodData m) throws IOException {
    5.81 +    private void generateMethod(String prefix, String name, MethodData m)
    5.82 +            throws IOException {
    5.83 +        final StackMapIterator stackMapIterator = m.createStackMapIterator();
    5.84 +        final LocalsMapper lmapper =
    5.85 +                new LocalsMapper(stackMapIterator.getArguments());
    5.86 +
    5.87 +        out.append(prefix).append(name).append(" = function(");
    5.88 +        lmapper.outputArguments(out);
    5.89 +        out.append(") {").append("\n");
    5.90 +
    5.91          final byte[] byteCodes = m.getCode();
    5.92 -        final StackMapIterator stackMapIterator = m.createStackMapIterator();
    5.93 -        final StackToVariableMapper mapper = new StackToVariableMapper();
    5.94 +        if (byteCodes == null) {
    5.95 +            out.append("  throw 'no code found for ")
    5.96 +               .append(m.getInternalSig()).append("';\n");
    5.97 +            out.append("};");
    5.98 +            return;
    5.99 +        }
   5.100 +
   5.101 +        final StackMapper smapper = new StackMapper();
   5.102 +
   5.103 +        final int maxLocals = m.getMaxLocals();
   5.104 +        if (maxLocals > 0) {
   5.105 +            // TODO: generate only used local variables
   5.106 +            for (int j = 0; j <= VarType.LAST; ++j) {
   5.107 +                out.append("\n  var ").append(Variable.getLocalVariable(j, 0));
   5.108 +                for (int i = 1; i < maxLocals; ++i) {
   5.109 +                    out.append(", ");
   5.110 +                    out.append(Variable.getLocalVariable(j, i));
   5.111 +                }
   5.112 +                out.append(';');
   5.113 +            }
   5.114 +        }
   5.115  
   5.116          // maxStack includes two stack positions for every pushed long / double
   5.117          // so this might generate more stack variables than we need
   5.118          final int maxStack = m.getMaxStack();
   5.119          if (maxStack > 0) {
   5.120              // TODO: generate only used stack variables
   5.121 -            for (int j = 0; j <= Variable.LAST_TYPE; ++j) {
   5.122 +            for (int j = 0; j <= VarType.LAST; ++j) {
   5.123                  out.append("\n  var ").append(Variable.getStackVariable(j, 0));
   5.124                  for (int i = 1; i < maxStack; ++i) {
   5.125                      out.append(", ");
   5.126 @@ -284,7 +262,8 @@
   5.127              stackMapIterator.advanceTo(i);
   5.128              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
   5.129                  lastStackFrame = stackMapIterator.getFrameIndex();
   5.130 -                mapper.syncWithFrameStack(stackMapIterator.getFrameStack());
   5.131 +                lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
   5.132 +                smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
   5.133                  out.append("    case " + i).append(": ");
   5.134              } else {
   5.135                  out.append("    /* " + i).append(" */ ");
   5.136 @@ -292,303 +271,293 @@
   5.137              final int c = readByte(byteCodes, i);
   5.138              switch (c) {
   5.139                  case opc_aload_0:
   5.140 -                    emit(out, "@1 = arg0;", mapper.pushA());
   5.141 +                    emit(out, "@1 = @2;", smapper.pushA(), lmapper.getA(0));
   5.142                      break;
   5.143                  case opc_iload_0:
   5.144 -                    emit(out, "@1 = arg0;", mapper.pushI());
   5.145 +                    emit(out, "@1 = @2;", smapper.pushI(), lmapper.getI(0));
   5.146                      break;
   5.147                  case opc_lload_0:
   5.148 -                    emit(out, "@1 = arg0;", mapper.pushL());
   5.149 +                    emit(out, "@1 = @2;", smapper.pushL(), lmapper.getL(0));
   5.150                      break;
   5.151                  case opc_fload_0:
   5.152 -                    emit(out, "@1 = arg0;", mapper.pushF());
   5.153 +                    emit(out, "@1 = @2;", smapper.pushF(), lmapper.getF(0));
   5.154                      break;
   5.155                  case opc_dload_0:
   5.156 -                    emit(out, "@1 = arg0;", mapper.pushD());
   5.157 +                    emit(out, "@1 = @2;", smapper.pushD(), lmapper.getD(0));
   5.158                      break;
   5.159                  case opc_aload_1:
   5.160 -                    emit(out, "@1 = arg1;", mapper.pushA());
   5.161 +                    emit(out, "@1 = @2;", smapper.pushA(), lmapper.getA(1));
   5.162                      break;
   5.163                  case opc_iload_1:
   5.164 -                    emit(out, "@1 = arg1;", mapper.pushI());
   5.165 +                    emit(out, "@1 = @2;", smapper.pushI(), lmapper.getI(1));
   5.166                      break;
   5.167                  case opc_lload_1:
   5.168 -                    emit(out, "@1 = arg1;", mapper.pushL());
   5.169 +                    emit(out, "@1 = @2;", smapper.pushL(), lmapper.getL(1));
   5.170                      break;
   5.171                  case opc_fload_1:
   5.172 -                    emit(out, "@1 = arg1;", mapper.pushF());
   5.173 +                    emit(out, "@1 = @2;", smapper.pushF(), lmapper.getF(1));
   5.174                      break;
   5.175                  case opc_dload_1:
   5.176 -                    emit(out, "@1 = arg1;", mapper.pushD());
   5.177 +                    emit(out, "@1 = @2;", smapper.pushD(), lmapper.getD(1));
   5.178                      break;
   5.179                  case opc_aload_2:
   5.180 -                    emit(out, "@1 = arg2;", mapper.pushA());
   5.181 +                    emit(out, "@1 = @2;", smapper.pushA(), lmapper.getA(2));
   5.182                      break;
   5.183                  case opc_iload_2:
   5.184 -                    emit(out, "@1 = arg2;", mapper.pushI());
   5.185 +                    emit(out, "@1 = @2;", smapper.pushI(), lmapper.getI(2));
   5.186                      break;
   5.187                  case opc_lload_2:
   5.188 -                    emit(out, "@1 = arg2;", mapper.pushL());
   5.189 +                    emit(out, "@1 = @2;", smapper.pushL(), lmapper.getL(2));
   5.190                      break;
   5.191                  case opc_fload_2:
   5.192 -                    emit(out, "@1 = arg2;", mapper.pushF());
   5.193 +                    emit(out, "@1 = @2;", smapper.pushF(), lmapper.getF(2));
   5.194                      break;
   5.195                  case opc_dload_2:
   5.196 -                    emit(out, "@1 = arg2;", mapper.pushD());
   5.197 +                    emit(out, "@1 = @2;", smapper.pushD(), lmapper.getD(2));
   5.198                      break;
   5.199                  case opc_aload_3:
   5.200 -                    emit(out, "@1 = arg3;", mapper.pushA());
   5.201 +                    emit(out, "@1 = @2;", smapper.pushA(), lmapper.getA(3));
   5.202                      break;
   5.203                  case opc_iload_3:
   5.204 -                    emit(out, "@1 = arg3;", mapper.pushI());
   5.205 +                    emit(out, "@1 = @2;", smapper.pushI(), lmapper.getI(3));
   5.206                      break;
   5.207                  case opc_lload_3:
   5.208 -                    emit(out, "@1 = arg3;", mapper.pushL());
   5.209 +                    emit(out, "@1 = @2;", smapper.pushL(), lmapper.getL(3));
   5.210                      break;
   5.211                  case opc_fload_3:
   5.212 -                    emit(out, "@1 = arg3;", mapper.pushF());
   5.213 +                    emit(out, "@1 = @2;", smapper.pushF(), lmapper.getF(3));
   5.214                      break;
   5.215                  case opc_dload_3:
   5.216 -                    emit(out, "@1 = arg3;", mapper.pushD());
   5.217 +                    emit(out, "@1 = @2;", smapper.pushD(), lmapper.getD(3));
   5.218                      break;
   5.219                  case opc_iload: {
   5.220                      final int indx = readByte(byteCodes, ++i);
   5.221 -                    emit(out, "@1 = arg@2;",
   5.222 -                         mapper.pushI(), Integer.toString(indx));
   5.223 +                    emit(out, "@1 = @2;", smapper.pushI(), lmapper.getI(indx));
   5.224                      break;
   5.225                  }
   5.226                  case opc_lload: {
   5.227                      final int indx = readByte(byteCodes, ++i);
   5.228 -                    emit(out, "@1 = arg@2;",
   5.229 -                         mapper.pushL(), Integer.toString(indx));
   5.230 +                    emit(out, "@1 = @2;", smapper.pushL(), lmapper.getL(indx));
   5.231                      break;
   5.232                  }
   5.233                  case opc_fload: {
   5.234                      final int indx = readByte(byteCodes, ++i);
   5.235 -                    emit(out, "@1 = arg@2;",
   5.236 -                         mapper.pushF(), Integer.toString(indx));
   5.237 +                    emit(out, "@1 = @2;", smapper.pushF(), lmapper.getF(indx));
   5.238                      break;
   5.239                  }
   5.240                  case opc_dload: {
   5.241                      final int indx = readByte(byteCodes, ++i);
   5.242 -                    emit(out, "@1 = arg@2;",
   5.243 -                         mapper.pushD(), Integer.toString(indx));
   5.244 +                    emit(out, "@1 = @2;", smapper.pushD(), lmapper.getD(indx));
   5.245                      break;
   5.246                  }
   5.247                  case opc_aload: {
   5.248                      final int indx = readByte(byteCodes, ++i);
   5.249 -                    emit(out, "@1 = arg@2;",
   5.250 -                         mapper.pushA(), Integer.toString(indx));
   5.251 +                    emit(out, "@1 = @2;", smapper.pushA(), lmapper.getA(indx));
   5.252                      break;
   5.253                  }
   5.254                  case opc_istore: {
   5.255                      final int indx = readByte(byteCodes, ++i);
   5.256 -                    emit(out, "arg@1 = @2;",
   5.257 -                         Integer.toString(indx), mapper.popI());
   5.258 +                    emit(out, "@1 = @2;", lmapper.setI(indx), smapper.popI());
   5.259                      break;
   5.260                  }
   5.261                  case opc_lstore: {
   5.262                      final int indx = readByte(byteCodes, ++i);
   5.263 -                    emit(out, "arg@1 = @2;",
   5.264 -                         Integer.toString(indx), mapper.popL());
   5.265 +                    emit(out, "@1 = @2;", lmapper.setL(indx), smapper.popL());
   5.266                      break;
   5.267                  }
   5.268                  case opc_fstore: {
   5.269                      final int indx = readByte(byteCodes, ++i);
   5.270 -                    emit(out, "arg@1 = @2;",
   5.271 -                         Integer.toString(indx), mapper.popF());
   5.272 +                    emit(out, "@1 = @2;", lmapper.setF(indx), smapper.popF());
   5.273                      break;
   5.274                  }
   5.275                  case opc_dstore: {
   5.276                      final int indx = readByte(byteCodes, ++i);
   5.277 -                    emit(out, "arg@1 = @2;",
   5.278 -                         Integer.toString(indx), mapper.popD());
   5.279 +                    emit(out, "@1 = @2;", lmapper.setD(indx), smapper.popD());
   5.280                      break;
   5.281                  }
   5.282                  case opc_astore: {
   5.283                      final int indx = readByte(byteCodes, ++i);
   5.284 -                    emit(out, "arg@1 = @2;",
   5.285 -                         Integer.toString(indx), mapper.popA());
   5.286 +                    emit(out, "@1 = @2;", lmapper.setA(indx), smapper.popA());
   5.287                      break;
   5.288                  }
   5.289                  case opc_astore_0:
   5.290 -                    emit(out, "arg0 = @1;", mapper.popA());
   5.291 +                    emit(out, "@1 = @2;", lmapper.setA(0), smapper.popA());
   5.292                      break;
   5.293                  case opc_istore_0:
   5.294 -                    emit(out, "arg0 = @1;", mapper.popI());
   5.295 +                    emit(out, "@1 = @2;", lmapper.setI(0), smapper.popI());
   5.296                      break;
   5.297                  case opc_lstore_0:
   5.298 -                    emit(out, "arg0 = @1;", mapper.popL());
   5.299 +                    emit(out, "@1 = @2;", lmapper.setL(0), smapper.popL());
   5.300                      break;
   5.301                  case opc_fstore_0:
   5.302 -                    emit(out, "arg0 = @1;", mapper.popF());
   5.303 +                    emit(out, "@1 = @2;", lmapper.setF(0), smapper.popF());
   5.304                      break;
   5.305                  case opc_dstore_0:
   5.306 -                    emit(out, "arg0 = @1;", mapper.popD());
   5.307 +                    emit(out, "@1 = @2;", lmapper.setD(0), smapper.popD());
   5.308                      break;
   5.309                  case opc_astore_1:
   5.310 -                    emit(out, "arg1 = @1;", mapper.popA());
   5.311 +                    emit(out, "@1 = @2;", lmapper.setA(1), smapper.popA());
   5.312                      break;
   5.313                  case opc_istore_1:
   5.314 -                    emit(out, "arg1 = @1;", mapper.popI());
   5.315 +                    emit(out, "@1 = @2;", lmapper.setI(1), smapper.popI());
   5.316                      break;
   5.317                  case opc_lstore_1:
   5.318 -                    emit(out, "arg1 = @1;", mapper.popL());
   5.319 +                    emit(out, "@1 = @2;", lmapper.setL(1), smapper.popL());
   5.320                      break;
   5.321                  case opc_fstore_1:
   5.322 -                    emit(out, "arg1 = @1;", mapper.popF());
   5.323 +                    emit(out, "@1 = @2;", lmapper.setF(1), smapper.popF());
   5.324                      break;
   5.325                  case opc_dstore_1:
   5.326 -                    emit(out, "arg1 = @1;", mapper.popD());
   5.327 +                    emit(out, "@1 = @2;", lmapper.setD(1), smapper.popD());
   5.328                      break;
   5.329                  case opc_astore_2:
   5.330 -                    emit(out, "arg2 = @1;", mapper.popA());
   5.331 +                    emit(out, "@1 = @2;", lmapper.setA(2), smapper.popA());
   5.332                      break;
   5.333                  case opc_istore_2:
   5.334 -                    emit(out, "arg2 = @1;", mapper.popI());
   5.335 +                    emit(out, "@1 = @2;", lmapper.setI(2), smapper.popI());
   5.336                      break;
   5.337                  case opc_lstore_2:
   5.338 -                    emit(out, "arg2 = @1;", mapper.popL());
   5.339 +                    emit(out, "@1 = @2;", lmapper.setL(2), smapper.popL());
   5.340                      break;
   5.341                  case opc_fstore_2:
   5.342 -                    emit(out, "arg2 = @1;", mapper.popF());
   5.343 +                    emit(out, "@1 = @2;", lmapper.setF(2), smapper.popF());
   5.344                      break;
   5.345                  case opc_dstore_2:
   5.346 -                    emit(out, "arg2 = @1;", mapper.popD());
   5.347 +                    emit(out, "@1 = @2;", lmapper.setD(2), smapper.popD());
   5.348                      break;
   5.349                  case opc_astore_3:
   5.350 -                    emit(out, "arg3 = @1;", mapper.popA());
   5.351 +                    emit(out, "@1 = @2;", lmapper.setA(3), smapper.popA());
   5.352                      break;
   5.353                  case opc_istore_3:
   5.354 -                    emit(out, "arg3 = @1;", mapper.popI());
   5.355 +                    emit(out, "@1 = @2;", lmapper.setI(3), smapper.popI());
   5.356                      break;
   5.357                  case opc_lstore_3:
   5.358 -                    emit(out, "arg3 = @1;", mapper.popL());
   5.359 +                    emit(out, "@1 = @2;", lmapper.setL(3), smapper.popL());
   5.360                      break;
   5.361                  case opc_fstore_3:
   5.362 -                    emit(out, "arg3 = @1;", mapper.popF());
   5.363 +                    emit(out, "@1 = @2;", lmapper.setF(3), smapper.popF());
   5.364                      break;
   5.365                  case opc_dstore_3:
   5.366 -                    emit(out, "arg3 = @1;", mapper.popD());
   5.367 +                    emit(out, "@1 = @2;", lmapper.setD(3), smapper.popD());
   5.368                      break;
   5.369                  case opc_iadd:
   5.370 -                    emit(out, "@1 += @2;", mapper.getI(1), mapper.popI());
   5.371 +                    emit(out, "@1 += @2;", smapper.getI(1), smapper.popI());
   5.372                      break;
   5.373                  case opc_ladd:
   5.374 -                    emit(out, "@1 += @2;", mapper.getL(1), mapper.popL());
   5.375 +                    emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
   5.376                      break;
   5.377                  case opc_fadd:
   5.378 -                    emit(out, "@1 += @2;", mapper.getF(1), mapper.popF());
   5.379 +                    emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
   5.380                      break;
   5.381                  case opc_dadd:
   5.382 -                    emit(out, "@1 += @2;", mapper.getD(1), mapper.popD());
   5.383 +                    emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
   5.384                      break;
   5.385                  case opc_isub:
   5.386 -                    emit(out, "@1 -= @2;", mapper.getI(1), mapper.popI());
   5.387 +                    emit(out, "@1 -= @2;", smapper.getI(1), smapper.popI());
   5.388                      break;
   5.389                  case opc_lsub:
   5.390 -                    emit(out, "@1 -= @2;", mapper.getL(1), mapper.popL());
   5.391 +                    emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
   5.392                      break;
   5.393                  case opc_fsub:
   5.394 -                    emit(out, "@1 -= @2;", mapper.getF(1), mapper.popF());
   5.395 +                    emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
   5.396                      break;
   5.397                  case opc_dsub:
   5.398 -                    emit(out, "@1 -= @2;", mapper.getD(1), mapper.popD());
   5.399 +                    emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
   5.400                      break;
   5.401                  case opc_imul:
   5.402 -                    emit(out, "@1 *= @2;", mapper.getI(1), mapper.popI());
   5.403 +                    emit(out, "@1 *= @2;", smapper.getI(1), smapper.popI());
   5.404                      break;
   5.405                  case opc_lmul:
   5.406 -                    emit(out, "@1 *= @2;", mapper.getL(1), mapper.popL());
   5.407 +                    emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
   5.408                      break;
   5.409                  case opc_fmul:
   5.410 -                    emit(out, "@1 *= @2;", mapper.getF(1), mapper.popF());
   5.411 +                    emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
   5.412                      break;
   5.413                  case opc_dmul:
   5.414 -                    emit(out, "@1 *= @2;", mapper.getD(1), mapper.popD());
   5.415 +                    emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
   5.416                      break;
   5.417                  case opc_idiv:
   5.418                      emit(out, "@1 = Math.floor(@1 / @2);",
   5.419 -                         mapper.getI(1), mapper.popI());
   5.420 +                         smapper.getI(1), smapper.popI());
   5.421                      break;
   5.422                  case opc_ldiv:
   5.423                      emit(out, "@1 = Math.floor(@1 / @2);",
   5.424 -                         mapper.getL(1), mapper.popL());
   5.425 +                         smapper.getL(1), smapper.popL());
   5.426                      break;
   5.427                  case opc_fdiv:
   5.428 -                    emit(out, "@1 /= @2;", mapper.getF(1), mapper.popF());
   5.429 +                    emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
   5.430                      break;
   5.431                  case opc_ddiv:
   5.432 -                    emit(out, "@1 /= @2;", mapper.getD(1), mapper.popD());
   5.433 +                    emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
   5.434                      break;
   5.435                  case opc_irem:
   5.436 -                    emit(out, "@1 %= @2;", mapper.getI(1), mapper.popI());
   5.437 +                    emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
   5.438                      break;
   5.439                  case opc_lrem:
   5.440 -                    emit(out, "@1 %= @2;", mapper.getL(1), mapper.popL());
   5.441 +                    emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
   5.442                      break;
   5.443                  case opc_frem:
   5.444 -                    emit(out, "@1 %= @2;", mapper.getF(1), mapper.popF());
   5.445 +                    emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
   5.446                      break;
   5.447                  case opc_drem:
   5.448 -                    emit(out, "@1 %= @2;", mapper.getD(1), mapper.popD());
   5.449 +                    emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
   5.450                      break;
   5.451                  case opc_iand:
   5.452 -                    emit(out, "@1 &= @2;", mapper.getI(1), mapper.popI());
   5.453 +                    emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
   5.454                      break;
   5.455                  case opc_land:
   5.456 -                    emit(out, "@1 &= @2;", mapper.getL(1), mapper.popL());
   5.457 +                    emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
   5.458                      break;
   5.459                  case opc_ior:
   5.460 -                    emit(out, "@1 |= @2;", mapper.getI(1), mapper.popI());
   5.461 +                    emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
   5.462                      break;
   5.463                  case opc_lor:
   5.464 -                    emit(out, "@1 |= @2;", mapper.getL(1), mapper.popL());
   5.465 +                    emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL());
   5.466                      break;
   5.467                  case opc_ixor:
   5.468 -                    emit(out, "@1 ^= @2;", mapper.getI(1), mapper.popI());
   5.469 +                    emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
   5.470                      break;
   5.471                  case opc_lxor:
   5.472 -                    emit(out, "@1 ^= @2;", mapper.getL(1), mapper.popL());
   5.473 +                    emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL());
   5.474                      break;
   5.475                  case opc_ineg:
   5.476 -                    emit(out, "@1 = -@1;", mapper.getI(0));
   5.477 +                    emit(out, "@1 = -@1;", smapper.getI(0));
   5.478                      break;
   5.479                  case opc_lneg:
   5.480 -                    emit(out, "@1 = -@1;", mapper.getL(0));
   5.481 +                    emit(out, "@1 = -@1;", smapper.getL(0));
   5.482                      break;
   5.483                  case opc_fneg:
   5.484 -                    emit(out, "@1 = -@1;", mapper.getF(0));
   5.485 +                    emit(out, "@1 = -@1;", smapper.getF(0));
   5.486                      break;
   5.487                  case opc_dneg:
   5.488 -                    emit(out, "@1 = -@1;", mapper.getD(0));
   5.489 +                    emit(out, "@1 = -@1;", smapper.getD(0));
   5.490                      break;
   5.491                  case opc_ishl:
   5.492 -                    emit(out, "@1 <<= @2;", mapper.getI(1), mapper.popI());
   5.493 +                    emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
   5.494                      break;
   5.495                  case opc_lshl:
   5.496 -                    emit(out, "@1 <<= @2;", mapper.getL(1), mapper.popI());
   5.497 +                    emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI());
   5.498                      break;
   5.499                  case opc_ishr:
   5.500 -                    emit(out, "@1 >>= @2;", mapper.getI(1), mapper.popI());
   5.501 +                    emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
   5.502                      break;
   5.503                  case opc_lshr:
   5.504 -                    emit(out, "@1 >>= @2;", mapper.getL(1), mapper.popI());
   5.505 +                    emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
   5.506                      break;
   5.507                  case opc_iushr:
   5.508 -                    emit(out, "@1 >>>= @2;", mapper.getI(1), mapper.popI());
   5.509 +                    emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
   5.510                      break;
   5.511                  case opc_lushr:
   5.512 -                    emit(out, "@1 >>>= @2;", mapper.getL(1), mapper.popI());
   5.513 +                    emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
   5.514                      break;
   5.515                  case opc_iinc: {
   5.516                      final int varIndx = readByte(byteCodes, ++i);
   5.517                      final int incrBy = byteCodes[++i];
   5.518                      if (incrBy == 1) {
   5.519 -                        emit(out, "arg@1++;", Integer.toString(varIndx));
   5.520 +                        emit(out, "@1++;", lmapper.getI(varIndx));
   5.521                      } else {
   5.522 -                        emit(out, "arg@1 += @2;",
   5.523 -                             Integer.toString(varIndx),
   5.524 +                        emit(out, "@1 += @2;",
   5.525 +                             lmapper.getI(varIndx),
   5.526                               Integer.toString(incrBy));
   5.527                      }
   5.528                      break;
   5.529 @@ -597,60 +566,60 @@
   5.530                      emit(out, "return;");
   5.531                      break;
   5.532                  case opc_ireturn:
   5.533 -                    emit(out, "return @1;", mapper.popI());
   5.534 +                    emit(out, "return @1;", smapper.popI());
   5.535                      break;
   5.536                  case opc_lreturn:
   5.537 -                    emit(out, "return @1;", mapper.popL());
   5.538 +                    emit(out, "return @1;", smapper.popL());
   5.539                      break;
   5.540                  case opc_freturn:
   5.541 -                    emit(out, "return @1;", mapper.popF());
   5.542 +                    emit(out, "return @1;", smapper.popF());
   5.543                      break;
   5.544                  case opc_dreturn:
   5.545 -                    emit(out, "return @1;", mapper.popD());
   5.546 +                    emit(out, "return @1;", smapper.popD());
   5.547                      break;
   5.548                  case opc_areturn:
   5.549 -                    emit(out, "return @1;", mapper.popA());
   5.550 +                    emit(out, "return @1;", smapper.popA());
   5.551                      break;
   5.552                  case opc_i2l:
   5.553 -                    emit(out, "@2 = @1;", mapper.popI(), mapper.pushL());
   5.554 +                    emit(out, "@2 = @1;", smapper.popI(), smapper.pushL());
   5.555                      break;
   5.556                  case opc_i2f:
   5.557 -                    emit(out, "@2 = @1;", mapper.popI(), mapper.pushF());
   5.558 +                    emit(out, "@2 = @1;", smapper.popI(), smapper.pushF());
   5.559                      break;
   5.560                  case opc_i2d:
   5.561 -                    emit(out, "@2 = @1;", mapper.popI(), mapper.pushD());
   5.562 +                    emit(out, "@2 = @1;", smapper.popI(), smapper.pushD());
   5.563                      break;
   5.564                  case opc_l2i:
   5.565 -                    emit(out, "@2 = @1;", mapper.popL(), mapper.pushI());
   5.566 +                    emit(out, "@2 = @1;", smapper.popL(), smapper.pushI());
   5.567                      break;
   5.568                      // max int check?
   5.569                  case opc_l2f:
   5.570 -                    emit(out, "@2 = @1;", mapper.popL(), mapper.pushF());
   5.571 +                    emit(out, "@2 = @1;", smapper.popL(), smapper.pushF());
   5.572                      break;
   5.573                  case opc_l2d:
   5.574 -                    emit(out, "@2 = @1;", mapper.popL(), mapper.pushD());
   5.575 +                    emit(out, "@2 = @1;", smapper.popL(), smapper.pushD());
   5.576                      break;
   5.577                  case opc_f2d:
   5.578 -                    emit(out, "@2 = @1;", mapper.popF(), mapper.pushD());
   5.579 +                    emit(out, "@2 = @1;", smapper.popF(), smapper.pushD());
   5.580                      break;
   5.581                  case opc_d2f:
   5.582 -                    emit(out, "@2 = @1;", mapper.popD(), mapper.pushF());
   5.583 +                    emit(out, "@2 = @1;", smapper.popD(), smapper.pushF());
   5.584                      break;
   5.585                  case opc_f2i:
   5.586                      emit(out, "@2 = Math.floor(@1);",
   5.587 -                         mapper.popF(), mapper.pushI());
   5.588 +                         smapper.popF(), smapper.pushI());
   5.589                      break;
   5.590                  case opc_f2l:
   5.591                      emit(out, "@2 = Math.floor(@1);",
   5.592 -                         mapper.popF(), mapper.pushL());
   5.593 +                         smapper.popF(), smapper.pushL());
   5.594                      break;
   5.595                  case opc_d2i:
   5.596                      emit(out, "@2 = Math.floor(@1);",
   5.597 -                         mapper.popD(), mapper.pushI());
   5.598 +                         smapper.popD(), smapper.pushI());
   5.599                      break;
   5.600                  case opc_d2l:
   5.601                      emit(out, "@2 = Math.floor(@1);",
   5.602 -                         mapper.popD(), mapper.pushL());
   5.603 +                         smapper.popD(), smapper.pushL());
   5.604                      break;
   5.605                  case opc_i2b:
   5.606                  case opc_i2c:
   5.607 @@ -658,55 +627,55 @@
   5.608                      out.append("/* number conversion */");
   5.609                      break;
   5.610                  case opc_aconst_null:
   5.611 -                    emit(out, "@1 = null;", mapper.pushA());
   5.612 +                    emit(out, "@1 = null;", smapper.pushA());
   5.613                      break;
   5.614                  case opc_iconst_m1:
   5.615 -                    emit(out, "@1 = -1;", mapper.pushI());
   5.616 +                    emit(out, "@1 = -1;", smapper.pushI());
   5.617                      break;
   5.618                  case opc_iconst_0:
   5.619 -                    emit(out, "@1 = 0;", mapper.pushI());
   5.620 +                    emit(out, "@1 = 0;", smapper.pushI());
   5.621                      break;
   5.622                  case opc_dconst_0:
   5.623 -                    emit(out, "@1 = 0;", mapper.pushD());
   5.624 +                    emit(out, "@1 = 0;", smapper.pushD());
   5.625                      break;
   5.626                  case opc_lconst_0:
   5.627 -                    emit(out, "@1 = 0;", mapper.pushL());
   5.628 +                    emit(out, "@1 = 0;", smapper.pushL());
   5.629                      break;
   5.630                  case opc_fconst_0:
   5.631 -                    emit(out, "@1 = 0;", mapper.pushF());
   5.632 +                    emit(out, "@1 = 0;", smapper.pushF());
   5.633                      break;
   5.634                  case opc_iconst_1:
   5.635 -                    emit(out, "@1 = 1;", mapper.pushI());
   5.636 +                    emit(out, "@1 = 1;", smapper.pushI());
   5.637                      break;
   5.638                  case opc_lconst_1:
   5.639 -                    emit(out, "@1 = 1;", mapper.pushL());
   5.640 +                    emit(out, "@1 = 1;", smapper.pushL());
   5.641                      break;
   5.642                  case opc_fconst_1:
   5.643 -                    emit(out, "@1 = 1;", mapper.pushF());
   5.644 +                    emit(out, "@1 = 1;", smapper.pushF());
   5.645                      break;
   5.646                  case opc_dconst_1:
   5.647 -                    emit(out, "@1 = 1;", mapper.pushD());
   5.648 +                    emit(out, "@1 = 1;", smapper.pushD());
   5.649                      break;
   5.650                  case opc_iconst_2:
   5.651 -                    emit(out, "@1 = 2;", mapper.pushI());
   5.652 +                    emit(out, "@1 = 2;", smapper.pushI());
   5.653                      break;
   5.654                  case opc_fconst_2:
   5.655 -                    emit(out, "@1 = 2;", mapper.pushF());
   5.656 +                    emit(out, "@1 = 2;", smapper.pushF());
   5.657                      break;
   5.658                  case opc_iconst_3:
   5.659 -                    emit(out, "@1 = 3;", mapper.pushI());
   5.660 +                    emit(out, "@1 = 3;", smapper.pushI());
   5.661                      break;
   5.662                  case opc_iconst_4:
   5.663 -                    emit(out, "@1 = 4;", mapper.pushI());
   5.664 +                    emit(out, "@1 = 4;", smapper.pushI());
   5.665                      break;
   5.666                  case opc_iconst_5:
   5.667 -                    emit(out, "@1 = 5;", mapper.pushI());
   5.668 +                    emit(out, "@1 = 5;", smapper.pushI());
   5.669                      break;
   5.670                  case opc_ldc: {
   5.671                      int indx = readByte(byteCodes, ++i);
   5.672                      String v = encodeConstant(indx);
   5.673 -                    int type = constantToVariableType(jc.getTag(indx));
   5.674 -                    emit(out, "@1 = @2;", mapper.pushT(type), v);
   5.675 +                    int type = VarType.fromConstantType(jc.getTag(indx));
   5.676 +                    emit(out, "@1 = @2;", smapper.pushT(type), v);
   5.677                      break;
   5.678                  }
   5.679                  case opc_ldc_w:
   5.680 @@ -714,110 +683,110 @@
   5.681                      int indx = readIntArg(byteCodes, i);
   5.682                      i += 2;
   5.683                      String v = encodeConstant(indx);
   5.684 -                    int type = constantToVariableType(jc.getTag(indx));
   5.685 -                    emit(out, "@1 = @2;", mapper.pushT(type), v);
   5.686 +                    int type = VarType.fromConstantType(jc.getTag(indx));
   5.687 +                    emit(out, "@1 = @2;", smapper.pushT(type), v);
   5.688                      break;
   5.689                  }
   5.690                  case opc_lcmp:
   5.691                      emit(out, "@3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
   5.692 -                         mapper.popL(), mapper.popL(), mapper.pushI());
   5.693 +                         smapper.popL(), smapper.popL(), smapper.pushI());
   5.694                      break;
   5.695                  case opc_fcmpl:
   5.696                  case opc_fcmpg:
   5.697                      emit(out, "@3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
   5.698 -                         mapper.popF(), mapper.popF(), mapper.pushI());
   5.699 +                         smapper.popF(), smapper.popF(), smapper.pushI());
   5.700                      break;
   5.701                  case opc_dcmpl:
   5.702                  case opc_dcmpg:
   5.703                      emit(out, "@3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
   5.704 -                         mapper.popD(), mapper.popD(), mapper.pushI());
   5.705 +                         smapper.popD(), smapper.popD(), smapper.pushI());
   5.706                      break;
   5.707                  case opc_if_acmpeq:
   5.708 -                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   5.709 +                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
   5.710                                     "===");
   5.711                      break;
   5.712                  case opc_if_acmpne:
   5.713 -                    i = generateIf(byteCodes, i, mapper.popA(), mapper.popA(),
   5.714 +                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
   5.715                                     "!=");
   5.716                      break;
   5.717                  case opc_if_icmpeq:
   5.718 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.719 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.720                                     "==");
   5.721                      break;
   5.722                  case opc_ifeq: {
   5.723                      int indx = i + readIntArg(byteCodes, i);
   5.724                      emit(out, "if (@1 == 0) { gt = @2; continue; }",
   5.725 -                         mapper.popI(), Integer.toString(indx));
   5.726 +                         smapper.popI(), Integer.toString(indx));
   5.727                      i += 2;
   5.728                      break;
   5.729                  }
   5.730                  case opc_ifne: {
   5.731                      int indx = i + readIntArg(byteCodes, i);
   5.732                      emit(out, "if (@1 != 0) { gt = @2; continue; }",
   5.733 -                         mapper.popI(), Integer.toString(indx));
   5.734 +                         smapper.popI(), Integer.toString(indx));
   5.735                      i += 2;
   5.736                      break;
   5.737                  }
   5.738                  case opc_iflt: {
   5.739                      int indx = i + readIntArg(byteCodes, i);
   5.740                      emit(out, "if (@1 < 0) { gt = @2; continue; }",
   5.741 -                         mapper.popI(), Integer.toString(indx));
   5.742 +                         smapper.popI(), Integer.toString(indx));
   5.743                      i += 2;
   5.744                      break;
   5.745                  }
   5.746                  case opc_ifle: {
   5.747                      int indx = i + readIntArg(byteCodes, i);
   5.748                      emit(out, "if (@1 <= 0) { gt = @2; continue; }",
   5.749 -                         mapper.popI(), Integer.toString(indx));
   5.750 +                         smapper.popI(), Integer.toString(indx));
   5.751                      i += 2;
   5.752                      break;
   5.753                  }
   5.754                  case opc_ifgt: {
   5.755                      int indx = i + readIntArg(byteCodes, i);
   5.756                      emit(out, "if (@1 > 0) { gt = @2; continue; }",
   5.757 -                         mapper.popI(), Integer.toString(indx));
   5.758 +                         smapper.popI(), Integer.toString(indx));
   5.759                      i += 2;
   5.760                      break;
   5.761                  }
   5.762                  case opc_ifge: {
   5.763                      int indx = i + readIntArg(byteCodes, i);
   5.764                      emit(out, "if (@1 >= 0) { gt = @2; continue; }",
   5.765 -                         mapper.popI(), Integer.toString(indx));
   5.766 +                         smapper.popI(), Integer.toString(indx));
   5.767                      i += 2;
   5.768                      break;
   5.769                  }
   5.770                  case opc_ifnonnull: {
   5.771                      int indx = i + readIntArg(byteCodes, i);
   5.772                      emit(out, "if (@1 !== null) { gt = @2; continue; }",
   5.773 -                         mapper.popA(), Integer.toString(indx));
   5.774 +                         smapper.popA(), Integer.toString(indx));
   5.775                      i += 2;
   5.776                      break;
   5.777                  }
   5.778                  case opc_ifnull: {
   5.779                      int indx = i + readIntArg(byteCodes, i);
   5.780                      emit(out, "if (@1 === null) { gt = @2; continue; }",
   5.781 -                         mapper.popA(), Integer.toString(indx));
   5.782 +                         smapper.popA(), Integer.toString(indx));
   5.783                      i += 2;
   5.784                      break;
   5.785                  }
   5.786                  case opc_if_icmpne:
   5.787 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.788 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.789                                     "!=");
   5.790                      break;
   5.791                  case opc_if_icmplt:
   5.792 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.793 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.794                                     "<");
   5.795                      break;
   5.796                  case opc_if_icmple:
   5.797 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.798 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.799                                     "<=");
   5.800                      break;
   5.801                  case opc_if_icmpgt:
   5.802 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.803 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.804                                     ">");
   5.805                      break;
   5.806                  case opc_if_icmpge:
   5.807 -                    i = generateIf(byteCodes, i, mapper.popI(), mapper.popI(),
   5.808 +                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
   5.809                                     ">=");
   5.810                      break;
   5.811                  case opc_goto: {
   5.812 @@ -832,7 +801,7 @@
   5.813                      table += 4;
   5.814                      int n = readInt4(byteCodes, table);
   5.815                      table += 4;
   5.816 -                    out.append("switch (").append(mapper.popI()).append(") {\n");
   5.817 +                    out.append("switch (").append(smapper.popI()).append(") {\n");
   5.818                      while (n-- > 0) {
   5.819                          int cnstnt = readInt4(byteCodes, table);
   5.820                          table += 4;
   5.821 @@ -852,7 +821,7 @@
   5.822                      table += 4;
   5.823                      int high = readInt4(byteCodes, table);
   5.824                      table += 4;
   5.825 -                    out.append("switch (").append(mapper.popI()).append(") {\n");
   5.826 +                    out.append("switch (").append(smapper.popI()).append(") {\n");
   5.827                      while (low <= high) {
   5.828                          int offset = i + readInt4(byteCodes, table);
   5.829                          table += 4;
   5.830 @@ -864,23 +833,23 @@
   5.831                      break;
   5.832                  }
   5.833                  case opc_invokeinterface: {
   5.834 -                    i = invokeVirtualMethod(byteCodes, i, mapper) + 2;
   5.835 +                    i = invokeVirtualMethod(byteCodes, i, smapper) + 2;
   5.836                      break;
   5.837                  }
   5.838                  case opc_invokevirtual:
   5.839 -                    i = invokeVirtualMethod(byteCodes, i, mapper);
   5.840 +                    i = invokeVirtualMethod(byteCodes, i, smapper);
   5.841                      break;
   5.842                  case opc_invokespecial:
   5.843 -                    i = invokeStaticMethod(byteCodes, i, mapper, false);
   5.844 +                    i = invokeStaticMethod(byteCodes, i, smapper, false);
   5.845                      break;
   5.846                  case opc_invokestatic:
   5.847 -                    i = invokeStaticMethod(byteCodes, i, mapper, true);
   5.848 +                    i = invokeStaticMethod(byteCodes, i, smapper, true);
   5.849                      break;
   5.850                  case opc_new: {
   5.851                      int indx = readIntArg(byteCodes, i);
   5.852                      String ci = jc.getClassName(indx);
   5.853                      emit(out, "@1 = new @2;",
   5.854 -                         mapper.pushA(), ci.replace('/', '_'));
   5.855 +                         smapper.pushA(), ci.replace('/', '_'));
   5.856                      addReference(ci);
   5.857                      i += 2;
   5.858                      break;
   5.859 @@ -888,21 +857,21 @@
   5.860                  case opc_newarray:
   5.861                      ++i; // skip type of array
   5.862                      emit(out, "@2 = new Array(@1).fillNulls();",
   5.863 -                         mapper.popI(), mapper.pushA());
   5.864 +                         smapper.popI(), smapper.pushA());
   5.865                      break;
   5.866                  case opc_anewarray:
   5.867                      i += 2; // skip type of array
   5.868                      emit(out, "@2 = new Array(@1).fillNulls();",
   5.869 -                         mapper.popI(), mapper.pushA());
   5.870 +                         smapper.popI(), smapper.pushA());
   5.871                      break;
   5.872                  case opc_multianewarray: {
   5.873                      i += 2;
   5.874                      int dim = readByte(byteCodes, ++i);
   5.875 -                    out.append("{ var a0 = new Array(").append(mapper.popI())
   5.876 +                    out.append("{ var a0 = new Array(").append(smapper.popI())
   5.877                         .append(").fillNulls();");
   5.878                      for (int d = 1; d < dim; d++) {
   5.879                          out.append("\n  var l" + d).append(" = ")
   5.880 -                           .append(mapper.popI()).append(';');
   5.881 +                           .append(smapper.popI()).append(';');
   5.882                          out.append("\n  for (var i" + d).append (" = 0; i" + d).
   5.883                              append(" < a" + (d - 1)).
   5.884                              append(".length; i" + d).append("++) {");
   5.885 @@ -914,110 +883,110 @@
   5.886                      for (int d = 1; d < dim; d++) {
   5.887                          out.append("\n  }");
   5.888                      }
   5.889 -                    out.append("\n").append(mapper.pushA()).append(" = a0; }");
   5.890 +                    out.append("\n").append(smapper.pushA()).append(" = a0; }");
   5.891                      break;
   5.892                  }
   5.893                  case opc_arraylength:
   5.894 -                    emit(out, "@2 = @1.length;", mapper.popA(), mapper.pushI());
   5.895 +                    emit(out, "@2 = @1.length;", smapper.popA(), smapper.pushI());
   5.896                      break;
   5.897                  case opc_lastore:
   5.898                      emit(out, "@3[@2] = @1;",
   5.899 -                         mapper.popL(), mapper.popI(), mapper.popA());
   5.900 +                         smapper.popL(), smapper.popI(), smapper.popA());
   5.901                      break;
   5.902                  case opc_fastore:
   5.903                      emit(out, "@3[@2] = @1;",
   5.904 -                         mapper.popF(), mapper.popI(), mapper.popA());
   5.905 +                         smapper.popF(), smapper.popI(), smapper.popA());
   5.906                      break;
   5.907                  case opc_dastore:
   5.908                      emit(out, "@3[@2] = @1;",
   5.909 -                         mapper.popD(), mapper.popI(), mapper.popA());
   5.910 +                         smapper.popD(), smapper.popI(), smapper.popA());
   5.911                      break;
   5.912                  case opc_aastore:
   5.913                      emit(out, "@3[@2] = @1;",
   5.914 -                         mapper.popA(), mapper.popI(), mapper.popA());
   5.915 +                         smapper.popA(), smapper.popI(), smapper.popA());
   5.916                      break;
   5.917                  case opc_iastore:
   5.918                  case opc_bastore:
   5.919                  case opc_castore:
   5.920                  case opc_sastore:
   5.921                      emit(out, "@3[@2] = @1;",
   5.922 -                         mapper.popI(), mapper.popI(), mapper.popA());
   5.923 +                         smapper.popI(), smapper.popI(), smapper.popA());
   5.924                      break;
   5.925                  case opc_laload:
   5.926                      emit(out, "@3 = @2[@1];",
   5.927 -                         mapper.popI(), mapper.popA(), mapper.pushL());
   5.928 +                         smapper.popI(), smapper.popA(), smapper.pushL());
   5.929                      break;
   5.930                  case opc_faload:
   5.931                      emit(out, "@3 = @2[@1];",
   5.932 -                         mapper.popI(), mapper.popA(), mapper.pushF());
   5.933 +                         smapper.popI(), smapper.popA(), smapper.pushF());
   5.934                      break;
   5.935                  case opc_daload:
   5.936                      emit(out, "@3 = @2[@1];",
   5.937 -                         mapper.popI(), mapper.popA(), mapper.pushD());
   5.938 +                         smapper.popI(), smapper.popA(), smapper.pushD());
   5.939                      break;
   5.940                  case opc_aaload:
   5.941                      emit(out, "@3 = @2[@1];",
   5.942 -                         mapper.popI(), mapper.popA(), mapper.pushA());
   5.943 +                         smapper.popI(), smapper.popA(), smapper.pushA());
   5.944                      break;
   5.945                  case opc_iaload:
   5.946                  case opc_baload:
   5.947                  case opc_caload:
   5.948                  case opc_saload:
   5.949                      emit(out, "@3 = @2[@1];",
   5.950 -                         mapper.popI(), mapper.popA(), mapper.pushI());
   5.951 +                         smapper.popI(), smapper.popA(), smapper.pushI());
   5.952                      break;
   5.953                  case opc_pop:
   5.954                  case opc_pop2:
   5.955 -                    mapper.pop(1);
   5.956 +                    smapper.pop(1);
   5.957                      out.append("/* pop */");
   5.958                      break;
   5.959                  case opc_dup: {
   5.960 -                    final Variable v = mapper.get(0);
   5.961 -                    emit(out, "@1 = @2;", mapper.pushT(v.getType()), v);
   5.962 +                    final Variable v = smapper.get(0);
   5.963 +                    emit(out, "@1 = @2;", smapper.pushT(v.getType()), v);
   5.964                      break;
   5.965                  }
   5.966                  case opc_dup2: {
   5.967 -                    if (mapper.get(0).isCategory2()) {
   5.968 -                        final Variable v = mapper.get(0);
   5.969 -                        emit(out, "@1 = @2;", mapper.pushT(v.getType()), v);
   5.970 +                    if (smapper.get(0).isCategory2()) {
   5.971 +                        final Variable v = smapper.get(0);
   5.972 +                        emit(out, "@1 = @2;", smapper.pushT(v.getType()), v);
   5.973                      } else {
   5.974 -                        final Variable v1 = mapper.get(0);
   5.975 -                        final Variable v2 = mapper.get(1);
   5.976 +                        final Variable v1 = smapper.get(0);
   5.977 +                        final Variable v2 = smapper.get(1);
   5.978                          emit(out, "{ @1 = @2; @3 = @4; }",
   5.979 -                             mapper.pushT(v2.getType()), v2,
   5.980 -                             mapper.pushT(v1.getType()), v1);
   5.981 +                             smapper.pushT(v2.getType()), v2,
   5.982 +                             smapper.pushT(v1.getType()), v1);
   5.983                      }
   5.984                      break;
   5.985                  }
   5.986                  case opc_dup_x1: {
   5.987 -                    final Variable vi1 = mapper.pop();
   5.988 -                    final Variable vi2 = mapper.pop();
   5.989 -                    final Variable vo3 = mapper.pushT(vi1.getType());
   5.990 -                    final Variable vo2 = mapper.pushT(vi2.getType());
   5.991 -                    final Variable vo1 = mapper.pushT(vi1.getType());
   5.992 +                    final Variable vi1 = smapper.pop();
   5.993 +                    final Variable vi2 = smapper.pop();
   5.994 +                    final Variable vo3 = smapper.pushT(vi1.getType());
   5.995 +                    final Variable vo2 = smapper.pushT(vi2.getType());
   5.996 +                    final Variable vo1 = smapper.pushT(vi1.getType());
   5.997  
   5.998                      emit(out, "{ @1 = @2; @3 = @4; @5 = @6; }",
   5.999                           vo1, vi1, vo2, vi2, vo3, vo1);
  5.1000                      break;
  5.1001                  }
  5.1002                  case opc_dup_x2: {
  5.1003 -                    if (mapper.get(1).isCategory2()) {
  5.1004 -                        final Variable vi1 = mapper.pop();
  5.1005 -                        final Variable vi2 = mapper.pop();
  5.1006 -                        final Variable vo3 = mapper.pushT(vi1.getType());
  5.1007 -                        final Variable vo2 = mapper.pushT(vi2.getType());
  5.1008 -                        final Variable vo1 = mapper.pushT(vi1.getType());
  5.1009 +                    if (smapper.get(1).isCategory2()) {
  5.1010 +                        final Variable vi1 = smapper.pop();
  5.1011 +                        final Variable vi2 = smapper.pop();
  5.1012 +                        final Variable vo3 = smapper.pushT(vi1.getType());
  5.1013 +                        final Variable vo2 = smapper.pushT(vi2.getType());
  5.1014 +                        final Variable vo1 = smapper.pushT(vi1.getType());
  5.1015  
  5.1016                          emit(out, "{ @1 = @2; @3 = @4; @5 = @6; }",
  5.1017                               vo1, vi1, vo2, vi2, vo3, vo1);
  5.1018                      } else {
  5.1019 -                        final Variable vi1 = mapper.pop();
  5.1020 -                        final Variable vi2 = mapper.pop();
  5.1021 -                        final Variable vi3 = mapper.pop();
  5.1022 -                        final Variable vo4 = mapper.pushT(vi1.getType());
  5.1023 -                        final Variable vo3 = mapper.pushT(vi3.getType());
  5.1024 -                        final Variable vo2 = mapper.pushT(vi2.getType());
  5.1025 -                        final Variable vo1 = mapper.pushT(vi1.getType());
  5.1026 +                        final Variable vi1 = smapper.pop();
  5.1027 +                        final Variable vi2 = smapper.pop();
  5.1028 +                        final Variable vi3 = smapper.pop();
  5.1029 +                        final Variable vo4 = smapper.pushT(vi1.getType());
  5.1030 +                        final Variable vo3 = smapper.pushT(vi3.getType());
  5.1031 +                        final Variable vo2 = smapper.pushT(vi2.getType());
  5.1032 +                        final Variable vo1 = smapper.pushT(vi1.getType());
  5.1033  
  5.1034                          emit(out, "{ @1 = @2; @3 = @4; @5 = @6; @7 = @8; }",
  5.1035                               vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
  5.1036 @@ -1026,29 +995,29 @@
  5.1037                  }
  5.1038                  case opc_bipush:
  5.1039                      emit(out, "@1 = @2;",
  5.1040 -                         mapper.pushI(), Integer.toString(byteCodes[++i]));
  5.1041 +                         smapper.pushI(), Integer.toString(byteCodes[++i]));
  5.1042                      break;
  5.1043                  case opc_sipush:
  5.1044                      emit(out, "@1 = @2;",
  5.1045 -                         mapper.pushI(),
  5.1046 +                         smapper.pushI(),
  5.1047                           Integer.toString(readIntArg(byteCodes, i)));
  5.1048                      i += 2;
  5.1049                      break;
  5.1050                  case opc_getfield: {
  5.1051                      int indx = readIntArg(byteCodes, i);
  5.1052                      String[] fi = jc.getFieldInfoName(indx);
  5.1053 -                    final int type = fieldToVariableType(fi[2].charAt(0));
  5.1054 +                    final int type = VarType.fromFieldType(fi[2].charAt(0));
  5.1055                      emit(out, "@2 = @1.fld_@3;",
  5.1056 -                         mapper.popA(), mapper.pushT(type), fi[1]);
  5.1057 +                         smapper.popA(), smapper.pushT(type), fi[1]);
  5.1058                      i += 2;
  5.1059                      break;
  5.1060                  }
  5.1061                  case opc_getstatic: {
  5.1062                      int indx = readIntArg(byteCodes, i);
  5.1063                      String[] fi = jc.getFieldInfoName(indx);
  5.1064 -                    final int type = fieldToVariableType(fi[2].charAt(0));
  5.1065 +                    final int type = VarType.fromFieldType(fi[2].charAt(0));
  5.1066                      emit(out, "@1 = @2.@3;",
  5.1067 -                         mapper.pushT(type), fi[0].replace('/', '_'), fi[1]);
  5.1068 +                         smapper.pushT(type), fi[0].replace('/', '_'), fi[1]);
  5.1069                      i += 2;
  5.1070                      addReference(fi[0]);
  5.1071                      break;
  5.1072 @@ -1056,18 +1025,18 @@
  5.1073                  case opc_putfield: {
  5.1074                      int indx = readIntArg(byteCodes, i);
  5.1075                      String[] fi = jc.getFieldInfoName(indx);
  5.1076 -                    final int type = fieldToVariableType(fi[2].charAt(0));
  5.1077 +                    final int type = VarType.fromFieldType(fi[2].charAt(0));
  5.1078                      emit(out, "@2.fld_@3 = @1;",
  5.1079 -                         mapper.popT(type), mapper.popA(), fi[1]);
  5.1080 +                         smapper.popT(type), smapper.popA(), fi[1]);
  5.1081                      i += 2;
  5.1082                      break;
  5.1083                  }
  5.1084                  case opc_putstatic: {
  5.1085                      int indx = readIntArg(byteCodes, i);
  5.1086                      String[] fi = jc.getFieldInfoName(indx);
  5.1087 -                    final int type = fieldToVariableType(fi[2].charAt(0));
  5.1088 +                    final int type = VarType.fromFieldType(fi[2].charAt(0));
  5.1089                      emit(out, "@1.@2 = @3;",
  5.1090 -                         fi[0].replace('/', '_'), fi[1], mapper.popT(type));
  5.1091 +                         fi[0].replace('/', '_'), fi[1], smapper.popT(type));
  5.1092                      i += 2;
  5.1093                      addReference(fi[0]);
  5.1094                      break;
  5.1095 @@ -1079,7 +1048,7 @@
  5.1096                          // no way to check arrays right now
  5.1097                          // XXX proper exception
  5.1098                          emit(out, "if (@1.$instOf_@2 != 1) throw {};",
  5.1099 -                             mapper.getA(0), type.replace('/', '_'));
  5.1100 +                             smapper.getA(0), type.replace('/', '_'));
  5.1101                      }
  5.1102                      i += 2;
  5.1103                      break;
  5.1104 @@ -1088,28 +1057,28 @@
  5.1105                      int indx = readIntArg(byteCodes, i);
  5.1106                      final String type = jc.getClassName(indx);
  5.1107                      emit(out, "@2 = @1.$instOf_@3 ? 1 : 0;",
  5.1108 -                         mapper.popA(), mapper.pushI(), type.replace('/', '_'));
  5.1109 +                         smapper.popA(), smapper.pushI(), type.replace('/', '_'));
  5.1110                      i += 2;
  5.1111                      break;
  5.1112                  }
  5.1113                  case opc_athrow: {
  5.1114 -                    final Variable v = mapper.popA();
  5.1115 -                    mapper.clear();
  5.1116 +                    final Variable v = smapper.popA();
  5.1117 +                    smapper.clear();
  5.1118  
  5.1119                      emit(out, "{ @1 = @2; throw @2; }",
  5.1120 -                         mapper.pushA(), v);
  5.1121 +                         smapper.pushA(), v);
  5.1122                      break;
  5.1123                  }
  5.1124  
  5.1125                  case opc_monitorenter: {
  5.1126                      out.append("/* monitor enter */");
  5.1127 -                    mapper.popA();
  5.1128 +                    smapper.popA();
  5.1129                      break;
  5.1130                  }
  5.1131  
  5.1132                  case opc_monitorexit: {
  5.1133                      out.append("/* monitor exit */");
  5.1134 -                    mapper.popA();
  5.1135 +                    smapper.popA();
  5.1136                      break;
  5.1137                  }
  5.1138  
  5.1139 @@ -1127,6 +1096,7 @@
  5.1140              out.append("\n");
  5.1141          }
  5.1142          out.append("  }\n");
  5.1143 +        out.append("};");
  5.1144      }
  5.1145  
  5.1146      private int generateIf(byte[] byteCodes, int i,
  5.1147 @@ -1274,7 +1244,7 @@
  5.1148          return name.toString();
  5.1149      }
  5.1150  
  5.1151 -    private int invokeStaticMethod(byte[] byteCodes, int i, final StackToVariableMapper mapper, boolean isStatic)
  5.1152 +    private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
  5.1153      throws IOException {
  5.1154          int methodIndex = readIntArg(byteCodes, i);
  5.1155          String[] mi = jc.getFieldInfoName(methodIndex);
  5.1156 @@ -1290,7 +1260,7 @@
  5.1157          }
  5.1158  
  5.1159          if (returnType[0] != 'V') {
  5.1160 -            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  5.1161 +            out.append(mapper.pushT(VarType.fromFieldType(returnType[0])))
  5.1162                 .append(" = ");
  5.1163          }
  5.1164  
  5.1165 @@ -1311,7 +1281,7 @@
  5.1166          addReference(in);
  5.1167          return i;
  5.1168      }
  5.1169 -    private int invokeVirtualMethod(byte[] byteCodes, int i, final StackToVariableMapper mapper)
  5.1170 +    private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
  5.1171      throws IOException {
  5.1172          int methodIndex = readIntArg(byteCodes, i);
  5.1173          String[] mi = jc.getFieldInfoName(methodIndex);
  5.1174 @@ -1327,7 +1297,7 @@
  5.1175          }
  5.1176  
  5.1177          if (returnType[0] != 'V') {
  5.1178 -            out.append(mapper.pushT(fieldToVariableType(returnType[0])))
  5.1179 +            out.append(mapper.pushT(VarType.fromFieldType(returnType[0])))
  5.1180                 .append(" = ");
  5.1181          }
  5.1182  
  5.1183 @@ -1517,56 +1487,6 @@
  5.1184          ap.parse(data, cd);
  5.1185      }
  5.1186  
  5.1187 -    private static int constantToVariableType(final byte constantTag) {
  5.1188 -        switch (constantTag) {
  5.1189 -            case CONSTANT_INTEGER:
  5.1190 -                return Variable.TYPE_INT;
  5.1191 -            case CONSTANT_FLOAT:
  5.1192 -                return Variable.TYPE_FLOAT;
  5.1193 -            case CONSTANT_LONG:
  5.1194 -                return Variable.TYPE_LONG;
  5.1195 -            case CONSTANT_DOUBLE:
  5.1196 -                return Variable.TYPE_DOUBLE;
  5.1197 -
  5.1198 -            case CONSTANT_CLASS:
  5.1199 -            case CONSTANT_UTF8:
  5.1200 -            case CONSTANT_UNICODE:
  5.1201 -            case CONSTANT_STRING:
  5.1202 -                return Variable.TYPE_REF;
  5.1203 -
  5.1204 -            case CONSTANT_FIELD:
  5.1205 -            case CONSTANT_METHOD:
  5.1206 -            case CONSTANT_INTERFACEMETHOD:
  5.1207 -            case CONSTANT_NAMEANDTYPE:
  5.1208 -                /* unclear how to handle for now */
  5.1209 -            default:
  5.1210 -                throw new IllegalStateException("Unhandled constant tag");
  5.1211 -        }
  5.1212 -    }
  5.1213 -
  5.1214 -    private static int fieldToVariableType(final char fieldType) {
  5.1215 -        switch (fieldType) {
  5.1216 -            case 'B':
  5.1217 -            case 'C':
  5.1218 -            case 'S':
  5.1219 -            case 'Z':
  5.1220 -            case 'I':
  5.1221 -                return Variable.TYPE_INT;
  5.1222 -            case 'J':
  5.1223 -                return Variable.TYPE_LONG;
  5.1224 -            case 'F':
  5.1225 -                return Variable.TYPE_FLOAT;
  5.1226 -            case 'D':
  5.1227 -                return Variable.TYPE_DOUBLE;
  5.1228 -            case 'L':
  5.1229 -            case '[':
  5.1230 -                return Variable.TYPE_REF;
  5.1231 -
  5.1232 -            default:
  5.1233 -                throw new IllegalStateException("Unhandled field type");
  5.1234 -        }
  5.1235 -    }
  5.1236 -
  5.1237      private static void emit(final Appendable out,
  5.1238                               final String format,
  5.1239                               final CharSequence... params) throws IOException {
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java	Wed Dec 12 11:04:02 2012 +0100
     6.3 @@ -0,0 +1,141 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +package org.apidesign.vm4brwsr;
    6.22 +
    6.23 +import java.io.IOException;
    6.24 +import org.apidesign.javap.RuntimeConstants;
    6.25 +import org.apidesign.javap.TypeArray;
    6.26 +
    6.27 +public final class LocalsMapper {
    6.28 +    private final TypeArray argTypeRecords;
    6.29 +    private final TypeArray localTypeRecords;
    6.30 +
    6.31 +    public LocalsMapper(final TypeArray stackMapArgs) {
    6.32 +        final TypeArray initTypeRecords = new TypeArray();
    6.33 +        updateRecords(initTypeRecords, stackMapArgs);
    6.34 +
    6.35 +        argTypeRecords = initTypeRecords;
    6.36 +        localTypeRecords = new TypeArray(initTypeRecords);
    6.37 +    }
    6.38 +
    6.39 +    public void outputArguments(final Appendable out) throws IOException {
    6.40 +        final int argRecordCount = argTypeRecords.getSize();
    6.41 +        if (argRecordCount > 0) {
    6.42 +            Variable variable = getVariable(argTypeRecords, 0);
    6.43 +            out.append(variable);
    6.44 +
    6.45 +            int i = variable.isCategory2() ? 2 : 1;
    6.46 +            while (i < argRecordCount) {
    6.47 +                variable = getVariable(argTypeRecords, i);
    6.48 +                out.append(", ");
    6.49 +                out.append(variable);
    6.50 +                i += variable.isCategory2() ? 2 : 1;
    6.51 +            }
    6.52 +        }
    6.53 +    }
    6.54 +
    6.55 +    public void syncWithFrameLocals(final TypeArray frameLocals) {
    6.56 +        updateRecords(localTypeRecords, frameLocals);
    6.57 +    }
    6.58 +
    6.59 +    public Variable setI(final int index) {
    6.60 +        return setT(index, VarType.INTEGER);
    6.61 +    }
    6.62 +
    6.63 +    public Variable setL(final int index) {
    6.64 +        return setT(index, VarType.LONG);
    6.65 +    }
    6.66 +
    6.67 +    public Variable setF(final int index) {
    6.68 +        return setT(index, VarType.FLOAT);
    6.69 +    }
    6.70 +
    6.71 +    public Variable setD(final int index) {
    6.72 +        return setT(index, VarType.DOUBLE);
    6.73 +    }
    6.74 +
    6.75 +    public Variable setA(final int index) {
    6.76 +        return setT(index, VarType.REFERENCE);
    6.77 +    }
    6.78 +
    6.79 +    public Variable setT(final int index, final int type) {
    6.80 +        updateRecord(localTypeRecords, index, type);
    6.81 +        return Variable.getLocalVariable(type, index);
    6.82 +    }
    6.83 +
    6.84 +    public Variable getI(final int index) {
    6.85 +        return getT(index, VarType.INTEGER);
    6.86 +    }
    6.87 +
    6.88 +    public Variable getL(final int index) {
    6.89 +        return getT(index, VarType.LONG);
    6.90 +    }
    6.91 +
    6.92 +    public Variable getF(final int index) {
    6.93 +        return getT(index, VarType.FLOAT);
    6.94 +    }
    6.95 +
    6.96 +    public Variable getD(final int index) {
    6.97 +        return getT(index, VarType.DOUBLE);
    6.98 +    }
    6.99 +
   6.100 +    public Variable getA(final int index) {
   6.101 +        return getT(index, VarType.REFERENCE);
   6.102 +    }
   6.103 +
   6.104 +    public Variable getT(final int index, final int type) {
   6.105 +        final int oldRecordValue = localTypeRecords.get(index);
   6.106 +        if ((oldRecordValue & 0xff) != type) {
   6.107 +            throw new IllegalStateException("Type mismatch");
   6.108 +        }
   6.109 +
   6.110 +        return Variable.getLocalVariable(type, index);
   6.111 +    }
   6.112 +
   6.113 +    private static void updateRecords(final TypeArray typeRecords,
   6.114 +                                      final TypeArray stackMapTypes) {
   6.115 +        final int srcSize = stackMapTypes.getSize();
   6.116 +        for (int i = 0, dstIndex = 0; i < srcSize; ++i) {
   6.117 +            final int smType = stackMapTypes.get(i);
   6.118 +            if (smType == RuntimeConstants.ITEM_Bogus) {
   6.119 +                ++dstIndex;
   6.120 +                continue;
   6.121 +            }
   6.122 +            final int varType = VarType.fromStackMapType(smType);
   6.123 +            updateRecord(typeRecords, dstIndex, varType);
   6.124 +            dstIndex += VarType.isCategory2(varType) ? 2 : 1;
   6.125 +        }
   6.126 +    }
   6.127 +
   6.128 +    private static void updateRecord(final TypeArray typeRecords,
   6.129 +                                     final int index, final int type) {
   6.130 +        if (typeRecords.getSize() < (index + 1)) {
   6.131 +            typeRecords.setSize(index + 1);
   6.132 +        }
   6.133 +
   6.134 +        final int oldRecordValue = typeRecords.get(index);
   6.135 +        final int usedTypesMask =
   6.136 +                (oldRecordValue >> 8) | (1 << type);
   6.137 +        typeRecords.set(index, (usedTypesMask << 8) | type);
   6.138 +    }
   6.139 +
   6.140 +    private static Variable getVariable(final TypeArray typeRecords,
   6.141 +                                        final int index) {
   6.142 +        return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index);
   6.143 +    }
   6.144 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java	Wed Dec 12 11:04:02 2012 +0100
     7.3 @@ -0,0 +1,194 @@
     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 +import org.apidesign.javap.TypeArray;
    7.24 +
    7.25 +public final class StackMapper {
    7.26 +    private final TypeArray stackTypeIndexPairs;
    7.27 +    private int[] typeCounters;
    7.28 +    private int[] typeMaxCounters;
    7.29 +
    7.30 +    public StackMapper() {
    7.31 +        stackTypeIndexPairs = new TypeArray();
    7.32 +        typeCounters = new int[VarType.LAST + 1];
    7.33 +        typeMaxCounters = new int[VarType.LAST + 1];
    7.34 +    }
    7.35 +
    7.36 +    public void clear() {
    7.37 +        for (int type = 0; type <= VarType.LAST; ++type) {
    7.38 +            typeCounters[type] = 0;
    7.39 +        }
    7.40 +        stackTypeIndexPairs.clear();
    7.41 +    }
    7.42 +
    7.43 +    public void syncWithFrameStack(final TypeArray frameStack) {
    7.44 +        clear();
    7.45 +
    7.46 +        final int size = frameStack.getSize();
    7.47 +        for (int i = 0; i < size; ++i) {
    7.48 +            pushTypeImpl(VarType.fromStackMapType(frameStack.get(i)));
    7.49 +        }
    7.50 +    }
    7.51 +
    7.52 +    public Variable pushI() {
    7.53 +        return pushT(VarType.INTEGER);
    7.54 +    }
    7.55 +
    7.56 +    public Variable pushL() {
    7.57 +        return pushT(VarType.LONG);
    7.58 +    }
    7.59 +
    7.60 +    public Variable pushF() {
    7.61 +        return pushT(VarType.FLOAT);
    7.62 +    }
    7.63 +
    7.64 +    public Variable pushD() {
    7.65 +        return pushT(VarType.DOUBLE);
    7.66 +    }
    7.67 +
    7.68 +    public Variable pushA() {
    7.69 +        return pushT(VarType.REFERENCE);
    7.70 +    }
    7.71 +
    7.72 +    public Variable pushT(final int type) {
    7.73 +        return getVariable(pushTypeImpl(type));
    7.74 +    }
    7.75 +
    7.76 +    public Variable popI() {
    7.77 +        return popT(VarType.INTEGER);
    7.78 +    }
    7.79 +
    7.80 +    public Variable popL() {
    7.81 +        return popT(VarType.LONG);
    7.82 +    }
    7.83 +
    7.84 +    public Variable popF() {
    7.85 +        return popT(VarType.FLOAT);
    7.86 +    }
    7.87 +
    7.88 +    public Variable popD() {
    7.89 +        return popT(VarType.DOUBLE);
    7.90 +    }
    7.91 +
    7.92 +    public Variable popA() {
    7.93 +        return popT(VarType.REFERENCE);
    7.94 +    }
    7.95 +
    7.96 +    public Variable popT(final int type) {
    7.97 +        final Variable variable = getT(0, type);
    7.98 +        popImpl(1);
    7.99 +        return variable;
   7.100 +    }
   7.101 +
   7.102 +    public Variable pop() {
   7.103 +        final Variable variable = get(0);
   7.104 +        popImpl(1);
   7.105 +        return variable;
   7.106 +    }
   7.107 +
   7.108 +    public void pop(final int count) {
   7.109 +        final int stackSize = stackTypeIndexPairs.getSize();
   7.110 +        if (count > stackSize) {
   7.111 +            throw new IllegalStateException("Stack underflow");
   7.112 +        }
   7.113 +        popImpl(count);
   7.114 +    }
   7.115 +
   7.116 +    public Variable getI(final int indexFromTop) {
   7.117 +        return getT(indexFromTop, VarType.INTEGER);
   7.118 +    }
   7.119 +
   7.120 +    public Variable getL(final int indexFromTop) {
   7.121 +        return getT(indexFromTop, VarType.LONG);
   7.122 +    }
   7.123 +
   7.124 +    public Variable getF(final int indexFromTop) {
   7.125 +        return getT(indexFromTop, VarType.FLOAT);
   7.126 +    }
   7.127 +
   7.128 +    public Variable getD(final int indexFromTop) {
   7.129 +        return getT(indexFromTop, VarType.DOUBLE);
   7.130 +    }
   7.131 +
   7.132 +    public Variable getA(final int indexFromTop) {
   7.133 +        return getT(indexFromTop, VarType.REFERENCE);
   7.134 +    }
   7.135 +
   7.136 +    public Variable getT(final int indexFromTop, final int type) {
   7.137 +        final int stackSize = stackTypeIndexPairs.getSize();
   7.138 +        if (indexFromTop >= stackSize) {
   7.139 +            throw new IllegalStateException("Stack underflow");
   7.140 +        }
   7.141 +        final int stackValue =
   7.142 +                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   7.143 +        if ((stackValue & 0xff) != type) {
   7.144 +            throw new IllegalStateException("Type mismatch");
   7.145 +        }
   7.146 +
   7.147 +        return getVariable(stackValue);
   7.148 +    }
   7.149 +
   7.150 +    public Variable get(final int indexFromTop) {
   7.151 +        final int stackSize = stackTypeIndexPairs.getSize();
   7.152 +        if (indexFromTop >= stackSize) {
   7.153 +            throw new IllegalStateException("Stack underflow");
   7.154 +        }
   7.155 +        final int stackValue =
   7.156 +                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   7.157 +
   7.158 +        return getVariable(stackValue);
   7.159 +    }
   7.160 +
   7.161 +    private int pushTypeImpl(final int type) {
   7.162 +        final int count = typeCounters[type];
   7.163 +        final int value = (count << 8) | (type & 0xff);
   7.164 +        incCounter(type);
   7.165 +        stackTypeIndexPairs.add(value);
   7.166 +
   7.167 +        return value;
   7.168 +    }
   7.169 +
   7.170 +    private void popImpl(final int count) {
   7.171 +        final int stackSize = stackTypeIndexPairs.getSize();
   7.172 +        for (int i = stackSize - count; i < stackSize; ++i) {
   7.173 +            final int value = stackTypeIndexPairs.get(i);
   7.174 +            decCounter(value & 0xff);
   7.175 +        }
   7.176 +
   7.177 +        stackTypeIndexPairs.setSize(stackSize - count);
   7.178 +    }
   7.179 +
   7.180 +    private void incCounter(final int type) {
   7.181 +        final int newValue = ++typeCounters[type];
   7.182 +        if (typeMaxCounters[type] < newValue) {
   7.183 +            typeMaxCounters[type] = newValue;
   7.184 +        }
   7.185 +    }
   7.186 +
   7.187 +    private void decCounter(final int type) {
   7.188 +        --typeCounters[type];
   7.189 +    }
   7.190 +
   7.191 +    public Variable getVariable(final int typeAndIndex) {
   7.192 +        final int type = typeAndIndex & 0xff;
   7.193 +        final int index = typeAndIndex >> 8;
   7.194 +
   7.195 +        return Variable.getStackVariable(type, index);
   7.196 +    }
   7.197 +}
     8.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java	Fri Dec 07 19:16:21 2012 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,230 +0,0 @@
     8.4 -/**
     8.5 - * Back 2 Browser Bytecode Translator
     8.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 - *
     8.8 - * This program is free software: you can redistribute it and/or modify
     8.9 - * it under the terms of the GNU General Public License as published by
    8.10 - * the Free Software Foundation, version 2 of the License.
    8.11 - *
    8.12 - * This program is distributed in the hope that it will be useful,
    8.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 - * GNU General Public License for more details.
    8.16 - *
    8.17 - * You should have received a copy of the GNU General Public License
    8.18 - * along with this program. Look for COPYING file in the top folder.
    8.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    8.20 - */
    8.21 -package org.apidesign.vm4brwsr;
    8.22 -
    8.23 -import org.apidesign.javap.TypeArray;
    8.24 -
    8.25 -import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
    8.26 -import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
    8.27 -import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
    8.28 -import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
    8.29 -import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
    8.30 -import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
    8.31 -import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
    8.32 -import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
    8.33 -import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
    8.34 -
    8.35 -public final class StackToVariableMapper {
    8.36 -    private final TypeArray stackTypeIndexPairs;
    8.37 -    private int[] typeCounters;
    8.38 -    private int[] typeMaxCounters;
    8.39 -
    8.40 -    public StackToVariableMapper() {
    8.41 -        stackTypeIndexPairs = new TypeArray();
    8.42 -        typeCounters = new int[Variable.LAST_TYPE + 1];
    8.43 -        typeMaxCounters = new int[Variable.LAST_TYPE + 1];
    8.44 -    }
    8.45 -
    8.46 -    public void clear() {
    8.47 -        for (int type = 0; type <= Variable.LAST_TYPE; ++type) {
    8.48 -            typeCounters[type] = 0;
    8.49 -        }
    8.50 -        stackTypeIndexPairs.clear();
    8.51 -    }
    8.52 -
    8.53 -    public void syncWithFrameStack(final TypeArray frameStack) {
    8.54 -        clear();
    8.55 -
    8.56 -        final int size = frameStack.getSize();
    8.57 -        for (int i = 0; i < size; ++i) {
    8.58 -            final int frameStackValue = frameStack.get(i);
    8.59 -            switch (frameStackValue & 0xff) {
    8.60 -                case ITEM_Integer:
    8.61 -                    pushTypeImpl(Variable.TYPE_INT);
    8.62 -                    break;
    8.63 -                case ITEM_Float:
    8.64 -                    pushTypeImpl(Variable.TYPE_FLOAT);
    8.65 -                    break;
    8.66 -                case ITEM_Double:
    8.67 -                    pushTypeImpl(Variable.TYPE_DOUBLE);
    8.68 -                    break;
    8.69 -                case ITEM_Long:
    8.70 -                    pushTypeImpl(Variable.TYPE_LONG);
    8.71 -                    break;
    8.72 -                case ITEM_Object:
    8.73 -                    pushTypeImpl(Variable.TYPE_REF);
    8.74 -                    break;
    8.75 -
    8.76 -                case ITEM_Bogus:
    8.77 -                case ITEM_Null:
    8.78 -                case ITEM_InitObject:
    8.79 -                case ITEM_NewObject:
    8.80 -                    /* unclear how to handle for now */
    8.81 -                default:
    8.82 -                    throw new IllegalStateException(
    8.83 -                                  "Unhandled frame stack type");
    8.84 -            }
    8.85 -        }
    8.86 -    }
    8.87 -
    8.88 -    public Variable pushI() {
    8.89 -        return pushT(Variable.TYPE_INT);
    8.90 -    }
    8.91 -
    8.92 -    public Variable pushL() {
    8.93 -        return pushT(Variable.TYPE_LONG);
    8.94 -    }
    8.95 -
    8.96 -    public Variable pushF() {
    8.97 -        return pushT(Variable.TYPE_FLOAT);
    8.98 -    }
    8.99 -
   8.100 -    public Variable pushD() {
   8.101 -        return pushT(Variable.TYPE_DOUBLE);
   8.102 -    }
   8.103 -
   8.104 -    public Variable pushA() {
   8.105 -        return pushT(Variable.TYPE_REF);
   8.106 -    }
   8.107 -
   8.108 -    public Variable pushT(final int type) {
   8.109 -        return getVariable(pushTypeImpl(type));
   8.110 -    }
   8.111 -
   8.112 -    public Variable popI() {
   8.113 -        return popT(Variable.TYPE_INT);
   8.114 -    }
   8.115 -
   8.116 -    public Variable popL() {
   8.117 -        return popT(Variable.TYPE_LONG);
   8.118 -    }
   8.119 -
   8.120 -    public Variable popF() {
   8.121 -        return popT(Variable.TYPE_FLOAT);
   8.122 -    }
   8.123 -
   8.124 -    public Variable popD() {
   8.125 -        return popT(Variable.TYPE_DOUBLE);
   8.126 -    }
   8.127 -
   8.128 -    public Variable popA() {
   8.129 -        return popT(Variable.TYPE_REF);
   8.130 -    }
   8.131 -
   8.132 -    public Variable popT(final int type) {
   8.133 -        final Variable variable = getT(0, type);
   8.134 -        popImpl(1);
   8.135 -        return variable;
   8.136 -    }
   8.137 -
   8.138 -    public Variable pop() {
   8.139 -        final Variable variable = get(0);
   8.140 -        popImpl(1);
   8.141 -        return variable;
   8.142 -    }
   8.143 -
   8.144 -    public void pop(final int count) {
   8.145 -        final int stackSize = stackTypeIndexPairs.getSize();
   8.146 -        if (count > stackSize) {
   8.147 -            throw new IllegalStateException("Stack underflow");
   8.148 -        }
   8.149 -        popImpl(count);
   8.150 -    }
   8.151 -
   8.152 -    public Variable getI(final int indexFromTop) {
   8.153 -        return getT(indexFromTop, Variable.TYPE_INT);
   8.154 -    }
   8.155 -
   8.156 -    public Variable getL(final int indexFromTop) {
   8.157 -        return getT(indexFromTop, Variable.TYPE_LONG);
   8.158 -    }
   8.159 -
   8.160 -    public Variable getF(final int indexFromTop) {
   8.161 -        return getT(indexFromTop, Variable.TYPE_FLOAT);
   8.162 -    }
   8.163 -
   8.164 -    public Variable getD(final int indexFromTop) {
   8.165 -        return getT(indexFromTop, Variable.TYPE_DOUBLE);
   8.166 -    }
   8.167 -
   8.168 -    public Variable getA(final int indexFromTop) {
   8.169 -        return getT(indexFromTop, Variable.TYPE_REF);
   8.170 -    }
   8.171 -
   8.172 -    public Variable getT(final int indexFromTop, final int type) {
   8.173 -        final int stackSize = stackTypeIndexPairs.getSize();
   8.174 -        if (indexFromTop >= stackSize) {
   8.175 -            throw new IllegalStateException("Stack underflow");
   8.176 -        }
   8.177 -        final int stackValue =
   8.178 -                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   8.179 -        if ((stackValue & 0xff) != type) {
   8.180 -            throw new IllegalStateException("Type mismatch");
   8.181 -        }
   8.182 -
   8.183 -        return getVariable(stackValue);
   8.184 -    }
   8.185 -
   8.186 -    public Variable get(final int indexFromTop) {
   8.187 -        final int stackSize = stackTypeIndexPairs.getSize();
   8.188 -        if (indexFromTop >= stackSize) {
   8.189 -            throw new IllegalStateException("Stack underflow");
   8.190 -        }
   8.191 -        final int stackValue =
   8.192 -                stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
   8.193 -
   8.194 -        return getVariable(stackValue);
   8.195 -    }
   8.196 -
   8.197 -    private int pushTypeImpl(final int type) {
   8.198 -        final int count = typeCounters[type];
   8.199 -        final int value = (count << 8) | (type & 0xff);
   8.200 -        incCounter(type);
   8.201 -        stackTypeIndexPairs.add(value);
   8.202 -
   8.203 -        return value;
   8.204 -    }
   8.205 -
   8.206 -    private void popImpl(final int count) {
   8.207 -        final int stackSize = stackTypeIndexPairs.getSize();
   8.208 -        for (int i = stackSize - count; i < stackSize; ++i) {
   8.209 -            final int value = stackTypeIndexPairs.get(i);
   8.210 -            decCounter(value & 0xff);
   8.211 -        }
   8.212 -
   8.213 -        stackTypeIndexPairs.setSize(stackSize - count);
   8.214 -    }
   8.215 -
   8.216 -    private void incCounter(final int type) {
   8.217 -        final int newValue = ++typeCounters[type];
   8.218 -        if (typeMaxCounters[type] < newValue) {
   8.219 -            typeMaxCounters[type] = newValue;
   8.220 -        }
   8.221 -    }
   8.222 -
   8.223 -    private void decCounter(final int type) {
   8.224 -        --typeCounters[type];
   8.225 -    }
   8.226 -
   8.227 -    public Variable getVariable(final int typeAndIndex) {
   8.228 -        final int type = typeAndIndex & 0xff;
   8.229 -        final int index = typeAndIndex >> 8;
   8.230 -
   8.231 -        return Variable.getStackVariable(type, index);
   8.232 -    }
   8.233 -}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java	Wed Dec 12 11:04:02 2012 +0100
     9.3 @@ -0,0 +1,110 @@
     9.4 +/**
     9.5 + * Back 2 Browser Bytecode Translator
     9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 + *
     9.8 + * This program is free software: you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License as published by
    9.10 + * the Free Software Foundation, version 2 of the License.
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program. Look for COPYING file in the top folder.
    9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    9.20 + */
    9.21 +package org.apidesign.vm4brwsr;
    9.22 +
    9.23 +import org.apidesign.javap.RuntimeConstants;
    9.24 +
    9.25 +public final class VarType {
    9.26 +    public static final int INTEGER = 0;
    9.27 +    public static final int LONG = 1;
    9.28 +    public static final int FLOAT = 2;
    9.29 +    public static final int DOUBLE = 3;
    9.30 +    public static final int REFERENCE = 4;
    9.31 +
    9.32 +    public static final int LAST = REFERENCE;
    9.33 +
    9.34 +    private VarType() {
    9.35 +    }
    9.36 +
    9.37 +    public static boolean isCategory2(final int varType) {
    9.38 +        return (varType == LONG) || (varType == DOUBLE);
    9.39 +    }
    9.40 +
    9.41 +    public static int fromStackMapType(final int smType) {
    9.42 +        switch (smType & 0xff) {
    9.43 +            case RuntimeConstants.ITEM_Integer:
    9.44 +                return VarType.INTEGER;
    9.45 +            case RuntimeConstants.ITEM_Float:
    9.46 +                return VarType.FLOAT;
    9.47 +            case RuntimeConstants.ITEM_Double:
    9.48 +                return VarType.DOUBLE;
    9.49 +            case RuntimeConstants.ITEM_Long:
    9.50 +                return VarType.LONG;
    9.51 +            case RuntimeConstants.ITEM_Object:
    9.52 +                return VarType.REFERENCE;
    9.53 +
    9.54 +            case RuntimeConstants.ITEM_Bogus:
    9.55 +            case RuntimeConstants.ITEM_Null:
    9.56 +            case RuntimeConstants.ITEM_InitObject:
    9.57 +            case RuntimeConstants.ITEM_NewObject:
    9.58 +                /* unclear how to handle for now */
    9.59 +            default:
    9.60 +                throw new IllegalStateException("Unhandled stack map type");
    9.61 +        }
    9.62 +    }
    9.63 +
    9.64 +    public static int fromConstantType(final byte constantTag) {
    9.65 +        switch (constantTag) {
    9.66 +            case RuntimeConstants.CONSTANT_INTEGER:
    9.67 +                return VarType.INTEGER;
    9.68 +            case RuntimeConstants.CONSTANT_FLOAT:
    9.69 +                return VarType.FLOAT;
    9.70 +            case RuntimeConstants.CONSTANT_LONG:
    9.71 +                return VarType.LONG;
    9.72 +            case RuntimeConstants.CONSTANT_DOUBLE:
    9.73 +                return VarType.DOUBLE;
    9.74 +
    9.75 +            case RuntimeConstants.CONSTANT_CLASS:
    9.76 +            case RuntimeConstants.CONSTANT_UTF8:
    9.77 +            case RuntimeConstants.CONSTANT_UNICODE:
    9.78 +            case RuntimeConstants.CONSTANT_STRING:
    9.79 +                return VarType.REFERENCE;
    9.80 +
    9.81 +            case RuntimeConstants.CONSTANT_FIELD:
    9.82 +            case RuntimeConstants.CONSTANT_METHOD:
    9.83 +            case RuntimeConstants.CONSTANT_INTERFACEMETHOD:
    9.84 +            case RuntimeConstants.CONSTANT_NAMEANDTYPE:
    9.85 +                /* unclear how to handle for now */
    9.86 +            default:
    9.87 +                throw new IllegalStateException("Unhandled constant tag");
    9.88 +        }
    9.89 +    }
    9.90 +
    9.91 +    public static int fromFieldType(final char fieldType) {
    9.92 +        switch (fieldType) {
    9.93 +            case 'B':
    9.94 +            case 'C':
    9.95 +            case 'S':
    9.96 +            case 'Z':
    9.97 +            case 'I':
    9.98 +                return VarType.INTEGER;
    9.99 +            case 'J':
   9.100 +                return VarType.LONG;
   9.101 +            case 'F':
   9.102 +                return VarType.FLOAT;
   9.103 +            case 'D':
   9.104 +                return VarType.DOUBLE;
   9.105 +            case 'L':
   9.106 +            case '[':
   9.107 +                return VarType.REFERENCE;
   9.108 +
   9.109 +            default:
   9.110 +                throw new IllegalStateException("Unhandled field type");
   9.111 +        }
   9.112 +    }
   9.113 +}
    10.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Variable.java	Fri Dec 07 19:16:21 2012 +0100
    10.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Variable.java	Wed Dec 12 11:04:02 2012 +0100
    10.3 @@ -18,15 +18,8 @@
    10.4  package org.apidesign.vm4brwsr;
    10.5  
    10.6  public final class Variable implements CharSequence {
    10.7 -    public static final int TYPE_INT = 0;
    10.8 -    public static final int TYPE_LONG = 1;
    10.9 -    public static final int TYPE_FLOAT = 2;
   10.10 -    public static final int TYPE_DOUBLE = 3;
   10.11 -    public static final int TYPE_REF = 4;
   10.12 -
   10.13 -    public static final int LAST_TYPE = TYPE_REF;
   10.14 -
   10.15      private static final String STACK_VAR_PREFIX = "st";
   10.16 +    private static final String LOCAL_VAR_PREFIX = "lc";
   10.17  
   10.18      private final String name;
   10.19      private final int type;
   10.20 @@ -46,6 +39,12 @@
   10.21          return new Variable(STACK_VAR_PREFIX, type, index);
   10.22      }
   10.23  
   10.24 +    public static Variable getLocalVariable(
   10.25 +            final int type, final int index) {
   10.26 +        // TODO: precreate frequently used variables
   10.27 +        return new Variable(LOCAL_VAR_PREFIX, type, index);
   10.28 +    }
   10.29 +
   10.30      public String getName() {
   10.31          return name;
   10.32      }
   10.33 @@ -59,7 +58,7 @@
   10.34      }
   10.35  
   10.36      public boolean isCategory2() {
   10.37 -        return (type == TYPE_LONG) || (type == TYPE_DOUBLE);
   10.38 +        return VarType.isCategory2(type);
   10.39      }
   10.40  
   10.41      @Override