Mercurial > hg > truffle
changeset 19538:fac54d234f30
Merge.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sun, 22 Feb 2015 17:17:45 +0100 |
parents | 9d5003af91f5 (diff) 9299e71df12a (current diff) |
children | 34462e7f0278 |
files | |
diffstat | 10 files changed, 798 insertions(+), 305 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Sun Feb 22 17:17:45 2015 +0100 @@ -42,7 +42,7 @@ import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -public abstract class AbstractBytecodeParser<T extends KindProvider, F extends AbstractFrameStateBuilder<T, F>> { +public abstract class AbstractBytecodeParser { static class Options { // @formatter:off @@ -63,7 +63,7 @@ */ public static final int TRACELEVEL_STATE = 2; - protected F frameState; + protected HIRFrameStateBuilder frameState; protected BciBlock currentBlock; protected final BytecodeStream stream; @@ -97,7 +97,7 @@ assert metaAccess != null; } - public void setCurrentFrameState(F frameState) { + public void setCurrentFrameState(HIRFrameStateBuilder frameState) { this.frameState = frameState; } @@ -114,7 +114,7 @@ } public void storeLocal(Kind kind, int index) { - T value; + ValueNode value; if (kind == Kind.Object) { value = frameState.xpop(); // astore and astore_<n> may be used to store a returnAddress (jsr) @@ -134,13 +134,13 @@ * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - protected abstract void handleUnresolvedCheckCast(JavaType type, T object); + protected abstract void handleUnresolvedCheckCast(JavaType type, ValueNode object); /** * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - protected abstract void handleUnresolvedInstanceOf(JavaType type, T object); + protected abstract void handleUnresolvedInstanceOf(JavaType type, ValueNode object); /** * @param type the type being instantiated @@ -151,26 +151,26 @@ * @param type the type of the array being instantiated * @param length the length of the array */ - protected abstract void handleUnresolvedNewObjectArray(JavaType type, T length); + protected abstract void handleUnresolvedNewObjectArray(JavaType type, ValueNode length); /** * @param type the type being instantiated * @param dims the dimensions for the multi-array */ - protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<T> dims); + protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<ValueNode> dims); /** * @param field the unresolved field * @param receiver the object containing the field or {@code null} if {@code field} is static */ - protected abstract void handleUnresolvedLoadField(JavaField field, T receiver); + protected abstract void handleUnresolvedLoadField(JavaField field, ValueNode receiver); /** * @param field the unresolved field * @param value the value being stored to the field * @param receiver the object containing the field or {@code null} if {@code field} is static */ - protected abstract void handleUnresolvedStoreField(JavaField field, T value, T receiver); + protected abstract void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver); /** * @param type @@ -179,7 +179,7 @@ // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind); - // protected abstract DispatchBeginNode handleException(T exceptionObject, int bci); + // protected abstract DispatchBeginNode handleException(ValueNode exceptionObject, int bci); private void genLoadConstant(int cpi, int opcode) { Object con = lookupConstant(cpi, opcode); @@ -200,24 +200,24 @@ } } - protected abstract T genLoadIndexed(T index, T array, Kind kind); + protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind); private void genLoadIndexed(Kind kind) { emitExplicitExceptions(frameState.peek(1), frameState.peek(0)); - T index = frameState.ipop(); - T array = frameState.apop(); + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); } - protected abstract T genStoreIndexed(T array, T index, Kind kind, T value); + protected abstract ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value); private void genStoreIndexed(Kind kind) { emitExplicitExceptions(frameState.peek(2), frameState.peek(1)); - T value = frameState.pop(kind.getStackKind()); - T index = frameState.ipop(); - T array = frameState.apop(); + ValueNode value = frameState.pop(kind.getStackKind()); + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); append(genStoreIndexed(array, index, kind, value)); } @@ -233,23 +233,23 @@ break; } case DUP: { - T w = frameState.xpop(); + ValueNode w = frameState.xpop(); frameState.xpush(w); frameState.xpush(w); break; } case DUP_X1: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w2); frameState.xpush(w1); break; } case DUP_X2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w3); frameState.xpush(w2); @@ -257,8 +257,8 @@ break; } case DUP2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w2); @@ -266,9 +266,9 @@ break; } case DUP2_X1: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w3); @@ -277,10 +277,10 @@ break; } case DUP2_X2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); - T w4 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + ValueNode w4 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w4); @@ -290,8 +290,8 @@ break; } case SWAP: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w2); break; @@ -301,27 +301,27 @@ } } - protected abstract T genIntegerAdd(Kind kind, T x, T y); + protected abstract ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerSub(Kind kind, T x, T y); + protected abstract ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerMul(Kind kind, T x, T y); + protected abstract ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y); - protected abstract T genFloatAdd(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatSub(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatMul(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatDiv(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatRem(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); private void genArithmeticOp(Kind result, int opcode) { - T y = frameState.pop(result); - T x = frameState.pop(result); + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); boolean isStrictFP = method.isStrict(); - T v; + ValueNode v; switch (opcode) { case IADD: case LADD: @@ -361,14 +361,14 @@ frameState.push(result, append(v)); } - protected abstract T genIntegerDiv(Kind kind, T x, T y); + protected abstract ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerRem(Kind kind, T x, T y); + protected abstract ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y); private void genIntegerDivOp(Kind result, int opcode) { - T y = frameState.pop(result); - T x = frameState.pop(result); - T v; + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + ValueNode v; switch (opcode) { case IDIV: case LDIV: @@ -384,22 +384,22 @@ frameState.push(result, append(v)); } - protected abstract T genNegateOp(T x); + protected abstract ValueNode genNegateOp(ValueNode x); private void genNegateOp(Kind kind) { frameState.push(kind, append(genNegateOp(frameState.pop(kind)))); } - protected abstract T genLeftShift(Kind kind, T x, T y); + protected abstract ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y); - protected abstract T genRightShift(Kind kind, T x, T y); + protected abstract ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y); - protected abstract T genUnsignedRightShift(Kind kind, T x, T y); + protected abstract ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y); private void genShiftOp(Kind kind, int opcode) { - T s = frameState.ipop(); - T x = frameState.pop(kind); - T v; + ValueNode s = frameState.ipop(); + ValueNode x = frameState.pop(kind); + ValueNode v; switch (opcode) { case ISHL: case LSHL: @@ -419,16 +419,16 @@ frameState.push(kind, append(v)); } - protected abstract T genAnd(Kind kind, T x, T y); + protected abstract ValueNode genAnd(Kind kind, ValueNode x, ValueNode y); - protected abstract T genOr(Kind kind, T x, T y); + protected abstract ValueNode genOr(Kind kind, ValueNode x, ValueNode y); - protected abstract T genXor(Kind kind, T x, T y); + protected abstract ValueNode genXor(Kind kind, ValueNode x, ValueNode y); private void genLogicOp(Kind kind, int opcode) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); - T v; + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + ValueNode v; switch (opcode) { case IAND: case LAND: @@ -448,29 +448,29 @@ frameState.push(kind, append(v)); } - protected abstract T genNormalizeCompare(T x, T y, boolean isUnorderedLess); + protected abstract ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess); private void genCompareOp(Kind kind, boolean isUnorderedLess) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess))); } - protected abstract T genFloatConvert(FloatConvert op, T input); + protected abstract ValueNode genFloatConvert(FloatConvert op, ValueNode input); private void genFloatConvert(FloatConvert op, Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); frameState.push(to.getStackKind(), append(genFloatConvert(op, input))); } - protected abstract T genNarrow(T input, int bitCount); + protected abstract ValueNode genNarrow(ValueNode input, int bitCount); - protected abstract T genSignExtend(T input, int bitCount); + protected abstract ValueNode genSignExtend(ValueNode input, int bitCount); - protected abstract T genZeroExtend(T input, int bitCount); + protected abstract ValueNode genZeroExtend(ValueNode input, int bitCount); private void genSignExtend(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); if (from != from.getStackKind()) { input = append(genNarrow(input, from.getBitCount())); } @@ -478,7 +478,7 @@ } private void genZeroExtend(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); if (from != from.getStackKind()) { input = append(genNarrow(input, from.getBitCount())); } @@ -486,45 +486,45 @@ } private void genNarrow(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount()))); } private void genIncrement() { int index = getStream().readLocalIndex(); int delta = getStream().readIncrement(); - T x = frameState.loadLocal(index); - T y = appendConstant(JavaConstant.forInt(delta)); + ValueNode x = frameState.loadLocal(index); + ValueNode y = appendConstant(JavaConstant.forInt(delta)); frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y))); } protected abstract void genGoto(); - protected abstract T genObjectEquals(T x, T y); + protected abstract ValueNode genObjectEquals(ValueNode x, ValueNode y); - protected abstract T genIntegerEquals(T x, T y); + protected abstract ValueNode genIntegerEquals(ValueNode x, ValueNode y); - protected abstract T genIntegerLessThan(T x, T y); + protected abstract ValueNode genIntegerLessThan(ValueNode x, ValueNode y); - protected abstract T genUnique(T x); + protected abstract ValueNode genUnique(ValueNode x); - protected abstract void genIf(T x, Condition cond, T y); + protected abstract void genIf(ValueNode x, Condition cond, ValueNode y); private void genIfZero(Condition cond) { - T y = appendConstant(JavaConstant.INT_0); - T x = frameState.ipop(); + ValueNode y = appendConstant(JavaConstant.INT_0); + ValueNode x = frameState.ipop(); genIf(x, cond, y); } private void genIfNull(Condition cond) { - T y = appendConstant(JavaConstant.NULL_POINTER); - T x = frameState.apop(); + ValueNode y = appendConstant(JavaConstant.NULL_POINTER); + ValueNode x = frameState.apop(); genIf(x, cond, y); } private void genIfSame(Kind kind, Condition cond) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); // assert !x.isDeleted() && !y.isDeleted(); genIf(x, cond, y); } @@ -579,41 +579,40 @@ } } - protected abstract T createCheckCast(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck); + protected abstract ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck); private void genCheckCast() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, CHECKCAST); - T object = frameState.apop(); + ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type); - T checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false)); + ValueNode checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false)); frameState.apush(checkCastNode); } else { handleUnresolvedCheckCast(type, object); } } - protected abstract T createInstanceOf(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck); + protected abstract ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck); - protected abstract T genConditional(T x); + protected abstract ValueNode genConditional(ValueNode x); private void genInstanceOf() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, INSTANCEOF); - T object = frameState.apop(); + ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { ResolvedJavaType resolvedType = (ResolvedJavaType) type; - T instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); + ValueNode instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); frameState.ipush(append(genConditional(genUnique(instanceOfNode)))); } else { handleUnresolvedInstanceOf(type, object); } } - protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents); + protected abstract ValueNode createNewInstance(ResolvedJavaType type, boolean fillContents); - @SuppressWarnings("unchecked") void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { @@ -621,7 +620,7 @@ if (skippedExceptionTypes != null) { for (ResolvedJavaType exceptionType : skippedExceptionTypes) { if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { - append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); return; } } @@ -672,7 +671,7 @@ private void genNewObjectArray(int cpi) { JavaType type = lookupType(cpi, ANEWARRAY); - T length = frameState.ipop(); + ValueNode length = frameState.ipop(); if (type instanceof ResolvedJavaType) { frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); } else { @@ -681,12 +680,12 @@ } - protected abstract T createNewArray(ResolvedJavaType elementType, T length, boolean fillContents); + protected abstract ValueNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents); private void genNewMultiArray(int cpi) { JavaType type = lookupType(cpi, MULTIANEWARRAY); int rank = getStream().readUByte(bci() + 3); - List<T> dims = new ArrayList<>(Collections.nCopies(rank, null)); + List<ValueNode> dims = new ArrayList<>(Collections.nCopies(rank, null)); for (int i = rank - 1; i >= 0; i--) { dims.set(i, frameState.ipop()); } @@ -697,18 +696,18 @@ } } - protected abstract T createNewMultiArray(ResolvedJavaType type, List<T> dims); + protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List<ValueNode> dims); - protected abstract T genLoadField(T receiver, ResolvedJavaField field); + protected abstract ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field); private void genGetField(JavaField field) { emitExplicitExceptions(frameState.peek(0), null); Kind kind = field.getKind(); - T receiver = frameState.apop(); + ValueNode receiver = frameState.apop(); if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); - if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) { + if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); } } else { @@ -716,15 +715,15 @@ } } - protected abstract void emitNullCheck(T receiver); + protected abstract void emitNullCheck(ValueNode receiver); - protected abstract void emitBoundsCheck(T index, T length); + protected abstract void emitBoundsCheck(ValueNode index, ValueNode length); private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions"); - protected abstract T genArrayLength(T x); + protected abstract ValueNode genArrayLength(ValueNode x); - protected void emitExplicitExceptions(T receiver, T outOfBoundsIndex) { + protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { assert receiver != null; if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) { @@ -733,19 +732,19 @@ emitNullCheck(receiver); if (outOfBoundsIndex != null) { - T length = append(genArrayLength(receiver)); + ValueNode length = append(genArrayLength(receiver)); emitBoundsCheck(outOfBoundsIndex, length); } EXPLICIT_EXCEPTIONS.increment(); } - protected abstract T genStoreField(T receiver, ResolvedJavaField field, T value); + protected abstract ValueNode genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value); private void genPutField(JavaField field) { emitExplicitExceptions(frameState.peek(1), null); - T value = frameState.pop(field.getKind().getStackKind()); - T receiver = frameState.apop(); + ValueNode value = frameState.pop(field.getKind().getStackKind()); + ValueNode receiver = frameState.apop(); if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { appendOptimizedStoreField(genStoreField(receiver, (ResolvedJavaField) field, value)); } else { @@ -766,7 +765,7 @@ } private void genPutStatic(JavaField field) { - T value = frameState.pop(field.getKind().getStackKind()); + ValueNode value = frameState.pop(field.getKind().getStackKind()); if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { appendOptimizedStoreField(genStoreField(null, (ResolvedJavaField) field, value)); } else { @@ -774,13 +773,13 @@ } } - protected void appendOptimizedStoreField(T store) { + protected void appendOptimizedStoreField(ValueNode store) { append(store); } - protected void appendOptimizedLoadField(Kind kind, T load) { + protected void appendOptimizedLoadField(Kind kind, ValueNode load) { // append the load to the instruction - T optimized = append(load); + ValueNode optimized = append(load); frameState.push(kind.getStackKind(), optimized); } @@ -794,11 +793,11 @@ protected abstract void genInvokeSpecial(JavaMethod target); - protected abstract void genReturn(T x); + protected abstract void genReturn(ValueNode x); - protected abstract T genMonitorEnter(T x); + protected abstract ValueNode genMonitorEnter(ValueNode x); - protected abstract T genMonitorExit(T x, T returnValue); + protected abstract ValueNode genMonitorExit(ValueNode x, ValueNode returnValue); protected abstract void genJsr(int dest); @@ -843,7 +842,7 @@ private void genSwitch(BytecodeSwitch bs) { int bci = bci(); - T value = frameState.ipop(); + ValueNode value = frameState.ipop(); int nofCases = bs.numberOfCases(); double[] keyProbabilities = switchProbability(nofCases + 1, bci); @@ -861,7 +860,7 @@ int[] keySuccessors = new int[nofCases + 1]; int deoptSuccessorIndex = -1; int nextSuccessorIndex = 0; - boolean constantValue = ((ValueNode) value).isConstant(); + boolean constantValue = value.isConstant(); for (int i = 0; i < nofCases + 1; i++) { if (i < nofCases) { keys[i] = bs.keyAt(i); @@ -888,7 +887,7 @@ } - protected abstract void genIntegerSwitch(T value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); + protected abstract void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); private static class SuccessorInfo { @@ -901,9 +900,9 @@ } } - protected abstract T appendConstant(JavaConstant constant); + protected abstract ValueNode appendConstant(JavaConstant constant); - protected abstract T append(T v); + protected abstract ValueNode append(ValueNode v); protected boolean isNeverExecutedCode(double probability) { return probability == 0 && optimisticOpts.removeNeverExecutedCode(); @@ -1182,7 +1181,7 @@ return method; } - public F getFrameState() { + public HIRFrameStateBuilder getFrameState() { return frameState; }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sun Feb 22 17:17:45 2015 +0100 @@ -172,7 +172,7 @@ private int peelIteration; } - public class BytecodeParser extends AbstractBytecodeParser<ValueNode, HIRFrameStateBuilder> implements GraphBuilderContext { + public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -642,8 +642,8 @@ return (ValueNode) currentGraph.unique((Node & ValueNumberable) x); } - protected ValueNode genIfNode(ValueNode condition, ValueNode falseSuccessor, ValueNode trueSuccessor, double d) { - return new IfNode((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d); + protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) { + return new IfNode(condition, falseSuccessor, trueSuccessor, d); } @Override @@ -1228,7 +1228,7 @@ } lastLoopExit = loopExit; Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); - newState.insertLoopProxies(loopExit, (HIRFrameStateBuilder) getEntryState(loop, this.getCurrentDimension())); + newState.insertLoopProxies(loopExit, getEntryState(loop, this.getCurrentDimension())); loopExit.setStateAfter(newState.create(bci)); } @@ -1239,7 +1239,7 @@ return new Target(target, state); } - private AbstractFrameStateBuilder<?, ?> getEntryState(BciBlock block, int dimension) { + private HIRFrameStateBuilder getEntryState(BciBlock block, int dimension) { int id = block.id; if (dimension == 0) { return entryStateArray[id]; @@ -1248,9 +1248,9 @@ } } - private AbstractFrameStateBuilder<?, ?> getEntryStateMultiDimension(int dimension, int id) { + private HIRFrameStateBuilder getEntryStateMultiDimension(int dimension, int id) { if (entryStateMatrix != null && dimension - 1 < entryStateMatrix.length) { - AbstractFrameStateBuilder<?, ?>[] entryStateArrayEntry = entryStateMatrix[dimension - 1]; + HIRFrameStateBuilder[] entryStateArrayEntry = entryStateMatrix[dimension - 1]; if (entryStateArrayEntry == null) { return null; } @@ -1342,10 +1342,10 @@ } private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) { - return createTarget(block, state, false); + return createTarget(block, state, false, false); } - private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean isGoto) { + private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) { assert block != null && state != null; assert !block.isExceptionEntry || state.stackSize() == 1; @@ -1358,7 +1358,7 @@ * this block again. */ FixedNode targetNode; - if (isGoto && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) { + if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) { setFirstInstruction(block, operatingDimension, lastInstr); lastInstr = null; } else { @@ -1367,7 +1367,7 @@ targetNode = getFirstInstruction(block, operatingDimension); Target target = checkLoopExit(targetNode, block, state); FixedNode result = target.fixed; - HIRFrameStateBuilder currentEntryState = target.state == state ? state.copy() : target.state; + HIRFrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state; setEntryState(block, operatingDimension, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); @@ -1376,7 +1376,7 @@ } // We already saw this block before, so we have to merge states. - if (!((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).isCompatibleWith(state)) { + if (!getEntryState(block, operatingDimension).isCompatibleWith(state)) { throw bailout("stacks do not match; bytecodes would not verify"); } @@ -1389,7 +1389,7 @@ LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block, operatingDimension); Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); FixedNode result = target.fixed; - ((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).merge(loopBegin, target.state); + getEntryState(block, operatingDimension).merge(loopBegin, target.state); Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; @@ -1430,7 +1430,7 @@ EndNode newEnd = currentGraph.add(new EndNode()); Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; - ((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).merge(mergeNode, target.state); + getEntryState(block, operatingDimension).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); Debug.log("createTarget %s: merging state, result: %s", block, result); @@ -1501,45 +1501,27 @@ protected void processBlock(BytecodeParser parser, BciBlock block) { // Ignore blocks that have no predecessors by the time their bytecodes are parsed - if (block == null || getFirstInstruction(block, this.getCurrentDimension()) == null) { + int currentDimension = this.getCurrentDimension(); + FixedWithNextNode firstInstruction = getFirstInstruction(block, currentDimension); + if (firstInstruction == null) { Debug.log("Ignoring block %s", block); return; } - try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, getFirstInstruction(block, this.getCurrentDimension()), block.isLoopHeader)) { + try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { - lastInstr = getFirstInstruction(block, this.getCurrentDimension()); - frameState = (HIRFrameStateBuilder) getEntryState(block, this.getCurrentDimension()); + lastInstr = firstInstruction; + frameState = getEntryState(block, currentDimension); parser.setCurrentFrameState(frameState); currentBlock = block; - if (lastInstr instanceof AbstractMergeNode) { - - AbstractMergeNode abstractMergeNode = (AbstractMergeNode) lastInstr; - if (abstractMergeNode.stateAfter() == null) { - int bci = block.startBci; - if (block instanceof ExceptionDispatchBlock) { - bci = ((ExceptionDispatchBlock) block).deoptBci; - } - abstractMergeNode.setStateAfter(frameState.create(bci)); - } + if (firstInstruction instanceof AbstractMergeNode) { + setMergeStateAfter(block, firstInstruction); } if (block == blockMap.getReturnBlock()) { - Kind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - beforeReturn(x); - this.returnValue = x; - this.beforeReturnNode = this.lastInstr; + handleReturnBlock(); } else if (block == blockMap.getUnwindBlock()) { - if (currentDepth == 0) { - frameState.setRethrowException(false); - createUnwind(); - } else { - ValueNode exception = frameState.apop(); - this.unwindValue = exception; - this.beforeUnwindNode = this.lastInstr; - } + handleUnwindBlock(); } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { @@ -1549,6 +1531,37 @@ } } + private void handleUnwindBlock() { + if (currentDepth == 0) { + frameState.setRethrowException(false); + createUnwind(); + } else { + ValueNode exception = frameState.apop(); + this.unwindValue = exception; + this.beforeUnwindNode = this.lastInstr; + } + } + + private void handleReturnBlock() { + Kind returnKind = method.getSignature().getReturnKind().getStackKind(); + ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); + assert frameState.stackSize() == 0; + beforeReturn(x); + this.returnValue = x; + this.beforeReturnNode = this.lastInstr; + } + + private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) { + AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction; + if (abstractMergeNode.stateAfter() == null) { + int bci = block.startBci; + if (block instanceof ExceptionDispatchBlock) { + bci = ((ExceptionDispatchBlock) block).deoptBci; + } + abstractMergeNode.setStateAfter(frameState.create(bci)); + } + } + /** * Remove loop header without loop ends. This can happen with degenerated loops like * this one: @@ -1636,7 +1649,7 @@ } private void appendGoto(BciBlock successor) { - FixedNode targetInstr = createTarget(successor, frameState, true); + FixedNode targetInstr = createTarget(successor, frameState, true, true); if (lastInstr != null && lastInstr != targetInstr) { lastInstr.setNext(targetInstr); } @@ -1788,17 +1801,107 @@ BciBlock trueBlock = currentBlock.getSuccessor(0); BciBlock falseBlock = currentBlock.getSuccessor(1); if (trueBlock == falseBlock) { + // The target block is the same independent of the condition. appendGoto(trueBlock); return; } - // the mirroring and negation operations get the condition into canonical form - boolean mirror = cond.canonicalMirror(); + ValueNode a = x; + ValueNode b = y; + + // Check whether the condition needs to mirror the operands. + if (cond.canonicalMirror()) { + a = y; + b = x; + } + + // Create the logic node for the condition. + LogicNode condition = createLogicNode(cond, a, b); + + // Check whether the condition needs to negate the result. boolean negate = cond.canonicalNegate(); - ValueNode a = mirror ? y : x; - ValueNode b = mirror ? x : y; + // Remove a logic negation node and fold it into the negate boolean. + if (condition instanceof LogicNegationNode) { + LogicNegationNode logicNegationNode = (LogicNegationNode) condition; + negate = !negate; + condition = logicNegationNode.getValue(); + } + + if (condition instanceof LogicConstantNode) { + genConstantTargetIf(trueBlock, falseBlock, negate, condition); + } else { + if (condition.graph() == null) { + condition = currentGraph.unique(condition); + } + + // Need to get probability based on current bci. + double probability = branchProbability(); + + if (negate) { + BciBlock tmpBlock = trueBlock; + trueBlock = falseBlock; + falseBlock = tmpBlock; + probability = 1 - probability; + } + + if (isNeverExecutedCode(probability)) { + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true)); + appendGoto(falseBlock); + return; + } else if (isNeverExecutedCode(1 - probability)) { + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false)); + appendGoto(trueBlock); + return; + } + int oldBci = stream.currentBCI(); + int trueBlockInt = checkPositiveIntConstantPushed(trueBlock); + if (trueBlockInt != -1) { + int falseBlockInt = checkPositiveIntConstantPushed(falseBlock); + if (falseBlockInt != -1) { + if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) { + return; + } + } + } + + this.controlFlowSplit = true; + FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false); + FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true); + ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); + append(ifNode); + } + } + + private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) { + if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) { + genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false); + return true; + } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) { + genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, true); + return true; + } + return false; + } + + private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) { + ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt)); + ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt)); + ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue); + if (conditionalNode.graph() == null) { + conditionalNode = currentGraph.addOrUnique(conditionalNode); + } + if (genReturn) { + this.genReturn(conditionalNode); + } else { + frameState.push(Kind.Int, conditionalNode); + appendGoto(trueBlock.getSuccessor(0)); + stream.setBCI(oldBci); + } + } + + private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) { LogicNode condition; assert !a.getKind().isNumericFloat(); if (cond == Condition.EQ || cond == Condition.NE) { @@ -1811,80 +1914,20 @@ assert a.getKind() != Kind.Object && !cond.isUnsigned(); condition = genIntegerLessThan(a, b); } - - if (condition instanceof LogicNegationNode) { - LogicNegationNode logicNegationNode = (LogicNegationNode) condition; - negate = !negate; - condition = logicNegationNode.getValue(); - } - - if (condition instanceof LogicConstantNode) { - LogicConstantNode constantLogicNode = (LogicConstantNode) condition; - boolean value = constantLogicNode.getValue(); - if (negate) { - value = !value; - } - BciBlock nextBlock = falseBlock; - if (value) { - nextBlock = trueBlock; - } - appendGoto(nextBlock); - } else { - - if (condition.graph() == null) { - condition = currentGraph.unique(condition); - } - - // Need to get probability based on current bci. - double probability = branchProbability(); - - int oldBci = stream.currentBCI(); - int trueBlockInt = checkPositiveIntConstantPushed(trueBlock); - if (trueBlockInt != -1) { - int falseBlockInt = checkPositiveIntConstantPushed(falseBlock); - if (falseBlockInt != -1) { + return condition; + } - boolean genReturn = false; - boolean genConditional = false; - if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) { - genConditional = true; - } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) { - genReturn = true; - genConditional = true; - } - - if (genConditional) { - ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt)); - ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt)); - if (negate) { - ConstantNode tmp = falseValue; - falseValue = trueValue; - trueValue = tmp; - } - ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue); - if (conditionalNode.graph() == null) { - conditionalNode = currentGraph.addOrUnique(conditionalNode); - } - if (genReturn) { - this.genReturn(conditionalNode); - } else { - frameState.push(Kind.Int, conditionalNode); - appendGoto(trueBlock.getSuccessor(0)); - stream.setBCI(oldBci); - } - return; - } - } - } - - this.controlFlowSplit = true; - - ValueNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); - ValueNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); - - ValueNode ifNode = negate ? genIfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : genIfNode(condition, trueSuccessor, falseSuccessor, probability); - append(ifNode); + private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) { + LogicConstantNode constantLogicNode = (LogicConstantNode) condition; + boolean value = constantLogicNode.getValue(); + if (negate) { + value = !value; } + BciBlock nextBlock = falseBlock; + if (value) { + nextBlock = trueBlock; + } + appendGoto(nextBlock); } private int checkPositiveIntConstantPushed(BciBlock block) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Sun Feb 22 17:17:45 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.java.BciBlockMapping.*; import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,11 +39,27 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; -public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode, HIRFrameStateBuilder> { +public final class HIRFrameStateBuilder { private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; + protected final ResolvedJavaMethod method; + protected int stackSize; + protected final ValueNode[] locals; + protected final ValueNode[] stack; + protected ValueNode[] lockedObjects; + + /** + * Specifies if asserting type checks are enabled. + */ + protected final boolean checkTypes; + + /** + * @see BytecodeFrame#rethrowException + */ + protected boolean rethrowException; + private MonitorIdNode[] monitorIds; private final StructuredGraph graph; private final Supplier<FrameState> outerFrameStateSupplier; @@ -54,7 +71,11 @@ * @param graph the target graph of Graal nodes created by the builder */ public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier<FrameState> outerFrameStateSupplier) { - super(method, checkTypes); + this.method = method; + this.locals = allocateArray(method.getMaxLocals()); + this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); + this.lockedObjects = allocateArray(0); + this.checkTypes = checkTypes; assert graph != null; @@ -63,7 +84,7 @@ this.outerFrameStateSupplier = outerFrameStateSupplier; } - public final void initializeFromArgumentsArray(ValueNode[] arguments) { + public void initializeFromArgumentsArray(ValueNode[] arguments) { int javaIndex = 0; int index = 0; @@ -82,7 +103,7 @@ } } - public final void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { + public void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { int javaIndex = 0; int index = 0; @@ -128,7 +149,17 @@ } private HIRFrameStateBuilder(HIRFrameStateBuilder other) { - super(other); + this.method = other.method; + this.stackSize = other.stackSize; + this.locals = other.locals.clone(); + this.stack = other.stack.clone(); + this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); + this.rethrowException = other.rethrowException; + this.checkTypes = other.checkTypes; + + assert locals.length == method.getMaxLocals(); + assert stack.length == Math.max(1, method.getMaxStackSize()); + assert other.graph != null; graph = other.graph; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); @@ -139,8 +170,7 @@ assert lockedObjects.length == monitorIds.length; } - @Override - protected ValueNode[] allocateArray(int length) { + private static ValueNode[] allocateArray(int length) { return length == 0 ? EMPTY_ARRAY : new ValueNode[length]; } @@ -175,12 +205,10 @@ return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(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"; @@ -210,10 +238,18 @@ assert isCompatibleWith(other); for (int i = 0; i < localsSize(); i++) { - storeLocal(i, merge(localAt(i), other.localAt(i), block)); + ValueNode curLocal = localAt(i); + ValueNode mergedLocal = merge(curLocal, other.localAt(i), block); + if (curLocal != mergedLocal) { + storeLocal(i, mergedLocal); + } } for (int i = 0; i < stackSize(); i++) { - storeStack(i, merge(stackAt(i), other.stackAt(i), block)); + ValueNode curStack = stackAt(i); + ValueNode mergedStack = merge(curStack, other.stackAt(i), block); + if (curStack != mergedStack) { + storeStack(i, mergedStack); + } } for (int i = 0; i < lockedObjects.length; i++) { lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block); @@ -224,7 +260,6 @@ private ValueNode merge(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) { if (currentValue == null || currentValue.isDeleted()) { return null; - } else if (block.isPhiAtMerge(currentValue)) { if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { propagateDelete((ValuePhiNode) currentValue); @@ -232,26 +267,27 @@ } ((PhiNode) currentValue).addInput(otherValue); return currentValue; - } else if (currentValue != otherValue) { assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for changed locals and all stack slots"; if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { return null; } - - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); - for (int i = 0; i < block.phiPredecessorCount(); i++) { - phi.addInput(currentValue); - } - phi.addInput(otherValue); - assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount(); - return phi; - + return createValuePhi(currentValue, otherValue, block); } else { return currentValue; } } + private ValuePhiNode createValuePhi(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) { + ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); + for (int i = 0; i < block.phiPredecessorCount(); i++) { + phi.addInput(currentValue); + } + phi.addInput(otherValue); + assert phi.valueCount() == block.phiPredecessorCount() + 1; + return phi; + } + private void propagateDelete(FloatingNode node) { assert node instanceof ValuePhiNode || node instanceof ProxyNode; if (node.isDeleted()) { @@ -380,7 +416,6 @@ /** * @return the current lock depth */ - @Override public int lockDepth() { assert lockedObjects.length == monitorIds.length; return lockedObjects.length; @@ -405,4 +440,433 @@ } return false; } + + public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { + /* + * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to + * remove it for normal compilations, but not for OSR compilations - otherwise dead object + * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with + * Kind.Illegal, because the conflicting branch might not have been parsed. + */ + if (liveness == null) { + return; + } + if (liveIn) { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveIn(block, i)) { + locals[i] = null; + } + } + } else { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveOut(block, i)) { + locals[i] = null; + } + } + } + } + + /** + * @see BytecodeFrame#rethrowException + */ + public boolean rethrowException() { + return rethrowException; + } + + /** + * @see BytecodeFrame#rethrowException + */ + public void setRethrowException(boolean b) { + rethrowException = b; + } + + /** + * Returns the size of the local variables. + * + * @return the size of the local variables + */ + public int localsSize() { + return locals.length; + } + + /** + * Gets the current size (height) of the stack. + */ + public int stackSize() { + return stackSize; + } + + /** + * Gets the value in the local variables at the specified index, without any sanity checking. + * + * @param i the index into the locals + * @return the instruction that produced the value for the specified local + */ + public ValueNode localAt(int i) { + return locals[i]; + } + + /** + * 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 ValueNode stackAt(int i) { + return stack[i]; + } + + /** + * Gets the value in the lock at the specified index, without any sanity checking. + * + * @param i the index into the lock + * @return the instruction that produced the value for the specified lock + */ + public ValueNode lockAt(int i) { + return lockedObjects[i]; + } + + public void storeLock(int i, ValueNode lock) { + lockedObjects[i] = lock; + } + + /** + * Loads the local variable at the specified index, checking that the returned value is non-null + * and that two-stack values are properly handled. + * + * @param i the index of the local variable to load + * @return the instruction that produced the specified local + */ + public ValueNode loadLocal(int i) { + ValueNode x = locals[i]; + assert assertLoadLocal(i, x); + return x; + } + + private boolean assertLoadLocal(int i, ValueNode x) { + assert x != null : i; + assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); + assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); + return true; + } + + /** + * Stores a given local variable at the specified index. If the value occupies two slots, 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, ValueNode x) { + assert assertStoreLocal(x); + locals[i] = x; + if (x != null && x.getKind().needsTwoSlots()) { + // 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 && p.getKind().needsTwoSlots()) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } + } + } + + private boolean assertStoreLocal(ValueNode x) { + assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; + return true; + } + + public void storeStack(int i, ValueNode x) { + assert assertStoreStack(i, x); + stack[i] = x; + } + + private boolean assertStoreStack(int i, ValueNode 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"; + return true; + } + + /** + * 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(Kind kind, ValueNode x) { + assert assertPush(kind, x); + xpush(x); + if (kind.needsTwoSlots()) { + xpush(null); + } + } + + private boolean assertPush(Kind kind, ValueNode x) { + assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + assert x != null && (!checkTypes || x.getKind() == kind); + return true; + } + + /** + * Pushes a value onto the stack without checking the type. + * + * @param x the instruction to push onto the stack + */ + public void xpush(ValueNode x) { + assert assertXpush(x); + stack[stackSize++] = x; + } + + private boolean assertXpush(ValueNode x) { + assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); + return true; + } + + /** + * 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(ValueNode x) { + assert assertInt(x); + xpush(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(ValueNode x) { + assert assertFloat(x); + xpush(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(ValueNode x) { + assert assertObject(x); + xpush(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(ValueNode x) { + assert assertLong(x); + xpush(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(ValueNode x) { + assert assertDouble(x); + xpush(x); + xpush(null); + } + + public void pushReturn(Kind kind, ValueNode x) { + if (kind != Kind.Void) { + push(kind.getStackKind(), x); + } + } + + /** + * 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 ValueNode pop(Kind kind) { + if (kind.needsTwoSlots()) { + xpop(); + } + assert assertPop(kind); + return xpop(); + } + + private boolean assertPop(Kind kind) { + assert kind != Kind.Void; + ValueNode x = xpeek(); + assert x != null && (!checkTypes || x.getKind() == kind); + return true; + } + + /** + * Pops a value off of the stack without checking the type. + * + * @return x the instruction popped off the stack + */ + public ValueNode xpop() { + return stack[--stackSize]; + } + + private ValueNode xpeek() { + return stack[stackSize - 1]; + } + + /** + * Pops a value off of the stack and checks that it is an int. + * + * @return x the instruction popped off the stack + */ + public ValueNode ipop() { + assert assertIntPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a float. + * + * @return x the instruction popped off the stack + */ + public ValueNode fpop() { + assert assertFloatPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is an object. + * + * @return x the instruction popped off the stack + */ + public ValueNode apop() { + assert assertObjectPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a long. + * + * @return x the instruction popped off the stack + */ + public ValueNode lpop() { + assert assertHighPeek(); + xpop(); + assert assertLongPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a double. + * + * @return x the instruction popped off the stack + */ + public ValueNode dpop() { + assert assertHighPeek(); + xpop(); + assert assertDoublePeek(); + return xpop(); + } + + /** + * Pop the specified number of slots off of this stack and return them as an array of + * instructions. + * + * @return an array containing the arguments off of the stack + */ + public ValueNode[] popArguments(int argSize) { + ValueNode[] result = allocateArray(argSize); + int newStackSize = stackSize; + for (int i = argSize - 1; i >= 0; i--) { + newStackSize--; + if (stack[newStackSize] == null) { + /* Two-slot value. */ + newStackSize--; + assert stack[newStackSize].getKind().needsTwoSlots(); + } else { + assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); + } + result[i] = stack[newStackSize]; + } + stackSize = newStackSize; + return result; + } + + /** + * Peeks an element from the operand stack. + * + * @param argumentNumber The number of the argument, relative from the top of the stack (0 = + * top). Long and double arguments only count as one argument, i.e., null-slots are + * ignored. + * @return The peeked argument. + */ + public ValueNode peek(int argumentNumber) { + int idx = stackSize() - 1; + for (int i = 0; i < argumentNumber; i++) { + if (stackAt(idx) == null) { + idx--; + assert stackAt(idx).getKind().needsTwoSlots(); + } + idx--; + } + return stackAt(idx); + } + + /** + * Clears all values on this stack. + */ + public void clearStack() { + stackSize = 0; + } + + private boolean assertLongPeek() { + return assertLong(xpeek()); + } + + private static boolean assertLong(ValueNode x) { + assert x != null && (x.getKind() == Kind.Long); + return true; + } + + private boolean assertIntPeek() { + return assertInt(xpeek()); + } + + private static boolean assertInt(ValueNode x) { + assert x != null && (x.getKind() == Kind.Int); + return true; + } + + private boolean assertFloatPeek() { + return assertFloat(xpeek()); + } + + private static boolean assertFloat(ValueNode x) { + assert x != null && (x.getKind() == Kind.Float); + return true; + } + + private boolean assertObjectPeek() { + return assertObject(xpeek()); + } + + private boolean assertObject(ValueNode x) { + assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); + return true; + } + + private boolean assertDoublePeek() { + return assertDouble(xpeek()); + } + + private static boolean assertDouble(ValueNode x) { + assert x != null && (x.getKind() == Kind.Double); + return true; + } + + private boolean assertHighPeek() { + assert xpeek() == null; + return true; + } }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Sun Feb 22 17:17:45 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; @@ -111,6 +112,12 @@ }; ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); + for (Node fixed : obsoleteNodes) { + if (fixed.isAlive()) { + fixed.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(fixed); + } + } } @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Sun Feb 22 17:17:45 2015 +0100 @@ -101,7 +101,7 @@ Debug.dump(graph, "after " + getName() + " iteration"); } - new DeadCodeEliminationPhase(Required).apply(graph); + new DeadCodeEliminationPhase(Optional).apply(graph); Set<Node> changedNodes = listener.getNodes(); for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Sun Feb 22 17:17:45 2015 +0100 @@ -130,23 +130,16 @@ * * @param node The fixed node that should be deleted. */ - public void deleteFixedNode(final FixedWithNextNode node) { + public void deleteNode(final Node node) { add("delete fixed node", (graph, obsoleteNodes) -> { - GraphUtil.unlinkFixedNode(node); - assert obsoleteNodes.add(node); + if (node instanceof FixedWithNextNode) { + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); + } + obsoleteNodes.add(node); }); } /** - * Removes the given fixed node from the control flow. - * - * @param node The fixed node that should be deleted. - */ - public void unlinkFixedNode(final FixedWithNextNode node) { - add("unlink fixed node", graph -> GraphUtil.unlinkFixedNode(node)); - } - - /** * Replaces the given node at its usages without deleting it. If the current node is a fixed * node it will be disconnected from the control flow, so that it will be deleted by a * subsequent {@link DeadCodeEliminationPhase} @@ -165,11 +158,9 @@ } node.replaceAtUsages(replacement); if (node instanceof FixedWithNextNode) { - FixedNode next = ((FixedWithNextNode) node).next(); - ((FixedWithNextNode) node).setNext(null); - node.replaceAtPredecessor(next); - assert obsoleteNodes.add(node); + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); } + GraphUtil.killWithUnusedFloatingInputs(node); }); } @@ -194,13 +185,4 @@ } }); } - - /** - * Performs a custom action. - * - * @param action The action that should be performed when the effects are applied. - */ - public void customAction(final Runnable action) { - add("customAction", graph -> action.run()); - } }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Sun Feb 22 17:17:45 2015 +0100 @@ -94,7 +94,7 @@ ValueNode value = getScalarAlias(store.value()); boolean result = false; if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); + effects.deleteNode(store); result = true; } state.killReadCache(store.field());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Sun Feb 22 17:17:45 2015 +0100 @@ -75,7 +75,7 @@ StoreFieldNode store = (StoreFieldNode) node; ValueNode value = getScalarAlias(store.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); + effects.deleteNode(store); deleted = true; } state.killReadCache(store.field()); @@ -108,7 +108,7 @@ ValueNode value = getScalarAlias(write.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); + effects.deleteNode(write); deleted = true; } processIdentity(state, write.location().getLocationIdentity()); @@ -141,7 +141,7 @@ ValueNode value = getScalarAlias(write.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); + effects.deleteNode(write); deleted = true; } processIdentity(state, write.getLocationIdentity());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Sun Feb 22 17:17:45 2015 +0100 @@ -62,7 +62,7 @@ } for (Node node : obsoleteNodes) { - if (node instanceof FixedNode) { + if (node instanceof FixedNode && !node.isDeleted()) { assert !flood.isMarked(node) : node; } } @@ -87,7 +87,7 @@ } boolean success = true; for (Node node : obsoleteNodes) { - if (flood.isMarked(node)) { + if (!node.isDeleted() && flood.isMarked(node)) { TTY.println("offending node path:"); Node current = node; TTY.print(current.toString());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Sun Feb 22 07:42:06 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Sun Feb 22 17:17:45 2015 +0100 @@ -117,9 +117,7 @@ @Override public void replaceWithVirtual(VirtualObjectNode virtual) { closure.addAndMarkAlias(virtual, current); - if (current instanceof FixedWithNextNode) { - effects.deleteFixedNode((FixedWithNextNode) current); - } + effects.deleteNode(current); deleted = true; } @@ -132,7 +130,7 @@ @Override public void delete() { - effects.deleteFixedNode((FixedWithNextNode) current); + effects.deleteNode(current); deleted = true; }