# HG changeset patch # User Thomas Wuerthinger # Date 1373228898 -7200 # Node ID 2ea604c4c6eca11a2993b94e6180db8c2da6cce8 # Parent e7c2a0aa1fffd7362c41827555f6877d93410939 Factor and improve unsafe load/store canonicalization. diff -r e7c2a0aa1fff -r 2ea604c4c6ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Sun Jul 07 21:30:25 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Sun Jul 07 22:28:18 2013 +0200 @@ -24,9 +24,10 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class UnsafeAccessNode extends FixedWithNextNode { +public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable { @Input private ValueNode object; @Input private ValueNode offset; @@ -57,4 +58,38 @@ public Kind accessKind() { return accessKind; } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (offset().isConstant()) { + long constantOffset = offset().asConstant().asLong(); + + // Try to canonicalize to a field access. + if (object().stamp() instanceof ObjectStamp) { + // TODO (gd) remove that once UnsafeAccess only have an object base + ObjectStamp receiverStamp = object().objectStamp(); + ResolvedJavaType receiverType = receiverStamp.type(); + ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset); + + // No need for checking that the receiver is non-null. The field access includes the + // null check and if a field is found, the offset is so small that this is never a + // valid access of an arbitrary address. + if (field != null && field.getKind() == this.accessKind()) { + return cloneAsFieldAccess(field); + } + } + + if (constantOffset != 0 && Integer.MAX_VALUE - displacement() >= constantOffset) { + int intDisplacement = (int) (constantOffset + displacement()); + if (constantOffset == intDisplacement) { + return cloneWithZeroOffset(intDisplacement); + } + } + } + return this; + } + + protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field); + + protected abstract ValueNode cloneWithZeroOffset(int intDisplacement); } diff -r e7c2a0aa1fff -r 2ea604c4c6ec 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 Sun Jul 07 21:30:25 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Sun Jul 07 22:28:18 2013 +0200 @@ -25,7 +25,6 @@ import static com.oracle.graal.graph.UnsafeAccess.*; 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.*; @@ -35,7 +34,7 @@ * Load of a value from a location specified as an offset relative to an object. No null check is * performed before the load. */ -public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable { +public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) { this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object); @@ -70,29 +69,13 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (offset().isConstant()) { - long constantOffset = offset().asConstant().asLong(); - if (constantOffset != 0) { - int intDisplacement = (int) (constantOffset + displacement()); - if (constantOffset == intDisplacement) { - Graph graph = this.graph(); - return graph.add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph.unique(ConstantNode.forInt(0, graph)), accessKind())); - } - } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once - // UnsafeAccess only have an - // object base - ObjectStamp receiverStamp = object().objectStamp(); - ResolvedJavaType receiverType = receiverStamp.type(); - if (receiverStamp.nonNull() && receiverType != null) { - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement()); - if (field != null && field.getKind() == this.accessKind()) { - return this.graph().add(new LoadFieldNode(object(), field)); - } - } - } - } - return this; + protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { + return this.graph().add(new LoadFieldNode(object(), field)); + } + + @Override + protected ValueNode cloneWithZeroOffset(int intDisplacement) { + return graph().add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph().unique(ConstantNode.forInt(0, graph())), accessKind())); } @SuppressWarnings("unchecked") diff -r e7c2a0aa1fff -r 2ea604c4c6ec 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 Sun Jul 07 21:30:25 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Sun Jul 07 22:28:18 2013 +0200 @@ -34,7 +34,7 @@ * Store of a value at a location specified as an offset relative to an object. No null check is * performed before the store. */ -public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint.Single { +public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; @@ -94,32 +94,17 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (offset().isConstant()) { - long constantOffset = offset().asConstant().asLong(); - if (constantOffset != 0) { - int intDisplacement = (int) (constantOffset + displacement()); - if (constantOffset == intDisplacement) { - UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind())); - unsafeStoreNode.setStateAfter(stateAfter()); - return unsafeStoreNode; - } - } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once - // UnsafeAccess only have an - // object base - ObjectStamp receiverStamp = object().objectStamp(); - if (receiverStamp.nonNull()) { - ResolvedJavaType receiverType = receiverStamp.type(); - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement()); - if (field != null && field.getKind() == this.accessKind()) { - StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value())); - storeFieldNode.setStateAfter(stateAfter()); - return storeFieldNode; - } - } - } - } - return this; + protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { + StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value())); + storeFieldNode.setStateAfter(stateAfter()); + return storeFieldNode; + } + + @Override + protected ValueNode cloneWithZeroOffset(int intDisplacement) { + UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind())); + unsafeStoreNode.setStateAfter(stateAfter()); + return unsafeStoreNode; } // specialized on value type until boxing/unboxing is sorted out in intrinsification diff -r e7c2a0aa1fff -r 2ea604c4c6ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Sun Jul 07 21:30:25 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Sun Jul 07 22:28:18 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*;