# HG changeset patch # User Josef Eisl # Date 1396892500 -7200 # Node ID 14e542e27076b166be0cef0c9e7228d926bc15c0 # Parent e098038093d5fde2b4e76ba4551d21cba205fab9 Lift implementation from HIRFrameStateBuilder up to AbstractFrameStateBuilder if possible. diff -r e098038093d5 -r 14e542e27076 graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java Mon Apr 07 17:01:54 2014 +0200 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java Mon Apr 07 19:41:40 2014 +0200 @@ -24,226 +24,35 @@ package com.oracle.graal.baseline; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.java.*; -public class LIRFrameStateBuilder extends AbstractFrameStateBuilder { +public class LIRFrameStateBuilder extends AbstractFrameStateBuilder { - private final Value[] locals; - private final Value[] stack; - private Value[] lockedObjects; + private static final Value[] EMPTY_ARRAY = new Value[0]; public LIRFrameStateBuilder(ResolvedJavaMethod method) { - super(method); - - this.locals = new Value[method.getMaxLocals()]; // we always need at least one stack slot (for exceptions) - this.stack = new Value[Math.max(1, method.getMaxStackSize())]; + super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); } protected LIRFrameStateBuilder(LIRFrameStateBuilder other) { super(other); - // TODO Auto-generated constructor stub - locals = other.locals; - stack = other.stack; - lockedObjects = other.lockedObjects; - } - - @Override - public int localsSize() { - return locals.length; - } - - @Override - public Value localAt(int i) { - return locals[i]; - } - - @Override - public Value stackAt(int i) { - return stack[i]; - } - - @Override - public Value loadLocal(int i) { - Value x = locals[i]; - assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; - assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); - return x; - } - - @Override - public void storeLocal(int i, Value x) { - assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; - locals[i] = x; - if (x != null && isTwoSlot(x.getKind())) { - // if this is a double word, then kill i+1 - locals[i + 1] = null; - } - if (x != null && i > 0) { - Value p = locals[i - 1]; - if (p != null && isTwoSlot(p.getKind())) { - // if there was a double word at i - 1, then kill it - locals[i - 1] = null; - } - } } @Override - public void storeStack(int i, Value x) { - assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; - stack[i] = x; - } - - @Override - public void push(Kind kind, Value x) { - assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; - xpush(assertKind(kind, x)); - if (isTwoSlot(kind)) { - xpush(null); - } - } - - @Override - public void xpush(Value x) { - assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); - stack[stackSize++] = x; - } - - @Override - public void ipush(Value x) { - xpush(assertInt(x)); - } - - @Override - public void fpush(Value x) { - xpush(assertFloat(x)); - } - - @Override - public void apush(Value x) { - xpush(assertObject(x)); - } - - @Override - public void lpush(Value x) { - xpush(assertLong(x)); - } - - @Override - public void dpush(Value x) { - xpush(assertDouble(x)); - - } - - @Override - public void pushReturn(Kind kind, Value x) { - if (kind != Kind.Void) { - push(kind.getStackKind(), x); - } + protected Value[] getEmtpyArray() { + return EMPTY_ARRAY; } @Override - public Value pop(Kind kind) { - assert kind != Kind.Void; - if (isTwoSlot(kind)) { - xpop(); - } - return assertKind(kind, xpop()); - } - - @Override - public Value xpop() { - Value result = stack[--stackSize]; - return result; - } - - @Override - public Value ipop() { - return assertInt(xpop()); - } - - @Override - public Value fpop() { - return assertFloat(xpop()); - } - - @Override - public Value apop() { - return assertObject(xpop()); - } - - @Override - public Value lpop() { - assertHigh(xpop()); - return assertLong(xpop()); - } - - @Override - public Value dpop() { - assertHigh(xpop()); - return assertDouble(xpop()); + public LIRFrameStateBuilder copy() { + return new LIRFrameStateBuilder(method); } @Override - public Value[] popArguments(int slotSize, int argSize) { - int base = stackSize - slotSize; - Value[] r = new Value[argSize]; - int argIndex = 0; - int stackindex = 0; - while (stackindex < slotSize) { - Value element = stack[base + stackindex]; - assert element != null; - r[argIndex++] = element; - stackindex += stackSlots(element.getKind()); - } - stackSize = base; - return r; - } - - @Override - public Value peek(int argumentNumber) { - int idx = stackSize() - 1; - for (int i = 0; i < argumentNumber; i++) { - if (stackAt(idx) == null) { - idx--; - assert isTwoSlot(stackAt(idx).getKind()); - } - idx--; - } - return stackAt(idx); - } - - private static Value assertKind(Kind kind, Value x) { - assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); - return x; - } - - private static Value assertLong(Value x) { - assert x != null && (x.getKind() == Kind.Long); - return x; - } - - private static Value assertInt(Value x) { - assert x != null && (x.getKind() == Kind.Int); - return x; - } - - private static Value assertFloat(Value x) { - assert x != null && (x.getKind() == Kind.Float); - return x; - } - - private static Value assertObject(Value x) { - assert x != null && (x.getKind() == Kind.Object); - return x; - } - - private static Value assertDouble(Value x) { - assert x != null && (x.getKind() == Kind.Double); - return x; - } - - private static void assertHigh(Value x) { - assert x == null; + public boolean isCompatibleWith(LIRFrameStateBuilder other) { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented("Auto-generated method stub"); } } diff -r e098038093d5 -r 14e542e27076 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Apr 07 17:01:54 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Apr 07 19:41:40 2014 +0200 @@ -43,7 +43,7 @@ import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -public abstract class AbstractBytecodeParser> { +public abstract class AbstractBytecodeParser> { static class Options { // @formatter:off diff -r e098038093d5 -r 14e542e27076 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Apr 07 17:01:54 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Apr 07 19:41:40 2014 +0200 @@ -23,19 +23,61 @@ package com.oracle.graal.java; +import java.util.*; + +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -public abstract class AbstractFrameStateBuilder { +public abstract class AbstractFrameStateBuilder> { protected final ResolvedJavaMethod method; protected int stackSize; + protected final T[] locals; + protected final T[] stack; + protected T[] lockedObjects; - public AbstractFrameStateBuilder(ResolvedJavaMethod method) { + /** + * @see BytecodeFrame#rethrowException + */ + protected boolean rethrowException; + + public AbstractFrameStateBuilder(ResolvedJavaMethod method, T[] l, T[] s, T[] lo) { this.method = method; + this.locals = l; + this.stack = s; + this.lockedObjects = lo; } - protected AbstractFrameStateBuilder(AbstractFrameStateBuilder other) { + protected AbstractFrameStateBuilder(S other) { this.method = other.method; + this.stackSize = other.stackSize; + this.locals = other.locals.clone(); + this.stack = other.stack.clone(); + this.lockedObjects = other.lockedObjects == getEmtpyArray() ? getEmtpyArray() : other.lockedObjects.clone(); + this.rethrowException = other.rethrowException; + + assert locals.length == method.getMaxLocals(); + assert stack.length == Math.max(1, method.getMaxStackSize()); + } + + public abstract S copy(); + + protected abstract T[] getEmtpyArray(); + + public abstract boolean isCompatibleWith(S other); + + /** + * @see BytecodeFrame#rethrowException + */ + public boolean rethrowException() { + return rethrowException; + } + + /** + * @see BytecodeFrame#rethrowException + */ + public void setRethrowException(boolean b) { + rethrowException = b; } /** @@ -43,7 +85,9 @@ * * @return the size of the local variables */ - public abstract int localsSize(); + public int localsSize() { + return locals.length; + } /** * Gets the current size (height) of the stack. @@ -58,7 +102,9 @@ * @param i the index into the locals * @return the instruction that produced the value for the specified local */ - public abstract T localAt(int i); + public T localAt(int i) { + return locals[i]; + } /** * Get the value on the stack at the specified stack index. @@ -66,7 +112,9 @@ * @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 abstract T stackAt(int i); + public T stackAt(int i) { + return stack[i]; + } /** * Loads the local variable at the specified index, checking that the returned value is non-null @@ -75,7 +123,12 @@ * @param i the index of the local variable to load * @return the instruction that produced the specified local */ - public abstract T loadLocal(int i); + public T loadLocal(int i) { + T x = locals[i]; + assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; + assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); + return x; + } /** * Stores a given local variable at the specified index. If the value occupies two slots, then @@ -84,9 +137,26 @@ * @param i the index at which to store * @param x the instruction which produces the value for the local */ - public abstract void storeLocal(int i, T x); + public void storeLocal(int i, T x) { + assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; + locals[i] = x; + if (x != null && isTwoSlot(x.getKind())) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (x != null && i > 0) { + T p = locals[i - 1]; + if (p != null && isTwoSlot(p.getKind())) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } + } + } - public abstract void storeStack(int i, T x); + public void storeStack(int i, T x) { + assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; + stack[i] = x; + } /** * Pushes an instruction onto the stack with the expected type. @@ -94,51 +164,76 @@ * @param kind the type expected for this instruction * @param x the instruction to push onto the stack */ - public abstract void push(Kind kind, T x); + public void push(Kind kind, T x) { + assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; + xpush(assertKind(kind, x)); + if (isTwoSlot(kind)) { + xpush(null); + } + } /** * Pushes a value onto the stack without checking the type. * * @param x the instruction to push onto the stack */ - public abstract void xpush(T x); + public void xpush(T x) { + assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + stack[stackSize++] = x; + } /** * Pushes a value onto the stack and checks that it is an int. * * @param x the instruction to push onto the stack */ - public abstract void ipush(T x); + public void ipush(T 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 abstract void fpush(T x); + public void fpush(T 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 abstract void apush(T x); + public void apush(T x) { + xpush(assertObject(x)); + } /** * Pushes a value onto the stack and checks that it is a long. * * @param x the instruction to push onto the stack */ - public abstract void lpush(T x); + public void lpush(T 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 abstract void dpush(T x); + public void dpush(T x) { + xpush(assertDouble(x)); + xpush(null); + } - public abstract void pushReturn(Kind kind, T x); + public void pushReturn(Kind kind, T x) { + if (kind != Kind.Void) { + push(kind.getStackKind(), x); + } + } /** * Pops an instruction off the stack with the expected type. @@ -146,49 +241,70 @@ * @param kind the expected type * @return the instruction on the top of the stack */ - public abstract T pop(Kind kind); + public T pop(Kind kind) { + assert kind != Kind.Void; + if (isTwoSlot(kind)) { + 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 abstract T xpop(); + public T xpop() { + T result = stack[--stackSize]; + return result; + } /** * Pops a value off of the stack and checks that it is an int. * * @return x the instruction popped off the stack */ - public abstract T ipop(); + public T 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 abstract T fpop(); + public T 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 abstract T apop(); + public T apop() { + return assertObject(xpop()); + } /** * Pops a value off of the stack and checks that it is a long. * * @return x the instruction popped off the stack */ - public abstract T lpop(); + public T 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 abstract T dpop(); + public T dpop() { + assertHigh(xpop()); + return assertDouble(xpop()); + } /** * Pop the specified number of slots off of this stack and return them as an array of @@ -196,7 +312,19 @@ * * @return an array containing the arguments off of the stack */ - public abstract T[] popArguments(int slotSize, int argSize); + public T[] popArguments(int slotSize, int argSize) { + int base = stackSize - slotSize; + List r = new ArrayList<>(argSize); + int stackindex = 0; + while (stackindex < slotSize) { + T element = stack[base + stackindex]; + assert element != null; + r.add(element); + stackindex += stackSlots(element.getKind()); + } + stackSize = base; + return r.toArray(getEmtpyArray()); + } /** * Peeks an element from the operand stack. @@ -206,7 +334,17 @@ * ignored. * @return The peeked argument. */ - public abstract T peek(int argumentNumber); + public T peek(int argumentNumber) { + int idx = stackSize() - 1; + for (int i = 0; i < argumentNumber; i++) { + if (stackAt(idx) == null) { + idx--; + assert isTwoSlot(stackAt(idx).getKind()); + } + idx--; + } + return stackAt(idx); + } public static int stackSlots(Kind kind) { return isTwoSlot(kind) ? 2 : 1; @@ -224,4 +362,38 @@ return kind == Kind.Long || kind == Kind.Double; } + private T assertKind(Kind kind, T x) { + assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); + return x; + } + + private T assertLong(T x) { + assert x != null && (x.getKind() == Kind.Long); + return x; + } + + private T assertInt(T x) { + assert x != null && (x.getKind() == Kind.Int); + return x; + } + + private T assertFloat(T x) { + assert x != null && (x.getKind() == Kind.Float); + return x; + } + + private T assertObject(T x) { + assert x != null && (x.getKind() == Kind.Object); + return x; + } + + private T assertDouble(T x) { + assert x != null && (x.getKind() == Kind.Double); + return x; + } + + private void assertHigh(T x) { + assert x == null; + } + } diff -r e098038093d5 -r 14e542e27076 graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Apr 07 17:01:54 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Apr 07 19:41:40 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.java; import static com.oracle.graal.graph.iterators.NodePredicates.*; -import static com.oracle.graal.nodes.ValueNodeUtil.*; import static java.lang.reflect.Modifier.*; import java.util.*; @@ -40,31 +39,19 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; -public class HIRFrameStateBuilder extends AbstractFrameStateBuilder { +public class HIRFrameStateBuilder extends AbstractFrameStateBuilder { private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; - private final ValueNode[] locals; - private final ValueNode[] stack; - private ValueNode[] lockedObjects; private MonitorIdNode[] monitorIds; private final StructuredGraph graph; - /** - * @see BytecodeFrame#rethrowException - */ - private boolean rethrowException; - public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) { - super(method); + super(method, new ValueNode[method.getMaxLocals()], new ValueNode[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); assert graph != null; - this.locals = new ValueNode[method.getMaxLocals()]; - // we always need at least one stack slot (for exceptions) - this.stack = new ValueNode[Math.max(1, method.getMaxStackSize())]; - this.lockedObjects = EMPTY_ARRAY; this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; @@ -103,12 +90,7 @@ super(other); assert other.graph != null; graph = other.graph; - locals = other.locals.clone(); - stack = other.stack.clone(); - lockedObjects = other.lockedObjects == EMPTY_ARRAY ? EMPTY_ARRAY : other.lockedObjects.clone(); monitorIds = other.monitorIds == EMPTY_MONITOR_ARRAY ? EMPTY_MONITOR_ARRAY : other.monitorIds.clone(); - stackSize = other.stackSize; - rethrowException = other.rethrowException; assert locals.length == method.getMaxLocals(); assert stack.length == Math.max(1, method.getMaxStackSize()); @@ -116,6 +98,11 @@ } @Override + protected ValueNode[] getEmtpyArray() { + return EMPTY_ARRAY; + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[locals: ["); @@ -142,10 +129,12 @@ return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false)); } + @Override public HIRFrameStateBuilder copy() { return new HIRFrameStateBuilder(this); } + @Override public boolean isCompatibleWith(HIRFrameStateBuilder other) { assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; @@ -336,35 +325,6 @@ } /** - * @see BytecodeFrame#rethrowException - */ - public boolean rethrowException() { - return rethrowException; - } - - /** - * @see BytecodeFrame#rethrowException - */ - public void setRethrowException(boolean b) { - rethrowException = b; - } - - @Override - public int localsSize() { - return locals.length; - } - - @Override - public ValueNode localAt(int i) { - return locals[i]; - } - - @Override - public ValueNode stackAt(int i) { - return stack[i]; - } - - /** * Adds a locked monitor to this frame state. * * @param object the object whose monitor will be locked. @@ -404,159 +364,6 @@ return lockedObjects.length; } - @Override - public ValueNode loadLocal(int i) { - ValueNode x = locals[i]; - assert !x.isDeleted(); - assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; - assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); - return x; - } - - @Override - public void storeLocal(int i, ValueNode x) { - assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; - locals[i] = x; - if (x != null && isTwoSlot(x.getKind())) { - // if this is a double word, then kill i+1 - locals[i + 1] = null; - } - if (x != null && i > 0) { - ValueNode p = locals[i - 1]; - if (p != null && isTwoSlot(p.getKind())) { - // if there was a double word at i - 1, then kill it - locals[i - 1] = null; - } - } - } - - @Override - public void storeStack(int i, ValueNode x) { - assert x == null || x.isAlive() && (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; - stack[i] = x; - } - - @Override - public void push(Kind kind, ValueNode x) { - assert x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; - xpush(assertKind(kind, x)); - if (isTwoSlot(kind)) { - xpush(null); - } - } - - @Override - public void xpush(ValueNode x) { - assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); - stack[stackSize++] = x; - } - - @Override - public void ipush(ValueNode x) { - xpush(assertInt(x)); - } - - @Override - public void fpush(ValueNode x) { - xpush(assertFloat(x)); - } - - @Override - public void apush(ValueNode x) { - xpush(assertObject(x)); - } - - @Override - public void lpush(ValueNode x) { - xpush(assertLong(x)); - xpush(null); - } - - @Override - public void dpush(ValueNode x) { - xpush(assertDouble(x)); - xpush(null); - } - - @Override - public void pushReturn(Kind kind, ValueNode x) { - if (kind != Kind.Void) { - push(kind.getStackKind(), x); - } - } - - @Override - public ValueNode pop(Kind kind) { - assert kind != Kind.Void; - if (isTwoSlot(kind)) { - xpop(); - } - return assertKind(kind, xpop()); - } - - @Override - public ValueNode xpop() { - ValueNode result = stack[--stackSize]; - assert result == null || !result.isDeleted(); - return result; - } - - @Override - public ValueNode ipop() { - return assertInt(xpop()); - } - - @Override - public ValueNode fpop() { - return assertFloat(xpop()); - } - - @Override - public ValueNode apop() { - return assertObject(xpop()); - } - - @Override - public ValueNode lpop() { - assertHigh(xpop()); - return assertLong(xpop()); - } - - @Override - public ValueNode dpop() { - assertHigh(xpop()); - return assertDouble(xpop()); - } - - @Override - public ValueNode[] popArguments(int slotSize, int argSize) { - int base = stackSize - slotSize; - ValueNode[] r = new ValueNode[argSize]; - int argIndex = 0; - int stackindex = 0; - while (stackindex < slotSize) { - ValueNode element = stack[base + stackindex]; - assert element != null; - r[argIndex++] = element; - stackindex += stackSlots(element.getKind()); - } - stackSize = base; - return r; - } - - @Override - public ValueNode peek(int argumentNumber) { - int idx = stackSize() - 1; - for (int i = 0; i < argumentNumber; i++) { - if (stackAt(idx) == null) { - idx--; - assert isTwoSlot(stackAt(idx).getKind()); - } - idx--; - } - return stackAt(idx); - } - public boolean contains(ValueNode value) { for (int i = 0; i < localsSize(); i++) { if (localAt(i) == value) {