changeset 5400:028c9ce0fc0f

added support for -G:+CheckcastCounters in checkcast snippets
author Doug Simon <doug.simon@oracle.com>
date Tue, 15 May 2012 10:03:33 +0200
parents c976c744c802
children 332a3c0d7b3b
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectStoreNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/GetObjectAddressNode.java
diffstat 9 files changed, 360 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue May 15 10:03:33 2012 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
@@ -1013,27 +1014,13 @@
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         Debug.dump(graph, "After inlining snippet %s", snippetCopy.method());
 
-//        if (tool != null) {
-//            boolean innerLowering = false;
-//            for (Node node : duplicates.values()) {
-//                if (node instanceof Lowerable) {
-//                    innerLowering = true;
-//                    ((Lowerable) node).lower(tool);
-//
-//                }
-//            }
-//            if (innerLowering) {
-//                Debug.dump(graph, "After inner lowering");
-//            }
-//        }
-
         // Remove all frame states from the inlined snippet graph. Snippets must be atomic (i.e. free
         // of side-effects that prevent deoptimizing to a point before the snippet).
         for (Node node : graph.getNewNodes(mark)) {
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState frameState = stateSplit.stateAfter();
-                assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node + "\n    " + replacee.graph();
+                assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node + "\n    " + frameState.toString(Verbosity.Debugger);
                 if (frameState != null) {
                     stateSplit.setStateAfter(null);
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue May 15 10:03:33 2012 +0200
@@ -289,6 +289,7 @@
         CiCompilationStatistics.clear("final");
         MethodEntryCounters.printCounters(compiler);
         HotSpotXirGenerator.printCounters(TTY.out().out());
+        CheckCastSnippets.printCounters(TTY.out().out());
     }
 
     private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Tue May 15 10:03:33 2012 +0200
@@ -28,8 +28,8 @@
 import java.util.*;
 
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate;
 import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.cri.*;
@@ -39,6 +39,7 @@
 import com.oracle.graal.hotspot.Compiler;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.snippets.*;
+import com.oracle.graal.hotspot.snippets.CheckCastSnippets.Counter;
 import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -81,7 +82,11 @@
         Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets());
         Snippets.install(this, compiler.getTarget(), new CheckCastSnippets());
         try {
-            checkcastSnippet = getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class));
+            if (GraalOptions.CheckcastCounters) {
+                checkcastSnippet = getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastWithCounters", Object.class, Object.class, Object[].class, boolean.class, Counter.class));
+            } else {
+                checkcastSnippet = getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class));
+            }
         } catch (NoSuchMethodException e) {
             throw new GraalInternalError(e);
         }
@@ -432,8 +437,12 @@
                 final CiConstant hintHubsConst = CiConstant.forObject(hintHubs);
                 hintHubsSet.put(hintHubsConst, hintHubsConst);
                 Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact);
-
-                InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
+                if (GraalOptions.CheckcastCounters) {
+                    Counter noHintsCounter = checkcast.targetClass() == null ? Counter.noHints_unknown : checkcast.targetClass().isInterface() ? Counter.noHints_iface : Counter.noHints_class;
+                    InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact), CiConstant.forObject(noHintsCounter));
+                } else {
+                    InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
+                }
                 new DeadCodeEliminationPhase().apply(graph);
             }
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Tue May 15 10:03:33 2012 +0200
@@ -1010,7 +1010,7 @@
     }
 
     private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) {
-        double percent = ((double) (count * 100)) / total;
+        double percent = total == 0D ? 0D : ((double) (count * 100)) / total;
         out.println(String.format("%16s: %5.2f%%%10d  // %s", name, percent, count, name.desc));
     }
 
@@ -1036,7 +1036,7 @@
         Arrays.sort(counters);
 
         out.println();
-        out.println("** Checkcast counters **");
+        out.println("** XIR checkcast counters **");
         for (Count c : counters) {
             printCounter(out, c.name, c.c, total);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue May 15 10:03:33 2012 +0200
@@ -21,8 +21,7 @@
  * questions.
  */
 package com.oracle.graal.hotspot.snippets;
-import com.oracle.graal.cri.*;
-import com.oracle.graal.graph.Node.*;
+import com.oracle.graal.graph.Node.Fold;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -32,6 +31,7 @@
 import com.oracle.max.cri.ci.*;
 
 
+@SuppressWarnings("unused")
 public class ArrayCopySnippets implements SnippetsInterface{
 
     @Snippet
@@ -346,92 +346,13 @@
             DirectObjectStoreNode.store(dest, header, i + destOffset, a);
         }
     }
-    private static class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
-        @Input private ValueNode object;
-
-        public GetObjectAddressNode(ValueNode obj) {
-            super(StampFactory.forKind(CiKind.Long));
-            this.object = obj;
-        }
-
-        @SuppressWarnings("unused")
-        @NodeIntrinsic
-        public static long get(Object array) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void generate(LIRGeneratorTool gen) {
-            CiValue obj = gen.newVariable(gen.target().wordKind);
-            gen.emitMove(gen.operand(object), obj);
-            gen.setResult(this, obj);
-        }
-    }
-    private static class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
-        @Input private ValueNode address;
-        @Input private ValueNode value;
-
-        public DirectStoreNode(ValueNode address, ValueNode value) {
-            super(StampFactory.illegal());
-            this.address = address;
-            this.value = value;
-        }
-
-        @SuppressWarnings("unused")
-        @NodeIntrinsic
-        public static void store(long address, long value) {
-            throw new UnsupportedOperationException();
-        }
-
-        @SuppressWarnings("unused")
-        @NodeIntrinsic
-        public static void store(long address, boolean value) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void generate(LIRGeneratorTool gen) {
-            CiValue v = gen.operand(value);
-            gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false);
-        }
-    }
-
-    private static class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
-        @Input private ValueNode object;
-        @Input private ValueNode value;
-        @Input private ValueNode offset;
-        private final int displacement;
-
-        public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) {
-            super(StampFactory.illegal());
-            this.object = object;
-            this.value = value;
-            this.offset = offset;
-            this.displacement = displacement;
-        }
-
-        @SuppressWarnings("unused")
-        @NodeIntrinsic
-        public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void lower(CiLoweringTool tool) {
-            StructuredGraph graph = (StructuredGraph) this.graph();
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
-            WriteNode write = graph.add(new WriteNode(object, value, location));
-            graph.replaceFixedWithFixed(this, write);
-        }
-    }
-
     @Fold
     private static int wordSize() {
         return CompilerImpl.getInstance().getTarget().wordSize;
     }
 
     @Fold
-    private static int arrayHeaderSizeFor(CiKind elementKind) {
+    static int arrayHeaderSizeFor(CiKind elementKind) {
         return CompilerImpl.getInstance().getConfig().getArrayOffset(elementKind);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Mon May 14 22:07:14 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue May 15 10:03:33 2012 +0200
@@ -21,18 +21,40 @@
  * questions.
  */
 package com.oracle.graal.hotspot.snippets;
+import static com.oracle.graal.hotspot.snippets.CheckCastSnippets.Counter.*;
+
+import java.io.*;
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Fold;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 
-
+/**
+ * Snippets used for lowering {@link CheckCastNode}s.
+ */
 public class CheckCastSnippets implements SnippetsInterface {
 
+    /**
+     * Checks that a given object is null or is a subtype of a given type.
+     *
+     * @param hub the hub of the type being checked against
+     * @param object the object whose type is being checked against {@code hub}
+     * @param hintHubs the hubs of objects that have been profiled during previous executions
+     * @param hintsAreExact specifies if {@code hintHubs} contains all subtypes of {@code hub}
+     * @return {@code object} if the type check succeeds
+     * @throws ClassCastException if the type check fails
+     */
     @Snippet
     public static Object checkcast(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact) {
         if (object == null) {
@@ -52,8 +74,138 @@
         return object;
     }
 
+    /**
+     * Counters for the various code paths through a type check.
+     */
+    public enum Counter {
+        hintsHit("hit a hint type"),
+        hintsMissed("missed the hint types"),
+        exact("tested type is (statically) final"),
+        noHints_class("profile information is not used (test type is a class)"),
+        noHints_iface("profile information is not used (test type is an interface)"),
+        noHints_unknown("test type is not a compile-time constant"),
+        isNull("object tested is null"),
+        exception("type test failed with a ClassCastException");
+
+        final String description;
+        final int index;
+        long count;
+
+        private Counter(String desc) {
+            this.description = desc;
+            this.index = ordinal();
+        }
+
+        @Fold
+        static int countOffset() {
+            try {
+                return (int) Unsafe.getUnsafe().objectFieldOffset(Counter.class.getDeclaredField("count"));
+            } catch (Exception e) {
+                throw new GraalInternalError(e);
+            }
+        }
+
+        /**
+         * Increments this counter if counters are enabled. The body of this method has been carefully crafted
+         * such that it contains no safepoints and no calls, neither of which are permissible in a snippet.
+         * Also, increments are not guaranteed to be atomic but that's acceptable for a counter like this.
+         */
+        void inc() {
+            if (ENABLED) {
+                DirectObjectStoreNode.store(this, countOffset(), 0, count + 1);
+            }
+        }
+
+        static final Counter[] VALUES = values();
+        static final boolean ENABLED = GraalOptions.CheckcastCounters;
+    }
+
+    /**
+     * @see #checkcast(Object, Object, Object[], boolean)
+     */
+    @Snippet
+    public static Object checkcastWithCounters(Object hub, Object object, Object[] hintHubs, boolean hintsAreExact, Counter noHintsCounter) {
+        if (object == null) {
+            isNull.inc();
+            return object;
+        }
+        Object objectHub = UnsafeLoadNode.load(object, 0, hubOffset(), CiKind.Object);
+        if (hintHubs.length == 0) {
+            noHintsCounter.inc();
+            if (!TypeCheckSlowPath.check(objectHub, hub)) {
+                exception.inc();
+                DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
+            }
+        } else {
+            // if we get an exact match: succeed immediately
+            for (int i = 0; i < hintHubs.length; i++) {
+                Object hintHub = hintHubs[i];
+                if (hintHub == objectHub) {
+                    if (hintsAreExact) {
+                        exact.inc();
+                    } else {
+                        hintsHit.inc();
+                    }
+                    return object;
+                }
+            }
+            if (!hintsAreExact) {
+                if (!TypeCheckSlowPath.check(objectHub, hub)) {
+                    exception.inc();
+                    DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
+                } else {
+                    hintsMissed.inc();
+                }
+            } else {
+                exception.inc();
+                DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
+            }
+        }
+        return object;
+    }
+
     @Fold
     private static int hubOffset() {
         return CompilerImpl.getInstance().getConfig().hubOffset;
     }
+
+    @Fold
+    private static boolean isInterface(RiResolvedType type) {
+        return type.isInterface();
+    }
+
+    public static void printCounter(PrintStream out, Counter c, long total) {
+        double percent = total == 0D ? 0D : ((double) (c.count * 100)) / total;
+        out.println(String.format("%16s: %5.2f%%%10d  // %s", c.name(), percent, c.count, c.description));
+    }
+
+    public static void printCounters(PrintStream out) {
+        if (!Counter.ENABLED) {
+            return;
+        }
+        Counter[] counters = Counter.values();
+        Arrays.sort(counters, new Comparator<Counter>() {
+            @Override
+            public int compare(Counter o1, Counter o2) {
+                if (o1.count > o2.count) {
+                    return -1;
+                } else if (o2.count > o1.count) {
+                    return 1;
+                }
+                return 0;
+            }
+
+        });
+
+        long total = 0;
+        for (Counter c : counters) {
+            total += c.count;
+        }
+
+        out.println();
+        out.println("** Checkcast counters **");
+        for (Counter c : counters) {
+            printCounter(out, c, total);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Tue May 15 10:03:33 2012 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.hotspot.snippets;
+
+import com.oracle.graal.cri.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * A special purpose store node that differs from {@link UnsafeStoreNode} in that
+ * it is not a {@link StateSplit} and does not include a write barrier.
+ */
+class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
+    @Input private ValueNode object;
+    @Input private ValueNode value;
+    @Input private ValueNode offset;
+    private final int displacement;
+
+    public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) {
+        super(StampFactory.illegal());
+        this.object = object;
+        this.value = value;
+        this.offset = offset;
+        this.displacement = displacement;
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, long value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void lower(CiLoweringTool tool) {
+        StructuredGraph graph = (StructuredGraph) this.graph();
+        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
+        WriteNode write = graph.add(new WriteNode(object, value, location));
+        graph.replaceFixedWithFixed(this, write);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectStoreNode.java	Tue May 15 10:03:33 2012 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.hotspot.snippets;
+
+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.max.cri.ci.*;
+
+/**
+ * A special purpose store node that differs from {@link UnsafeStoreNode} in that
+ * it is not a {@link StateSplit} and takes a computed address instead of an object.
+ */
+class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
+    @Input private ValueNode address;
+    @Input private ValueNode value;
+
+    public DirectStoreNode(ValueNode address, ValueNode value) {
+        super(StampFactory.illegal());
+        this.address = address;
+        this.value = value;
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void store(long address, long value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void store(long address, boolean value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        CiValue v = gen.operand(value);
+        gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/GetObjectAddressNode.java	Tue May 15 10:03:33 2012 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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.hotspot.snippets;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
+
+/**
+ * Intrinsification for getting the address of an object.
+ * The code path(s) between a call to {@link #get(Object)} and all uses
+ * of the returned value must be atomic. The only exception to this is
+ * if the usage is not an attempt to dereference the value.
+ */
+class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
+    @Input private ValueNode object;
+
+    public GetObjectAddressNode(ValueNode obj) {
+        super(StampFactory.forKind(CiKind.Long));
+        this.object = obj;
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static long get(Object array) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        CiValue obj = gen.newVariable(gen.target().wordKind);
+        gen.emitMove(gen.operand(object), obj);
+        gen.setResult(this, obj);
+    }
+}