changeset 7220:fcae6d960acd

added more compiler intrinsics
author Christian Haeubl <haeubl@ssw.jku.at>
date Tue, 11 Dec 2012 08:28:00 +0100
parents 69b3b2695fea
children 2ae3e26b7e9a
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceMethodSubstitution.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java src/cpu/x86/vm/graalRuntime_x86.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp
diffstat 25 files changed, 1041 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Tue Dec 11 08:28:00 2012 +0100
@@ -64,7 +64,7 @@
         public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
             this.context = context;
             this.subtype = subtype;
-            assert !subtype.isInterface();
+            assert !subtype.isInterface() : subtype.toString() + " : " + context.toString();
         }
 
         @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Tue Dec 11 08:28:00 2012 +0100
@@ -32,6 +32,8 @@
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
+import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*;
+import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*;
 import static com.oracle.graal.lir.amd64.AMD64Call.*;
 
 import com.oracle.graal.api.code.*;
@@ -44,7 +46,6 @@
     public AMD64HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         super(config, graalRuntime);
 
-        HotSpotVMConfig c = config;
         Kind word = graalRuntime.getTarget().wordKind;
 
         addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub,
@@ -78,48 +79,58 @@
                 /* arg0: object */ arg(0, Kind.Object),
                 /* arg1:   lock */ arg(1, word));
 
-        addRuntimeCall(MONITOREXIT, c.monitorExitStub,
+        addRuntimeCall(MONITOREXIT, config.monitorExitStub,
                 /*        temps */ new Register[] {rax, rbx},
                 /*          ret */ ret(Kind.Void),
                 /* arg0: object */ arg(0, Kind.Object),
                 /* arg1:   lock */ arg(1, word));
 
-        addRuntimeCall(NEW_OBJECT_ARRAY, c.newObjectArrayStub,
+        addRuntimeCall(NEW_OBJECT_ARRAY, config.newObjectArrayStub,
                 /*        temps */ new Register[] {rcx, rdi, rsi},
                 /*          ret */ rax.asValue(Kind.Object),
                 /* arg0:    hub */ rdx.asValue(word),
                 /* arg1: length */ rbx.asValue(Kind.Int));
 
-        addRuntimeCall(NEW_TYPE_ARRAY, c.newTypeArrayStub,
+        addRuntimeCall(NEW_TYPE_ARRAY, config.newTypeArrayStub,
                 /*        temps */ new Register[] {rcx, rdi, rsi},
                 /*          ret */ rax.asValue(Kind.Object),
                 /* arg0:    hub */ rdx.asValue(word),
                 /* arg1: length */ rbx.asValue(Kind.Int));
 
-        addRuntimeCall(NEW_INSTANCE, c.newInstanceStub,
+        addRuntimeCall(NEW_INSTANCE, config.newInstanceStub,
                 /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Object),
                 /* arg0:    hub */ rdx.asValue(word));
 
-        addRuntimeCall(NEW_MULTI_ARRAY, c.newMultiArrayStub,
+        addRuntimeCall(NEW_MULTI_ARRAY, config.newMultiArrayStub,
                 /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Object),
                 /* arg0:    hub */ rax.asValue(word),
                 /* arg1:   rank */ rbx.asValue(Kind.Int),
                 /* arg2:   dims */ rcx.asValue(word));
 
-        addRuntimeCall(VERIFY_OOP, c.verifyOopStub,
+        addRuntimeCall(VERIFY_OOP, config.verifyOopStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
                 /* arg0: object */ r13.asValue(Kind.Object));
 
-        addRuntimeCall(VM_ERROR, c.vmErrorStub,
+        addRuntimeCall(VM_ERROR, config.vmErrorStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
                 /* arg0:  where */ arg(0, Kind.Object),
                 /* arg1: format */ arg(1, Kind.Object),
                 /* arg2:  value */ arg(2, Kind.Long));
 
+        addRuntimeCall(IDENTITY_HASHCODE, config.identityHashCodeStub,
+                /*        temps */ null,
+                /*          ret */ rax.asValue(Kind.Int),
+                /* arg0:    obj */ rdx.asValue(Kind.Object));
+
+        addRuntimeCall(THREAD_IS_INTERRUPTED, config.threadIsInterruptedStub,
+                /*        temps */ null,
+                /*          ret */ rax.asValue(Kind.Boolean),
+                /* arg0: thread */ rdx.asValue(Kind.Object),
+      /* arg1: clearInterrupted */ rdx.asValue(Kind.Boolean));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Dec 11 08:28:00 2012 +0100
@@ -36,6 +36,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.snippets.*;
 
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
@@ -240,15 +241,12 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getCapability(Class<T> clazz) {
-        if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class) {
+        if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) {
             return (T) getRuntime();
         }
         if (clazz == GraalCompiler.class) {
             return (T) getCompiler();
         }
-        if (clazz == MetaAccessProvider.class) {
-            return (T) getRuntime();
-        }
         if (clazz == RuntimeInterpreterInterface.class) {
             return (T) getRuntimeInterpreterInterface();
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Dec 11 08:28:00 2012 +0100
@@ -130,6 +130,16 @@
     public int threadObjectOffset;
 
     /**
+     * The value of JavaThread::osthread_offset().
+     */
+    public int osThreadOffset;
+
+    /**
+     * The value of OSThread::interrupted_offset().
+     */
+    public int osThreadInterruptedOffset;
+
+    /**
      * The value of markOopDesc::unlocked_value.
      */
     public int unlockedMask;
@@ -155,6 +165,16 @@
     public int biasedLockPattern;
 
     /**
+     * Identity hash code value when uninitialized.
+     */
+    public int uninitializedIdentityHashCodeValue;
+
+    /**
+     * Mark word right shift to get identity hash code.
+     */
+    public int identityHashCodeShift;
+
+    /**
      * Offset of _access_flags in metaspace Method object.
      */
     public int methodAccessFlagsOffset;
@@ -204,6 +224,26 @@
     public int klassAccessFlagsOffset;
 
     /**
+     * The offset of the _layout_helper field in a Klass.
+     */
+    public int klassLayoutHelperOffset;
+
+    /**
+     * Bit pattern in the klass layout helper that can be used to identify arrays.
+     */
+    public int arrayKlassLayoutHelperIdentifier;
+
+    /**
+     * The offset of the _componentMirror field in an ArrayKlass.
+     */
+    public int arrayKlassComponentMirrorOffset;
+
+    /**
+     * The offset of the _super field in a Klass.
+     */
+    public int klassSuperKlassOffset;
+
+    /**
      * The offset of the injected klass field in a {@link Class}.
      */
     public int klassOffset;
@@ -266,6 +306,8 @@
     public long logPrimitiveStub;
     public long logObjectStub;
     public long logPrintfStub;
+    public long threadIsInterruptedStub;
+    public long identityHashCodeStub;
 
     public void check() {
         assert vmPageSize >= 16;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Dec 11 08:28:00 2012 +0100
@@ -573,7 +573,7 @@
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
-        if (GraalOptions.Intrinsify) {
+        if (GraalOptions.Intrinsify && GraalOptions.IntrinsifyArrayCopy) {
             phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
         }
         return phasePlan;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Dec 11 08:28:00 2012 +0100
@@ -174,7 +174,7 @@
                 }
                 type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass);
             }
-            if (unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) {
+            if (type.isInterface() || unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) {
                 return null;
             }
             return type;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Dec 11 08:28:00 2012 +0100
@@ -29,7 +29,6 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.snippets.SystemSnippets.*;
 import static com.oracle.graal.java.GraphBuilderPhase.*;
-import static com.oracle.graal.nodes.StructuredGraph.*;
 import static com.oracle.graal.nodes.UnwindNode.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.snippets.Log.*;
@@ -70,7 +69,7 @@
 /**
  * HotSpot implementation of {@link GraalCodeCacheProvider}.
  */
-public abstract class HotSpotRuntime implements GraalCodeCacheProvider {
+public abstract class HotSpotRuntime implements GraalCodeCacheProvider, SnippetProvider {
     public final HotSpotVMConfig config;
 
     protected final RegisterConfig regConfig;
@@ -267,9 +266,24 @@
     protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig);
 
     public void installSnippets(SnippetInstaller installer, Assumptions assumptions) {
-        installer.install(SystemSnippets.class);
-        installer.install(UnsafeSnippets.class);
-        installer.install(ArrayCopySnippets.class);
+        if (GraalOptions.IntrinsifyObjectMethods) {
+            installer.install(ObjectSnippets.class);
+        }
+        if (GraalOptions.IntrinsifySystemMethods) {
+            installer.install(SystemSnippets.class);
+        }
+        if (GraalOptions.IntrinsifyThreadMethods) {
+            installer.install(ThreadSnippets.class);
+        }
+        if (GraalOptions.IntrinsifyUnsafeMethods) {
+            installer.install(UnsafeSnippets.class);
+        }
+        if (GraalOptions.IntrinsifyClassMethods) {
+            installer.install(ClassSnippets.class);
+        }
+        if (GraalOptions.IntrinsifyArrayCopy) {
+            installer.install(ArrayCopySnippets.class);
+        }
 
         installer.install(CheckCastSnippets.class);
         installer.install(InstanceOfSnippets.class);
@@ -664,54 +678,6 @@
 
     @Override
     public StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters) {
-        ResolvedJavaType holder = method.getDeclaringClass();
-        String fullName = method.getName() + ((HotSpotSignature) method.getSignature()).asString();
-        Kind wordKind = graalRuntime.getTarget().wordKind;
-        if (MetaUtil.isJavaLangObject(holder)) {
-            if (fullName.equals("getClass()Ljava/lang/Class;")) {
-                ValueNode obj = (ValueNode) parameters.get(0);
-                ObjectStamp stamp = (ObjectStamp) obj.stamp();
-                if (stamp.nonNull() && stamp.isExactType()) {
-                    HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) stamp.type();
-                    StructuredGraph graph = new StructuredGraph();
-                    ValueNode result = ConstantNode.forObject(type.mirror(), this, graph);
-                    ReturnNode ret = graph.add(new ReturnNode(result));
-                    graph.start().setNext(ret);
-                    return graph;
-                }
-                StructuredGraph graph = new StructuredGraph();
-                LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull()));
-                LoadHubNode hub = graph.add(new LoadHubNode(receiver, wordKind));
-                Stamp resultStamp = StampFactory.declaredNonNull(lookupJavaType(Class.class));
-                FloatingReadNode result = graph.unique(new FloatingReadNode(hub, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.classMirrorOffset, graph), null, resultStamp));
-                ReturnNode ret = graph.add(new ReturnNode(result));
-                graph.start().setNext(hub);
-                hub.setNext(ret);
-                return graph;
-            }
-        } else if (holder.equals(lookupJavaType(Class.class))) {
-            if (fullName.equals("getModifiers()I")) {
-                StructuredGraph graph = new StructuredGraph();
-                LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull()));
-                SafeReadNode klass = safeRead(graph, wordKind, receiver, config.klassOffset, StampFactory.forKind(wordKind), INVALID_GRAPH_ID);
-                graph.start().setNext(klass);
-                LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.klassModifierFlagsOffset, graph);
-                FloatingReadNode readModifiers = graph.unique(new FloatingReadNode(klass, location, null, StampFactory.intValue()));
-                CompareNode isZero = CompareNode.createCompareNode(Condition.EQ, klass, ConstantNode.defaultForKind(wordKind, graph));
-                GuardNode guard = graph.unique(new GuardNode(isZero, graph.start(), NullCheckException, InvalidateReprofile, true, INVALID_GRAPH_ID));
-                readModifiers.dependencies().add(guard);
-                ReturnNode ret = graph.add(new ReturnNode(readModifiers));
-                klass.setNext(ret);
-                return graph;
-            }
-        } else if (holder.equals(lookupJavaType(Thread.class))) {
-            if (fullName.equals("currentThread()Ljava/lang/Thread;")) {
-                StructuredGraph graph = new StructuredGraph();
-                ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset, this))));
-                graph.start().setNext(ret);
-                return graph;
-            }
-        }
         return null;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Tue Dec 11 08:28:00 2012 +0100
@@ -33,8 +33,8 @@
 
     private int threadObjectOffset;
 
-    public CurrentThread(int threadObjectOffset, CodeCacheProvider runtime) {
-        super(StampFactory.declaredNonNull(runtime.lookupJavaType(Thread.class)));
+    public CurrentThread(int threadObjectOffset) {
+        super(StampFactory.declaredNonNull(HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaType(Thread.class)));
         this.threadObjectOffset = threadObjectOffset;
     }
 
@@ -45,5 +45,5 @@
     }
 
     @NodeIntrinsic
-    public static native Object get(@ConstantNodeParameter int threadObjectOffset);
+    public static native Thread get(@ConstantNodeParameter int threadObjectOffset);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's {@code graal_identityhashcode} stub.
+ */
+public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable {
+    @Input private final ValueNode object;
+    public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, Kind.Int, Kind.Object);
+
+    public IdentityHashCodeStubCall(ValueNode object) {
+        super(StampFactory.forKind(Kind.Int));
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(IdentityHashCodeStubCall.IDENTITY_HASHCODE);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native int call(Object object);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's ThreadIsInterrupted stub.
+ */
+public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable {
+    @Input private final ValueNode thread;
+    public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, Kind.Boolean, Kind.Object, Kind.Boolean);
+
+    public ThreadIsInterruptedStubCall(ValueNode thread) {
+        super(StampFactory.forKind(Kind.Boolean));
+        this.thread = thread;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(thread));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native boolean call(Thread thread);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,104 @@
+/*
+ * 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 static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.snippets.*;
+
+@ClassSubstitution(java.lang.Class.class)
+public class ClassSnippets implements SnippetsInterface {
+    @InstanceMethodSubstitution
+    public static int getModifiers(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        if (klass == Word.zero()) {
+            return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
+        } else {
+            return loadIntFromWord(klass, klassModifierFlagsOffset());
+        }
+    }
+
+    @InstanceMethodSubstitution
+    public static boolean isInterface(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        if (klass == Word.zero()) {
+            return false;
+        } else {
+            int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+            return (accessFlags & Modifier.INTERFACE) != 0;
+        }
+    }
+
+    @InstanceMethodSubstitution
+    public static boolean isArray(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        if (klass == Word.zero()) {
+            return false;
+        } else {
+            int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+            return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0;
+        }
+    }
+
+    @InstanceMethodSubstitution
+    public static boolean isPrimitive(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        return klass == Word.zero();
+    }
+
+    @InstanceMethodSubstitution
+    public static Class<?> getSuperclass(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        if (klass != Word.zero()) {
+            int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+            if ((accessFlags & Modifier.INTERFACE) == 0) {
+                int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+                if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
+                    return Object.class;
+                } else {
+                    Word superKlass = loadWordFromWord(klass, klassSuperKlassOffset());
+                    if (superKlass == Word.zero()) {
+                        return null;
+                    } else {
+                        return (Class<?>) loadObjectFromWord(superKlass, classMirrorOffset());
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @InstanceMethodSubstitution
+    public static Class<?> getComponentType(final Class<?> thisObj) {
+        Word klass = loadWordFromObject(thisObj, klassOffset());
+        if (klass != Word.zero()) {
+            int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+            if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
+                return (Class<?>) loadObjectFromWord(klass, arrayKlassComponentMirrorOffset());
+            }
+        }
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Dec 11 08:28:00 2012 +0100
@@ -56,6 +56,21 @@
     }
 
     @Fold
+    static int threadObjectOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().threadObjectOffset;
+    }
+
+    @Fold
+    static int osThreadOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().osThreadOffset;
+    }
+
+    @Fold
+    static int osThreadInterruptedOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().osThreadInterruptedOffset;
+    }
+
+    @Fold
     static Kind wordKind() {
         return HotSpotGraalRuntime.getInstance().getTarget().wordKind;
     }
@@ -86,6 +101,46 @@
     }
 
     @Fold
+    static int klassOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().klassOffset;
+    }
+
+    @Fold
+    static int klassModifierFlagsOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().klassModifierFlagsOffset;
+    }
+
+    @Fold
+    static int klassAccessFlagsOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().klassAccessFlagsOffset;
+    }
+
+    @Fold
+    static int klassLayoutHelperOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().klassLayoutHelperOffset;
+    }
+
+    @Fold
+    static int arrayKlassLayoutHelperIdentifier() {
+        return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassLayoutHelperIdentifier;
+    }
+
+    @Fold
+    static int arrayKlassComponentMirrorOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassComponentMirrorOffset;
+    }
+
+    @Fold
+    static int klassSuperKlassOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().klassSuperKlassOffset;
+    }
+
+    @Fold
+    static int classMirrorOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().classMirrorOffset;
+    }
+
+    @Fold
     static int markOffset() {
         return HotSpotGraalRuntime.getInstance().getConfig().markOffset;
     }
@@ -198,6 +253,16 @@
         return HotSpotGraalRuntime.getInstance().getConfig().useBiasedLocking;
     }
 
+    @Fold
+    static int uninitializedIdentityHashCodeValue() {
+        return HotSpotGraalRuntime.getInstance().getConfig().uninitializedIdentityHashCodeValue;
+    }
+
+    @Fold
+    static int identityHashCodeShift() {
+        return HotSpotGraalRuntime.getInstance().getConfig().identityHashCodeShift;
+    }
+
     /**
      * Loads the hub from a object, null checking it first.
      */
@@ -235,6 +300,10 @@
         return loadWordFromWordIntrinsic(address, 0, offset, wordKind());
     }
 
+    static Object loadObjectFromWord(Word address, int offset) {
+        return UnsafeLoadNode.load(address, 0, offset, Kind.Object);
+    }
+
     static Word loadWordFromObject(Object object, int offset) {
         return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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 static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.snippets.*;
+
+@ClassSubstitution(java.lang.Object.class)
+public class ObjectSnippets implements SnippetsInterface {
+    @InstanceMethodSubstitution("getClass")
+    public static Class<?> getClassSnippet(final Object thisObj) {
+        Word hub = loadHub(thisObj);
+        return (Class<?>) loadObjectFromWord(hub, classMirrorOffset());
+    }
+
+    @InstanceMethodSubstitution
+    public static int hashCode(final Object thisObj) {
+        Word mark = loadWordFromObject(thisObj, markOffset());
+
+        // this code is independent from biased locking (although it does not look that way)
+        final Word biasedLock = mark.and(biasedLockMaskInPlace());
+        if (biasedLock.toLong() == unlockedMask()) {
+            int hash = (int) (mark.toLong() >>> identityHashCodeShift());
+            if (hash != uninitializedIdentityHashCodeValue()) {
+                return hash;
+            }
+        }
+
+        return IdentityHashCodeStubCall.call(thisObj);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Tue Dec 11 08:28:00 2012 +0100
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
+import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+
 import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.*;
 
@@ -46,7 +49,25 @@
         return callLong(JAVA_TIME_NANOS);
     }
 
+    public static int identityHashCode(Object x) {
+        if (x == null) {
+            return 0;
+        }
+
+        Word mark = loadWordFromObject(x, markOffset());
+
+        // this code is independent from biased locking (although it does not look that way)
+        final Word biasedLock = mark.and(biasedLockMaskInPlace());
+        if (biasedLock.toLong() == unlockedMask()) {
+            int hash = (int) (mark.toLong() >>> identityHashCodeShift());
+            if (hash != uninitializedIdentityHashCodeValue()) {
+                return hash;
+            }
+        }
+
+        return IdentityHashCodeStubCall.call(x);
+    }
+
     @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true)
     public static native long callLong(@ConstantNodeParameter Descriptor descriptor);
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,51 @@
+/*
+ * 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 static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.snippets.*;
+
+
+@ClassSubstitution(java.lang.Thread.class)
+public class ThreadSnippets implements SnippetsInterface {
+    public static Thread currentThread() {
+        return CurrentThread.get(threadObjectOffset());
+    }
+
+    @InstanceMethodSubstitution
+    @SuppressWarnings("unused")
+    private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
+        Thread thread = CurrentThread.get(threadObjectOffset());
+        if (thisObject == thread) {
+            Word osThread = loadWordFromObject(thisObject, osThreadOffset());
+            boolean interrupted = loadIntFromWord(osThread, osThreadInterruptedOffset()) == 1;
+            if (!interrupted || !clearInterrupted) {
+                return interrupted;
+            }
+        }
+
+        return ThreadIsInterruptedStubCall.call(thisObject);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Tue Dec 11 08:28:00 2012 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Dec 11 08:28:00 2012 +0100
@@ -198,6 +198,15 @@
     public static boolean OptTailDuplication                 = true;
     public static boolean OptEliminatePartiallyRedundantGuards = true;
 
+    // Intrinsification settings
+    public static boolean IntrinsifyArrayCopy                = false;
+    public static boolean IntrinsifyObjectMethods            = true;
+    public static boolean IntrinsifySystemMethods            = true;
+    public static boolean IntrinsifyClassMethods             = true;
+    public static boolean IntrinsifyThreadMethods            = true;
+    public static boolean IntrinsifyUnsafeMethods            = true;
+    public static boolean IntrinsifyMathMethods              = true;
+
     /**
      * Counts the various paths taken through snippets.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,393 @@
+/*
+ * 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.snippets;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+
+public class IntrinsificationTest extends GraalCompilerTest {
+    @Test
+    public void testObjectIntrinsics() {
+        test("getClassSnippet");
+        test("objectHashCodeSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean getClassSnippet(Object obj) {
+        return obj.getClass() == String.class;
+    }
+    @SuppressWarnings("all")
+    public static int objectHashCodeSnippet(A obj) {
+        return obj.hashCode();
+    }
+
+
+    @Test
+    public void testClassIntrinsics() {
+        test("getModifiersSnippet");
+//        test("isInstanceSnippet");
+        test("isInterfaceSnippet");
+        test("isArraySnippet");
+        test("isPrimitiveSnippet");
+        test("getSuperClassSnippet");
+        test("getComponentTypeSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int getModifiersSnippet(Class<?> clazz) {
+        return clazz.getModifiers();
+    }
+    @SuppressWarnings("all")
+    public static boolean isInstanceSnippet(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+    @SuppressWarnings("all")
+    public static boolean isInterfaceSnippet(Class<?> clazz) {
+        return clazz.isInterface();
+    }
+    @SuppressWarnings("all")
+    public static boolean isArraySnippet(Class<?> clazz) {
+        return clazz.isArray();
+    }
+    @SuppressWarnings("all")
+    public static boolean isPrimitiveSnippet(Class<?> clazz) {
+        return clazz.isPrimitive();
+    }
+    @SuppressWarnings("all")
+    public static Class<?> getSuperClassSnippet(Class<?> clazz) {
+        return clazz.getSuperclass();
+    }
+    @SuppressWarnings("all")
+    public static Class<?> getComponentTypeSnippet(Class<?> clazz) {
+        return clazz.getComponentType();
+    }
+
+
+    @Test
+    public void testThreadIntrinsics() {
+        test("currentThreadSnippet");
+        test("threadIsInterruptedSnippet");
+        test("threadInterruptedSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static Thread currentThreadSnippet() {
+        return Thread.currentThread();
+    }
+    @SuppressWarnings("all")
+    public static boolean threadIsInterruptedSnippet(Thread thread) {
+        return thread.isInterrupted();
+    }
+    @SuppressWarnings("all")
+    public static boolean threadInterruptedSnippet() {
+        return Thread.interrupted();
+    }
+
+
+    @Test
+    public void testSystemIntrinsics() {
+        test("systemTimeSnippet");
+        test("systemIdentityHashCode");
+//        test("arraycopySnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static long systemTimeSnippet() {
+        return System.currentTimeMillis() + System.nanoTime();
+    }
+    @SuppressWarnings("all")
+    public static int systemIdentityHashCode(Object obj) {
+        return System.identityHashCode(obj);
+    }
+    @SuppressWarnings("all")
+    public static void arraycopySnippet(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        System.arraycopy(src, srcPos, dest, destPos, length);
+    }
+
+
+    @Test
+    public void testUnsafeIntrinsics() {
+        test("unsafeCompareAndSwapIntSnippet");
+        test("unsafeCompareAndSwapLongSnippet");
+        test("unsafeCompareAndSwapObjectSnippet");
+
+        test("unsafeGetBooleanSnippet");
+        test("unsafeGetByteSnippet");
+        test("unsafeGetShortSnippet");
+        test("unsafeGetCharSnippet");
+        test("unsafeGetIntSnippet");
+        test("unsafeGetFloatSnippet");
+        test("unsafeGetDoubleSnippet");
+        test("unsafeGetObjectSnippet");
+
+        test("unsafePutBooleanSnippet");
+        test("unsafePutByteSnippet");
+        test("unsafePutShortSnippet");
+        test("unsafePutCharSnippet");
+        test("unsafePutIntSnippet");
+        test("unsafePutFloatSnippet");
+        test("unsafePutDoubleSnippet");
+        test("unsafePutObjectSnippet");
+
+        // test("unsafeDirectMemoryReadSnippet");
+        // test("unsafeDirectMemoryWriteSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapIntSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapLongSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapObjectSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeGetBooleanSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getBoolean(obj, offset) &&
+               unsafe.getBooleanVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetByteSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getByte(obj, offset) +
+               unsafe.getByteVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetShortSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getShort(obj, offset) +
+               unsafe.getShortVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetCharSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getChar(obj, offset) +
+               unsafe.getCharVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetIntSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getInt(obj, offset) +
+               unsafe.getIntVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static long unsafeGetLongSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getLong(obj, offset) +
+               unsafe.getLongVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static float unsafeGetFloatSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getFloat(obj, offset) +
+               unsafe.getFloatVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static double unsafeGetDoubleSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getDouble(obj, offset) +
+               unsafe.getDoubleVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeGetObjectSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutBooleanSnippet(Unsafe unsafe, Object obj, long offset, boolean value) {
+        unsafe.putBoolean(obj, offset, value);
+        unsafe.putBooleanVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutByteSnippet(Unsafe unsafe, Object obj, long offset, byte value) {
+        unsafe.putByte(obj, offset, value);
+        unsafe.putByteVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutShortSnippet(Unsafe unsafe, Object obj, long offset, short value) {
+        unsafe.putShort(obj, offset, value);
+        unsafe.putShortVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutCharSnippet(Unsafe unsafe, Object obj, long offset, char value) {
+        unsafe.putChar(obj, offset, value);
+        unsafe.putCharVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutIntSnippet(Unsafe unsafe, Object obj, long offset, int value) {
+        unsafe.putInt(obj, offset, value);
+        unsafe.putIntVolatile(obj, offset, value);
+        unsafe.putOrderedInt(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutLongSnippet(Unsafe unsafe, Object obj, long offset, long value) {
+        unsafe.putLong(obj, offset, value);
+        unsafe.putLongVolatile(obj, offset, value);
+        unsafe.putOrderedLong(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutFloatSnippet(Unsafe unsafe, Object obj, long offset, float value) {
+        unsafe.putFloat(obj, offset, value);
+        unsafe.putFloatVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutDoubleSnippet(Unsafe unsafe, Object obj, long offset, double value) {
+        unsafe.putDouble(obj, offset, value);
+        unsafe.putDoubleVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutObjectSnippet(Unsafe unsafe, Object obj, long offset, Object value) {
+        unsafe.putObject(obj, offset, value);
+        unsafe.putObjectVolatile(obj, offset, value);
+        unsafe.putOrderedObject(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static double unsafeDirectMemoryReadSnippet(Unsafe unsafe, long address) {
+        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
+        return unsafe.getByte(address) +
+               unsafe.getShort(address) +
+               unsafe.getChar(address) +
+               unsafe.getInt(address) +
+               unsafe.getLong(address) +
+               unsafe.getFloat(address) +
+               unsafe.getDouble(address);
+    }
+    @SuppressWarnings("all")
+    public static void unsafeDirectMemoryWriteSnippet(Unsafe unsafe, long address, byte value) {
+        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
+        unsafe.putByte(address, value);
+        unsafe.putShort(address, value);
+        unsafe.putChar(address, (char) value);
+        unsafe.putInt(address, value);
+        unsafe.putLong(address, value);
+        unsafe.putFloat(address, value);
+        unsafe.putDouble(address, value);
+    }
+
+
+    @Test
+    public void testMathIntrinsics() {
+        test("mathSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static double mathSnippet(double value) {
+        return Math.abs(value) +
+               Math.sqrt(value) +
+               Math.log(value) +
+               Math.log10(value) +
+               Math.sin(value) +
+               Math.cos(value) +
+               Math.tan(value);
+//               Math.exp(value) +
+//               Math.pow(value, 13);
+    }
+
+
+    @Test
+    public void testIntegerIntrinsics() {
+        // TODO (chaeubl): some methods have Java implementations -> check more than Invoke nodes
+        test("integerSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int integerSnippet(int value) {
+        return Integer.reverseBytes(value) +
+               Integer.numberOfLeadingZeros(value) +
+               Integer.numberOfTrailingZeros(value);
+    }
+
+
+    @Test
+    public void testLongIntrinsics() {
+        test("longSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static long longSnippet(long value) {
+        return Long.reverseBytes(value) +
+               Long.numberOfLeadingZeros(value) +
+               Long.numberOfTrailingZeros(value);
+    }
+
+
+    @Test
+    public void testFloatIntrinsics() {
+        test("floatSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static float floatSnippet(float value) {
+        return Float.intBitsToFloat(Float.floatToIntBits(value));
+    }
+
+
+    @Test
+    public void testDoubleIntrinsics() {
+        test("doubleSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static double doubleSnippet(double value) {
+        return Double.longBitsToDouble(Double.doubleToLongBits(value));
+    }
+
+
+    private StructuredGraph test(final String snippet) {
+        return Debug.scope("IntrinsificationTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                PhasePlan phasePlan = getDefaultPhasePlan();
+                Assumptions assumptions = new Assumptions(true);
+                Debug.dump(graph, "Graph");
+                new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                Debug.dump(graph, "Graph");
+                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                assertNoInvokes(graph);
+                return graph;
+            }
+        });
+    }
+
+    private static boolean assertNoInvokes(StructuredGraph graph) {
+        for (Invoke invoke: graph.getInvokes()) {
+            fail(invoke.toString());
+        }
+        return false;
+    }
+
+    private static class A {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceMethodSubstitution.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,34 @@
+/*
+ * 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.snippets;
+
+import java.lang.annotation.*;
+
+/**
+ * Denotes a method that substitutes a method of another class.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface InstanceMethodSubstitution {
+    String value() default "";
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Dec 06 13:53:36 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Dec 11 08:28:00 2012 +0100
@@ -91,7 +91,7 @@
                     throw new RuntimeException("Snippet must not be abstract or native");
                 }
                 ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
-                assert snippet.getCompilerStorage().get(Graph.class) == null;
+                assert snippet.getCompilerStorage().get(Graph.class) == null : method;
                 StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
                 //System.out.println("snippet: " + graph);
                 snippet.getCompilerStorage().put(Graph.class, graph);
@@ -105,7 +105,19 @@
                 continue;
             }
             try {
-                Method originalMethod = originalClazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
+                InstanceMethodSubstitution methodSubstitution = method.getAnnotation(InstanceMethodSubstitution.class);
+                String originalName = method.getName();
+                Class<?>[] originalParameters = method.getParameterTypes();
+                if (methodSubstitution != null) {
+                    if (!methodSubstitution.value().isEmpty()) {
+                        originalName = methodSubstitution.value();
+                    }
+                    assert originalParameters.length >= 1 : "must be a static method with the this object as its first parameter";
+                    Class<?>[] newParameters = new Class<?>[originalParameters.length - 1];
+                    System.arraycopy(originalParameters, 1, newParameters, 0, newParameters.length);
+                    originalParameters = newParameters;
+                }
+                Method originalMethod = originalClazz.getDeclaredMethod(originalName, originalParameters);
                 if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) {
                     throw new RuntimeException("Snippet has incompatible return type");
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,30 @@
+/*
+ * 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.snippets;
+
+import com.oracle.graal.api.code.*;
+
+
+public interface SnippetProvider {
+    void installSnippets(SnippetInstaller installer, Assumptions assumptions);
+}
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Thu Dec 06 13:53:36 2012 +0100
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Tue Dec 11 08:28:00 2012 +0100
@@ -1179,6 +1179,35 @@
       break;
     }
 
+    case graal_identity_hash_code_id: {
+      Register obj = j_rarg0; // Incoming
+      __ set_info("identity_hash_code", dont_gc_arguments);
+      __ enter();
+      OopMap* map = save_live_registers(sasm, 1);
+      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_identity_hash_code), obj);
+      oop_maps = new OopMapSet();
+      oop_maps->add_gc_map(call_offset, map);
+      restore_live_registers_except_rax(sasm);
+      __ leave();
+      __ ret(0);
+      break;
+    }
+    case graal_thread_is_interrupted_id: {
+      Register thread = j_rarg0;
+      Register clear_interrupted = j_rarg1;
+
+      __ set_info("identity_hash_code", dont_gc_arguments);
+      __ enter();
+      OopMap* map = save_live_registers(sasm, 1);
+      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_thread_is_interrupted), thread, clear_interrupted);
+      oop_maps = new OopMapSet();
+      oop_maps->add_gc_map(call_offset, map);
+      restore_live_registers_except_rax(sasm);
+      __ leave();
+      __ ret(0);
+      break;
+    }
+
     default:
       { GraalStubFrame f(sasm, "unimplemented entry", dont_gc_arguments);
         __ movptr(rax, (int)id);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Dec 06 13:53:36 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Dec 11 08:28:00 2012 +0100
@@ -630,6 +630,8 @@
   set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset()));
   set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset()));
   set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset()));
+  set_int(env, config, "osThreadOffset", in_bytes(JavaThread::osthread_offset()));
+  set_int(env, config, "osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset()));
   set_int(env, config, "unlockedMask", (int) markOopDesc::unlocked_value);
   set_int(env, config, "biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place);
   set_int(env, config, "ageMaskInPlace", (int) markOopDesc::age_mask_in_place);
@@ -648,6 +650,8 @@
   set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
   set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
   set_int(env, config, "klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset()));
+  set_int(env, config, "klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
+  set_int(env, config, "klassSuperKlassOffset", in_bytes(Klass::super_offset()));
   set_int(env, config, "klassOffset", java_lang_Class::klass_offset_in_bytes());
   set_int(env, config, "graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes());
   set_int(env, config, "methodDataOffset", in_bytes(Method::method_data_offset()));
@@ -655,6 +659,12 @@
   set_int(env, config, "methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset()));
   set_int(env, config, "basicLockSize", sizeof(BasicLock));
   set_int(env, config, "basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes());
+  set_int(env, config, "uninitializedIdentityHashCodeValue", markOopDesc::no_hash);
+  set_int(env, config, "identityHashCodeShift", markOopDesc::hash_shift);
+
+  set_int(env, config, "arrayKlassLayoutHelperIdentifier", 0x80000000);
+  assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set");
+  set_int(env, config, "arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset()));
   
   set_int(env, config, "metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes());
   set_int(env, config, "metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes());
@@ -699,6 +709,8 @@
   set_long(env, config, "logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id)));
   set_long(env, config, "logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id)));
   set_long(env, config, "logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id)));
+  set_long(env, config, "identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id)));
+  set_long(env, config, "threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id)));
 
 
   BarrierSet* bs = Universe::heap()->barrier_set();
--- a/src/share/vm/graal/graalRuntime.cpp	Thu Dec 06 13:53:36 2012 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Tue Dec 11 08:28:00 2012 +0100
@@ -595,6 +595,23 @@
   }
 JRT_END
 
+JRT_ENTRY(jint, GraalRuntime::graal_identity_hash_code(JavaThread* thread, oop obj))
+  return (jint) obj->identity_hash();
+JRT_END
+
+JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted))
+  // TEMP:
+  tty->print_cr("ThreadIsInterruptedSlowCase");
+
+  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
+  Handle receiverHandle(thread, receiver);
+  JRT_BLOCK
+    MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
+    JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
+    return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+  JRT_BLOCK_END
+JRT_END
+
 // JVM_InitializeGraalRuntime
 JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass))
   return VMToCompiler::graalRuntimePermObject();
--- a/src/share/vm/graal/graalRuntime.hpp	Thu Dec 06 13:53:36 2012 +0100
+++ b/src/share/vm/graal/graalRuntime.hpp	Tue Dec 11 08:28:00 2012 +0100
@@ -99,6 +99,8 @@
   stub(graal_log_object)              \
   stub(graal_log_printf)              \
   stub(graal_log_primitive)           \
+  stub(graal_identity_hash_code)      \
+  stub(graal_thread_is_interrupted)   \
   last_entry(number_of_ids)
 
 #define DECLARE_STUB_ID(x)       x ## _id ,
@@ -144,6 +146,9 @@
   static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value);
   static void graal_log_printf(JavaThread* thread, oop format, jlong value);
   static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+  
+  static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd);
+  static jboolean graal_thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte);
 
   // Note: Must be kept in sync with constants in com.oracle.graal.snippets.Log
   enum {