# HG changeset patch # User Thomas Wuerthinger # Date 1358349427 -3600 # Node ID 921bde171d1d601d4d413a175432c977078d32ef # Parent 4fc2763e670e3ac2dedb213773e1eaf8e31f3952# Parent 94f032472c289345959050e7e5c85f829ac44706 Merge. diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -25,7 +25,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * A node that changes the type of its input, usually narrowing it. @@ -68,9 +67,9 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - tool.replaceWithVirtual(virtual); + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.replaceWithVirtual(state.getVirtualObject()); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * A value proxy that is inserted in the frame state of a loop exit for any value that is @@ -87,9 +86,9 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(value()); - if (virtual != null) { - tool.replaceWithVirtual(virtual); + State state = tool.getObjectState(value); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.replaceWithVirtual(state.getVirtualObject()); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -76,7 +76,7 @@ @Override public void virtualize(VirtualizerTool tool) { - if (tool.getVirtualState(object()) != null || tool.getMaterializedValue(object()) != null) { + if (tool.getObjectState(object) != null) { tool.replaceWithValue(ConstantNode.forBoolean(false, graph())); } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.virtual.*; @NodeInfo(shortName = "==") public final class ObjectEqualsNode extends CompareNode implements Virtualizable { @@ -73,17 +72,17 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtualX = tool.getVirtualState(x()); - VirtualObjectNode virtualY = tool.getVirtualState(y()); - boolean xVirtual = virtualX != null; - boolean yVirtual = virtualY != null; + State stateX = tool.getObjectState(x()); + State stateY = tool.getObjectState(y()); + boolean xVirtual = stateX != null && stateX.getState() == EscapeState.Virtual; + boolean yVirtual = stateY != null && stateY.getState() == EscapeState.Virtual; if (xVirtual ^ yVirtual) { // one of them is virtual: they can never be the same objects tool.replaceWithValue(ConstantNode.forBoolean(false, graph())); } else if (xVirtual && yVirtual) { // both are virtual: check if they refer to the same object - tool.replaceWithValue(ConstantNode.forBoolean(virtualX == virtualY, graph())); + tool.replaceWithValue(ConstantNode.forBoolean(stateX == stateY, graph())); } } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -34,8 +34,8 @@ public final class BoxNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Canonicalizable { @Input private ValueNode source; - private int bci; - private Kind sourceKind; + private final int bci; + private final Kind sourceKind; public BoxNode(ValueNode value, ResolvedJavaType type, Kind sourceKind, int bci) { super(StampFactory.exactNonNull(type)); diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * Loads an object's {@linkplain Representation#ObjectHub hub}, null-checking the object first. @@ -76,9 +75,10 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - tool.replaceWithValue(ConstantNode.forConstant(virtual.type().getEncoding(Representation.ObjectHub), tool.getMetaAccessProvider(), graph())); + State state = tool.getObjectState(object); + if (state != null) { + Constant constantHub = state.getVirtualObject().type().getEncoding(Representation.ObjectHub); + tool.replaceWithValue(ConstantNode.forConstant(constantHub, tool.getMetaAccessProvider(), graph())); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * Load of a value from a location specified as an offset relative to an object. @@ -55,19 +54,14 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(offset()); if (indexValue.isConstant()) { - int fieldIndex = virtual.fieldIndexForOffset(indexValue.asConstant().asLong()); - if (fieldIndex != -1) { - ValueNode result = tool.getVirtualEntry(virtual, fieldIndex); - VirtualObjectNode virtualResult = tool.getVirtualState(result); - if (virtualResult != null) { - tool.replaceWithVirtual(virtualResult); - } else { - tool.replaceWithValue(result); - } + long offset = indexValue.asConstant().asLong() + displacement(); + int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); + if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) { + tool.replaceWith(state.getEntry(entryIndex)); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * Store of a value at a location specified as an offset relative to an object. @@ -74,13 +73,14 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(offset()); if (indexValue.isConstant()) { - int fieldIndex = virtual.fieldIndexForOffset(indexValue.asConstant().asLong()); - if (fieldIndex != -1) { - tool.setVirtualEntry(virtual, fieldIndex, value()); + long offset = indexValue.asConstant().asLong() + displacement(); + int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); + if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) { + tool.setVirtualEntry(state, entryIndex, value()); tool.delete(); } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -96,7 +96,8 @@ } } for (ValueNode node : dependencies().nonNull().and(isNotA(BeginNode.class))) { - if (tool.getVirtualState(node) == null) { + State state = tool.getObjectState(node); + if (state == null || state.getState() != EscapeState.Virtual) { return; } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -28,7 +28,6 @@ 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. @@ -72,12 +71,12 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - Debug.log("monitor operation %s on %s\n", this, virtual); - int newLockCount = tool.getVirtualLockCount(virtual) + (this instanceof MonitorEnterNode ? 1 : -1); - tool.setVirtualLockCount(virtual, newLockCount); - tool.replaceFirstInput(object(), virtual); + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual) { + 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() { diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * The {@code ArrayLength} instruction gets the length of an array. @@ -71,10 +70,10 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(array()); - if (virtual != null) { - assert virtual instanceof VirtualArrayNode : virtual; - tool.replaceWithValue(ConstantNode.forInt(virtual.entryCount(), graph())); + State state = tool.getObjectState(array()); + if (state != null) { + assert state.getVirtualObject().type().isArray(); + tool.replaceWithValue(ConstantNode.forInt(state.getVirtualObject().entryCount(), graph())); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * Implements a type check against a compile-time known type. @@ -100,9 +99,9 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null && type().isAssignableFrom(virtual.type())) { - tool.replaceWithVirtual(virtual); + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.replaceWithVirtual(state.getVirtualObject()); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * The {@code InstanceOfNode} represents an instanceof test. @@ -129,9 +128,9 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - tool.replaceWithValue(ConstantNode.forBoolean(type().isAssignableFrom(virtual.type()), graph())); + State state = tool.getObjectState(object); + if (state != null) { + tool.replaceWithValue(ConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph())); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -73,17 +73,11 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - int fieldIndex = ((VirtualInstanceNode) virtual).fieldIndex(field()); + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual) { + int fieldIndex = ((VirtualInstanceNode) state.getVirtualObject()).fieldIndex(field()); if (fieldIndex != -1) { - ValueNode result = tool.getVirtualEntry(virtual, fieldIndex); - VirtualObjectNode virtualResult = tool.getVirtualState(result); - if (virtualResult != null) { - tool.replaceWithVirtual(virtualResult); - } else { - tool.replaceWithValue(result); - } + tool.replaceWith(state.getEntry(fieldIndex)); } } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * The {@code LoadIndexedNode} represents a read from an element of an array. @@ -54,18 +53,12 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtualArray = tool.getVirtualState(array()); - if (virtualArray != null) { + State arrayState = tool.getObjectState(array()); + if (arrayState != null && arrayState.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(index()); int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index >= 0 && index < virtualArray.entryCount()) { - ValueNode result = tool.getVirtualEntry(virtualArray, index); - VirtualObjectNode virtualResult = tool.getVirtualState(result); - if (virtualResult != null) { - tool.replaceWithVirtual(virtualResult); - } else { - tool.replaceWithValue(result); - } + if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { + tool.replaceWith(arrayState.getEntry(index)); } } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -31,13 +31,12 @@ /** * The {@code NewArrayNode} class is the base of all instructions that allocate arrays. */ -public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, ArrayLengthProvider { +public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, VirtualizableAllocation, ArrayLengthProvider { @Input private ValueNode length; private final ResolvedJavaType elementType; private final boolean fillContents; - public static final int MaximumEscapeAnalysisArrayLength = 32; private final boolean locked; @Override @@ -105,19 +104,19 @@ } @Override - public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { + public void virtualize(VirtualizerTool tool) { if (length().asConstant() != null) { final int constantLength = length().asConstant().asInt(); - if (constantLength >= 0 && constantLength < MaximumEscapeAnalysisArrayLength) { + if (constantLength >= 0 && constantLength < tool.getMaximumEntryCount()) { ValueNode[] state = new ValueNode[constantLength]; ConstantNode defaultForKind = constantLength == 0 ? null : ConstantNode.defaultForKind(elementType().getKind(), graph()); for (int i = 0; i < constantLength; i++) { state[i] = defaultForKind; } - VirtualObjectNode virtualObject = new VirtualArrayNode(nextVirtualId, elementType, constantLength); - return new ObjectDesc[]{new ObjectDesc(virtualObject, state, 0)}; + VirtualObjectNode virtualObject = new VirtualArrayNode(tool.getNextVirtualId(), elementType, constantLength); + tool.createVirtualObject(virtualObject, state, 0); + tool.replaceWithVirtual(virtualObject); } } - return null; } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -33,7 +33,7 @@ * The {@code NewInstanceNode} represents the allocation of an instance class object. */ @NodeInfo(nameTemplate = "New {p#instanceClass/s}") -public final class NewInstanceNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, Node.IterableNodeType { +public final class NewInstanceNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType { private final ResolvedJavaType instanceClass; private final boolean fillContents; @@ -82,7 +82,7 @@ } @Override - public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { + public void virtualize(VirtualizerTool tool) { if (instanceClass != null) { assert !instanceClass().isArray(); ResolvedJavaField[] fields = instanceClass().getInstanceFields(true); @@ -90,9 +90,9 @@ for (int i = 0; i < state.length; i++) { state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph()); } - VirtualObjectNode virtualObject = new VirtualInstanceNode(nextVirtualId, instanceClass(), fields); - return new ObjectDesc[]{new ObjectDesc(virtualObject, state, 0)}; + VirtualObjectNode virtualObject = new VirtualInstanceNode(tool.getNextVirtualId(), instanceClass(), fields); + tool.createVirtualObject(virtualObject, state, 0); + tool.replaceWithVirtual(virtualObject); } - return null; } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -69,11 +69,11 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - int fieldIndex = ((VirtualInstanceNode) virtual).fieldIndex(field()); + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual) { + int fieldIndex = ((VirtualInstanceNode) state.getVirtualObject()).fieldIndex(field()); if (fieldIndex != -1) { - tool.setVirtualEntry(virtual, fieldIndex, value()); + tool.setVirtualEntry(state, fieldIndex, value()); tool.delete(); } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; /** * The {@code StoreIndexedNode} represents a write to an array element. @@ -68,12 +67,12 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtualArray = tool.getVirtualState(array()); - if (virtualArray != null) { + State arrayState = tool.getObjectState(array()); + if (arrayState != null && arrayState.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(index()); int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index >= 0 && index < virtualArray.entryCount()) { - tool.setVirtualEntry(virtualArray, index, value()); + if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { + tool.setVirtualEntry(arrayState, index, value()); tool.delete(); } } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeAnalyzable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeAnalyzable.java Wed Jan 16 15:39:59 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 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.spi; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.virtual.*; - -public interface EscapeAnalyzable { - - public static class ObjectDesc { - - public final VirtualObjectNode virtualObject; - public final ValueNode[] entryState; - public final int lockCount; - - public ObjectDesc(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount) { - this.virtualObject = virtualObject; - this.entryState = entryState; - this.lockCount = lockCount; - } - } - - ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess); -} diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Wed Jan 16 16:17:07 2013 +0100 @@ -22,12 +22,37 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; + /** * This interface allows a node to convey information about what its effect would be if some of its inputs were - * virtualized. + * virtualized. The {@link #virtualize(VirtualizerTool)} method will only be called for nodes that have some interaction + * with virtualized nodes. However, the virtualized nodes might have been re-materialized in the meantime. */ public interface Virtualizable { + public static enum EscapeState { + Virtual, ThreadLocal, Global + } + + public abstract static class State { + + public abstract EscapeState getState(); + + public abstract VirtualObjectNode getVirtualObject(); + + public abstract void setEntry(int index, ValueNode value); + + public abstract ValueNode getEntry(int index); + + public abstract int getLockCount(); + + public abstract void setLockCount(int lockCount); + + public abstract ValueNode getMaterializedValue(); + } + /** * A node class can implement this method to convey information about what its effect would be if some of its inputs * were virtualized. All modifications must be made through the supplied tool, and not directly on the node, because diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java Wed Jan 16 16:17:07 2013 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 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.spi; + +/** + * This interface allows a node to convey information about what its effect would be if some of its inputs were + * virtualized. + * + * The difference to {@link Virtualizable} is that the {@link #virtualize(VirtualizerTool)} method will be called + * regardless of whether this node had any interaction with virtualized nodes. This interface can therefore be used for + * object allocations, for which virtualization introduces new virtualized objects. + * + */ +public interface VirtualizableAllocation extends Virtualizable { + +} diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Wed Jan 16 16:17:07 2013 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.Virtualizable.State; import com.oracle.graal.nodes.virtual.*; /** @@ -41,50 +42,46 @@ */ MetaAccessProvider getMetaAccessProvider(); + /** + * This method should be used to query the maximum size of virtualized objects before attempting virtualization. + * + * @return the maximum number of entries for virtualized objects. + */ + int getMaximumEntryCount(); + + /** + * @return the next id for virtual objects (can be used for the VirtualObject constructor). + */ + int getNextVirtualId(); + // methods working on virtualized/materialized objects /** + * Introduces a new virtual object to the current state. + * + * @param virtualObject the new virtual object. + * @param entryState the initial state of the virtual object's fields. + * @param lockCount the initial locking depth. + */ + void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount); + + /** * Queries the current state of the given value: if it is virtualized (thread-local and the compiler knows all * entries) or not. * * @param value the value whose state should be queried. - * @return the {@link VirtualObjectNode} representing the value if it is virtualized, null otherwise. + * @return the {@link State} representing the value if it has been virtualized at some point, null otherwise. */ - VirtualObjectNode getVirtualState(ValueNode value); - - /** - * Retrieves the entry (field or array element) with the given index in the virtualized object. - * - * @param virtual the virtualized object - * @param index the index to be queried. - * @return the entry at the given index. - */ - ValueNode getVirtualEntry(VirtualObjectNode virtual, int index); + State getObjectState(ValueNode value); /** * Sets the entry (field or array element) with the given index in the virtualized object. * - * @param virtual the virtualized object. + * @param state the state. * @param index the index to be set. * @param value the new value for the given index. */ - void setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value); - - /** - * Retrieves the lock count of the given virtualized object. - * - * @param virtual the virtualized object. - * @return the number of locks. - */ - int getVirtualLockCount(VirtualObjectNode virtual); - - /** - * Sets the lock count of the given virtualized object. - * - * @param virtual the virtualized object. - * @param lockCount the new lock count. - */ - void setVirtualLockCount(VirtualObjectNode virtual, int lockCount); + void setVirtualEntry(State state, int index, ValueNode value); /** * Queries the current state of the given value: if it was materialized or not. @@ -142,4 +139,12 @@ * @param action the custom action. */ void customAction(Runnable action); + + /** + * This method performs either {@link #replaceWithValue(ValueNode)} or + * {@link #replaceWithVirtual(VirtualObjectNode)}, depending on the given value. + * + * @param value the replacement value + */ + void replaceWith(ValueNode value); } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -32,10 +32,12 @@ @Input ValueNode unboxedValue; private final ResolvedJavaType type; + private final Kind kind; - public BoxedVirtualObjectNode(int virtualId, ResolvedJavaType type, ValueNode unboxedValue) { + public BoxedVirtualObjectNode(int virtualId, ResolvedJavaType type, Kind kind, ValueNode unboxedValue) { super(virtualId); this.type = type; + this.kind = kind; this.unboxedValue = unboxedValue; } @@ -60,8 +62,13 @@ } @Override - public int fieldIndexForOffset(long constantOffset) { + public int entryIndexForOffset(long constantOffset) { // (lstadler) unsafe access to a newly created boxing object should only ever touch the value field return 0; } + + @Override + public Kind entryKind(int index) { + return kind; + } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -74,7 +74,7 @@ } @Override - public int fieldIndexForOffset(long constantOffset) { + public int entryIndexForOffset(long constantOffset) { int baseOffset; int indexScale; switch (componentType.getKind()) { @@ -127,4 +127,10 @@ } return (int) elementIndex; } + + @Override + public Kind entryKind(int index) { + assert index >= 0 && index < length; + return componentType.getKind(); + } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -77,7 +77,13 @@ } @Override - public int fieldIndexForOffset(long constantOffset) { + public int entryIndexForOffset(long constantOffset) { return fieldIndex(type.findInstanceFieldWithOffset(constantOffset)); } + + @Override + public Kind entryKind(int index) { + assert index >= 0 && index < fields.length; + return fields[index].getKind(); + } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -58,5 +58,7 @@ // nothing to do in here - this method allows subclasses to respond to materialization } - public abstract int fieldIndexForOffset(long constantOffset); + public abstract int entryIndexForOffset(long constantOffset); + + public abstract Kind entryKind(int index); } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java Wed Jan 16 16:17:07 2013 +0100 @@ -80,7 +80,7 @@ StructuredGraph graph = (StructuredGraph) phiNode.graph(); result = graph.add(new PhiNode(kind, phiNode.merge())); phiReplacements.put(phiNode, result); - virtualizeUsages(phiNode, result, type); + virtualizeUsages(phiNode, result, type, kind); int i = 0; for (ValueNode n : phiNode.values()) { ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements); @@ -116,7 +116,7 @@ private void tryEliminate(BoxNode boxNode) { assert boxNode.objectStamp().isExactType(); - virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type()); + virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind()); if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) { // Elimination failed, because boxing object escapes. @@ -130,12 +130,12 @@ ((StructuredGraph) boxNode.graph()).removeFixed(boxNode); } - private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType) { + private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) { ValueNode virtualValueNode = null; VirtualObjectNode virtualObjectNode = null; for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) { if (virtualValueNode == null) { - virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, replacement)); + virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, sourceKind, replacement)); } n.replaceFirstInput(boxNode, virtualObjectNode); } diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Jan 16 16:17:07 2013 +0100 @@ -74,6 +74,7 @@ public static boolean EscapeAnalysisHistogram = ____; public static int EscapeAnalysisIterations = 2; public static String EscapeAnalyzeOnly = null; + public static int MaximumEscapeAnalysisArrayLength = 32; public static double TailDuplicationProbability = 0.5; public static int TailDuplicationTrivialSize = 1; diff -r 4fc2763e670e -r 921bde171d1d graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -86,12 +86,12 @@ @Override public void virtualize(VirtualizerTool tool) { - VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null) { - if (virtual instanceof VirtualArrayNode) { - tool.setVirtualEntry(virtual, targetIndex(), value()); + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual) { + if (state.getVirtualObject() instanceof VirtualArrayNode) { + tool.setVirtualEntry(state, targetIndex(), value()); } else { - tool.setVirtualEntry(virtual, ((VirtualInstanceNode) virtual).fieldIndex(targetField()), value()); + tool.setVirtualEntry(state, ((VirtualInstanceNode) state.getVirtualObject()).fieldIndex(targetField()), value()); } tool.delete(); } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Wed Jan 16 16:17:07 2013 +0100 @@ -31,7 +31,7 @@ import com.oracle.graal.nodes.virtual.*; @NodeInfo(nameTemplate = "Materialize {i#virtualObject}") -public final class MaterializeObjectNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, Node.IterableNodeType, Canonicalizable { +public final class MaterializeObjectNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType, Canonicalizable, ArrayLengthProvider { @Input private final NodeInputList values; @Input private final VirtualObjectNode virtualObject; @@ -49,6 +49,12 @@ } @Override + public ValueNode length() { + assert virtualObject.type().isArray(); + return ConstantNode.forInt(values.size(), graph()); + } + + @Override public void lower(LoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); if (virtualObject instanceof VirtualInstanceNode) { @@ -101,7 +107,8 @@ } @Override - public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { - return new ObjectDesc[] {new ObjectDesc(virtualObject, values.toArray(new ValueNode[values.size()]), lockCount)}; + public void virtualize(VirtualizerTool tool) { + tool.createVirtualObject(virtualObject, values.toArray(new ValueNode[values.size()]), lockCount); + tool.replaceWithVirtual(virtualObject); } } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Wed Jan 16 16:17:07 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.Virtualizable.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.MergeableBlockState; import com.oracle.graal.virtual.nodes.*; @@ -75,14 +76,15 @@ return new BlockState(this); } - public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) { + 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, deferred, deferredStores, materializeEffects); + materializeChangedBefore(fixed, virtual, state, deferred, deferredStores, materializeEffects); materializeEffects.addAll(deferredStores); } - private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet deferred, GraphEffectList deferredStores, GraphEffectList materializeEffects) { + private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, HashSet deferred, GraphEffectList deferredStores, GraphEffectList materializeEffects) { trace("materializing %s at %s", virtual, fixed); ObjectState obj = getObjectState(virtual); if (obj.getLockCount() > 0 && obj.virtual.type().isArray()) { @@ -115,7 +117,7 @@ } } newObject.setProbability(fixed.probability()); - obj.setMaterializedValue(newObject); + obj.escape(newObject, state); materializeEffects.addFixedNodeBefore(newObject, fixed); } else { // some entries are not default constants - do the materialization @@ -123,13 +125,13 @@ MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount()); ValueNode[] values = new ValueNode[obj.getEntries().length]; materialize.setProbability(fixed.probability()); - obj.setMaterializedValue(materialize); + 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, deferred, deferredStores, materializeEffects); + materializeChangedBefore(fixed, valueObj.virtual, state, deferred, deferredStores, materializeEffects); } if (deferred.contains(valueObj.virtual)) { Kind fieldKind; diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Wed Jan 16 16:17:07 2013 +0100 @@ -156,9 +156,8 @@ * * @param node The frame state to which the state should be added. * @param state The virtual object state to add. - * @param reusedVirtualObjects A set of all reused virtual objects. */ - public void addVirtualMapping(final FrameState node, final EscapeObjectState state, final HashSet reusedVirtualObjects) { + public void addVirtualMapping(final FrameState node, final EscapeObjectState state) { add(new Effect() { @Override @@ -172,11 +171,7 @@ FrameState stateAfter = node; for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { if (stateAfter.virtualObjectMappingAt(i).object() == state.object()) { - if (reusedVirtualObjects.contains(state.object())) { - stateAfter.virtualObjectMappings().remove(i); - } else { - throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", stateAfter, state.object()); - } + stateAfter.virtualObjectMappings().remove(i); } } stateAfter.addVirtualObjectMapping(graph.add(state)); diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Wed Jan 16 16:17:07 2013 +0100 @@ -23,6 +23,8 @@ package com.oracle.graal.virtual.phases.ea; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; /** @@ -30,22 +32,26 @@ * It describes the fields or array elements (called "entries") and the lock count if the object is still virtual. * If the object was materialized, it contains the current materialized value. */ -class ObjectState { +class ObjectState extends Virtualizable.State { public final VirtualObjectNode virtual; + + private EscapeState state; private ValueNode[] entries; private ValueNode materializedValue; private int lockCount; - public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, int lockCount) { + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, int lockCount) { this.virtual = virtual; this.entries = entries; + this.state = state; this.lockCount = lockCount; } - public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, int lockCount) { + public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, EscapeState state, int lockCount) { this.virtual = virtual; this.materializedValue = materializedValue; + this.state = state; this.lockCount = lockCount; } @@ -54,41 +60,56 @@ entries = other.entries == null ? null : other.entries.clone(); materializedValue = other.materializedValue; lockCount = other.lockCount; + state = other.state; } public ObjectState cloneState() { return new ObjectState(this); } + @Override + public EscapeState getState() { + return state; + } + + @Override + public VirtualObjectNode getVirtualObject() { + return virtual; + } + public boolean isVirtual() { - assert (entries == null) ^ (materializedValue == null); - return materializedValue == null; + return state == EscapeState.Virtual; } public ValueNode[] getEntries() { - assert isVirtual(); + assert isVirtual() && entries != null; return entries; } + @Override public ValueNode getEntry(int index) { assert isVirtual(); return entries[index]; } + @Override public void setEntry(int index, ValueNode value) { assert isVirtual(); entries[index] = value; } - public ValueNode getMaterializedValue() { + public void escape(ValueNode materialized, EscapeState newState) { + assert state == EscapeState.Virtual || (state == EscapeState.ThreadLocal && newState == EscapeState.Global); + state = newState; + materializedValue = materialized; + entries = null; assert !isVirtual(); - return materializedValue; } - public void setMaterializedValue(ValueNode value) { - assert isVirtual(); - materializedValue = value; - entries = null; + @Override + public ValueNode getMaterializedValue() { + assert state == EscapeState.ThreadLocal || state == EscapeState.Global; + return materializedValue; } public void updateMaterializedValue(ValueNode value) { @@ -96,10 +117,12 @@ materializedValue = value; } + @Override public int getLockCount() { return lockCount; } + @Override public void setLockCount(int lockCount) { this.lockCount = lockCount; } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Wed Jan 16 16:17:07 2013 +0100 @@ -33,7 +33,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.common.CanonicalizerPhase.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.EffectList.Effect; @@ -75,7 +75,7 @@ boolean analyzableNodes = false; for (Node node : graph.getNodes()) { - if (node instanceof EscapeAnalyzable) { + if (node instanceof VirtualizableAllocation) { analyzableNodes = true; break; } diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Jan 16 16:17:07 2013 +0100 @@ -25,8 +25,6 @@ import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; @@ -36,9 +34,8 @@ import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.spi.EscapeAnalyzable.ObjectDesc; +import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo; @@ -47,37 +44,24 @@ class PartialEscapeClosure extends BlockIteratorClosure { - public static final ConcurrentHashMap, AtomicLong> materializeReasons = new ConcurrentHashMap<>(); - - static { - if (GraalOptions.EscapeAnalysisHistogram) { - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - for (Map.Entry, AtomicLong> entry : materializeReasons.entrySet()) { - System.out.println(entry.getKey() + ": " + entry.getValue()); - } - } - }); - } - } - - private static final DebugMetric metricAllocationRemoved = Debug.metric("AllocationRemoved "); + public static final DebugMetric METRIC_MATERIALIZATIONS = Debug.metric("Materializations"); + public static final DebugMetric METRIC_MATERIALIZATIONS_PHI = Debug.metric("MaterializationsPhi"); + public static final DebugMetric METRIC_MATERIALIZATIONS_MERGE = Debug.metric("MaterializationsMerge"); + public static final DebugMetric METRIC_MATERIALIZATIONS_UNHANDLED = Debug.metric("MaterializationsUnhandled"); + public static final DebugMetric METRIC_MATERIALIZATIONS_LOOP_REITERATION = Debug.metric("MaterializationsLoopReiteration"); + public static final DebugMetric METRIC_MATERIALIZATIONS_LOOP_END = Debug.metric("MaterializationsLoopEnd"); + public static final DebugMetric METRIC_ALLOCATION_REMOVED = Debug.metric("AllocationRemoved "); private final NodeBitMap usages; private final SchedulePhase schedule; private final GraphEffectList effects = new GraphEffectList(); - private final HashSet reusedVirtualObjects = new HashSet<>(); - private int virtualIds = 0; private final VirtualizerToolImpl tool; - private final MetaAccessProvider metaAccess; public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess) { this.usages = usages; this.schedule = schedule; - this.metaAccess = metaAccess; tool = new VirtualizerToolImpl(effects, usages, metaAccess); } @@ -86,7 +70,7 @@ } public int getVirtualIdCount() { - return virtualIds; + return tool.getNextVirtualId(); } @Override @@ -96,39 +80,11 @@ FixedWithNextNode lastFixedNode = null; for (Node node : nodeList) { - ObjectDesc[] newAllocations = null; - if (node instanceof EscapeAnalyzable) { - newAllocations = ((EscapeAnalyzable) node).getAllocations(virtualIds, metaAccess); - } - - if (newAllocations != null) { - trace("{{%s}} ", node); - for (ObjectDesc desc : newAllocations) { - VirtualObjectNode virtualObject = desc.virtualObject; - if (virtualObject.isAlive()) { - reusedVirtualObjects.add(virtualObject); - state.addAndMarkAlias(virtualObject, virtualObject, usages); - } else { - effects.addFloatingNode(virtualObject); - } - ValueNode[] fieldState = desc.entryState; - for (int i = 0; i < fieldState.length; i++) { - fieldState[i] = state.getScalarAlias(fieldState[i]); - } - state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, desc.lockCount)); - state.addAndMarkAlias(virtualObject, virtualObject, usages); - } - state.addAndMarkAlias(newAllocations[0].virtualObject, (ValueNode) node, usages); - effects.deleteFixedNode((FixedWithNextNode) node); - metricAllocationRemoved.add(newAllocations.length); - virtualIds += newAllocations.length; + if (usages.isMarked(node) || node instanceof VirtualizableAllocation) { + trace("[[%s]] ", node); + processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); } else { - if (usages.isMarked(node)) { - trace("[[%s]] ", node); - processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); - } else { - trace("%s ", node); - } + trace("%s ", node); } if (node instanceof FixedWithNextNode && node.isAlive()) { @@ -138,7 +94,6 @@ trace(")\n end state: %s\n", state); } - private void processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { tool.reset(state, node); if (node instanceof Virtualizable) { @@ -217,7 +172,7 @@ } else { v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); } - effects.addVirtualMapping(stateAfter, v, reusedVirtualObjects); + effects.addVirtualMapping(stateAfter, v); } } } @@ -228,29 +183,24 @@ ObjectState obj = state.getObjectState(input); if (obj != null) { trace("replacing input %s at %s: %s", input, node, obj); - if (GraalOptions.EscapeAnalysisHistogram && obj.isVirtual()) { - AtomicLong counter = materializeReasons.get(node.getClass()); - if (counter == null) { - counter = new AtomicLong(); - materializeReasons.put(node.getClass(), counter); - } - counter.incrementAndGet(); - } - replaceWithMaterialized(input, node, insertBefore, state, obj); + replaceWithMaterialized(input, node, insertBefore, state, obj, METRIC_MATERIALIZATIONS_UNHANDLED); } } } - private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { + private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, DebugMetric metric) { assert obj != null; - if (obj.isVirtual()) { - state.materializeBefore(materializeBefore, obj.virtual, effects); + if (obj.getState() == EscapeState.Virtual) { + metric.increment(); + state.materializeBefore(materializeBefore, obj.virtual, EscapeState.Global, effects); + } else { + assert obj.getState() == EscapeState.Global; } assert !obj.isVirtual(); } - private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj) { - ensureMaterialized(state, obj, materializeBefore); + private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, DebugMetric metric) { + ensureMaterialized(state, obj, materializeBefore, metric); effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); } @@ -298,12 +248,12 @@ BlockState state = states.get(i); ObjectState obj = state.getObjectState(object); materialized |= obj.isVirtual(); - ensureMaterialized(state, obj, merge.forwardEndAt(i)); + ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE); effects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); } - newState.addObject(object, new ObjectState(object, materializedValuePhi, lockCount)); + newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, lockCount)); } else { - newState.addObject(object, new ObjectState(object, singleValue, lockCount)); + newState.addObject(object, new ObjectState(object, singleValue, EscapeState.Global, lockCount)); } } else { assert virtual == states.size(); @@ -330,7 +280,7 @@ ObjectState obj = state.getObjectState(fields[index]); if (obj != null) { materialized |= obj.isVirtual(); - ensureMaterialized(state, obj, merge.forwardEndAt(i)); + ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE); fields[index] = obj.getMaterializedValue(); } effects.addPhiInput(phis[index], fields[index]); @@ -343,7 +293,7 @@ } } } - newState.addObject(object, new ObjectState(object, values, lockCount)); + newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, lockCount)); } } } @@ -413,7 +363,7 @@ ObjectState obj = states.get(i).getObjectState(value); if (obj != null) { materialized |= obj.isVirtual(); - replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj); + replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj, METRIC_MATERIALIZATIONS_PHI); } } } @@ -492,7 +442,10 @@ for (VirtualObjectNode virtualObject : additionalMaterializations) { ObjectState obj = initialState.getObjectState(virtualObject); if (obj.isVirtual()) { - initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, effects); + METRIC_MATERIALIZATIONS_LOOP_REITERATION.increment(); + initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, EscapeState.Global, effects); + } else { + assert obj.getState() == EscapeState.Global; } } } @@ -604,7 +557,8 @@ if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { if (endValueObj != null) { if (endValueObj.isVirtual()) { - loopEndState.materializeBefore(loopEnd, endValueObj.virtual, successEffects); + METRIC_MATERIALIZATIONS_LOOP_END.increment(); + loopEndState.materializeBefore(loopEnd, endValueObj.virtual, EscapeState.Global, successEffects); materialized = true; } } @@ -631,7 +585,7 @@ } } else { if (initialMaterialized) { - loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, successEffects); + loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, EscapeState.Global, successEffects); materialized = true; } else { if (loopEndObj.virtual != initialObj.virtual) { @@ -663,7 +617,8 @@ // good. } } else { - if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) || (endValueObj == null && valueObj.getMaterializedValue() != endValue)) { + if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) || + (endValueObj == null && valueObj.getMaterializedValue() != endValue)) { phis.add(new PhiDesc(state.virtual, i)); } else { // either endValue has the same materialized value as value or endValue is the diff -r 4fc2763e670e -r 921bde171d1d 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 Wed Jan 16 15:39:59 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Wed Jan 16 16:17:07 2013 +0100 @@ -22,11 +22,16 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; +import com.oracle.graal.nodes.spi.Virtualizable.State; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; class VirtualizerToolImpl implements VirtualizerTool { @@ -44,6 +49,7 @@ private boolean customAction; private BlockState state; private ValueNode current; + private int virtualIds = 0; @Override public MetaAccessProvider getMetaAccessProvider() { @@ -66,51 +72,32 @@ } @Override - public VirtualObjectNode getVirtualState(ValueNode value) { - ObjectState obj = state.getObjectState(value); - return obj != null && obj.isVirtual() ? obj.virtual : null; + public int getNextVirtualId() { + return virtualIds; } @Override - public ValueNode getVirtualEntry(VirtualObjectNode virtual, int index) { - ObjectState obj = state.getObjectState(virtual); - assert obj != null && obj.isVirtual() : "not virtual: " + obj; - ValueNode result = obj.getEntry(index); - ValueNode materialized = getMaterializedValue(result); - return materialized != null ? materialized : result; + public State getObjectState(ValueNode value) { + return state.getObjectState(value); } @Override - public void setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value) { - ObjectState obj = state.getObjectState(virtual); + public void setVirtualEntry(State objectState, int index, ValueNode value) { + ObjectState obj = (ObjectState) objectState; assert obj != null && obj.isVirtual() : "not virtual: " + obj; - if (getVirtualState(value) == null) { - ValueNode materialized = getMaterializedValue(value); - if (materialized != null) { - obj.setEntry(index, materialized); + ObjectState valueState = state.getObjectState(value); + if (valueState == null) { + obj.setEntry(index, getReplacedValue(value)); + } else { + if (valueState.getState() == EscapeState.Virtual) { + obj.setEntry(index, value); } else { - obj.setEntry(index, getReplacedValue(value)); + obj.setEntry(index, valueState.getMaterializedValue()); } - } else { - obj.setEntry(index, value); } } @Override - public int getVirtualLockCount(VirtualObjectNode virtual) { - ObjectState obj = state.getObjectState(virtual); - assert obj != null && obj.isVirtual() : "not virtual: " + obj; - return obj.getLockCount(); - } - - @Override - public void setVirtualLockCount(VirtualObjectNode virtual, int lockCount) { - ObjectState obj = state.getObjectState(virtual); - assert obj != null && obj.isVirtual() : "not virtual: " + obj; - obj.setLockCount(lockCount); - } - - @Override public ValueNode getMaterializedValue(ValueNode value) { ObjectState obj = state.getObjectState(value); return obj != null && !obj.isVirtual() ? obj.getMaterializedValue() : null; @@ -154,4 +141,40 @@ effects.customAction(action); customAction = true; } + + @Override + public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount) { + trace("{{%s}} ", current); + if (virtualObject.isAlive()) { + state.addAndMarkAlias(virtualObject, virtualObject, usages); + } else { + effects.addFloatingNode(virtualObject); + } + 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.addAndMarkAlias(virtualObject, virtualObject, usages); + PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment(); + virtualIds++; + } + + @Override + public int getMaximumEntryCount() { + return GraalOptions.MaximumEscapeAnalysisArrayLength; + } + + @Override + public void replaceWith(ValueNode node) { + State resultState = getObjectState(node); + if (resultState == null) { + replaceWithValue(node); + } else { + if (resultState.getState() == EscapeState.Virtual) { + replaceWithVirtual(resultState.getVirtualObject()); + } else { + replaceWithValue(resultState.getMaterializedValue()); + } + } + } }