# HG changeset patch # User Gilles Duboscq # Date 1354192308 -3600 # Node ID 08fe3a509cf1945f1a54ed72d68c826671a3007a # Parent 05ce1defa4f917a845962d5d38e29188a1da8f97 Canoncialize UnsafeLoad/Store diff -r 05ce1defa4f9 -r 08fe3a509cf1 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 Thu Nov 29 13:24:08 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Thu Nov 29 13:31:48 2012 +0100 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes.extended; 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.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; @@ -32,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 { +public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable { public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) { this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object); @@ -71,6 +73,30 @@ } } + @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(); + if (receiverStamp.nonNull()) { + ResolvedJavaType receiverType = receiverStamp.type(); + ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement()); + if (field != null) { + return this.graph().add(new LoadFieldNode(object(), field, StructuredGraph.INVALID_GRAPH_ID)); + } + } + } + } + return this; + } + @NodeIntrinsic public static native T load(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind kind); diff -r 05ce1defa4f9 -r 08fe3a509cf1 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 Thu Nov 29 13:24:08 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Thu Nov 29 13:31:48 2012 +0100 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes.extended; 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.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; @@ -32,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 { +public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; @@ -85,6 +87,30 @@ } } + @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 UnsafeStoreNode(this.stamp(), object(), intDisplacement, graph.unique(ConstantNode.forInt(0, graph)), value(), accessKind())); + } + } 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) { + return this.graph().add(new StoreFieldNode(object(), field, value(), StructuredGraph.INVALID_GRAPH_ID)); + } + } + } + } + return this; + } + // specialized on value type until boxing/unboxing is sorted out in intrinsification @NodeIntrinsic public static native void store(Object object, @ConstantNodeParameter int displacement, long offset, Object value, @ConstantNodeParameter Kind kind);