1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java Thu Nov 29 20:19:00 2012 +0100
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/StackToVariableMapper.java Fri Dec 07 15:02:35 2012 +0100
1.3 @@ -17,77 +17,214 @@
1.4 */
1.5 package org.apidesign.vm4brwsr;
1.6
1.7 +import org.apidesign.javap.TypeArray;
1.8 +
1.9 +import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
1.10 +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
1.11 +import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
1.12 +import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
1.13 +import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
1.14 +import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
1.15 +import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
1.16 +import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
1.17 +import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
1.18 +
1.19 public final class StackToVariableMapper {
1.20 - private static final String VAR_NAME_PREFIX = "stack";
1.21 -
1.22 - private int stackSize;
1.23 - private StringBuilder varNameBuilder;
1.24 -
1.25 - private int maxStackSize;
1.26 + private final TypeArray stackTypeIndexPairs;
1.27 + private int[] typeCounters;
1.28 + private int[] typeMaxCounters;
1.29
1.30 public StackToVariableMapper() {
1.31 - varNameBuilder = new StringBuilder(VAR_NAME_PREFIX);
1.32 + stackTypeIndexPairs = new TypeArray();
1.33 + typeCounters = new int[Variable.LAST_TYPE + 1];
1.34 + typeMaxCounters = new int[Variable.LAST_TYPE + 1];
1.35 }
1.36
1.37 - public void reset(final int newStackSize) {
1.38 - stackSize = newStackSize;
1.39 - if (maxStackSize < stackSize) {
1.40 - maxStackSize = stackSize;
1.41 + public void clear() {
1.42 + for (int type = 0; type <= Variable.LAST_TYPE; ++type) {
1.43 + typeCounters[type] = 0;
1.44 + }
1.45 + stackTypeIndexPairs.clear();
1.46 + }
1.47 +
1.48 + public void syncWithFrameStack(final TypeArray frameStack) {
1.49 + clear();
1.50 +
1.51 + final int size = frameStack.getSize();
1.52 + for (int i = 0; i < size; ++i) {
1.53 + final int frameStackValue = frameStack.get(i);
1.54 + switch (frameStackValue & 0xff) {
1.55 + case ITEM_Integer:
1.56 + pushTypeImpl(Variable.TYPE_INT);
1.57 + break;
1.58 + case ITEM_Float:
1.59 + pushTypeImpl(Variable.TYPE_FLOAT);
1.60 + break;
1.61 + case ITEM_Double:
1.62 + pushTypeImpl(Variable.TYPE_DOUBLE);
1.63 + break;
1.64 + case ITEM_Long:
1.65 + pushTypeImpl(Variable.TYPE_LONG);
1.66 + break;
1.67 + case ITEM_Object:
1.68 + pushTypeImpl(Variable.TYPE_REF);
1.69 + break;
1.70 +
1.71 + case ITEM_Bogus:
1.72 + case ITEM_Null:
1.73 + case ITEM_InitObject:
1.74 + case ITEM_NewObject:
1.75 + /* unclear how to handle for now */
1.76 + default:
1.77 + throw new IllegalStateException(
1.78 + "Unhandled frame stack type");
1.79 + }
1.80 }
1.81 }
1.82
1.83 - public void push(final int numOfElements) {
1.84 - stackSize += numOfElements;
1.85 - if (maxStackSize < stackSize) {
1.86 - maxStackSize = stackSize;
1.87 + public Variable pushI() {
1.88 + return pushT(Variable.TYPE_INT);
1.89 + }
1.90 +
1.91 + public Variable pushL() {
1.92 + return pushT(Variable.TYPE_LONG);
1.93 + }
1.94 +
1.95 + public Variable pushF() {
1.96 + return pushT(Variable.TYPE_FLOAT);
1.97 + }
1.98 +
1.99 + public Variable pushD() {
1.100 + return pushT(Variable.TYPE_DOUBLE);
1.101 + }
1.102 +
1.103 + public Variable pushA() {
1.104 + return pushT(Variable.TYPE_REF);
1.105 + }
1.106 +
1.107 + public Variable pushT(final int type) {
1.108 + return getVariable(pushTypeImpl(type));
1.109 + }
1.110 +
1.111 + public Variable popI() {
1.112 + return popT(Variable.TYPE_INT);
1.113 + }
1.114 +
1.115 + public Variable popL() {
1.116 + return popT(Variable.TYPE_LONG);
1.117 + }
1.118 +
1.119 + public Variable popF() {
1.120 + return popT(Variable.TYPE_FLOAT);
1.121 + }
1.122 +
1.123 + public Variable popD() {
1.124 + return popT(Variable.TYPE_DOUBLE);
1.125 + }
1.126 +
1.127 + public Variable popA() {
1.128 + return popT(Variable.TYPE_REF);
1.129 + }
1.130 +
1.131 + public Variable popT(final int type) {
1.132 + final Variable variable = getT(0, type);
1.133 + popImpl(1);
1.134 + return variable;
1.135 + }
1.136 +
1.137 + public Variable pop() {
1.138 + final Variable variable = get(0);
1.139 + popImpl(1);
1.140 + return variable;
1.141 + }
1.142 +
1.143 + public void pop(final int count) {
1.144 + final int stackSize = stackTypeIndexPairs.getSize();
1.145 + if (count > stackSize) {
1.146 + throw new IllegalStateException("Stack underflow");
1.147 + }
1.148 + popImpl(count);
1.149 + }
1.150 +
1.151 + public Variable getI(final int indexFromTop) {
1.152 + return getT(indexFromTop, Variable.TYPE_INT);
1.153 + }
1.154 +
1.155 + public Variable getL(final int indexFromTop) {
1.156 + return getT(indexFromTop, Variable.TYPE_LONG);
1.157 + }
1.158 +
1.159 + public Variable getF(final int indexFromTop) {
1.160 + return getT(indexFromTop, Variable.TYPE_FLOAT);
1.161 + }
1.162 +
1.163 + public Variable getD(final int indexFromTop) {
1.164 + return getT(indexFromTop, Variable.TYPE_DOUBLE);
1.165 + }
1.166 +
1.167 + public Variable getA(final int indexFromTop) {
1.168 + return getT(indexFromTop, Variable.TYPE_REF);
1.169 + }
1.170 +
1.171 + public Variable getT(final int indexFromTop, final int type) {
1.172 + final int stackSize = stackTypeIndexPairs.getSize();
1.173 + if (indexFromTop >= stackSize) {
1.174 + throw new IllegalStateException("Stack underflow");
1.175 + }
1.176 + final int stackValue =
1.177 + stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
1.178 + if ((stackValue & 0xff) != type) {
1.179 + throw new IllegalStateException("Type mismatch");
1.180 + }
1.181 +
1.182 + return getVariable(stackValue);
1.183 + }
1.184 +
1.185 + public Variable get(final int indexFromTop) {
1.186 + final int stackSize = stackTypeIndexPairs.getSize();
1.187 + if (indexFromTop >= stackSize) {
1.188 + throw new IllegalStateException("Stack underflow");
1.189 + }
1.190 + final int stackValue =
1.191 + stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
1.192 +
1.193 + return getVariable(stackValue);
1.194 + }
1.195 +
1.196 + private int pushTypeImpl(final int type) {
1.197 + final int count = typeCounters[type];
1.198 + final int value = (count << 8) | (type & 0xff);
1.199 + incCounter(type);
1.200 + stackTypeIndexPairs.add(value);
1.201 +
1.202 + return value;
1.203 + }
1.204 +
1.205 + private void popImpl(final int count) {
1.206 + final int stackSize = stackTypeIndexPairs.getSize();
1.207 + for (int i = stackSize - count; i < stackSize; ++i) {
1.208 + final int value = stackTypeIndexPairs.get(i);
1.209 + decCounter(value & 0xff);
1.210 + }
1.211 +
1.212 + stackTypeIndexPairs.setSize(stackSize - count);
1.213 + }
1.214 +
1.215 + private void incCounter(final int type) {
1.216 + final int newValue = ++typeCounters[type];
1.217 + if (typeMaxCounters[type] < newValue) {
1.218 + typeMaxCounters[type] = newValue;
1.219 }
1.220 }
1.221
1.222 - public String push() {
1.223 - push(1);
1.224 - return get(0);
1.225 + private void decCounter(final int type) {
1.226 + --typeCounters[type];
1.227 }
1.228
1.229 - public void pop(final int numOfElements) {
1.230 - if (numOfElements > stackSize) {
1.231 - throw new IllegalStateException("Stack underflow");
1.232 - }
1.233 - stackSize -= numOfElements;
1.234 - }
1.235 + public Variable getVariable(final int typeAndIndex) {
1.236 + final int type = typeAndIndex & 0xff;
1.237 + final int index = typeAndIndex >> 8;
1.238
1.239 - public String pop() {
1.240 - final String variableName = get(0);
1.241 - pop(1);
1.242 - return variableName;
1.243 - }
1.244 -
1.245 - public String get(final int indexFromTop) {
1.246 - if (indexFromTop >= stackSize) {
1.247 - throw new IllegalStateException("Stack underflow");
1.248 - }
1.249 -
1.250 - return constructVariableName(stackSize - indexFromTop - 1);
1.251 - }
1.252 -
1.253 - public String top() {
1.254 - return get(0);
1.255 - }
1.256 -
1.257 - public String bottom() {
1.258 - if (stackSize == 0) {
1.259 - throw new IllegalStateException("Stack underflow");
1.260 - }
1.261 -
1.262 - return constructVariableName(0);
1.263 - }
1.264 -
1.265 - public int getMaxStackSize() {
1.266 - return maxStackSize;
1.267 - }
1.268 -
1.269 - public String constructVariableName(final int index) {
1.270 - varNameBuilder.setLength(VAR_NAME_PREFIX.length());
1.271 - varNameBuilder.append(index);
1.272 - return varNameBuilder.toString();
1.273 + return Variable.getStackVariable(type, index);
1.274 }
1.275 }