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@307: public final class StackMapper { lubomir@281: private final TypeArray stackTypeIndexPairs; lubomir@281: private int[] typeCounters; lubomir@281: private int[] typeMaxCounters; lubomir@221: lubomir@307: public StackMapper() { lubomir@281: stackTypeIndexPairs = new TypeArray(); lubomir@307: typeCounters = new int[VarType.LAST + 1]; lubomir@307: typeMaxCounters = new int[VarType.LAST + 1]; lubomir@221: } lubomir@221: lubomir@281: public void clear() { lubomir@307: for (int type = 0; type <= VarType.LAST; ++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@307: pushTypeImpl(VarType.fromStackMapType(frameStack.get(i))); lubomir@221: } lubomir@221: } lubomir@221: lubomir@281: public Variable pushI() { lubomir@307: return pushT(VarType.INTEGER); lubomir@281: } lubomir@281: lubomir@281: public Variable pushL() { lubomir@307: return pushT(VarType.LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable pushF() { lubomir@307: return pushT(VarType.FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable pushD() { lubomir@307: return pushT(VarType.DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable pushA() { lubomir@307: return pushT(VarType.REFERENCE); 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@307: return popT(VarType.INTEGER); lubomir@281: } lubomir@281: lubomir@281: public Variable popL() { lubomir@307: return popT(VarType.LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable popF() { lubomir@307: return popT(VarType.FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable popD() { lubomir@307: return popT(VarType.DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable popA() { lubomir@307: return popT(VarType.REFERENCE); 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@307: return getT(indexFromTop, VarType.INTEGER); lubomir@281: } lubomir@281: lubomir@281: public Variable getL(final int indexFromTop) { lubomir@307: return getT(indexFromTop, VarType.LONG); lubomir@281: } lubomir@281: lubomir@281: public Variable getF(final int indexFromTop) { lubomir@307: return getT(indexFromTop, VarType.FLOAT); lubomir@281: } lubomir@281: lubomir@281: public Variable getD(final int indexFromTop) { lubomir@307: return getT(indexFromTop, VarType.DOUBLE); lubomir@281: } lubomir@281: lubomir@281: public Variable getA(final int indexFromTop) { lubomir@307: return getT(indexFromTop, VarType.REFERENCE); 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: }