# HG changeset patch # User Lukas Stadler # Date 1332323222 -3600 # Node ID 51111665eda6a102019f319b8c82788f2bacade8 # Parent e2da6471a9a122e661a3096ed727f25b01f37c59 Support for recording a leaf graph id for each deoptimization point in the debug info. diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Wed Mar 21 10:47:02 2012 +0100 @@ -43,9 +43,9 @@ private HashMap virtualObjects = new HashMap<>(); - public LIRDebugInfo build(FrameState topState, LockScope locks, List pointerSlots, LabelRef exceptionEdge) { + public LIRDebugInfo build(FrameState topState, LockScope locks, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { assert virtualObjects.size() == 0; - CiFrame frame = computeFrameForState(topState, locks); + CiFrame frame = computeFrameForState(topState, locks, leafGraphId); CiVirtualObject[] virtualObjectsArray = null; if (virtualObjects.size() != 0) { @@ -106,7 +106,7 @@ return new LIRDebugInfo(frame, virtualObjectsArray, pointerSlots, exceptionEdge); } - private CiFrame computeFrameForState(FrameState state, LockScope locks) { + private CiFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) { int numLocals = state.localsSize(); int numStack = state.stackSize(); int numLocks = (locks != null && locks.callerState == state.outerFrameState()) ? locks.stateDepth + 1 : 0; @@ -133,14 +133,14 @@ CiFrame caller = null; if (state.outerFrameState() != null) { - caller = computeFrameForState(state.outerFrameState(), nextLock); + caller = computeFrameForState(state.outerFrameState(), nextLock, -1); } else { if (nextLock != null) { throw new CiBailout("unbalanced monitors: found monitor for unknown frame"); } } assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI; - CiFrame frame = new CiFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, state.localsSize(), state.stackSize(), numLocks); + CiFrame frame = new CiFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, state.localsSize(), state.stackSize(), numLocks, leafGraphId); return frame; } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Mar 21 10:47:02 2012 +0100 @@ -249,15 +249,20 @@ public LIRDebugInfo state() { assert lastState != null : "must have state before instruction"; - return stateFor(lastState); + return stateFor(lastState, -1); } - public LIRDebugInfo stateFor(FrameState state) { - return stateFor(state, null, null); + public LIRDebugInfo state(long leafGraphId) { + assert lastState != null : "must have state before instruction"; + return stateFor(lastState, leafGraphId); } - public LIRDebugInfo stateFor(FrameState state, List pointerSlots, LabelRef exceptionEdge) { - return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge); + public LIRDebugInfo stateFor(FrameState state, long leafGraphId) { + return stateFor(state, null, null, leafGraphId); + } + + public LIRDebugInfo stateFor(FrameState state, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { + return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge, leafGraphId); } /** @@ -528,7 +533,7 @@ // The state before the monitor enter is used for null checks, so it must not contain the newly locked object. curLocks = new LockScope(curLocks, x.stateAfter().outerFrameState(), x, lockData); // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object. - LIRDebugInfo stateAfter = stateFor(x.stateAfter()); + LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1); XirSnippet snippet = xir.genMonitorEnter(site(x, x.object()), obj, lockAddress); emitXir(snippet, x, stateBefore, stateAfter, true, null, null); @@ -745,20 +750,21 @@ } @Override - public void emitGuardCheck(BooleanNode comp) { + public void emitGuardCheck(BooleanNode comp, long leafGraphId) { if (comp instanceof NullCheckNode && !((NullCheckNode) comp).expectedNull) { - emitNullCheckGuard((NullCheckNode) comp); + emitNullCheckGuard((NullCheckNode) comp, leafGraphId); } else if (comp instanceof ConstantNode && comp.asConstant().asBoolean()) { // True constant, nothing to emit. + // False constants are handled within emitBranch. } else { // Fall back to a normal branch. - LIRDebugInfo info = state(); + LIRDebugInfo info = state(leafGraphId); LabelRef stubEntry = createDeoptStub(DeoptAction.InvalidateReprofile, info, comp); emitBranch(comp, null, stubEntry, info); } } - protected abstract void emitNullCheckGuard(NullCheckNode node); + protected abstract void emitNullCheckGuard(NullCheckNode node, long leafGraphId); public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { if (node instanceof NullCheckNode) { @@ -926,7 +932,7 @@ if (!target().invokeSnippetAfterArguments) { // This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it // destroys rdx, which is also used to pass a parameter. Therefore, the snippet must be before the parameters are assigned to their locations. - LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci())); + LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId()); destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } @@ -939,11 +945,11 @@ if (target().invokeSnippetAfterArguments) { // This is the version currently active for HotSpot. - LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null); + LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId()); destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } - LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null); + LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId()); emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks); if (isLegal(resultOperand)) { @@ -985,7 +991,6 @@ return argList; } - protected abstract LabelRef createDeoptStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo); @Override @@ -1046,7 +1051,7 @@ } // TODO is it correct here that the pointerSlots are not passed to the oop map generation? - info = stateFor(stateBeforeReturn); + info = stateFor(stateBeforeReturn, -1); } emitCall(x.call(), resultOperand, argList, CiConstant.forLong(0), info, null); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java Wed Mar 21 10:47:02 2012 +0100 @@ -79,7 +79,7 @@ } BeginNode ifBlockBegin = findBeginNode(ifNode); Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode)); + FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.leafGraphId())); otherBegin.replaceAtUsages(ifBlockBegin); FixedNode next = otherBegin.next(); otherBegin.setNext(null); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Wed Mar 21 10:47:02 2012 +0100 @@ -59,8 +59,8 @@ } @Override - public Node createGuard(Node condition) { - // TODO (thomaswue): Docuemnt why this must not be called on floating nodes. + public Node createGuard(Node condition, long leafGraphId) { + // TODO (thomaswue): Document why this must not be called on floating nodes. throw new UnsupportedOperationException(); } }; @@ -117,7 +117,7 @@ } @Override - public Node createGuard(Node condition) { + public Node createGuard(Node condition, long leafGraphId) { FixedNode guardAnchor = (FixedNode) getGuardAnchor(); if (GraalOptions.OptEliminateGuards) { for (Node usage : condition.usages()) { @@ -126,7 +126,7 @@ } } } - GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor)); + GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, leafGraphId)); activeGuards.grow(); activeGuards.mark(newGuard); return newGuard; diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Mar 21 10:47:02 2012 +0100 @@ -498,16 +498,20 @@ return result; } - @Override public void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo) { + assert cond != null; LIRDebugInfo info = state(); LabelRef stubEntry = createDeoptStub(action, info, deoptInfo); - if (cond != null) { - append(new BranchOp(cond, stubEntry, info)); - } else { - append(new JumpOp(stubEntry, info)); - } + append(new BranchOp(cond, stubEntry, info)); + } + + + @Override + public void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId) { + LIRDebugInfo info = state(leafGraphId); + LabelRef stubEntry = createDeoptStub(action, info, deoptInfo); + append(new JumpOp(stubEntry, info)); } @Override @@ -555,10 +559,10 @@ } @Override - protected void emitNullCheckGuard(NullCheckNode node) { + protected void emitNullCheckGuard(NullCheckNode node, long leafGraphId) { assert !node.expectedNull; Variable value = load(operand(node.object())); - LIRDebugInfo info = state(); + LIRDebugInfo info = state(leafGraphId); append(new NullCheckOp(value, info)); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Wed Mar 21 10:47:02 2012 +0100 @@ -176,7 +176,7 @@ ValueNode receiver = invoke.callTarget().receiver(); ReadHubNode objectClass = graph.add(new ReadHubNode(receiver)); IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClass, type)); - FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode)); + FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, invoke.leafGraphId())); AnchorNode anchor = graph.add(new AnchorNode()); assert invoke.predecessor() != null; @@ -304,7 +304,7 @@ if (shouldFallbackToInvoke()) { unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false); } else { - unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)); + unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, invoke.leafGraphId())); } // replace the invoke exception edge @@ -369,7 +369,7 @@ ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver())); graph.addBeforeFixed(invoke.node(), objectClassNode); - FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)); + FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, invoke.leafGraphId())); FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, new BeginNode[] {calleeEntryNode}, unknownTypeNode); FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); @@ -812,7 +812,7 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); - DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptAction.InvalidateRecompile); + DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptAction.InvalidateRecompile, invoke.leafGraphId()); unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode)); // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state // (because there is no "after exception" frame state!) @@ -900,7 +900,7 @@ NodeInputList parameters = callTarget.arguments(); ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.stamp().nonNull()) { - graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false))))); + graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), invoke.leafGraphId()))); } } } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Wed Mar 21 10:47:02 2012 +0100 @@ -113,5 +113,7 @@ int RiMethod_vtableEntryOffset(HotSpotMethodResolved method); + long[] getDeoptedLeafGraphIds(); + // Checkstyle: resume } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Wed Mar 21 10:47:02 2012 +0100 @@ -162,5 +162,8 @@ @Override public native int RiMethod_vtableEntryOffset(HotSpotMethodResolved method); + @Override + public native long[] getDeoptedLeafGraphIds(); + // Checkstyle: resume } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Wed Mar 21 10:47:02 2012 +0100 @@ -218,7 +218,7 @@ if (n instanceof ArrayLengthNode) { ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; - SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array(), arrayLengthNode.stamp()); + SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array(), arrayLengthNode.stamp(), StructuredGraph.INVALID_GRAPH_ID); graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength); safeReadArrayLength.lower(tool); } else if (n instanceof LoadFieldNode) { @@ -229,7 +229,7 @@ int displacement = ((HotSpotField) field.field()).offset(); assert field.kind() != CiKind.Illegal; ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph), field.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)))); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixedWithFixed(field, memoryRead); } else if (n instanceof StoreFieldNode) { StoreFieldNode storeField = (StoreFieldNode) n; @@ -238,7 +238,7 @@ } HotSpotField field = (HotSpotField) storeField.field(); WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph))); - memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)))); + memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); @@ -247,7 +247,7 @@ } } else if (n instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool); + GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool, loadIndexed.leafGraphId()); CiKind elementKind = loadIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); @@ -256,7 +256,7 @@ graph.replaceFixedWithFixed(loadIndexed, memoryRead); } else if (n instanceof StoreIndexedNode) { StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool); + GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool, storeIndexed.leafGraphId()); CiKind elementKind = storeIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); @@ -277,7 +277,7 @@ } else { AnchorNode anchor = graph.add(new AnchorNode()); graph.addBeforeFixed(storeIndexed, anchor); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false))); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), StructuredGraph.INVALID_GRAPH_ID); ReadNode arrayClass = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull())); arrayClass.setGuard(guard); graph.addBeforeFixed(storeIndexed, arrayClass); @@ -300,7 +300,7 @@ IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph); location.setIndexScalingEnabled(false); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)))); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; @@ -318,7 +318,7 @@ ReadHubNode objectClassNode = (ReadHubNode) n; LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph); ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)))); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixed(objectClassNode, memoryRead); } } @@ -327,8 +327,8 @@ return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph); } - private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { - return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length()))); + private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) { + return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), leafGraphId); } @Override @@ -348,7 +348,7 @@ } StructuredGraph graph = new StructuredGraph(); LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); - SafeReadNode klassOop = safeReadHub(graph, receiver); + SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); ReadNode result = graph.add(new ReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull())); ReturnNode ret = graph.add(new ReturnNode(result)); graph.start().setNext(klassOop); @@ -359,7 +359,7 @@ if (fullName.equals("getModifiers()I")) { StructuredGraph graph = new StructuredGraph(); LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); - SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull()); + SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID); graph.start().setNext(klassOop); // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null) ReadNode result = graph.add(new ReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), StampFactory.forKind(CiKind.Int))); @@ -378,16 +378,16 @@ return null; } - private SafeReadNode safeReadHub(Graph graph, ValueNode value) { - return safeRead(graph, CiKind.Object, value, config.hubOffset, StampFactory.objectNonNull()); + private SafeReadNode safeReadHub(Graph graph, ValueNode value, long leafGraphId) { + return safeRead(graph, CiKind.Object, value, config.hubOffset, StampFactory.objectNonNull(), leafGraphId); } - private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value, Stamp stamp) { - return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset, stamp); + private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value, Stamp stamp, long leafGraphId) { + return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset, stamp, leafGraphId); } - private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset, Stamp stamp) { - return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp)); + private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset, Stamp stamp, long leafGraphId) { + return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp, leafGraphId)); } public RiResolvedType getType(Class clazz) { @@ -428,4 +428,9 @@ plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); return compiler.getCompiler().compileMethod(method, graph, -1, plan); } + + @Override + public long[] getDeoptedLeafGraphIds() { + return compiler.getVMEntries().getDeoptedLeafGraphIds(); + } } diff -r e2da6471a9a1 -r 51111665eda6 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 Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 21 10:47:02 2012 +0100 @@ -27,6 +27,7 @@ import java.lang.reflect.*; import java.util.*; +import java.util.concurrent.atomic.*; import com.oracle.max.cri.ci.*; @@ -89,10 +90,9 @@ private BitSet canTrapBitSet; - public static final Map cachedGraphs = new WeakHashMap<>(); - private final GraphBuilderConfiguration config; + private long graphId; /** * Node that marks the begin of block during bytecode parsing. When a block is identified the first @@ -120,6 +120,7 @@ @Override protected void run(StructuredGraph graph) { method = graph.method(); + graphId = graph.graphId(); profilingInfo = method.profilingInfo(); assert method.code() != null : "method must contain bytecodes: " + method; this.stream = new BytecodeStream(method.code()); @@ -201,10 +202,6 @@ n.safeDelete(); } } - - if (GraalOptions.CacheGraphs && !currentGraph.hasNode(DeoptimizeNode.class)) { - cachedGraphs.put(method, currentGraph.copy()); - } } private Block unwindBlock(int bci) { @@ -328,7 +325,7 @@ if (riType instanceof RiResolvedType) { frameState.push(CiKind.Object, append(ConstantNode.forCiConstant(((RiResolvedType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph))); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.push(CiKind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); } } else if (con instanceof CiConstant) { @@ -345,7 +342,7 @@ ValueNode index = frameState.ipop(); ValueNode array = frameState.apop(); ValueNode length = append(currentGraph.add(new ArrayLengthNode(array))); - ValueNode v = append(currentGraph.add(new LoadIndexedNode(array, index, length, kind))); + ValueNode v = append(currentGraph.add(new LoadIndexedNode(array, index, length, kind, graphId))); frameState.push(kind.stackKind(), v); } @@ -356,7 +353,7 @@ ValueNode index = frameState.ipop(); ValueNode array = frameState.apop(); ValueNode length = append(currentGraph.add(new ArrayLengthNode(array))); - StoreIndexedNode result = currentGraph.add(new StoreIndexedNode(array, index, length, kind, value)); + StoreIndexedNode result = currentGraph.add(new StoreIndexedNode(array, index, length, kind, value, graphId)); append(result); } @@ -587,7 +584,7 @@ private void genThrow(int bci) { ValueNode exception = frameState.apop(); - FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)))); + FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), graphId)); append(node); append(handleException(exception, bci)); } @@ -679,7 +676,7 @@ frameState.apush(checkCast); } else { ValueNode object = frameState.apop(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph)))))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -697,7 +694,7 @@ frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)); IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1)); append(ifNode); lastInstr = trueSucc; @@ -711,7 +708,7 @@ NewInstanceNode n = currentGraph.add(new NewInstanceNode((RiResolvedType) type)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -752,7 +749,7 @@ NewArrayNode n = currentGraph.add(new NewObjectArrayNode((RiResolvedType) type, length)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } @@ -769,7 +766,7 @@ FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((RiResolvedType) type, dims)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -783,7 +780,7 @@ LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (RiResolvedField) field)); appendOptimizedLoadField(kind, load); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.push(kind.stackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); } } @@ -884,7 +881,7 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (RiResolvedField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); } } @@ -926,7 +923,7 @@ if (initialized) { return appendConstant(((RiResolvedType) holder).getEncoding(representation)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); return null; } } @@ -987,7 +984,7 @@ } private void genInvokeDeopt(RiMethod unresolvedTarget, boolean withReceiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); frameState.popArguments(unresolvedTarget.signature().argumentSlots(withReceiver), unresolvedTarget.signature().argumentCount(withReceiver)); CiKind kind = unresolvedTarget.signature().returnKind(false); if (kind != CiKind.Void) { @@ -1024,7 +1021,7 @@ private void appendInvoke(InvokeKind invokeKind, RiResolvedMethod targetMethod, ValueNode[] args) { CiKind resultType = targetMethod.signature().returnKind(false); if (GraalOptions.DeoptALot) { - DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptAction.None)); + DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptAction.None, StructuredGraph.INVALID_GRAPH_ID)); deoptimize.setMessage("invoke " + targetMethod.name()); append(deoptimize); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); @@ -1033,7 +1030,7 @@ BeginNode exceptionEdge = handleException(null, bci()); ValueNode result; if (exceptionEdge != null) { - InvokeWithExceptionNode invoke = currentGraph.add(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + InvokeWithExceptionNode invoke = currentGraph.add(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci(), graphId)); result = append(invoke); frameState.pushReturn(resultType, result); Block nextBlock = currentBlock.successors.get(0); @@ -1044,7 +1041,7 @@ invoke.setNext(createTarget(nextBlock, frameState)); invoke.setStateAfter(frameState.create(nextBlock.startBci)); } else { - result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci()))); + result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci(), graphId))); frameState.pushReturn(resultType, result); } } @@ -1113,7 +1110,7 @@ ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph)))))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), graphId))); if (!successor.jsrScope.equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); } @@ -1199,7 +1196,7 @@ private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1; if (probability == 0 && config.useBranchPrediction()) { - return currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)); + return currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, graphId)); } else { return createTarget(block, stateAfter); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Wed Mar 21 10:47:02 2012 +0100 @@ -27,6 +27,6 @@ public interface CiLoweringTool { GraalRuntime getRuntime(); Node getGuardAnchor(); - Node createGuard(Node condition); + Node createGuard(Node condition, long leafGraphId); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java Wed Mar 21 10:47:02 2012 +0100 @@ -39,4 +39,6 @@ StructuredGraph intrinsicGraph(RiResolvedMethod caller, int bci, RiResolvedMethod method, List parameters); CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph); + + long[] getDeoptedLeafGraphIds(); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -39,14 +39,16 @@ @Data private String message; @Data private final DeoptAction action; + private final long leafGraphId; public DeoptimizeNode() { - this(DeoptAction.InvalidateReprofile); + this(DeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID); } - public DeoptimizeNode(DeoptAction action) { + public DeoptimizeNode(DeoptAction action, long leafGraphId) { super(StampFactory.illegal()); this.action = action; + this.leafGraphId = leafGraphId; } public void setMessage(String message) { @@ -61,9 +63,13 @@ return action; } + public long leafGraphId() { + return leafGraphId; + } + @Override public void generate(LIRGeneratorTool gen) { - gen.emitDeoptimizeOn(null, action, message); + gen.emitDeoptimize(action, message, leafGraphId); } @NodeIntrinsic diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -31,16 +31,18 @@ public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType { @Input private final NodeInputList conditions; + private final long leafGraphId; - public FixedGuardNode(BooleanNode condition) { + public FixedGuardNode(BooleanNode condition, long leafGraphId) { super(StampFactory.illegal()); + this.leafGraphId = leafGraphId; this.conditions = new NodeInputList<>(this, new BooleanNode[] {condition}); } @Override public void generate(LIRGeneratorTool gen) { for (BooleanNode condition : conditions()) { - gen.emitGuardCheck(condition); + gen.emitGuardCheck(condition, leafGraphId); } } @@ -64,7 +66,7 @@ if (next != null) { tool.deleteBranch(next); } - setNext(graph().add(new DeoptimizeNode(DeoptAction.InvalidateRecompile))); + setNext(graph().add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, leafGraphId))); return; } } @@ -78,7 +80,7 @@ public void lower(CiLoweringTool tool) { AnchorNode newAnchor = graph().add(new AnchorNode()); for (BooleanNode b : conditions) { - newAnchor.addGuard((GuardNode) tool.createGuard(b)); + newAnchor.addGuard((GuardNode) tool.createGuard(b, leafGraphId)); } ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -32,6 +32,7 @@ @Input private BooleanNode condition; @Input(notDataflow = true) private FixedNode anchor; + private final long leafGraphId; public FixedNode anchor() { return anchor; @@ -54,15 +55,16 @@ condition = x; } - public GuardNode(BooleanNode condition, FixedNode anchor) { + public GuardNode(BooleanNode condition, FixedNode anchor, long leafGraphId) { super(StampFactory.illegal()); this.condition = condition; this.anchor = anchor; + this.leafGraphId = leafGraphId; } @Override public void generate(LIRGeneratorTool gen) { - gen.emitGuardCheck(condition()); + gen.emitGuardCheck(condition(), leafGraphId); } @Override diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Wed Mar 21 10:47:02 2012 +0100 @@ -58,4 +58,6 @@ boolean megamorph(); void setMegamorph(boolean megamorph); + + long leafGraphId(); } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -41,6 +41,7 @@ // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt @Data private boolean megamorph; private boolean useForInlining; + private final long leafGraphId; /** * Constructs a new Invoke instruction. @@ -50,10 +51,11 @@ * @param target the target method being called * @param args the list of instructions producing arguments to the invocation, including the receiver object */ - public InvokeNode(MethodCallTargetNode callTarget, int bci) { + public InvokeNode(MethodCallTargetNode callTarget, int bci, long leafGraphId) { super(callTarget.returnStamp()); this.callTarget = callTarget; this.bci = bci; + this.leafGraphId = leafGraphId; this.megamorph = false; this.useForInlining = true; } @@ -82,6 +84,11 @@ } @Override + public long leafGraphId() { + return leafGraphId; + } + + @Override public Map getDebugProperties() { Map debugProperties = super.getDebugProperties(); if (callTarget != null && callTarget.targetMethod() != null) { diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -41,16 +41,18 @@ // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt @Data private boolean megamorph; private boolean useForInlining; + private final long leafGraphId; /** * @param kind * @param blockSuccessors * @param branchProbability */ - public InvokeWithExceptionNode(MethodCallTargetNode callTarget, BeginNode exceptionEdge, int bci) { + public InvokeWithExceptionNode(MethodCallTargetNode callTarget, BeginNode exceptionEdge, int bci, long leafGraphId) { super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0}); this.bci = bci; this.callTarget = callTarget; + this.leafGraphId = leafGraphId; this.megamorph = true; this.useForInlining = true; } @@ -96,6 +98,11 @@ } @Override + public long leafGraphId() { + return leafGraphId; + } + + @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Long) { return super.toString(Verbosity.Short) + "(bci=" + bci() + ")"; diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Wed Mar 21 10:47:02 2012 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import java.util.*; +import java.util.concurrent.atomic.*; import com.oracle.max.cri.ri.*; import com.oracle.graal.graph.*; @@ -36,8 +37,19 @@ * This node is the start of the control flow of the graph. */ public class StructuredGraph extends Graph { + + public static final long INVALID_GRAPH_ID = -1; + private static final AtomicLong uniqueGraphIds = new AtomicLong(); private final BeginNode start; private final RiResolvedMethod method; + private final long graphId; + + /** + * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. + */ + public StructuredGraph() { + this(null, null); + } /** * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. @@ -50,13 +62,7 @@ super(name); this.start = add(new BeginNode()); this.method = method; - } - - /** - * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. - */ - public StructuredGraph() { - this((String) null); + this.graphId = uniqueGraphIds.incrementAndGet(); } public StructuredGraph(RiResolvedMethod method) { @@ -71,6 +77,10 @@ return method; } + public long graphId() { + return graphId; + } + @Override public StructuredGraph copy() { return copy(name); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -57,7 +57,7 @@ public void expand(BoxingMethodPool pool) { RiResolvedMethod boxingMethod = pool.getBoxingMethod(sourceKind); MethodCallTargetNode callTarget = graph().add(new MethodCallTargetNode(InvokeKind.Static, boxingMethod, new ValueNode[]{source}, boxingMethod.signature().returnType(boxingMethod.holder()))); - InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci)); + InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci, -1)); invokeNode.setProbability(this.probability()); invokeNode.setStateAfter(stateAfter()); ((StructuredGraph) graph()).replaceFixedWithFixed(this, invokeNode); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeAccessNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeAccessNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -30,11 +30,13 @@ @Input private ValueNode object; @Input private LocationNode location; + private final long leafGraphId; - public SafeAccessNode(ValueNode object, LocationNode location, Stamp stamp) { + public SafeAccessNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) { super(stamp); this.object = object; this.location = location; + this.leafGraphId = leafGraphId; } public ValueNode object() { @@ -44,4 +46,8 @@ public LocationNode location() { return location; } + + public long leafGraphId() { + return leafGraphId; + } } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -31,15 +31,15 @@ public class SafeReadNode extends SafeAccessNode implements Lowerable { - public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp) { - super(object, location, stamp); + public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) { + super(object, location, stamp, leafGraphId); assert object != null && location != null; } @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false))); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), StructuredGraph.INVALID_GRAPH_ID); ReadNode read = graph.add(new ReadNode(object(), location(), stamp())); read.setGuard(guard); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -34,8 +34,8 @@ @Input private ValueNode value; - public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location) { - super(object, location, StampFactory.forKind(CiKind.Void)); + public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location, long leafGraphId) { + super(object, location, StampFactory.forKind(CiKind.Void), leafGraphId); this.value = value; } @@ -46,7 +46,7 @@ @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false))); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), StructuredGraph.INVALID_GRAPH_ID); WriteNode write = graph.add(new WriteNode(object(), value(), location())); write.setGuard(guard); graph.replaceFixedWithFixed(this, write); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -46,6 +46,7 @@ } private final CiKind elementType; + private final long leafGraphId; /** * Create an new AccessIndexedNode. @@ -55,11 +56,12 @@ * @param length the instruction producing the length * @param elementKind the type of the elements of the array */ - protected AccessIndexedNode(Stamp stamp, ValueNode array, ValueNode index, ValueNode length, CiKind elementKind) { + protected AccessIndexedNode(Stamp stamp, ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, long leafGraphId) { super(stamp, array); this.index = index; this.length = length; this.elementType = elementKind; + this.leafGraphId = leafGraphId; } /** @@ -70,6 +72,10 @@ return elementType; } + public long leafGraphId() { + return leafGraphId; + } + @Override public void typeFeedback(TypeFeedbackTool tool) { tool.addScalar(index()).constantBound(Condition.GE, CiConstant.INT_0); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -41,8 +41,8 @@ * @param length the instruction producing the length * @param elementKind the element type */ - public LoadIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind) { - super(createStamp(array, elementKind), array, index, length, elementKind); + public LoadIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, long leafGraphId) { + super(createStamp(array, elementKind), array, index, length, elementKind, leafGraphId); } private static Stamp createStamp(ValueNode array, CiKind kind) { diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Wed Mar 21 10:47:02 2012 +0100 @@ -47,8 +47,8 @@ * @param elementKind the element type * @param value the value to store into the array */ - public StoreIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, ValueNode value) { - super(StampFactory.illegal(), array, index, length, elementKind); + public StoreIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, ValueNode value, long leafGraphId) { + super(StampFactory.illegal(), array, index, length, elementKind, leafGraphId); this.value = value; } diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Mar 21 10:47:02 2012 +0100 @@ -79,12 +79,13 @@ public abstract CiValue emitConvert(ConvertNode.Op opcode, CiValue inputVal); public abstract void emitMembar(int barriers); - public abstract void emitDeoptimizeOn(Condition of, DeoptAction action, Object deoptInfo); + public abstract void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo); + public abstract void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId); public abstract CiValue emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args); public abstract void emitIf(IfNode i); public abstract void emitConditional(ConditionalNode i); - public abstract void emitGuardCheck(BooleanNode comp); + public abstract void emitGuardCheck(BooleanNode comp, long leafGraphId); public abstract void emitLookupSwitch(LookupSwitchNode i); public abstract void emitTableSwitch(TableSwitchNode i); diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java Wed Mar 21 10:47:02 2012 +0100 @@ -114,8 +114,17 @@ } @Override - public boolean notExactType(RiResolvedType type) { - return false; + public boolean notExactType(final RiResolvedType type) { + return store.prove(Info.class, new BooleanPredicate() { + @Override + public boolean evaluate(Info element) { + if (element instanceof ObjectTypeExact) { + return ((ObjectTypeExact) element).type != type; + } else { + return (element instanceof Equals) && ((Equals) element).constant.isNull(); + } + } + }); } @Override diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java Wed Mar 21 10:47:02 2012 +0100 @@ -24,10 +24,10 @@ import java.util.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.max.cri.ci.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; public class ScalarTypeFeedbackStore extends TypeFeedbackStore implements ScalarTypeFeedbackTool, CloneableTypeFeedback { diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCodePos.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCodePos.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCodePos.java Wed Mar 21 10:47:02 2012 +0100 @@ -32,10 +32,8 @@ * can be used by the runtime system to reconstruct a source-level stack trace * for exceptions and to create {@linkplain CiFrame frames} for deoptimization. */ -public class CiCodePos implements Serializable { - /** - * - */ +public abstract class CiCodePos implements Serializable { + private static final long serialVersionUID = 8633885274526033515L; /** diff -r e2da6471a9a1 -r 51111665eda6 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiFrame.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiFrame.java Fri Mar 16 11:03:54 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiFrame.java Wed Mar 21 10:47:02 2012 +0100 @@ -65,6 +65,8 @@ */ public final int numLocks; + public final long leafGraphId; + public final boolean rethrowException; public final boolean duringCall; @@ -81,15 +83,16 @@ * @param numStack the depth of the stack * @param numLocks the number of locked objects */ - public CiFrame(CiFrame caller, RiResolvedMethod method, int bci, boolean rethrowException, boolean duringCall, CiValue[] values, int numLocals, int numStack, int numLocks) { + public CiFrame(CiFrame caller, RiResolvedMethod method, int bci, boolean rethrowException, boolean duringCall, CiValue[] values, int numLocals, int numStack, int numLocks, long leafGraphId) { super(caller, method, bci); assert values != null; this.rethrowException = rethrowException; + this.duringCall = duringCall; this.values = values; - this.numLocks = numLocks; this.numLocals = numLocals; this.numStack = numStack; - this.duringCall = duringCall; + this.numLocks = numLocks; + this.leafGraphId = leafGraphId; assert !rethrowException || numStack == 1 : "must have exception on top of the stack"; } diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/c1/c1_IR.cpp --- a/src/share/vm/c1/c1_IR.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/c1/c1_IR.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -210,7 +210,7 @@ void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { // record the safepoint before recording the debug info for enclosing scopes - recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); + recorder->add_safepoint(pc_offset, -1, _oop_map->deep_copy()); _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke); recorder->end_safepoint(pc_offset); } diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/code/debugInfoRec.cpp --- a/src/share/vm/code/debugInfoRec.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/code/debugInfoRec.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -127,14 +127,14 @@ _oopmaps->add_gc_map(pc_offset, map); } -void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) { +void DebugInformationRecorder::add_safepoint(int pc_offset, jlong leaf_graph_id, OopMap* map) { assert(!_oop_recorder->is_complete(), "not frozen yet"); // Store the new safepoint // Add the oop map add_oopmap(pc_offset, map); - add_new_pc_offset(pc_offset); + add_new_pc_offset(pc_offset, leaf_graph_id); assert(_recording_state == rs_null, "nesting of recording calls"); debug_only(_recording_state = rs_safepoint); @@ -150,7 +150,7 @@ debug_only(_recording_state = rs_non_safepoint); } -void DebugInformationRecorder::add_new_pc_offset(int pc_offset) { +void DebugInformationRecorder::add_new_pc_offset(int pc_offset, jlong leaf_graph_id) { assert(_pcs_length == 0 || last_pc()->pc_offset() < pc_offset, "must specify a new, larger pc offset"); @@ -168,7 +168,7 @@ assert(_pcs_size > _pcs_length, "There must be room for after expanding"); _pcs[_pcs_length++] = PcDesc(pc_offset, DebugInformationRecorder::serialized_null, - DebugInformationRecorder::serialized_null); + DebugInformationRecorder::serialized_null, leaf_graph_id); } diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/code/debugInfoRec.hpp --- a/src/share/vm/code/debugInfoRec.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/code/debugInfoRec.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -82,7 +82,7 @@ void add_oopmap(int pc_offset, OopMap* map); // adds a jvm mapping at pc-offset, for a safepoint only - void add_safepoint(int pc_offset, OopMap* map); + void add_safepoint(int pc_offset, jlong leaf_graph_id, OopMap* map); // adds a jvm mapping at pc-offset, for a non-safepoint (profile point) void add_non_safepoint(int pc_offset); @@ -188,7 +188,7 @@ guarantee(_pcs_length > 1, "a safepoint must be declared already"); return &_pcs[_pcs_length-2]; } - void add_new_pc_offset(int pc_offset); + void add_new_pc_offset(int pc_offset, jlong leaf_graph_id = -1); void end_scopes(int pc_offset, bool is_safepoint); int serialize_monitor_values(GrowableArray* monitors); diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/code/pcDesc.cpp --- a/src/share/vm/code/pcDesc.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/code/pcDesc.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -29,11 +29,12 @@ #include "code/scopeDesc.hpp" #include "memory/resourceArea.hpp" -PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) { +PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset, jlong leaf_graph_id) { _pc_offset = pc_offset; _scope_decode_offset = scope_decode_offset; _obj_decode_offset = obj_decode_offset; _flags = 0; + GRAAL_ONLY(_leaf_graph_id = leaf_graph_id); } address PcDesc::real_pc(const nmethod* code) const { @@ -43,7 +44,11 @@ void PcDesc::print(nmethod* code) { #ifndef PRODUCT ResourceMark rm; +#ifdef GRAAL + tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x leaf_graph_id=%d):", real_pc(code), pc_offset(), _flags, leaf_graph_id()); +#else tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags); +#endif if (scope_decode_offset() == DebugInformationRecorder::serialized_null) { return; diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/code/pcDesc.hpp --- a/src/share/vm/code/pcDesc.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/code/pcDesc.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -38,6 +38,7 @@ int _pc_offset; // offset from start of nmethod int _scope_decode_offset; // offset for scope in nmethod int _obj_decode_offset; + GRAAL_ONLY(jlong _leaf_graph_id;) enum { PCDESC_reexecute = 1 << 0, @@ -56,14 +57,16 @@ int pc_offset() const { return _pc_offset; } int scope_decode_offset() const { return _scope_decode_offset; } int obj_decode_offset() const { return _obj_decode_offset; } + jlong leaf_graph_id() const { return _leaf_graph_id; } void set_pc_offset(int x) { _pc_offset = x; } void set_scope_decode_offset(int x) { _scope_decode_offset = x; } void set_obj_decode_offset(int x) { _obj_decode_offset = x; } + void set_leaf_graph_id(jlong x) { _leaf_graph_id = x; } // Constructor (only used for static in nmethod.cpp) // Also used by ScopeDesc::sender()] - PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset); + PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset, jlong leaf_graph_id); enum { // upper and lower exclusive limits real offsets: @@ -81,7 +84,9 @@ bool is_same_info(const PcDesc* pd) { return _scope_decode_offset == pd->_scope_decode_offset && _obj_decode_offset == pd->_obj_decode_offset && - _flags == pd->_flags; + _flags == pd->_flags + GRAAL_ONLY(&& _leaf_graph_id == pd->_leaf_graph_id) + ; } bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; } diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -428,19 +428,16 @@ } } -void CodeInstaller::record_scope(jint pc_offset, oop code_pos, GrowableArray* objects) { - oop caller_pos = CiCodePos::caller(code_pos); - if (caller_pos != NULL) { - record_scope(pc_offset, caller_pos, objects); - } - oop frame = NULL; - if (code_pos->klass()->klass_part()->name() == vmSymbols::com_oracle_max_cri_ci_CiFrame()) { - frame = code_pos; +void CodeInstaller::record_scope(jint pc_offset, oop frame, GrowableArray* objects) { + assert(frame->klass() == CiFrame::klass(), "CiFrame expected"); + oop caller_frame = CiCodePos::caller(frame); + if (caller_frame != NULL) { + record_scope(pc_offset, caller_frame, objects); } - oop hotspot_method = CiCodePos::method(code_pos); + oop hotspot_method = CiCodePos::method(frame); methodOop method = getMethodFromHotSpotMethod(hotspot_method); - jint bci = CiCodePos::bci(code_pos); + jint bci = CiCodePos::bci(frame); bool reexecute; if (bci == -1) { reexecute = false; @@ -456,64 +453,60 @@ tty->print_cr("Recording scope pc_offset=%d bci=%d frame=%d", pc_offset, bci, frame); } - if (frame != NULL) { - jint local_count = CiFrame::numLocals(frame); - jint expression_count = CiFrame::numStack(frame); - jint monitor_count = CiFrame::numLocks(frame); - arrayOop values = (arrayOop) CiFrame::values(frame); + jint local_count = CiFrame::numLocals(frame); + jint expression_count = CiFrame::numStack(frame); + jint monitor_count = CiFrame::numLocks(frame); + arrayOop values = (arrayOop) CiFrame::values(frame); - assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); + assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); - GrowableArray* locals = new GrowableArray (); - GrowableArray* expressions = new GrowableArray (); - GrowableArray* monitors = new GrowableArray (); + GrowableArray* locals = new GrowableArray (); + GrowableArray* expressions = new GrowableArray (); + GrowableArray* monitors = new GrowableArray (); - if (TraceGraal >= 2) { - tty->print_cr("Scope at bci %d with %d values", bci, values->length()); - tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); - } + if (TraceGraal >= 2) { + tty->print_cr("Scope at bci %d with %d values", bci, values->length()); + tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); + } - for (jint i = 0; i < values->length(); i++) { - ScopeValue* second = NULL; - oop value = ((oop*) values->base(T_OBJECT))[i]; + for (jint i = 0; i < values->length(); i++) { + ScopeValue* second = NULL; + oop value = ((oop*) values->base(T_OBJECT))[i]; - if (i < local_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); - if (second != NULL) { - locals->append(second); - } - locals->append(first); - } else if (i < local_count + expression_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); - if (second != NULL) { - expressions->append(second); - } - expressions->append(first); - } else { - monitors->append(get_monitor_value(value, _total_frame_size, objects)); + if (i < local_count) { + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); + if (second != NULL) { + locals->append(second); } + locals->append(first); + } else if (i < local_count + expression_count) { + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); if (second != NULL) { - i++; - assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue"); - assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue"); + expressions->append(second); } + expressions->append(first); + } else { + monitors->append(get_monitor_value(value, _total_frame_size, objects)); } - - _debug_recorder->dump_object_pool(objects); + if (second != NULL) { + i++; + assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue"); + assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue"); + } + } - DebugToken* locals_token = _debug_recorder->create_scope_values(locals); - DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); - DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); + _debug_recorder->dump_object_pool(objects); + + DebugToken* locals_token = _debug_recorder->create_scope_values(locals); + DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); + DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); - bool throw_exception = false; - if (CiFrame::rethrowException(frame)) { - throw_exception = true; - } + bool throw_exception = false; + if (CiFrame::rethrowException(frame)) { + throw_exception = true; + } - _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); - } else { - _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, false, false, false, NULL, NULL, NULL); - } + _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { @@ -522,7 +515,7 @@ // address instruction = _instructions->start() + pc_offset; // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); - _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); + _debug_recorder->add_safepoint(pc_offset, -1, create_oop_map(_total_frame_size, _parameter_count, debug_info)); oop code_pos = CiDebugInfo::codePos(debug_info); record_scope(pc_offset, code_pos, new GrowableArray()); @@ -636,9 +629,9 @@ } if (debug_info != NULL) { - _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); - oop code_pos = CiDebugInfo::codePos(debug_info); - record_scope(next_pc_offset, code_pos, new GrowableArray()); + oop frame = CiDebugInfo::codePos(debug_info); + _debug_recorder->add_safepoint(next_pc_offset, CiFrame::leafGraphId(frame), create_oop_map(_total_frame_size, _parameter_count, debug_info)); + record_scope(next_pc_offset, frame, new GrowableArray()); } if (runtime_call != NULL) { diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -47,6 +47,8 @@ JavaThread* THREAD = JavaThread::current(); TRACE_graal_1("GraalCompiler::initialize"); + _deopted_leaf_graph_count = 0; + initialize_buffer_blob(); Runtime1::initialize(THREAD->get_buffer_blob()); @@ -91,6 +93,47 @@ } } +void GraalCompiler::deopt_leaf_graph(jlong leaf_graph_id) { + assert(leaf_graph_id != -1, "unexpected leaf graph id"); + + if (_deopted_leaf_graph_count < LEAF_GRAPH_ARRAY_SIZE) { + MutexLockerEx y(GraalDeoptLeafGraphIds_lock, Mutex::_no_safepoint_check_flag); + if (_deopted_leaf_graph_count < LEAF_GRAPH_ARRAY_SIZE) { + _deopted_leaf_graphs[_deopted_leaf_graph_count++] = leaf_graph_id; + } + } +} + +oop GraalCompiler::dump_deopted_leaf_graphs(TRAPS) { + if (_deopted_leaf_graph_count == 0) { + return NULL; + } + jlong* elements; + int length; + { + MutexLockerEx y(GraalDeoptLeafGraphIds_lock, Mutex::_no_safepoint_check_flag); + if (_deopted_leaf_graph_count == 0) { + return NULL; + } + if (_deopted_leaf_graph_count == LEAF_GRAPH_ARRAY_SIZE) { + length = 0; + } else { + length = _deopted_leaf_graph_count; + } + elements = new jlong[length]; + for (int i = 0; i < length; i++) { + elements[i] = _deopted_leaf_graphs[i]; + } + _deopted_leaf_graph_count = 0; + } + typeArrayOop array = oopFactory::new_longArray(length, CHECK_NULL); + for (int i = 0; i < length; i++) { + array->long_at_put(i, elements[i]); + } + delete elements; + return array; +} + void GraalCompiler::initialize_buffer_blob() { JavaThread* THREAD = JavaThread::current(); diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -23,13 +23,18 @@ #include "compiler/abstractCompiler.hpp" +#define LEAF_GRAPH_ARRAY_SIZE (8192) + class GraalCompiler : public AbstractCompiler { private: bool _initialized; - static GraalCompiler* _instance; + static GraalCompiler* _instance; + + jlong _deopted_leaf_graphs[LEAF_GRAPH_ARRAY_SIZE]; + int _deopted_leaf_graph_count; public: @@ -56,6 +61,9 @@ void compile_method(methodHandle target, int entry_bci, jboolean blocking); + void deopt_leaf_graph(jlong leaf_graph_id); + oop dump_deopted_leaf_graphs(TRAPS); + // Print compilation timers and statistics virtual void print_timers(); diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -966,6 +966,21 @@ return vtable_entry_offset; } +// public native long[] getDeoptedLeafGraphIds(); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getDeoptedLeafGraphIds(JNIEnv *, jobject) { + TRACE_graal_3("CompilerToVM::getDeoptedLeafGraphIds"); + + VM_ENTRY_MARK; + + // the contract for this method is as follows: + // returning null: no deopted leaf graphs + // returning array (size > 0): the ids of the deopted leaf graphs + // returning array (size == 0): there was an overflow, the compiler needs to clear its cache completely + + oop array = GraalCompiler::instance()->dump_deopted_leaf_graphs(CHECK_NULL); + return JNIHandles::make_local(array); +} + #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_##f)) @@ -1029,6 +1044,7 @@ {CC"disassembleJava", CC"("RESOLVED_METHOD")"STRING, FN_PTR(disassembleJava)}, {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, {CC"RiMethod_vtableEntryOffset", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_vtableEntryOffset)}, + {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, }; int CompilerToVM_methods_count() { diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -163,6 +163,7 @@ int_field(CiFrame, numLocals) \ int_field(CiFrame, numStack) \ int_field(CiFrame, numLocks) \ + long_field(CiFrame, leafGraphId) \ boolean_field(CiFrame, rethrowException) \ boolean_field(CiFrame, duringCall) \ end_class \ diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -86,6 +86,11 @@ #endif #endif +#ifdef GRAAL +#include "graal/graalCompiler.hpp" +#endif + + bool DeoptimizationMarker::_is_active = false; Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame, @@ -201,6 +206,19 @@ // Create a growable array of VFrames where each VFrame represents an inlined // Java frame. This storage is allocated with the usual system arena. assert(deoptee.is_compiled_frame(), "Wrong frame type"); + +#ifdef GRAAL + PcDesc* pc_desc = ((nmethod*) deoptee.cb())->pc_desc_at(deoptee.pc()); + int decode_offset; + if (pc_desc != NULL && pc_desc->leaf_graph_id() != -1) { + GraalCompiler* compiler = (GraalCompiler*) ((nmethod*) deoptee.cb())->compiler(); + if (PrintDeoptimizationDetails) { + tty->print_cr("leaf graph id: %d", pc_desc->leaf_graph_id()); + } + compiler->deopt_leaf_graph(pc_desc->leaf_graph_id()); + } +#endif + GrowableArray* chunk = new GrowableArray(10); vframe* vf = vframe::new_vframe(&deoptee, &map, thread); while (!vf->is_top()) { diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/runtime/mutexLocker.cpp --- a/src/share/vm/runtime/mutexLocker.cpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/runtime/mutexLocker.cpp Wed Mar 21 10:47:02 2012 +0100 @@ -141,6 +141,10 @@ Mutex* JfrBuffer_lock = NULL; Mutex* JfrStream_lock = NULL; +#ifdef GRAAL +Mutex* GraalDeoptLeafGraphIds_lock = NULL; +#endif // GRAAL + #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; static int _num_mutex; @@ -285,6 +289,10 @@ def(JfrMsg_lock , Monitor, nonleaf+2, true); def(JfrBuffer_lock , Mutex, nonleaf+3, true); def(JfrStream_lock , Mutex, nonleaf+4, true); + +#ifdef GRAAL + def(GraalDeoptLeafGraphIds_lock , Mutex, special, true); +#endif // GRAAL } GCMutexLocker::GCMutexLocker(Monitor * mutex) { diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/runtime/mutexLocker.hpp --- a/src/share/vm/runtime/mutexLocker.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/runtime/mutexLocker.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -143,6 +143,10 @@ extern Mutex* JfrBuffer_lock; // protects JFR buffer operations extern Mutex* JfrStream_lock; // protects JFR stream access +#ifdef GRAAL +extern Mutex* GraalDeoptLeafGraphIds_lock; // protects access to the global array of deopt'ed leaf graphs +#endif // GRAAL + // A MutexLocker provides mutual exclusion with respect to a given mutex // for the scope which contains the locker. The lock is an OS lock, not // an object lock, and the two do not interoperate. Do not use Mutex-based diff -r e2da6471a9a1 -r 51111665eda6 src/share/vm/utilities/macros.hpp --- a/src/share/vm/utilities/macros.hpp Fri Mar 16 11:03:54 2012 +0100 +++ b/src/share/vm/utilities/macros.hpp Wed Mar 21 10:47:02 2012 +0100 @@ -258,6 +258,14 @@ #define NOT_EMBEDDED(code) code #endif +#ifdef GRAAL +#define GRAAL_ONLY(code...) code +#define NOT_GRAAL(code...) +#else +#define GRAAL_ONLY(code...) +#define NOT_GRAAL(code...) code +#endif + #define define_pd_global(type, name, value) const type pd_##name = value; #endif // SHARE_VM_UTILITIES_MACROS_HPP