# HG changeset patch # User Thomas Wuerthinger # Date 1424614794 -3600 # Node ID 97b35083d49d58ce398bb04efd96221ccfdcffa6 # Parent 50b19dc35c660fd6351e2db4a7d4939be83e9e29 Reduce casting in AbstractBytecodeParser. Consolidate asserts in HIRFrameStateBuilder. diff -r 50b19dc35c66 -r 97b35083d49d 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 Sun Feb 22 14:41:35 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Sun Feb 22 15:19:54 2015 +0100 @@ -42,7 +42,7 @@ import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -public abstract class AbstractBytecodeParser> { +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_ 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 dims); + protected abstract void handleUnresolvedNewMultiArray(JavaType type, List 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 dims = new ArrayList<>(Collections.nCopies(rank, null)); + List 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 dims); + protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List 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 actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); + protected abstract void genIntegerSwitch(ValueNode value, ArrayList 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; } diff -r 50b19dc35c66 -r 97b35083d49d graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sun Feb 22 14:41:35 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sun Feb 22 15:19:54 2015 +0100 @@ -172,7 +172,7 @@ private int peelIteration; } - public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { + public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -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; } @@ -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); @@ -1508,7 +1508,7 @@ try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, getFirstInstruction(block, this.getCurrentDimension()), block.isLoopHeader)) { lastInstr = getFirstInstruction(block, this.getCurrentDimension()); - frameState = (HIRFrameStateBuilder) getEntryState(block, this.getCurrentDimension()); + frameState = getEntryState(block, this.getCurrentDimension()); parser.setCurrentFrameState(frameState); currentBlock = block; diff -r 50b19dc35c66 -r 97b35083d49d 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 Sun Feb 22 14:41:35 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Sun Feb 22 15:19:54 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 { +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 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 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"; @@ -380,7 +408,6 @@ /** * @return the current lock depth */ - @Override public int lockDepth() { assert lockedObjects.length == monitorIds.length; return lockedObjects.length; @@ -405,4 +432,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; + } }