# HG changeset patch # User Doug Simon # Date 1367496744 -7200 # Node ID cf8104ed68ba83f608cbd1644ff422284cc3e67b # Parent 9384ec90632be792e5b5526aad55711a5c6b1acd# Parent 106f0a0acafa389ef55f560df6e4473eab8647cc Merge. diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu May 02 14:12:24 2013 +0200 @@ -31,7 +31,6 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; /** @@ -334,10 +333,6 @@ new CanonicalizerPhase().apply(graph, context); new PartialEscapeAnalysisPhase(false, false).apply(graph, context); - for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) { - materialize.getVirtualObject().materializeAt(materialize, materialize.getValues(), false, materialize.getLockCount()); - } - new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Thu May 02 14:12:24 2013 +0200 @@ -35,16 +35,15 @@ import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; /** - * In these test cases the probability of all invokes is set to a high value, such that an - * InliningPhase should inline them all. After that, the EscapeAnalysisPhase is expected to remove - * all allocations and return the correct values. + * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct + * values. */ public class EscapeAnalysisTest extends GraalCompilerTest { @@ -230,7 +229,7 @@ Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); } - int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); + int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(CommitAllocationNode.class).count(); Assert.assertEquals(0, newInstanceCount); return returnNode; } diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu May 02 14:12:24 2013 +0200 @@ -35,17 +35,16 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; /** - * In these test cases the probability of all invokes is set to a high value, such that an - * InliningPhase should inline them all. After that, the PartialEscapeAnalysisPhase is expected to - * remove all allocations and return the correct values. + * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct + * values. */ public class PartialEscapeAnalysisTest extends GraalCompilerTest { @@ -137,9 +136,9 @@ NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply(); double probabilitySum = 0; int materializeCount = 0; - for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) { - probabilitySum += nodeProbabilities.get(materialize); - materializeCount++; + for (CommitAllocationNode materialize : result.getNodes(CommitAllocationNode.class)) { + probabilitySum += nodeProbabilities.get(materialize) * materialize.getVirtualObjects().size(); + materializeCount += materialize.getVirtualObjects().size(); } Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount); Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01); diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu May 02 14:12:24 2013 +0200 @@ -165,7 +165,6 @@ throw new GraalInternalError("no mapping found for virtual object %s", obj); } if (state instanceof MaterializedObjectState) { - assert !(((MaterializedObjectState) state).materializedValue() instanceof VirtualObjectNode); return toValue(((MaterializedObjectState) state).materializedValue()); } else { assert obj.entryCount() == 0 || state instanceof VirtualObjectState; diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu May 02 14:12:24 2013 +0200 @@ -458,7 +458,7 @@ * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the * ideal graph visualizer). */ - public Map getDebugProperties() { + public final Map getDebugProperties() { return getDebugProperties(new HashMap<>()); } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu May 02 14:12:24 2013 +0200 @@ -78,6 +78,7 @@ import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.printer.*; import com.oracle.graal.replacements.*; @@ -665,7 +666,7 @@ HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object(); assert loadField.kind() != Kind.Illegal; - ReadNode memoryRead = graph.add(new ReadNode(object, ConstantLocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); + ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp())); tool.createNullCheckGuard(memoryRead.dependencies(), object); graph.replaceFixedWithFixed(loadField, memoryRead); @@ -680,9 +681,8 @@ StoreFieldNode storeField = (StoreFieldNode) n; HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object(); - LocationNode location = ConstantLocationNode.create(field, field.getKind(), field.offset(), graph); WriteBarrierType barrierType = getFieldStoreBarrierType(storeField); - WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType)); + WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType)); tool.createNullCheckGuard(memoryWrite.dependencies(), object); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); @@ -774,6 +774,70 @@ FixedGuardNode node = (FixedGuardNode) n; ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated()))); graph.replaceFixedWithFixed(node, newAnchor); + } else if (n instanceof CommitAllocationNode) { + CommitAllocationNode commit = (CommitAllocationNode) n; + + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + + FixedWithNextNode newObject; + if (virtual instanceof VirtualInstanceNode) { + 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)); + } + graph.addBeforeFixed(commit, 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[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[commit.getVirtualObjects().indexOf(value)]; + } + graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE))); + } + } else { + VirtualArrayNode array = (VirtualArrayNode) virtual; + ResolvedJavaType element = array.componentType(); + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos++); + if (value instanceof VirtualObjectNode) { + int indexOf = commit.getVirtualObjects().indexOf(value); + assert indexOf != -1 : commit + " " + value; + 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()); + graph.replaceFloating(addObject, allocations[index]); + } + graph.removeFixed(commit); } else if (n instanceof CheckCastNode) { checkcastSnippets.lower((CheckCastNode) n, tool); } else if (n instanceof CheckCastDynamicNode) { @@ -881,6 +945,10 @@ return barrierType; } + private static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field) { + return ConstantLocationNode.create(field, field.getKind(), field.offset(), graph); + } + private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind); return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Thu May 02 14:12:24 2013 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}") public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable { @@ -97,7 +98,21 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); + if (loweringType == LoweringType.BEFORE_GUARDS) { + tool.getRuntime().lower(this, tool); + } else { + FixedNode next = next(); + setNext(null); + DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); + IfNode ifNode; + if (negated) { + ifNode = graph().add(new IfNode(condition, deopt, next, 0)); + } else { + ifNode = graph().add(new IfNode(condition, next, deopt, 1)); + } + ((FixedWithNextNode) predecessor()).setNext(ifNode); + GraphUtil.killWithUnusedFloatingInputs(this); + } } @Override diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Thu May 02 14:12:24 2013 +0200 @@ -52,7 +52,8 @@ if (computePostdominators) { cfg.computePostdominators(); } - assert CFGVerifier.verify(cfg); + // there's not much to verify when connectBlocks == false + assert !connectBlocks || CFGVerifier.verify(cfg); return cfg; } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Thu May 02 14:12:24 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) { @@ -111,7 +100,9 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); + if (loweringType == LoweringType.AFTER_GUARDS) { + tool.getRuntime().lower(this, tool); + } } @Override @@ -125,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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Thu May 02 14:12:24 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()) { @@ -88,7 +78,9 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); + if (loweringType == LoweringType.AFTER_GUARDS) { + tool.getRuntime().lower(this, tool); + } } @Override @@ -101,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 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Thu May 02 14:12:24 2013 +0200 @@ -63,7 +63,9 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); + if (loweringType == LoweringType.AFTER_GUARDS) { + tool.getRuntime().lower(this, tool); + } } public ResolvedJavaType type() { diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Thu May 02 14:12:24 2013 +0200 @@ -73,8 +73,11 @@ ValueNode indexValue = tool.getReplacedValue(index()); int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { - tool.setVirtualEntry(arrayState, index, value()); - tool.delete(); + ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType(); + if (componentType.isPrimitive() || value.objectStamp().alwaysNull() || componentType.isAssignableFrom(value.objectStamp().type())) { + tool.setVirtualEntry(arrayState, index, value()); + tool.delete(); + } } } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Thu May 02 14:12:24 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.virtual; + +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Selects one object from a {@link CommitAllocationNode}. The object is identified by its + * {@link VirtualObjectNode}. + */ +public class AllocatedObjectNode extends FloatingNode implements Virtualizable { + + @Input private VirtualObjectNode virtualObject; + @Input private CommitAllocationNode commit; + + public AllocatedObjectNode(VirtualObjectNode virtualObject) { + super(StampFactory.exactNonNull(virtualObject.type())); + this.virtualObject = virtualObject; + } + + public VirtualObjectNode getVirtualObject() { + return virtualObject; + } + + public CommitAllocationNode getCommit() { + return commit; + } + + public void setCommit(CommitAllocationNode x) { + updateUsages(commit, x); + commit = x; + } + + @Override + public void virtualize(VirtualizerTool tool) { + tool.replaceWithVirtual(getVirtualObject()); + } +} diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Thu May 02 14:12:24 2013 +0200 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.virtual; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}") +public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType, Simplifiable { + + @Input private final NodeInputList virtualObjects = new NodeInputList<>(this); + @Input private final NodeInputList values = new NodeInputList<>(this); + private final List locks = new ArrayList<>(); + + public CommitAllocationNode() { + super(StampFactory.forVoid()); + } + + public List getVirtualObjects() { + return virtualObjects; + } + + public List getValues() { + return values; + } + + public List getLocks() { + return locks; + } + + @Override + public boolean verify() { + assertTrue(virtualObjects.size() == locks.size(), "lockCounts size doesn't match"); + int valueCount = 0; + for (VirtualObjectNode virtual : virtualObjects) { + valueCount += virtual.entryCount(); + } + assertTrue(values.size() == valueCount, "values size doesn't match"); + return super.verify(); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + if (loweringType == LoweringType.AFTER_GUARDS) { + tool.getRuntime().lower(this, tool); + } + } + + @Override + public void virtualize(VirtualizerTool tool) { + int pos = 0; + 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]), locks.get(i)); + pos += entryCount; + } + tool.delete(); + } + + @Override + public Map getDebugProperties(Map map) { + Map properties = super.getDebugProperties(map); + int valuePos = 0; + for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { + VirtualObjectNode virtual = virtualObjects.get(objIndex); + StringBuilder s = new StringBuilder(); + s.append(MetaUtil.toJavaName(virtual.type(), false)).append("["); + for (int i = 0; i < virtual.entryCount(); i++) { + ValueNode value = values.get(valuePos++); + s.append(i == 0 ? "" : ",").append(value == null ? "_" : value.toString(Verbosity.Id)); + } + s.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()); + } + return properties; + } + + @Override + public void simplify(SimplifierTool tool) { + boolean[] used = new boolean[virtualObjects.size()]; + int usedCount = 0; + for (Node usage : usages()) { + AllocatedObjectNode addObject = (AllocatedObjectNode) usage; + int index = virtualObjects.indexOf(addObject.getVirtualObject()); + assert !used[index]; + used[index] = true; + usedCount++; + } + boolean progress; + do { + progress = false; + int valuePos = 0; + for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { + VirtualObjectNode virtualObject = virtualObjects.get(objIndex); + if (used[objIndex]) { + for (int i = 0; i < virtualObject.entryCount(); i++) { + int index = virtualObjects.indexOf(values.get(valuePos + i)); + if (index != -1 && !used[index]) { + progress = true; + used[index] = true; + usedCount++; + } + } + } + valuePos += virtualObject.entryCount(); + } + + } while (progress); + + if (usedCount < virtualObjects.size()) { + List newVirtualObjects = 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); + newLocks.add(locks.get(objIndex)); + newValues.addAll(values.subList(valuePos, valuePos + virtualObject.entryCount())); + } + valuePos += virtualObject.entryCount(); + } + virtualObjects.clear(); + virtualObjects.addAll(newVirtualObjects); + locks.clear(); + locks.addAll(newLocks); + values.clear(); + values.addAll(newValues); + } + } + +} diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Thu May 02 14:12:24 2013 +0200 @@ -22,14 +22,11 @@ */ package com.oracle.graal.nodes.virtual; -import java.util.*; - import sun.misc.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]") @@ -72,7 +69,7 @@ } @Override - public String fieldName(int index) { + public String entryName(int index) { return "[" + index + "]"; } @@ -143,17 +140,7 @@ } @Override - public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { - StructuredGraph graph = (StructuredGraph) graph(); - ResolvedJavaType element = componentType(); - NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount(), graph), defaultValuesOnly, lockCount > 0)); - materializeNode.replaceAtUsages(newArray); - graph.addBeforeFixed(materializeNode, newArray); - if (!defaultValuesOnly) { - for (int i = 0; i < entryCount(); i++) { - graph.addBeforeFixed(materializeNode, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i)))); - } - } - graph.removeFixed(materializeNode); + public AllocatedObjectNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { + return new AllocatedObjectNode(this); } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Thu May 02 14:12:24 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.virtual; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -48,11 +46,9 @@ } @Override - public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { - assert values.size() == 1; - assert lockCount == 0; - StructuredGraph graph = (StructuredGraph) graph(); - BoxNode valueOf = graph.add(new BoxNode(values.get(0), type(), boxingKind)); - graph.replaceFixedWithFixed(materializeNode, valueOf); + public ValueNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { + assert entries.length == 1; + assert locks.length == 0; + return new BoxNode(entries[0], type(), boxingKind); } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Thu May 02 14:12:24 2013 +0200 @@ -22,14 +22,11 @@ */ package com.oracle.graal.nodes.virtual; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -@NodeInfo(nameTemplate = "VirtualInstance {p#type}") +@NodeInfo(nameTemplate = "VirtualInstance {p#type/s}") public class VirtualInstanceNode extends VirtualObjectNode { private final ResolvedJavaType type; @@ -68,7 +65,7 @@ } @Override - public String fieldName(int index) { + public String entryName(int index) { return fields[index].getName(); } @@ -99,16 +96,7 @@ } @Override - public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { - StructuredGraph graph = (StructuredGraph) graph(); - NewInstanceNode newInstance = graph.add(new NewInstanceNode(type(), defaultValuesOnly, lockCount > 0)); - materializeNode.replaceAtUsages(newInstance); - graph.addBeforeFixed(materializeNode, newInstance); - if (!defaultValuesOnly) { - for (int i = 0; i < entryCount(); i++) { - graph.addBeforeFixed(materializeNode, graph.add(new StoreFieldNode(newInstance, field(i), values.get(i)))); - } - } - graph.removeFixed(materializeNode); + public ValueNode getMaterializedRepresentation(ValueNode[] entries, int[] locks) { + return new AllocatedObjectNode(this); } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Thu May 02 14:12:24 2013 +0200 @@ -22,41 +22,68 @@ */ package com.oracle.graal.nodes.virtual; -import java.util.*; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -@NodeInfo(nameTemplate = "VirtualObject {p#type}") public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable { public VirtualObjectNode() { super(StampFactory.virtual()); } + /** + * The type of object described by this {@link VirtualObjectNode}. In case of arrays, this is + * the array type (and not the component type). + */ public abstract ResolvedJavaType type(); + /** + * The number of entries this virtual object has. Either the number of fields or the number of + * array elements. + */ public abstract int entryCount(); + /** + * Returns the name of the entry at the given index. Only used for debugging purposes. + */ + public abstract String entryName(int i); + + /** + * If the given index denotes an entry in this virtual object, the index of this entry is + * returned. If no such entry can be found, this method returns -1. + */ + public abstract int entryIndexForOffset(long constantOffset); + + /** + * Returns the {@link Kind} of the entry at the given index. + */ + public abstract Kind entryKind(int index); + + /** + * Returns an exact duplicate of this virtual object node, which has not been added to the graph + * yet. + */ + public abstract VirtualObjectNode duplicate(); + + /** + * Specifies whether this virtual object has an object identity. If not, then the result of a + * comparison of two virtual objects is determined by comparing their contents. + */ + public boolean hasIdentity() { + return true; + } + + /** + * Returns a node that can be used to materialize this virtual object. If this returns an + * {@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[] locks); + @Override public void generate(LIRGeneratorTool gen) { // nothing to do... } - - public abstract String fieldName(int i); - - public abstract void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount); - - public abstract int entryIndexForOffset(long constantOffset); - - public abstract Kind entryKind(int index); - - public abstract VirtualObjectNode duplicate(); - - public boolean hasIdentity() { - return true; - } } diff -r 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Thu May 02 12:19:41 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; - -@NodeInfo(nameTemplate = "Materialize {i#virtualObject}") -public final class MaterializeObjectNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType, Canonicalizable, ArrayLengthProvider { - - @Input private final NodeInputList values; - @Input private final VirtualObjectNode virtualObject; - private final int lockCount; - - public MaterializeObjectNode(VirtualObjectNode virtualObject, int lockCount) { - super(StampFactory.exactNonNull(virtualObject.type())); - this.virtualObject = virtualObject; - this.lockCount = lockCount; - this.values = new NodeInputList<>(this, virtualObject.entryCount()); - } - - public NodeInputList getValues() { - return values; - } - - public VirtualObjectNode getVirtualObject() { - return virtualObject; - } - - public int getLockCount() { - return lockCount; - } - - @Override - public ValueNode length() { - assert virtualObject.type().isArray(); - return ConstantNode.forInt(values.size(), graph()); - } - - /** - * @return true if the object that will be created is without locks and has only entries that - * are {@link Constant#defaultForKind(Kind)}, false otherwise. - */ - public boolean isDefault() { - if (lockCount > 0) { - return false; - } else { - for (ValueNode value : values) { - if (!value.isConstant() || !value.asConstant().isDefaultForKind()) { - return false; - } - } - } - return true; - } - - @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - virtualObject.materializeAt(this, values, isDefault(), lockCount); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (usages().isEmpty()) { - return null; - } else { - return this; - } - } - - @Override - public void virtualize(VirtualizerTool tool) { - tool.createVirtualObject(virtualObject, values.toArray(new ValueNode[values.size()]), lockCount); - tool.replaceWithVirtual(virtualObject); - } -} diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Thu May 02 14:12:24 2013 +0200 @@ -26,14 +26,11 @@ import java.util.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.virtual.nodes.*; class BlockState { @@ -151,62 +148,50 @@ public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) { PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment(); - HashSet deferred = new HashSet<>(); - GraphEffectList deferredStores = new GraphEffectList(); - materializeChangedBefore(fixed, virtual, state, deferred, deferredStores, materializeEffects); - materializeEffects.addAll(deferredStores); + List objects = new ArrayList<>(2); + List values = new ArrayList<>(8); + List locks = new ArrayList<>(2); + List otherAllocations = new ArrayList<>(2); + materializeWithCommit(virtual, objects, locks, values, otherAllocations, state); + + materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations); } - private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, HashSet deferred, GraphEffectList deferredStores, - GraphEffectList materializeEffects) { - trace("materializing %s at %s", virtual, fixed); + 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[] fieldState = obj.getEntries(); - MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount()); - ValueNode[] values = new ValueNode[obj.getEntries().length]; - obj.escape(materialize, state); - deferred.add(virtual); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - materializeChangedBefore(fixed, valueObj.virtual, state, deferred, deferredStores, materializeEffects); + ValueNode[] entries = obj.getEntries(); + ValueNode representation = virtual.getMaterializedRepresentation(entries, obj.getLocks()); + obj.escape(representation, state); + if (representation instanceof AllocatedObjectNode) { + objects.add((AllocatedObjectNode) representation); + locks.add(obj.getLocks()); + int pos = values.size(); + while (values.size() < pos + entries.length) { + values.add(null); + } + for (int i = 0; i < entries.length; i++) { + ObjectState entryObj = getObjectState(entries[i]); + if (entryObj != null) { + if (entryObj.isVirtual()) { + materializeWithCommit(entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state); + } + values.set(pos + i, entryObj.getMaterializedValue()); + } else { + values.set(pos + i, entries[i]); } - if (deferred.contains(valueObj.virtual)) { - Kind fieldKind; - CyclicMaterializeStoreNode store; - if (virtual instanceof VirtualArrayNode) { - store = new CyclicMaterializeStoreNode(materialize, valueObj.getMaterializedValue(), i); - fieldKind = ((VirtualArrayNode) virtual).componentType().getKind(); - } else { - VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual; - store = new CyclicMaterializeStoreNode(materialize, valueObj.getMaterializedValue(), instanceObject.field(i)); - fieldKind = instanceObject.field(i).getType().getKind(); - } - deferredStores.addFixedNodeBefore(store, fixed); - values[i] = ConstantNode.defaultForKind(fieldKind, fixed.graph()); - } else { - values[i] = valueObj.getMaterializedValue(); + } + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode instance = (VirtualInstanceNode) virtual; + for (int i = 0; i < entries.length; i++) { + readCache.put(new ReadCacheEntry(instance.field(i), representation), values.get(pos + i)); } - } else { - values[i] = fieldState[i]; } + } else { + otherAllocations.add(representation); + assert obj.getLocks().length == 0; } - deferred.remove(virtual); - - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode instance = (VirtualInstanceNode) virtual; - for (int i = 0; i < fieldState.length; i++) { - readCache.put(new ReadCacheEntry(instance.field(i), materialize), fieldState[i]); - } - } - - materializeEffects.addMaterialization(materialize, fixed, values); } void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) { diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Thu May 02 14:12:24 2013 +0200 @@ -26,10 +26,10 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.virtual.nodes.*; public class GraphEffectList extends EffectList { @@ -118,33 +118,6 @@ } /** - * Add the materialization node to the graph's control flow at the given position, and then sets - * its values. - * - * @param node The materialization node that should be added. - * @param position The fixed node before which the materialization node should be added. - * @param values The values for the materialization node's entries. - */ - public void addMaterialization(final MaterializeObjectNode node, final FixedNode position, final ValueNode[] values) { - add(new Effect() { - - @Override - public String name() { - return "addMaterialization"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { - assert !node.isAlive() && !node.isDeleted() && position.isAlive(); - graph.addBeforeFixed(position, graph.add(node)); - for (int i = 0; i < values.length; i++) { - node.getValues().set(i, values[i]); - } - } - }); - } - - /** * Adds an value to the given phi node. * * @param node The phi node to which the value should be added. @@ -330,4 +303,68 @@ } }); } + + /** + * Add the materialization node to the graph's control flow at the given position, and then sets + * its values. + * + * @param position The fixed node before which the materialization node should be added. + * @param objects The allocated objects. + * @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 locks, final List values, + final List otherAllocations) { + add(new Effect() { + + @Override + public String name() { + return "addMaterializationBefore"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { + for (ValueNode otherAllocation : otherAllocations) { + graph.add(otherAllocation); + if (otherAllocation instanceof FixedWithNextNode) { + graph.addBeforeFixed(position, (FixedWithNextNode) otherAllocation); + } else { + assert otherAllocation instanceof FloatingNode; + } + } + if (!objects.isEmpty()) { + CommitAllocationNode commit; + if (position.predecessor() instanceof CommitAllocationNode) { + commit = (CommitAllocationNode) position.predecessor(); + } else { + commit = graph.add(new CommitAllocationNode()); + graph.addBeforeFixed(position, commit); + } + for (AllocatedObjectNode obj : objects) { + graph.add(obj); + commit.getVirtualObjects().add(obj.getVirtualObject()); + obj.setCommit(commit); + } + commit.getValues().addAll(values); + commit.getLocks().addAll(locks); + + assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count(); + HashSet materializedValues = new HashSet<>(commit.usages().filter(AllocatedObjectNode.class).snapshot()); + for (int i = 0; i < commit.getValues().size(); i++) { + if (materializedValues.contains(commit.getValues().get(i))) { + commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject()); + } + } + + } + } + + @Override + public boolean isVisible() { + return true; + } + }); + } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Thu May 02 14:12:24 2013 +0200 @@ -36,32 +36,69 @@ */ class ObjectState extends Virtualizable.State { - public final VirtualObjectNode virtual; + 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,24 +157,56 @@ } @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++) { - str.append(virtual.fieldName(i)).append('=').append(entries[i]).append(' '); + str.append(virtual.entryName(i)).append('=').append(entries[i]).append(' '); } } if (materializedValue != null) { @@ -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 9384ec90632b -r cf8104ed68ba graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Thu May 02 14:12:24 2013 +0200 @@ -32,13 +32,13 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.nodes.*; public class PartialEscapeAnalysisPhase extends BasePhase { @@ -126,8 +126,13 @@ private static boolean matches(StructuredGraph graph, String filter) { if (filter != null) { - ResolvedJavaMethod method = graph.method(); - return method != null && MetaUtil.format("%H.%n", method).contains(filter); + if (filter.startsWith("~")) { + ResolvedJavaMethod method = graph.method(); + return method == null || !MetaUtil.format("%H.%n", method).contains(filter.substring(1)); + } else { + ResolvedJavaMethod method = graph.method(); + return method != null && MetaUtil.format("%H.%n", method).contains(filter); + } } return true; } @@ -203,32 +208,36 @@ public static Map getHints(StructuredGraph graph) { NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply(); Map hints = null; - for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) { + for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) { double sum = 0; double invokeSum = 0; - for (Node usage : materialize.usages()) { - if (usage instanceof FixedNode) { - sum += probabilities.get((FixedNode) usage); - } else { - if (usage instanceof MethodCallTargetNode) { - invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode()); - } - for (Node secondLevelUage : materialize.usages()) { - if (secondLevelUage instanceof FixedNode) { - sum += probabilities.get(((FixedNode) secondLevelUage)); + for (Node commitUsage : commit.usages()) { + for (Node usage : commitUsage.usages()) { + if (usage instanceof FixedNode) { + sum += probabilities.get((FixedNode) usage); + } else { + if (usage instanceof MethodCallTargetNode) { + invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode()); + } + for (Node secondLevelUage : usage.usages()) { + if (secondLevelUage instanceof FixedNode) { + sum += probabilities.get(((FixedNode) secondLevelUage)); + } } } } } // TODO(lstadler) get rid of this magic number if (sum > 100 && invokeSum > 0) { - for (Node usage : materialize.usages()) { - if (usage instanceof MethodCallTargetNode) { - if (hints == null) { - hints = new HashMap<>(); + for (Node commitUsage : commit.usages()) { + for (Node usage : commitUsage.usages()) { + if (usage instanceof MethodCallTargetNode) { + if (hints == null) { + hints = new HashMap<>(); + } + Invoke invoke = ((MethodCallTargetNode) usage).invoke(); + hints.put(invoke, sum / invokeSum); } - Invoke invoke = ((MethodCallTargetNode) usage).invoke(); - hints.put(invoke, sum / invokeSum); } } } diff -r 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu May 02 14:12:24 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 9384ec90632b -r cf8104ed68ba 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 Thu May 02 12:19:41 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Thu May 02 14:12:24 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(); }