lubomir@221: /** lubomir@221: * Back 2 Browser Bytecode Translator lubomir@221: * Copyright (C) 2012 Jaroslav Tulach lubomir@221: * lubomir@221: * This program is free software: you can redistribute it and/or modify lubomir@221: * it under the terms of the GNU General Public License as published by lubomir@221: * the Free Software Foundation, version 2 of the License. lubomir@221: * lubomir@221: * This program is distributed in the hope that it will be useful, lubomir@221: * but WITHOUT ANY WARRANTY; without even the implied warranty of lubomir@221: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the lubomir@221: * GNU General Public License for more details. lubomir@221: * lubomir@221: * You should have received a copy of the GNU General Public License lubomir@221: * along with this program. Look for COPYING file in the top folder. lubomir@221: * If not, see http://opensource.org/licenses/GPL-2.0. lubomir@221: */ lubomir@221: package org.apidesign.vm4brwsr; lubomir@221: lubomir@281: import org.apidesign.javap.TypeArray; lubomir@281: lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Integer; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Float; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Double; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Long; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Null; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_Object; lubomir@281: import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject; lubomir@281: lubomir@221: public final class StackToVariableMapper { lubomir@281: private final TypeArray stackTypeIndexPairs; lubomir@281: private int[] typeCounters; lubomir@281: private int[] typeMaxCounters; lubomir@221: lubomir@221: public StackToVariableMapper() { lubomir@281: stackTypeIndexPairs = new TypeArray(); lubomir@281: typeCounters = new int[Variable.LAST_TYPE + 1]; lubomir@281: typeMaxCounters = new int[Variable.LAST_TYPE + 1]; lubomir@221: } lubomir@221: lubomir@281: public void clear() { lubomir@281: for (int type = 0; type <= Variable.LAST_TYPE; ++type) { lubomir@281: typeCounters[type] = 0; lubomir@281: } lubomir@281: stackTypeIndexPairs.clear(); lubomir@281: } lubomir@281: lubomir@281: public void syncWithFrameStack(final TypeArray frameStack) { lubomir@281: clear(); lubomir@281: lubomir@281: final int size = frameStack.getSize(); lubomir@281: for (int i = 0; i < size; ++i) { lubomir@281: final int frameStackValue = frameStack.get(i); lubomir@281: switch (frameStackValue & 0xff) { lubomir@281: case ITEM_Integer: lubomir@281: pushTypeImpl(Variable.TYPE_INT); lubomir@281: break; lubomir@281: case ITEM_Float: lubomir@281: pushTypeImpl(Variable.TYPE_FLOAT); lubomir@281: break; lubomir@281: case ITEM_Double: lubomir@281: pushTypeImpl(Variable.TYPE_DOUBLE); lubomir@281: break; lubomir@281: case ITEM_Long: lubomir@281: pushTypeImpl(Variable.TYPE_LONG); lubomir@281: break; lubomir@281: case ITEM_Object: lubomir@281: pushTypeImpl(Variable.TYPE_REF); lubomir@281: break; lubomir@281: lubomir@281: case ITEM_Bogus: lubomir@281: case ITEM_Null: lubomir@281: case ITEM_InitObject: lubomir@281: case ITEM_NewObject: lubomir@281: /* unclear how to handle for now */ lubomir@281: default: lubomir@281: throw new IllegalStateException( lubomir@281: "Unhandled frame stack type"); lubomir@281: } lubomir@221: } lubomir@221: } lubomir@221: lubomir@281: public Variable pushI() { lubomir@281: return pushT(Variable.TYPE_INT); lubomir@281: } lubomir@281: lubomir@281: public Variable pushL() { lubomir@281: return pushT(Variable.TYPE_LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable pushF() { lubomir@281: return pushT(Variable.TYPE_FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable pushD() { lubomir@281: return pushT(Variable.TYPE_DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable pushA() { lubomir@281: return pushT(Variable.TYPE_REF); lubomir@281: } lubomir@281: lubomir@281: public Variable pushT(final int type) { lubomir@281: return getVariable(pushTypeImpl(type)); lubomir@281: } lubomir@281: lubomir@281: public Variable popI() { lubomir@281: return popT(Variable.TYPE_INT); lubomir@281: } lubomir@281: lubomir@281: public Variable popL() { lubomir@281: return popT(Variable.TYPE_LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable popF() { lubomir@281: return popT(Variable.TYPE_FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable popD() { lubomir@281: return popT(Variable.TYPE_DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable popA() { lubomir@281: return popT(Variable.TYPE_REF); lubomir@281: } lubomir@281: lubomir@281: public Variable popT(final int type) { lubomir@281: final Variable variable = getT(0, type); lubomir@281: popImpl(1); lubomir@281: return variable; lubomir@281: } lubomir@281: lubomir@281: public Variable pop() { lubomir@281: final Variable variable = get(0); lubomir@281: popImpl(1); lubomir@281: return variable; lubomir@281: } lubomir@281: lubomir@281: public void pop(final int count) { lubomir@281: final int stackSize = stackTypeIndexPairs.getSize(); lubomir@281: if (count > stackSize) { lubomir@281: throw new IllegalStateException("Stack underflow"); lubomir@281: } lubomir@281: popImpl(count); lubomir@281: } lubomir@281: lubomir@281: public Variable getI(final int indexFromTop) { lubomir@281: return getT(indexFromTop, Variable.TYPE_INT); lubomir@281: } lubomir@281: lubomir@281: public Variable getL(final int indexFromTop) { lubomir@281: return getT(indexFromTop, Variable.TYPE_LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable getF(final int indexFromTop) { lubomir@281: return getT(indexFromTop, Variable.TYPE_FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable getD(final int indexFromTop) { lubomir@281: return getT(indexFromTop, Variable.TYPE_DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable getA(final int indexFromTop) { lubomir@281: return getT(indexFromTop, Variable.TYPE_REF); lubomir@281: } lubomir@281: lubomir@281: public Variable getT(final int indexFromTop, final int type) { lubomir@281: final int stackSize = stackTypeIndexPairs.getSize(); lubomir@281: if (indexFromTop >= stackSize) { lubomir@281: throw new IllegalStateException("Stack underflow"); lubomir@281: } lubomir@281: final int stackValue = lubomir@281: stackTypeIndexPairs.get(stackSize - indexFromTop - 1); lubomir@281: if ((stackValue & 0xff) != type) { lubomir@281: throw new IllegalStateException("Type mismatch"); lubomir@281: } lubomir@281: lubomir@281: return getVariable(stackValue); lubomir@281: } lubomir@281: lubomir@281: public Variable get(final int indexFromTop) { lubomir@281: final int stackSize = stackTypeIndexPairs.getSize(); lubomir@281: if (indexFromTop >= stackSize) { lubomir@281: throw new IllegalStateException("Stack underflow"); lubomir@281: } lubomir@281: final int stackValue = lubomir@281: stackTypeIndexPairs.get(stackSize - indexFromTop - 1); lubomir@281: lubomir@281: return getVariable(stackValue); lubomir@281: } lubomir@281: lubomir@281: private int pushTypeImpl(final int type) { lubomir@281: final int count = typeCounters[type]; lubomir@281: final int value = (count << 8) | (type & 0xff); lubomir@281: incCounter(type); lubomir@281: stackTypeIndexPairs.add(value); lubomir@281: lubomir@281: return value; lubomir@281: } lubomir@281: lubomir@281: private void popImpl(final int count) { lubomir@281: final int stackSize = stackTypeIndexPairs.getSize(); lubomir@281: for (int i = stackSize - count; i < stackSize; ++i) { lubomir@281: final int value = stackTypeIndexPairs.get(i); lubomir@281: decCounter(value & 0xff); lubomir@281: } lubomir@281: lubomir@281: stackTypeIndexPairs.setSize(stackSize - count); lubomir@281: } lubomir@281: lubomir@281: private void incCounter(final int type) { lubomir@281: final int newValue = ++typeCounters[type]; lubomir@281: if (typeMaxCounters[type] < newValue) { lubomir@281: typeMaxCounters[type] = newValue; lubomir@221: } lubomir@221: } lubomir@221: lubomir@281: private void decCounter(final int type) { lubomir@281: --typeCounters[type]; lubomir@221: } lubomir@221: lubomir@281: public Variable getVariable(final int typeAndIndex) { lubomir@281: final int type = typeAndIndex & 0xff; lubomir@281: final int index = typeAndIndex >> 8; lubomir@221: lubomir@281: return Variable.getStackVariable(type, index); lubomir@221: } lubomir@221: }