# HG changeset patch # User Doug Simon # Date 1354205639 -3600 # Node ID b3c94e1e18e9caf87ddef9fe7abb764d0a56a6e4 # Parent eec7173947a149f01a53b5c4eb5e60c09f1df160# Parent bb6d2860e431e21469f65f96ee574482781a6473 Merge. diff -r eec7173947a1 -r b3c94e1e18e9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu Nov 29 17:13:13 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu Nov 29 17:13:59 2012 +0100 @@ -46,7 +46,7 @@ /** * Number of successive successful installations. */ - private long successfulInstallations; + private long successfulInstallations = MINIMUM_SUCCESSFUL_INSTALLATIONS_PER_FAILURE; /** * The minimum expected number of successful code installations between each code diff -r eec7173947a1 -r b3c94e1e18e9 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 Nov 29 17:13:13 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Nov 29 17:13:59 2012 +0100 @@ -518,14 +518,14 @@ } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph, false); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, false); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); // An unsafe read must not floating outside its block as may float above an explicit null check on its object. memoryRead.dependencies().add(BeginNode.prevBegin(load)); graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph, false); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, false); ValueNode object = store.object(); WriteNode write = graph.add(new WriteNode(object, store.value(), location)); write.setStateAfter(store.stateAfter()); diff -r eec7173947a1 -r b3c94e1e18e9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Thu Nov 29 17:13:59 2012 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, 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.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + + +public abstract class UnsafeAccessNode extends FixedWithNextNode { + @Input private ValueNode object; + @Input private ValueNode offset; + private final int displacement; + private final Kind accessKind; + + public UnsafeAccessNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, Kind accessKind) { + super(stamp); + assert accessKind != null; + this.object = object; + this.displacement = displacement; + this.offset = offset; + this.accessKind = accessKind; + } + + public ValueNode object() { + return object; + } + + public int displacement() { + return displacement; + } + + public ValueNode offset() { + return offset; + } + + public Kind accessKind() { + return accessKind; + } +} diff -r eec7173947a1 -r b3c94e1e18e9 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 17:13:13 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Thu Nov 29 17:13:59 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,43 +34,18 @@ * 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 FixedWithNextNode implements Lowerable, Virtualizable { - - @Input private ValueNode object; - @Input private ValueNode offset; - private final int displacement; - private final Kind loadKind; +public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable { - public ValueNode object() { - return object; - } - - public int displacement() { - return displacement; - } - - public ValueNode offset() { - return offset; + public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) { + this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object); } - public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) { - super(nonNull ? StampFactory.objectNonNull() : StampFactory.object()); - this.object = object; - this.displacement = displacement; - this.offset = offset; - this.loadKind = Kind.Object; + public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, Kind accessKind) { + this(StampFactory.forKind(accessKind.getStackKind()), object, displacement, offset, accessKind); } - public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, Kind kind) { - super(StampFactory.forKind(kind.getStackKind())); - this.object = object; - this.displacement = displacement; - this.offset = offset; - this.loadKind = kind; - } - - public Kind loadKind() { - return loadKind; + public UnsafeLoadNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, Kind accessKind) { + super(stamp, object, displacement, offset, accessKind); } @Override @@ -96,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 eec7173947a1 -r b3c94e1e18e9 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 17:13:13 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Thu Nov 29 17:13:59 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,14 +34,20 @@ * 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 FixedWithNextNode implements StateSplit, Lowerable, Virtualizable { +public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable { + + @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode value; - private final int displacement; - private final Kind storeKind; - @Input(notDataflow = true) private FrameState stateAfter; + public UnsafeStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, Kind accessKind) { + this(StampFactory.forVoid(), object, displacement, offset, value, accessKind); + } + + public UnsafeStoreNode(Stamp stamp, ValueNode object, int displacement, ValueNode offset, ValueNode value, Kind accessKind) { + super(stamp, object, displacement, offset, accessKind); + assert accessKind != Kind.Void && accessKind != Kind.Illegal; + this.value = value; + } public FrameState stateAfter() { return stateAfter; @@ -55,43 +63,10 @@ return true; } - public UnsafeStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, Kind kind) { - super(StampFactory.forVoid()); - assert kind != Kind.Void && kind != Kind.Illegal; - this.object = object; - this.displacement = displacement; - this.offset = offset; - this.value = value; - this.storeKind = kind; - } - - public ValueNode object() { - return object; - } - - public int displacement() { - return displacement; - } - - public ValueNode offset() { - return offset; - } - public ValueNode value() { return value; } - public Kind storeKind() { - return storeKind; - } - - @Override - public boolean verify() { - assertTrue(storeKind != null, "UnsafeStoreNode must have a store kind"); - assertTrue(object != null, "UnsafeStoreNode should have an object"); - return super.verify(); - } - @Override public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); @@ -112,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);