/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2011, Stefan Hepp (stefan@stefant.org). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.common.type; import org.apache.bcel.generic.Type; import javax.crypto.spec.IvParameterSpec; import java.util.ArrayList; import java.util.List; /** * @author Stefan Hepp (stefan@stefant.org) */ public class ValueTable { private final List<ValueInfo> locals; private final List<ValueInfo> stack; public ValueTable() { locals = new ArrayList<ValueInfo>(4); stack = new ArrayList<ValueInfo>(4); } public List<ValueInfo> getLocals() { return locals; } public List<ValueInfo> getStack() { return stack; } public ValueInfo setLocalValue(int index, ValueInfo value) { for (int i = locals.size(); i <= index; i++) { locals.add(ValueInfo.UNUSED); } ValueInfo old = locals.set(index, value); if (value.usesTwoSlots()) { if (locals.size() > index+1) { locals.set(index+1, ValueInfo.CONTINUED); } else { locals.add(ValueInfo.CONTINUED); } } return old; } public ValueInfo getLocalValue(int index) { if (index >= locals.size()) return ValueInfo.UNUSED; return locals.get(index); } public int addLocalValue(ValueInfo value) { int pos = locals.size(); locals.add(value); if (value.usesTwoSlots()) { locals.add(ValueInfo.CONTINUED); } return pos; } public void push(ValueInfo value) { push(value, true); } public void push(ValueInfo value, boolean addContinueMarker) { if (Type.VOID.equals(value.getType()) && !value.isThisReference()) return; stack.add(value); if (addContinueMarker && value.usesTwoSlots()) { stack.add(ValueInfo.CONTINUED); } } /** * @param down number of slots down from the top slot * @return the value on the stack counted down from the top */ public ValueInfo top(int down) { if (stack.size()-down-1<0) return ValueInfo.UNUSED; return stack.get(stack.size()-down-1); } /** * @return the top stack slot value. */ public ValueInfo top() { if (stack.isEmpty()) return ValueInfo.UNUSED; return stack.get(stack.size()-1); } /** * @return remove the top slot from the stack and return it. */ public ValueInfo pop() { if (stack.isEmpty()) return ValueInfo.UNUSED; return stack.remove(stack.size()-1); } /** * remove the top slot from the stack, or if there is a 64bit value on top, remove two slots. * @return the removed value. */ public ValueInfo popValue() { ValueInfo top = pop(); return top.isContinued() ? pop() : top; } /** * remove the top n slots from the stack. * @param num number of slots to remove */ public void pop(int num) { for (int i = 0; i < num; i++) { pop(); } } /** * @return the top slot from the stack, or if there is a 64bit value on top, the second slot down. */ public ValueInfo topValue() { ValueInfo top = top(); return top.isContinued() ? top(1) : top; } public ValueInfo getStackEntry(int index) { if (stack.size() <= index) return ValueInfo.UNUSED; return stack.get(index); } public int getLocalsSize() { return locals.size(); } public int getStackSize() { return stack.size(); } public void clear() { locals.clear(); stack.clear(); } /** * Insert a value into the stack. This does not create an additional slot if the value is of category 2. * @param down number of slots down from the top to insert the new value into. * @param value the new value to insert. */ public void insert(int down, ValueInfo value) { stack.add(stack.size()-down, value); } public void clearStack() { stack.clear(); } }