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