# HG changeset patch # User Lukas Stadler # Date 1367335773 -7200 # Node ID 106f0a0acafa389ef55f560df6e4473eab8647cc # Parent f364c77077ff04752594b18406da24ccd3612596 refactored monitor handling in EA: MonitorEnter/Exit is removed, not eliminated diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 17:29:33 2013 +0200 @@ -777,34 +777,33 @@ } else if (n instanceof CommitAllocationNode) { CommitAllocationNode commit = (CommitAllocationNode) n; - List allocations = new ArrayList<>(commit.getVirtualObjects().size()); + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int lockCount = commit.getLockCounts().get(objIndex); int entryCount = virtual.entryCount(); FixedWithNextNode newObject; if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true, lockCount > 0)); + newObject = graph.add(new NewInstanceNode(virtual.type(), true)); } else { ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType(); - newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true, lockCount > 0)); + newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true)); } graph.addBeforeFixed(commit, newObject); - allocations.add(newObject); + allocations[objIndex] = newObject; } int valuePos = 0; for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); int entryCount = virtual.entryCount(); - ValueNode newObject = allocations.get(objIndex); + ValueNode newObject = allocations[objIndex]; if (virtual instanceof VirtualInstanceNode) { VirtualInstanceNode instance = (VirtualInstanceNode) virtual; for (int i = 0; i < entryCount; i++) { ValueNode value = commit.getValues().get(valuePos++); if (value instanceof VirtualObjectNode) { - value = allocations.get(commit.getVirtualObjects().indexOf(value)); + value = allocations[commit.getVirtualObjects().indexOf(value)]; } graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE))); } @@ -816,18 +815,27 @@ if (value instanceof VirtualObjectNode) { int indexOf = commit.getVirtualObjects().indexOf(value); assert indexOf != -1 : commit + " " + value; - value = allocations.get(indexOf); + value = allocations[indexOf]; } graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE))); } } } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); + allocations[objIndex] = anchor; + graph.addBeforeFixed(commit, anchor); + } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + for (int lockDepth : commit.getLocks().get(objIndex)) { + MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth)); + graph.addBeforeFixed(commit, enter); + } + } for (Node usage : commit.usages().snapshot()) { AllocatedObjectNode addObject = (AllocatedObjectNode) usage; int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); - FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations.get(index))); - graph.addBeforeFixed(commit, anchor); - graph.replaceFloating(addObject, anchor); + graph.replaceFloating(addObject, allocations[index]); } graph.removeFixed(commit); } else if (n instanceof CheckCastNode) { diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -38,22 +38,12 @@ * is locked (ensuring the GC sees and updates the object) so it must come after any null pointer * check on the object. */ -public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter, MonitorReference { - - private final boolean eliminated; +public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter { - private int lockDepth = -1; + private int lockDepth; - public BeginLockScopeNode(boolean eliminated) { + public BeginLockScopeNode(int lockDepth) { super(StampFactory.forWord()); - this.eliminated = eliminated; - } - - public int getLockDepth() { - return lockDepth; - } - - public void setLockDepth(int lockDepth) { this.lockDepth = lockDepth; } @@ -72,12 +62,10 @@ assert lockDepth != -1; HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; StackSlot slot = hsGen.getLockSlot(lockDepth); - if (!eliminated) { - Value result = gen.emitAddress(slot); - gen.setResult(this, result); - } + Value result = gen.emitAddress(slot); + gen.setResult(this, result); } @NodeIntrinsic - public static native Word beginLockScope(@ConstantNodeParameter boolean eliminated); + public static native Word beginLockScope(@ConstantNodeParameter int lockDepth); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -28,26 +28,18 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}. */ -public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable, MonitorReference { +public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable { - private int lockDepth = -1; + private int lockDepth; - public CurrentLockNode() { + public CurrentLockNode(int lockDepth) { super(StampFactory.forWord()); - } - - public int getLockDepth() { - return lockDepth; - } - - public void setLockDepth(int lockDepth) { this.lockDepth = lockDepth; } @@ -62,5 +54,5 @@ } @NodeIntrinsic - public static native Word currentLock(); + public static native Word currentLock(@ConstantNodeParameter int lockDepth); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -39,16 +39,14 @@ @Input private final ValueNode allocationSize; private final ResolvedJavaType type; private final boolean fillContents; - private final boolean locked; - public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode allocationSize, ResolvedJavaType type, boolean fillContents, boolean locked) { + public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode allocationSize, ResolvedJavaType type, boolean fillContents) { super(StampFactory.exactNonNull(type)); this.memory = memory; this.type = type; this.length = length; this.allocationSize = allocationSize; this.fillContents = fillContents; - this.locked = locked; } public ValueNode memory() { @@ -77,16 +75,11 @@ return fillContents; } - public boolean locked() { - return locked; - } - @Override public void lower(LoweringTool tool, LoweringType loweringType) { tool.getRuntime().lower(this, tool); } @NodeIntrinsic - public static native Object initialize(Object memory, int length, int allocationSize, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents, - @ConstantNodeParameter boolean locked); + public static native Object initialize(Object memory, int length, int allocationSize, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -37,14 +37,12 @@ @Input private final ValueNode memory; private final ResolvedJavaType type; private final boolean fillContents; - private final boolean locked; - public InitializeObjectNode(ValueNode memory, ResolvedJavaType type, boolean fillContents, boolean locked) { + public InitializeObjectNode(ValueNode memory, ResolvedJavaType type, boolean fillContents) { super(StampFactory.exactNonNull(type)); this.memory = memory; this.type = type; this.fillContents = fillContents; - this.locked = locked; } public ValueNode memory() { @@ -59,10 +57,6 @@ return fillContents; } - public boolean locked() { - return locked; - } - @Override public void lower(LoweringTool tool, LoweringType loweringType) { tool.getRuntime().lower(this, tool); diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Tue Apr 30 17:29:33 2013 +0200 @@ -28,29 +28,21 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code graal_monitorexit} stub. */ -public class MonitorExitStubCall extends DeoptimizingStubCall implements LIRGenLowerable, MonitorReference { +public class MonitorExitStubCall extends DeoptimizingStubCall implements LIRGenLowerable { @Input private final ValueNode object; private int lockDepth; public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, void.class, Object.class, Word.class); - public MonitorExitStubCall(ValueNode object) { + public MonitorExitStubCall(ValueNode object, int lockDepth) { super(StampFactory.forVoid()); this.object = object; - } - - public int getLockDepth() { - return lockDepth; - } - - public void setLockDepth(int lockDepth) { this.lockDepth = lockDepth; } @@ -64,5 +56,5 @@ } @NodeIntrinsic - public static native void call(Object hub); + public static native void call(Object hub, @ConstantNodeParameter int lockDepth); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Apr 30 17:29:33 2013 +0200 @@ -76,7 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { + public static void monitorenter(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -86,7 +86,7 @@ // Load the mark word - this includes a null-check on object final Word mark = loadWordFromObject(object, markOffset()); - final Word lock = beginLockScope(false); + final Word lock = beginLockScope(lockDepth); trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); trace(trace, " lock: 0x%016lx\n", lock); @@ -248,17 +248,11 @@ } } - @Snippet - public static void monitorenterEliminated() { - incCounter(); - beginLockScope(true); - } - /** * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -266,13 +260,13 @@ } // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above - final Word lock = beginLockScope(false); + final Word lock = beginLockScope(lockDepth); traceObject(trace, "+lock{stub}", object); MonitorEnterStubCall.call(object, lock); } @Snippet - public static void monitorexit(Object object, @ConstantParameter boolean trace) { + public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -291,7 +285,7 @@ } } - final Word lock = CurrentLockNode.currentLock(); + final Word lock = CurrentLockNode.currentLock(lockDepth); // Load displaced mark final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(), DISPLACED_MARK_WORD_LOCATION); @@ -309,7 +303,7 @@ // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. traceObject(trace, "-lock{stub}", object); - MonitorExitStubCall.call(object); + MonitorExitStubCall.call(object, lockDepth); } else { traceObject(trace, "-lock{cas}", object); } @@ -322,16 +316,10 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(Object object, @ConstantParameter boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); - MonitorExitStubCall.call(object); - endLockScope(); - decCounter(); - } - - @Snippet - public static void monitorexitEliminated() { + MonitorExitStubCall.call(object, lockDepth); endLockScope(); decCounter(); } @@ -398,8 +386,6 @@ private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit"); private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub"); private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub"); - private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated"); - private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated"); private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter"); private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); @@ -416,18 +402,16 @@ FrameState stateAfter = monitorenterNode.stateAfter(); Arguments args; - if (monitorenterNode.eliminated()) { - args = new Arguments(monitorenterEliminated); + if (useFastLocking) { + args = new Arguments(monitorenter); } else { - if (useFastLocking) { - args = new Arguments(monitorenter); - } else { - args = new Arguments(monitorenterStub); - } - args.add("object", monitorenterNode.object()); - args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + args = new Arguments(monitorenterStub); } + args.add("object", monitorenterNode.object()); + args.addConst("lockDepth", monitorenterNode.getLockDepth()); + args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); + boolean tracingEnabledForMethod = stateAfter != null && (isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || tracingEnabledForMethod); Map nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args); @@ -436,9 +420,6 @@ BeginLockScopeNode begin = (BeginLockScopeNode) n; begin.setStateAfter(stateAfter); } - if (n instanceof MonitorReference) { - ((MonitorReference) n).setLockDepth(monitorenterNode.getLockDepth()); - } } } @@ -447,17 +428,14 @@ FrameState stateAfter = monitorexitNode.stateAfter(); Arguments args; - if (monitorexitNode.eliminated()) { - args = new Arguments(monitorexitEliminated); + if (useFastLocking) { + args = new Arguments(monitorexit); } else { - if (useFastLocking) { - args = new Arguments(monitorexit); - } else { - args = new Arguments(monitorexitStub); - } - args.add("object", monitorexitNode.object()); - args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + args = new Arguments(monitorexitStub); } + args.add("object", monitorexitNode.object()); + args.addConst("lockDepth", monitorexitNode.getLockDepth()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); Map nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args); @@ -466,9 +444,6 @@ EndLockScopeNode end = (EndLockScopeNode) n; end.setStateAfter(stateAfter); } - if (n instanceof MonitorReference) { - ((MonitorReference) n).setLockDepth(monitorexitNode.getLockDepth()); - } } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Apr 30 17:29:33 2013 +0200 @@ -72,18 +72,14 @@ } @Snippet - public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { + public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents) { Object result; if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { new_stub.inc(); result = NewInstanceStubCall.call(hub); } else { - if (locked) { - formatObject(hub, size, memory, thread().or(biasedLockPattern()), fillContents); - } else { - formatObject(hub, size, memory, prototypeMarkWord, fillContents); - } + formatObject(hub, size, memory, prototypeMarkWord, fillContents); result = memory.toObject(); } /* @@ -95,16 +91,7 @@ } @Snippet - public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents, - @ConstantParameter boolean locked) { - if (locked) { - return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); - } else { - return initializeArray(memory, hub, length, allocationSize, prototypeMarkWord, headerSize, fillContents); - } - } - - private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) { + public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents) { Object result; if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { newarray_stub.inc(); @@ -132,7 +119,7 @@ } int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); Word memory = TLABAllocateNode.allocateVariableSize(allocationSize); - return InitializeArrayNode.initialize(memory, length, allocationSize, type, fillContents, false); + return InitializeArrayNode.initialize(memory, length, allocationSize, type, fillContents); } /** @@ -243,7 +230,7 @@ graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); memory = tlabAllocateNode; } - InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type, newInstanceNode.fillContents(), newInstanceNode.locked())); + InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type, newInstanceNode.fillContents())); graph.replaceFixedWithFixed(newInstanceNode, initializeNode); } @@ -269,7 +256,7 @@ * anyway for both allocation and initialization - it just needs to be non-null */ ConstantNode size = ConstantNode.forInt(-1, graph); - InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { // Calculate aligned size @@ -277,7 +264,7 @@ ConstantNode sizeNode = ConstantNode.forInt(size, graph); tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode)); graph.addBeforeFixed(newArrayNode, tlabAllocateNode); - InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else { Arguments args = new Arguments(allocateArrayAndInitialize); @@ -319,7 +306,6 @@ args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); - args.addConst("locked", initializeNode.locked()); SnippetTemplate template = template(args); Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); @@ -345,7 +331,6 @@ args.add("prototypeMarkWord", type.prototypeMarkWord()); args.addConst("headerSize", headerSize); args.addConst("fillContents", initializeNode.fillContents()); - args.addConst("locked", initializeNode.locked()); SnippetTemplate template = template(args); Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -103,7 +103,7 @@ newEntryState[i] = originalState.getEntry(i); } VirtualObjectNode newVirtual = originalVirtual.duplicate(); - tool.createVirtualObject(newVirtual, newEntryState, 0); + tool.createVirtualObject(newVirtual, newEntryState, null); tool.replaceWithVirtual(newVirtual); } } else { @@ -134,7 +134,7 @@ } } }); - tool.createVirtualObject(newVirtual, state, 0); + tool.createVirtualObject(newVirtual, state, null); tool.replaceWithVirtual(newVirtual); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue Apr 30 17:29:33 2013 +0200 @@ -54,7 +54,7 @@ int instanceSize = layoutHelper; Pointer memory = NewObjectSnippets.allocate(instanceSize); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false); + Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false); memory = Word.fromObject(result); for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) { @@ -72,7 +72,7 @@ Pointer memory = NewObjectSnippets.allocate(sizeInBytes); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false); + Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false); memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { diff -r f364c77077ff -r 106f0a0acafa 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 Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 30 17:29:33 2013 +0200 @@ -828,7 +828,7 @@ void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { - NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false)); + NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true)); frameState.apush(append(n)); } else { handleUnresolvedNewInstance(type); @@ -870,7 +870,7 @@ private void genNewPrimitiveArray(int typeCode) { Class clazz = arrayTypeCodeToClass(typeCode); ResolvedJavaType elementType = runtime.lookupJavaType(clazz); - NewArrayNode nta = currentGraph.add(new NewArrayNode(elementType, frameState.ipop(), true, false)); + NewArrayNode nta = currentGraph.add(new NewArrayNode(elementType, frameState.ipop(), true)); frameState.apush(append(nta)); } @@ -878,7 +878,7 @@ JavaType type = lookupType(cpi, ANEWARRAY); ValueNode length = frameState.ipop(); if (type instanceof ResolvedJavaType) { - NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false)); + NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true)); frameState.apush(append(n)); } else { handleUnresolvedNewObjectArray(type, length); diff -r f364c77077ff -r 106f0a0acafa 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 Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -76,7 +76,7 @@ VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind); assert newVirtual.getFields().length == 1; - tool.createVirtualObject(newVirtual, new ValueNode[]{v}, 0); + tool.createVirtualObject(newVirtual, new ValueNode[]{v}, null); tool.replaceWithVirtual(newVirtual); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -23,43 +23,24 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.code.*; -import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release. *

- * The VM needs information about monitors in the debug information. This information is built from - * the nesting level of {@link MonitorEnterNode} when the LIR is constructed. Therefore, monitor - * nodes must not be removed from the graph unless it is guaranteed that the nesting level does not - * change. For example, you must not remove a {@link MonitorEnterNode} for a thread-local object or - * for a recursive locking. Instead, mark the node as {@link #eliminated}. This makes sure that the - * meta data still contains the complete locking hierarchy. - *

* The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and * throws a {@link BailoutException} instead during graph building. */ -public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint, Virtualizable { +public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint { @Input private ValueNode object; - private boolean eliminated; public ValueNode object() { return object; } - public boolean eliminated() { - return eliminated; - } - - public void eliminate() { - eliminated = true; - } - /** * Creates a new AccessMonitor instruction. * @@ -69,22 +50,4 @@ super(StampFactory.forVoid()); this.object = object; } - - @Override - public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().getClass() == VirtualInstanceNode.class) { - Debug.log("monitor operation %s on %s\n", this, state); - int newLockCount = state.getLockCount() + (this instanceof MonitorEnterNode ? 1 : -1); - state.setLockCount(newLockCount); - tool.replaceFirstInput(object(), state.getVirtualObject()); - tool.customAction(new Runnable() { - - @Override - public void run() { - eliminate(); - } - }); - } - } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -29,7 +29,7 @@ /** * The {@code MonitorEnterNode} represents the acquisition of a monitor. */ -public final class MonitorEnterNode extends AccessMonitorNode implements Lowerable, MonitorEnter, MonitorReference { +public final class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, MonitorEnter, MonitorReference { private int lockDepth; @@ -48,6 +48,7 @@ return new Object[]{LocationNode.ANY_LOCATION}; } + @Override public void lower(LoweringTool tool, LoweringType loweringType) { tool.getRuntime().lower(this, tool); } @@ -59,4 +60,13 @@ public void setLockDepth(int lockDepth) { this.lockDepth = lockDepth; } + + @Override + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { + state.addLock(getLockDepth()); + tool.delete(); + } + } } diff -r f364c77077ff -r 106f0a0acafa 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 Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -22,15 +22,15 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.graph.*; /** * The {@code MonitorEnterNode} represents a monitor release. */ -public final class MonitorExitNode extends AccessMonitorNode implements Lowerable, Node.IterableNodeType, MonitorExit, MonitorReference { +public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, Node.IterableNodeType, MonitorExit, MonitorReference { private int lockDepth; @@ -49,6 +49,7 @@ return new Object[]{LocationNode.ANY_LOCATION}; } + @Override public void lower(LoweringTool tool, LoweringType loweringType) { tool.getRuntime().lower(this, tool); } @@ -60,4 +61,14 @@ public void setLockDepth(int lockDepth) { this.lockDepth = lockDepth; } + + @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(); + } + } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -38,8 +38,6 @@ private final ResolvedJavaType elementType; private final boolean fillContents; - private final boolean locked; - @Override public ValueNode length() { return length; @@ -52,14 +50,12 @@ * the array itself). * @param length the node that produces the length for this allocation. * @param fillContents determines whether the array elements should be initialized to zero/null. - * @param locked determines whether the array should be locked immediately. */ - public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) { + public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { super(StampFactory.exactNonNull(elementType.getArrayClass())); this.length = length; this.elementType = elementType; this.fillContents = fillContents; - this.locked = locked; } /** @@ -70,13 +66,6 @@ } /** - * @return true if the array will be locked immediately. - */ - public boolean locked() { - return locked; - } - - /** * The list of node which produce input for this instruction. */ public ValueNode dimension(int index) { @@ -127,7 +116,7 @@ state[i] = defaultForKind; } VirtualObjectNode virtualObject = new VirtualArrayNode(elementType, constantLength); - tool.createVirtualObject(virtualObject, state, 0); + tool.createVirtualObject(virtualObject, state, null); tool.replaceWithVirtual(virtualObject); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -37,7 +37,6 @@ private final ResolvedJavaType instanceClass; private final boolean fillContents; - private final boolean locked; /** * Constructs a NewInstanceNode. @@ -45,13 +44,11 @@ * @param type the class being allocated * @param fillContents determines whether the new object's fields should be initialized to * zero/null. - * @param locked determines whether the new object should be locked immediately. */ - public NewInstanceNode(ResolvedJavaType type, boolean fillContents, boolean locked) { + public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { super(StampFactory.exactNonNull(type)); this.instanceClass = type; this.fillContents = fillContents; - this.locked = locked; } /** @@ -70,13 +67,6 @@ return fillContents; } - /** - * @return true if the new object will be locked immediately. - */ - public boolean locked() { - return locked; - } - @Override public ValueNode canonical(CanonicalizerTool tool) { if (usages().isEmpty()) { @@ -103,7 +93,7 @@ for (int i = 0; i < state.length; i++) { state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph()); } - tool.createVirtualObject(virtualObject, state, 0); + tool.createVirtualObject(virtualObject, state, null); tool.replaceWithVirtual(virtualObject); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Tue Apr 30 17:29:33 2013 +0200 @@ -47,9 +47,9 @@ public abstract ValueNode getEntry(int index); - public abstract int getLockCount(); + public abstract void addLock(int depth); - public abstract void setLockCount(int lockCount); + public abstract int removeLock(); public abstract ValueNode getMaterializedValue(); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Tue Apr 30 17:29:33 2013 +0200 @@ -64,9 +64,9 @@ * * @param virtualObject the new virtual object. * @param entryState the initial state of the virtual object's fields. - * @param lockCount the initial locking depth. + * @param locks the initial locking depths. */ - void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount); + void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int[] locks); /** * Queries the current state of the given value: if it is virtualized (thread-local and the diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -35,7 +35,7 @@ @Input private final NodeInputList virtualObjects = new NodeInputList<>(this); @Input private final NodeInputList values = new NodeInputList<>(this); - private final List lockCounts = new ArrayList<>(); + private final List locks = new ArrayList<>(); public CommitAllocationNode() { super(StampFactory.forVoid()); @@ -49,13 +49,13 @@ return values; } - public List getLockCounts() { - return lockCounts; + public List getLocks() { + return locks; } @Override public boolean verify() { - assertTrue(virtualObjects.size() == lockCounts.size(), "lockCounts size doesn't match"); + assertTrue(virtualObjects.size() == locks.size(), "lockCounts size doesn't match"); int valueCount = 0; for (VirtualObjectNode virtual : virtualObjects) { valueCount += virtual.entryCount(); @@ -77,7 +77,7 @@ for (int i = 0; i < virtualObjects.size(); i++) { VirtualObjectNode virtualObject = virtualObjects.get(i); int entryCount = virtualObject.entryCount(); - tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), lockCounts.get(i)); + tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), locks.get(i)); pos += entryCount; } tool.delete(); @@ -96,8 +96,8 @@ s.append(i == 0 ? "" : ",").append(value == null ? "_" : value.toString(Verbosity.Id)); } s.append("]"); - if (lockCounts.get(objIndex) > 0) { - s.append(" locked(").append(lockCounts.get(objIndex)).append(")"); + if (locks.get(objIndex).length > 0) { + s.append(" locked(").append(Arrays.toString(locks.get(objIndex))).append(")"); } properties.put("object(" + virtual.toString(Verbosity.Id) + ")", s.toString()); } @@ -138,22 +138,22 @@ if (usedCount < virtualObjects.size()) { List newVirtualObjects = new ArrayList<>(usedCount); - List newLockCounts = new ArrayList<>(usedCount); + List newLocks = new ArrayList<>(usedCount); List newValues = new ArrayList<>(); int valuePos = 0; for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { VirtualObjectNode virtualObject = virtualObjects.get(objIndex); if (used[objIndex]) { newVirtualObjects.add(virtualObject); - newLockCounts.add(lockCounts.get(objIndex)); + newLocks.add(locks.get(objIndex)); newValues.addAll(values.subList(valuePos, valuePos + virtualObject.entryCount())); } valuePos += virtualObject.entryCount(); } virtualObjects.clear(); virtualObjects.addAll(newVirtualObjects); - lockCounts.clear(); - lockCounts.addAll(newLockCounts); + locks.clear(); + locks.addAll(newLocks); values.clear(); values.addAll(newValues); } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -140,8 +140,7 @@ } @Override - public AllocatedObjectNode getMaterializedRepresentation(ValueNode[] entries, int lockCount) { - assert lockCount == 0; + public AllocatedObjectNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { return new AllocatedObjectNode(this); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -46,9 +46,9 @@ } @Override - public ValueNode getMaterializedRepresentation(ValueNode[] entries, int lockCount) { + public ValueNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { assert entries.length == 1; - assert lockCount == 0; + assert locks.length == 0; return new BoxNode(entries[0], type(), boxingKind); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -96,7 +96,7 @@ } @Override - public ValueNode getMaterializedRepresentation(ValueNode[] entries, int lockCount) { + public ValueNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { return new AllocatedObjectNode(this); } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Tue Apr 30 17:29:33 2013 +0200 @@ -80,7 +80,7 @@ * {@link AllocatedObjectNode} then this node will be attached to a {@link CommitAllocationNode} * , otherwise the node will just be added to the graph. */ - public abstract ValueNode getMaterializedRepresentation(ValueNode[] entries, int lockCount); + public abstract ValueNode getMaterializedRepresentation(ValueNode[] entries, int[] locks); @Override public void generate(LIRGeneratorTool gen) { diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Tue Apr 30 17:29:33 2013 +0200 @@ -26,7 +26,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -151,26 +150,23 @@ PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment(); List objects = new ArrayList<>(2); List values = new ArrayList<>(8); - List lockCounts = new ArrayList<>(2); + List locks = new ArrayList<>(2); List otherAllocations = new ArrayList<>(2); - materializeWithCommit(virtual, objects, lockCounts, values, otherAllocations, state); + materializeWithCommit(virtual, objects, locks, values, otherAllocations, state); - materializeEffects.addMaterializationBefore(fixed, objects, lockCounts, values, otherAllocations); + materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations); } - private void materializeWithCommit(VirtualObjectNode virtual, List objects, List lockCounts, List values, List otherAllocations, EscapeState state) { + private void materializeWithCommit(VirtualObjectNode virtual, List objects, List locks, List values, List otherAllocations, EscapeState state) { trace("materializing %s", virtual); ObjectState obj = getObjectState(virtual); - if (obj.getLockCount() > 0 && obj.virtual.type().isArray()) { - throw new BailoutException("array materialized with lock"); - } ValueNode[] entries = obj.getEntries(); - ValueNode representation = virtual.getMaterializedRepresentation(entries, obj.getLockCount()); + ValueNode representation = virtual.getMaterializedRepresentation(entries, obj.getLocks()); obj.escape(representation, state); if (representation instanceof AllocatedObjectNode) { objects.add((AllocatedObjectNode) representation); - lockCounts.add(obj.getLockCount()); + locks.add(obj.getLocks()); int pos = values.size(); while (values.size() < pos + entries.length) { values.add(null); @@ -179,7 +175,7 @@ ObjectState entryObj = getObjectState(entries[i]); if (entryObj != null) { if (entryObj.isVirtual()) { - materializeWithCommit(entryObj.getVirtualObject(), objects, lockCounts, values, otherAllocations, state); + materializeWithCommit(entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state); } values.set(pos + i, entryObj.getMaterializedValue()); } else { @@ -194,7 +190,7 @@ } } else { otherAllocations.add(representation); - assert obj.getLockCount() == 0; + assert obj.getLocks().length == 0; } } diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Tue Apr 30 17:29:33 2013 +0200 @@ -310,12 +310,12 @@ * * @param position The fixed node before which the materialization node should be added. * @param objects The allocated objects. - * @param lockCounts The lock count for each object. + * @param locks The lock depths for each object. * @param values The values (field, elements) of all objects. * @param otherAllocations A list of allocations that need to be added before the rest (used for * boxing allocations). */ - public void addMaterializationBefore(final FixedNode position, final List objects, final List lockCounts, final List values, + public void addMaterializationBefore(final FixedNode position, final List objects, final List locks, final List values, final List otherAllocations) { add(new Effect() { @@ -348,7 +348,7 @@ obj.setCommit(commit); } commit.getValues().addAll(values); - commit.getLockCounts().addAll(lockCounts); + commit.getLocks().addAll(locks); assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count(); HashSet materializedValues = new HashSet<>(commit.usages().filter(AllocatedObjectNode.class).snapshot()); diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Tue Apr 30 17:29:33 2013 +0200 @@ -36,32 +36,69 @@ */ class ObjectState extends Virtualizable.State { + private static final int[] EMPTY_INT_ARRAY = new int[0]; + + public static final class LockState { + + public final int depth; + public final LockState next; + + private LockState(int depth, LockState next) { + this.depth = depth; + this.next = next; + } + + @Override + public String toString() { + return next == null ? String.valueOf(depth) : depth + "," + next; + } + + public static boolean equals(LockState a, LockState b) { + if ((a == null) != (b == null)) { + return false; + } + if (a != null) { + if (a.depth != b.depth) { + return false; + } + return equals(a.next, b.next); + } + return true; + } + } + final VirtualObjectNode virtual; private EscapeState state; private ValueNode[] entries; private ValueNode materializedValue; - private int lockCount; + private LockState locks; - public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, int lockCount) { + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, int[] locks) { this.virtual = virtual; this.entries = entries; this.state = state; - this.lockCount = lockCount; + if (locks == null) { + this.locks = null; + } else { + for (int i = locks.length - 1; i >= 0; i--) { + this.locks = new LockState(locks[i], this.locks); + } + } } - public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, EscapeState state, int lockCount) { + public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, EscapeState state, LockState locks) { this.virtual = virtual; this.materializedValue = materializedValue; this.state = state; - this.lockCount = lockCount; + this.locks = locks; } private ObjectState(ObjectState other) { virtual = other.virtual; entries = other.entries == null ? null : other.entries.clone(); materializedValue = other.materializedValue; - lockCount = other.lockCount; + locks = other.locks; state = other.state; } @@ -120,20 +157,52 @@ } @Override - public int getLockCount() { - return lockCount; + public void addLock(int depth) { + locks = new LockState(depth, locks); } @Override - public void setLockCount(int lockCount) { - this.lockCount = lockCount; + public int removeLock() { + try { + return locks.depth; + } finally { + locks = locks.next; + } + } + + public int[] getLocks() { + if (locks == null) { + return EMPTY_INT_ARRAY; + } + int cnt = 0; + LockState current = locks; + while (current != null) { + cnt++; + current = current.next; + } + int[] result = new int[cnt]; + current = locks; + cnt = 0; + while (current != null) { + result[cnt++] = current.depth; + current = current.next; + } + return result; + } + + public boolean hasLocks() { + return locks != null; + } + + public boolean locksEqual(ObjectState other) { + return LockState.equals(locks, other.locks); } @Override public String toString() { StringBuilder str = new StringBuilder().append('{'); - if (lockCount > 0) { - str.append('l').append(lockCount).append(' '); + if (locks != null) { + str.append('l').append(locks).append(' '); } if (entries != null) { for (int i = 0; i < entries.length; i++) { @@ -152,7 +221,7 @@ final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(entries); - result = prime * result + lockCount; + result = prime * result + (locks != null ? locks.depth : 0); result = prime * result + ((materializedValue == null) ? 0 : materializedValue.hashCode()); result = prime * result + ((state == null) ? 0 : state.hashCode()); result = prime * result + ((virtual == null) ? 0 : virtual.hashCode()); @@ -171,7 +240,7 @@ if (!Arrays.equals(entries, other.entries)) { return false; } - if (lockCount != other.lockCount) { + if (!LockState.equals(locks, other.locks)) { return false; } if (materializedValue == null) { diff -r f364c77077ff -r 106f0a0acafa 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 Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Apr 30 17:29:33 2013 +0200 @@ -238,7 +238,7 @@ } }); for (ObjectState obj : state.getStates()) { - if (obj.isVirtual() && obj.getLockCount() > 0) { + if (obj.isVirtual() && obj.hasLocks()) { virtual.add(obj); } } @@ -502,7 +502,6 @@ } int virtual = 0; ObjectState startObj = objStates[0]; - int lockCount = startObj.getLockCount(); boolean locksMatch = true; ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue(); for (ObjectState obj : objStates) { @@ -514,7 +513,7 @@ singleValue = null; } } - locksMatch &= obj.getLockCount() == lockCount; + locksMatch &= obj.locksEqual(startObj); } assert virtual < states.size() || locksMatch : "mismatching lock counts at " + merge; @@ -531,9 +530,9 @@ ensureMaterialized(state, obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); } - newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, lockCount)); + newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, null)); } else { - newState.addObject(object, new ObjectState(object, singleValue, EscapeState.Global, lockCount)); + newState.addObject(object, new ObjectState(object, singleValue, EscapeState.Global, null)); } } else { assert virtual == states.size(); @@ -567,7 +566,7 @@ values[index] = phis[index]; } } - newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, lockCount)); + newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, startObj.getLocks())); } } @@ -638,7 +637,7 @@ } } mergeEffects.addFloatingNode(virtual, "valueObjectNode"); - newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, 0)); + newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, null)); newState.addAndMarkAlias(virtual, virtual, usages); newState.addAndMarkAlias(virtual, phi, usages); } else { diff -r f364c77077ff -r 106f0a0acafa graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Tue Apr 30 12:14:59 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Tue Apr 30 17:29:33 2013 +0200 @@ -148,7 +148,7 @@ } @Override - public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount) { + public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int[] locks) { trace("{{%s}} ", current); if (virtualObject.isAlive()) { state.addAndMarkAlias(virtualObject, virtualObject, usages); @@ -158,7 +158,7 @@ for (int i = 0; i < entryState.length; i++) { entryState[i] = state.getScalarAlias(entryState[i]); } - state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount)); + state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, locks)); state.addAndMarkAlias(virtualObject, virtualObject, usages); PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment(); }