# HG changeset patch # User Thomas Wuerthinger # Date 1381837887 -7200 # Node ID b6e3b44ab44f03f262d04245237f5f85650836b5 # Parent 7421885a2b9d968ac06ca78c55793327b17e5f6e# Parent 8c53ba3efbc967bb66c41378316ddafd867c8b61 Merge. diff -r 7421885a2b9d -r b6e3b44ab44f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Tue Oct 15 01:25:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Tue Oct 15 13:51:27 2013 +0200 @@ -40,12 +40,12 @@ public class UnsafeLoadSnippets implements Snippets { @Snippet - public static Object lowerUnsafeLoad(Object object, long displacement) { + public static Object lowerUnsafeLoad(Object object, long offset) { Object fixedObject = FixedValueAnchorNode.getObject(object); - if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) { - return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.PRECISE, true); + if (object instanceof java.lang.ref.Reference && referentOffset() == offset) { + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE, true); } else { - return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.NONE, true); + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE, true); } } diff -r 7421885a2b9d -r b6e3b44ab44f 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 Tue Oct 15 01:25:31 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Oct 15 13:51:27 2013 +0200 @@ -1218,12 +1218,12 @@ return monitorEnter; } - private MonitorExitNode genMonitorExit(ValueNode x) { + private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) { ValueNode lockedObject = frameState.popLock(); if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, frameState.lockDepth())); + MonitorExitNode monitorExit = append(new MonitorExitNode(x, returnValue, frameState.lockDepth())); return monitorExit; } @@ -1619,7 +1619,7 @@ assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); + synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); append(new UnwindNode(exception)); } @@ -1628,7 +1628,7 @@ ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); assert frameState.stackSize() == 0; - synchronizedEpilogue(FrameState.AFTER_BCI); + synchronizedEpilogue(FrameState.AFTER_BCI, x); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } @@ -1640,9 +1640,9 @@ append(new ReturnNode(x)); } - private void synchronizedEpilogue(int bci) { + private void synchronizedEpilogue(int bci, ValueNode returnValue) { if (Modifier.isSynchronized(method.getModifiers())) { - MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject); + MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); monitorExit.setStateAfter(frameState.create(bci)); assert !frameState.rethrowException(); } @@ -2002,7 +2002,7 @@ case CHECKCAST : genCheckCast(); break; case INSTANCEOF : genInstanceOf(); break; case MONITORENTER : genMonitorEnter(frameState.apop()); break; - case MONITOREXIT : genMonitorExit(frameState.apop()); break; + case MONITOREXIT : genMonitorExit(frameState.apop(), null); break; case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break; case IFNULL : genIfNull(Condition.EQ); break; case IFNONNULL : genIfNull(Condition.NE); break; diff -r 7421885a2b9d -r b6e3b44ab44f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Oct 15 01:25:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Oct 15 13:51:27 2013 +0200 @@ -199,7 +199,7 @@ case Long: return ConstantNode.forLong(value, graph); default: - throw new InternalError("Should not reach here"); + throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); } } @@ -210,7 +210,7 @@ case Double: return ConstantNode.forDouble(value, graph); default: - throw new InternalError("Should not reach here"); + throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); } } diff -r 7421885a2b9d -r b6e3b44ab44f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Tue Oct 15 01:25:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Tue Oct 15 13:51:27 2013 +0200 @@ -34,17 +34,24 @@ public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference { private int lockDepth; + @Input private ValueNode escapedReturnValue; /** * Creates a new MonitorExitNode. * * @param object the instruction produces the object value */ - public MonitorExitNode(ValueNode object, int lockDepth) { + public MonitorExitNode(ValueNode object, ValueNode escapedReturnValue, int lockDepth) { super(object); + this.escapedReturnValue = escapedReturnValue; this.lockDepth = lockDepth; } + public void setEscapedReturnValue(ValueNode x) { + updateUsages(escapedReturnValue, x); + this.escapedReturnValue = x; + } + @Override public LocationIdentity getLocationIdentity() { return LocationIdentity.ANY_LOCATION; @@ -65,11 +72,20 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object()); - if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { - int removedLock = state.removeLock(); - assert removedLock == getLockDepth(); - tool.delete(); + /* + * The last MonitorExitNode of a synchronized method cannot be removed anyway, and we need + * it to materialize the return value. + * + * TODO: replace this with correct handling of AFTER_BCI frame states in the runtime. + */ + if (stateAfter().bci != FrameState.AFTER_BCI) { + setEscapedReturnValue(null); + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { + int removedLock = state.removeLock(); + assert removedLock == getLockDepth(); + tool.delete(); + } } } } diff -r 7421885a2b9d -r b6e3b44ab44f graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Oct 15 01:25:31 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Oct 15 13:51:27 2013 +0200 @@ -111,85 +111,6 @@ return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode); } if (isMarked) { - if (node instanceof NodeWithState) { - NodeWithState nodeWithState = (NodeWithState) node; - FrameState stateAfter = nodeWithState.getState(); - if (stateAfter != null) { - if (stateAfter.usages().count() > 1) { - if (nodeWithState instanceof StateSplit) { - StateSplit split = (StateSplit) nodeWithState; - stateAfter = (FrameState) stateAfter.copyWithInputs(); - split.setStateAfter(stateAfter); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - final HashSet virtual = new HashSet<>(); - stateAfter.applyToNonVirtual(new NodeClosure() { - - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = getObjectState(state, value); - if (valueObj != null) { - virtual.add(valueObj); - effects.replaceFirstInput(usage, value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.getStates()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); - } - } - } - }); - for (ObjectState obj : state.getStates()) { - if (obj.isVirtual() && obj.hasLocks()) { - virtual.add(obj); - } - } - - ArrayDeque queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.isVirtual()) { - for (ValueNode field : obj.getEntries()) { - if (field instanceof VirtualObjectNode) { - ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); - if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } - } - } - } - } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.isVirtual()) { - ValueNode[] fieldState = obj.getEntries().clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(state, fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.getMaterializedValue(); - } - } - } - v = new VirtualObjectState(obj.virtual, fieldState); - } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); - } - effects.addVirtualMapping(stateAfter, v); - } - } - } for (ValueNode input : node.inputs().filter(ValueNode.class)) { ObjectState obj = getObjectState(state, input); if (obj != null) { @@ -201,10 +122,92 @@ replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED); } } + if (node instanceof NodeWithState) { + processNodeWithState((NodeWithState) node, state, effects); + } } return false; } + private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) { + FrameState stateAfter = nodeWithState.getState(); + if (stateAfter != null) { + if (stateAfter.usages().count() > 1) { + if (nodeWithState instanceof StateSplit) { + StateSplit split = (StateSplit) nodeWithState; + stateAfter = (FrameState) stateAfter.copyWithInputs(); + split.setStateAfter(stateAfter); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + final HashSet virtual = new HashSet<>(); + stateAfter.applyToNonVirtual(new NodeClosure() { + + @Override + public void apply(Node usage, ValueNode value) { + ObjectState valueObj = getObjectState(state, value); + if (valueObj != null) { + virtual.add(valueObj); + effects.replaceFirstInput(usage, value, valueObj.virtual); + } else if (value instanceof VirtualObjectNode) { + ObjectState virtualObj = null; + for (ObjectState obj : state.getStates()) { + if (value == obj.virtual) { + virtualObj = obj; + break; + } + } + if (virtualObj != null) { + virtual.add(virtualObj); + } + } + } + }); + for (ObjectState obj : state.getStates()) { + if (obj.isVirtual() && obj.hasLocks()) { + virtual.add(obj); + } + } + + ArrayDeque queue = new ArrayDeque<>(virtual); + while (!queue.isEmpty()) { + ObjectState obj = queue.removeLast(); + if (obj.isVirtual()) { + for (ValueNode field : obj.getEntries()) { + if (field instanceof VirtualObjectNode) { + ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); + if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { + virtual.add(fieldObj); + queue.addLast(fieldObj); + } + } + } + } + } + for (ObjectState obj : virtual) { + EscapeObjectState v; + if (obj.isVirtual()) { + ValueNode[] fieldState = obj.getEntries().clone(); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = getObjectState(state, fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + fieldState[i] = valueObj.virtual; + } else { + fieldState[i] = valueObj.getMaterializedValue(); + } + } + } + v = new VirtualObjectState(obj.virtual, fieldState); + } else { + v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); + } + effects.addVirtualMapping(stateAfter, v); + } + } + } + private void ensureMaterialized(BlockT state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) { assert obj != null; if (obj.getState() == EscapeState.Virtual) { diff -r 7421885a2b9d -r b6e3b44ab44f mx/commands.py --- a/mx/commands.py Tue Oct 15 01:25:31 2013 +0200 +++ b/mx/commands.py Tue Oct 15 13:51:27 2013 +0200 @@ -955,12 +955,11 @@ vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) tasks.append(t.stop()) - # temporarily disable G1 verification until merge issues are resolved - # with VM('graal', 'product'): - # t = Task('BootstrapWithG1GCVerification:product') - # out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - # vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) - # tasks.append(t.stop()) + with VM('graal', 'product'): + t = Task('BootstrapWithG1GCVerification:product') + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + tasks.append(t.stop()) with VM('graal', 'product'): t = Task('BootstrapWithRegisterPressure:product') diff -r 7421885a2b9d -r b6e3b44ab44f src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Tue Oct 15 01:25:31 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Tue Oct 15 13:51:27 2013 +0200 @@ -1405,13 +1405,6 @@ // cache call. if (!is_osr_method() && !is_not_entrant()) { address stub = SharedRuntime::get_handle_wrong_method_stub(); -#ifdef GRAAL - if (_graal_installed_code != NULL) { - // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. - HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); - _graal_installed_code = NULL; - } -#endif NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub); } @@ -1491,6 +1484,12 @@ } else { assert(state == not_entrant, "other cases may need to be handled differently"); } +#ifdef GRAAL + if (_graal_installed_code != NULL) { + // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. + HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); + } +#endif if (TraceCreateZombies) { ResourceMark m;