Mercurial > hg > truffle
diff graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java @ 2611:bd235cb4375a
FrameState cleanup: split into FrameStateBuilder and fixed-size FrameState, removed MutableFrameState
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Fri, 06 May 2011 17:08:00 +0200 |
parents | |
children | 3558ca7088c0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Fri May 06 17:08:00 2011 +0200 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.c1x.value; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.sun.c1x.graph.*; +import com.sun.c1x.ir.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + +import static com.sun.c1x.value.ValueUtil.*; +import static java.lang.reflect.Modifier.*; + + +public class FrameStateBuilder { + + private final Graph graph; + + private final Value[] locals; + private final Value[] stack; + private final ArrayList<Value> locks; + + private int stackIndex; + + public FrameStateBuilder(RiMethod method, Graph graph) { + this.graph = graph; + this.locals = new Value[method.maxLocals()]; + this.stack = new Value[method.maxStackSize()]; + + int index = 0; + if (!isStatic(method.accessFlags())) { + // add the receiver and assume it is non null + Local local = new Local(method.holder().kind(), index, graph); + local.setFlag(Value.Flag.NonNull, true); + local.setDeclaredType(method.holder()); + storeLocal(index, local); + index = 1; + } + RiSignature sig = method.signature(); + int max = sig.argumentCount(false); + RiType accessingClass = method.holder(); + for (int i = 0; i < max; i++) { + RiType type = sig.argumentTypeAt(i, accessingClass); + CiKind kind = type.kind().stackKind(); + Local local = new Local(kind, index, graph); + if (type.isResolved()) { + local.setDeclaredType(type); + } + storeLocal(index, local); + index += kind.sizeInSlots(); + } + this.locks = new ArrayList<Value>(); + } + + public void initializeFrom(FrameState other) { + assert locals.length == other.localsSize; + assert stack.length >= other.stackSize(); + + this.stackIndex = other.stackSize(); + System.arraycopy(other.values, 0, locals, 0, locals.length); + System.arraycopy(other.values, other.localsSize(), stack, 0, stackIndex); + locks.clear(); + for (int i = 0; i < other.locksSize(); i++) { + locks.add(other.lockAt(i)); + } + } + + public FrameState create(int bci) { + return new FrameState(bci, locals, stack, stackIndex, locks); + } + + /** + * Pushes an instruction onto the stack with the expected type. + * @param kind the type expected for this instruction + * @param x the instruction to push onto the stack + */ + public void push(CiKind kind, Value x) { + assert kind != CiKind.Void; + xpush(assertKind(kind, x)); + if (kind.sizeInSlots() == 2) { + xpush(null); + } + } + + /** + * Pushes a value onto the stack without checking the type. + * @param x the instruction to push onto the stack + */ + public void xpush(Value x) { + stack[stackIndex++] = x; + } + + /** + * Pushes a value onto the stack and checks that it is an int. + * @param x the instruction to push onto the stack + */ + public void ipush(Value x) { + xpush(assertInt(x)); + } + + /** + * Pushes a value onto the stack and checks that it is a float. + * @param x the instruction to push onto the stack + */ + public void fpush(Value x) { + xpush(assertFloat(x)); + } + + /** + * Pushes a value onto the stack and checks that it is an object. + * @param x the instruction to push onto the stack + */ + public void apush(Value x) { + xpush(assertObject(x)); + } + + /** + * Pushes a value onto the stack and checks that it is a word. + * @param x the instruction to push onto the stack + */ + public void wpush(Value x) { + xpush(assertWord(x)); + } + + /** + * Pushes a value onto the stack and checks that it is a JSR return address. + * @param x the instruction to push onto the stack + */ + public void jpush(Value x) { + xpush(assertJsr(x)); + } + + /** + * Pushes a value onto the stack and checks that it is a long. + * + * @param x the instruction to push onto the stack + */ + public void lpush(Value x) { + xpush(assertLong(x)); + xpush(null); + } + + /** + * Pushes a value onto the stack and checks that it is a double. + * @param x the instruction to push onto the stack + */ + public void dpush(Value x) { + xpush(assertDouble(x)); + xpush(null); + } + + /** + * Pops an instruction off the stack with the expected type. + * @param kind the expected type + * @return the instruction on the top of the stack + */ + public Value pop(CiKind kind) { + if (kind.sizeInSlots() == 2) { + xpop(); + } + return assertKind(kind, xpop()); + } + + /** + * Pops a value off of the stack without checking the type. + * @return x the instruction popped off the stack + */ + public Value xpop() { + return stack[--stackIndex]; + } + + /** + * Pops a value off of the stack and checks that it is an int. + * @return x the instruction popped off the stack + */ + public Value ipop() { + return assertInt(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is a float. + * @return x the instruction popped off the stack + */ + public Value fpop() { + return assertFloat(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is an object. + * @return x the instruction popped off the stack + */ + public Value apop() { + return assertObject(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is a word. + * @return x the instruction popped off the stack + */ + public Value wpop() { + return assertWord(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is a JSR return address. + * @return x the instruction popped off the stack + */ + public Value jpop() { + return assertJsr(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is a long. + * @return x the instruction popped off the stack + */ + public Value lpop() { + assertHigh(xpop()); + return assertLong(xpop()); + } + + /** + * Pops a value off of the stack and checks that it is a double. + * @return x the instruction popped off the stack + */ + public Value dpop() { + assertHigh(xpop()); + return assertDouble(xpop()); + } + + /** + * Pop the specified number of slots off of this stack and return them as an array of instructions. + * @param size the number of arguments off of the stack + * @return an array containing the arguments off of the stack + */ + public Value[] popArguments(int size) { + int base = stackIndex - size; + Value[] r = new Value[size]; + for (int i = 0; i < size; ++i) { + assert stack[base + i] != null || stack[base + i - 1].kind.jvmSlots == 2; + r[i] = stack[base + i]; + } + stackIndex = base; + return r; + } + + /** + * Truncates this stack to the specified size. + * @param size the size to truncate to + */ + public void truncateStack(int size) { + stackIndex = size; + assert stackIndex >= 0; + } + + /** + * Clears all values on this stack. + */ + public void clearStack() { + stackIndex = 0; + } + + /** + * Loads the local variable at the specified index. + * + * @param i the index of the local variable to load + * @return the instruction that produced the specified local + */ + public Value loadLocal(int i) { + Value x = locals[i]; + if (x != null) { + if (x.isIllegal()) { + return null; + } + assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi; + } + return x; + } + + /** + * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word}, + * then the next local variable index is also overwritten. + * + * @param i the index at which to store + * @param x the instruction which produces the value for the local + */ + public void storeLocal(int i, Value x) { + locals[i] = x; + if (isDoubleWord(x)) { + // (tw) if this was a double word then kill i+1 + locals[i + 1] = null; + } + if (i > 0) { + // if there was a double word at i - 1, then kill it + Value p = locals[i - 1]; + if (isDoubleWord(p)) { + locals[i - 1] = null; + } + } + } + + /** + * Locks a new object within the specified IRScope. + * @param scope the IRScope in which this locking operation occurs + * @param obj the object being locked + */ + public void lock(IR ir, Value obj, int totalNumberOfLocks) { + locks.add(obj); + ir.updateMaxLocks(totalNumberOfLocks); + } + + /** + * Unlock the lock on the top of the stack. + */ + public void unlock() { + locks.remove(locks.size() - 1); + } + + /** + * Get the value on the stack at the specified stack index. + * + * @param i the index into the stack, with {@code 0} being the bottom of the stack + * @return the instruction at the specified position in the stack + */ + public final Value stackAt(int i) { + return stack[i]; + } + + /** + * Gets the value in the local variables at the specified index. + * + * @param i the index into the locals + * @return the instruction that produced the value for the specified local + */ + public final Value localAt(int i) { + return locals[i]; + } + + /** + * Retrieves the lock at the specified index in the lock stack. + * @param i the index into the lock stack + * @return the instruction which produced the object at the specified location in the lock stack + */ + public final Value lockAt(int i) { + return locks.get(i); + } + + /** + * Returns the size of the local variables. + * + * @return the size of the local variables + */ + public int localsSize() { + return locals.length; + } + + /** + * Gets number of locks held by this frame state. + */ + public int locksSize() { + return locks.size(); + } + + /** + * Gets the current size (height) of the stack. + */ + public int stackSize() { + return stackIndex; + } + + public Iterator<Value> locals() { + return new ValueArrayIterator(locals); + } + + public Iterator<Value> stack() { + return new ValueArrayIterator(locals); + } + + public List<Value> locks() { + return Collections.unmodifiableList(locks); + } + + + private static class ValueArrayIterator implements Iterator<Value> { + private final Value[] array; + private int index; + private int length; + + public ValueArrayIterator(Value[] array, int length) { + assert length <= array.length; + this.array = array; + this.index = 0; + } + + public ValueArrayIterator(Value[] array) { + this(array, array.length); + } + + @Override + public boolean hasNext() { + return index < array.length; + } + + @Override + public Value next() { + return array[index++]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("cannot remove from array"); + } + + } + +}