changeset 15052:5e6f29f287d6

added InstanceKlass::_graal_node_class field to accelerate Node.getNodeClass()
author Doug Simon <doug.simon@oracle.com>
date Thu, 10 Apr 2014 00:01:30 +0200
parents 2df054b37edc
children 04f1723150b4
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeClassSubstitutionsTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.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/HotSpotConstantReflectionProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NodeClassSubstitutions.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/vmStructs_graal.hpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp
diffstat 19 files changed, 327 insertions(+), 125 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeClassSubstitutionsTest.java	Thu Apr 10 00:01:30 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific substitutions for {@link NodeClass}.
+ */
+public class HotSpotNodeClassSubstitutionsTest extends MethodSubstitutionTest {
+
+    @Test
+    public void test() {
+        test("get", ValueNode.class);
+    }
+
+    public static NodeClass get(Class<?> c) {
+        return NodeClass.get(c);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java	Thu Apr 10 00:01:30 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific substitutions for {@link Node}.
+ */
+public class HotSpotNodeSubstitutionsTest extends MethodSubstitutionTest {
+
+    @Test
+    public void test() {
+        StructuredGraph graph = new StructuredGraph();
+        test("getNodeClass", ConstantNode.forInt(42, graph));
+    }
+
+    public static NodeClass getNodeClass(Node n) {
+        return n.getNodeClass();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Apr 10 00:01:30 2014 +0200
@@ -857,6 +857,7 @@
     @HotSpotVMField(name = "Array<Klass*>::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset;
     @HotSpotVMField(name = "Array<Klass*>::_data[0]", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset;
 
+    @HotSpotVMField(name = "InstanceKlass::_graal_node_class", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int klassNodeClassOffset;
     @HotSpotVMField(name = "InstanceKlass::_source_file_name_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSourceFileNameIndexOffset;
     @HotSpotVMField(name = "InstanceKlass::_init_state", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int klassStateOffset;
     @HotSpotVMField(name = "InstanceKlass::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Apr 10 00:01:30 2014 +0200
@@ -36,7 +36,7 @@
 
     /**
      * Copies the original bytecode of a given method into a given byte array.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      * @param code the array into which to copy the original bytecode
      * @return the value of {@code code}
@@ -49,7 +49,7 @@
 
     /**
      * Determines if a given metaspace Method object has balanced monitors.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object to query
      * @return true if the method has balanced monitors
      */
@@ -63,7 +63,7 @@
      * <li>the method may have a bytecode breakpoint set</li>
      * <li>the method may have other bytecode features that require special handling by the VM</li>
      * </ul>
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object to query
      * @return true if the method can be inlined
      */
@@ -75,7 +75,7 @@
      * <li>a CompileOracle directive may forces inlining of this methods</li>
      * <li>an annotation forces inlining of this method</li>
      * </ul>
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object to query
      * @return true if the method should be inlined
      */
@@ -83,7 +83,7 @@
 
     /**
      * Used to implement {@link ResolvedJavaType#findUniqueConcreteMethod(ResolvedJavaMethod)}.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method on which to based the search
      * @return the metaspace Method result or 0 is there is no unique concrete method for
      *         {@code metaspaceMethod}
@@ -92,7 +92,7 @@
 
     /**
      * Returns the implementor for the given interface class.
-     * 
+     *
      * @param metaspaceKlass the metaspace klass to get the implementor for
      * @return the implementor as metaspace klass pointer or null if there is no implementor
      */
@@ -100,7 +100,7 @@
 
     /**
      * Determines if a given metaspace method is ignored by security stack walks.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      * @return true if the method is ignored
      */
@@ -108,7 +108,7 @@
 
     /**
      * Converts a name to a metaspace klass.
-     * 
+     *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
      * @param accessingClass the context of resolution (may be null)
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
@@ -134,7 +134,7 @@
 
     /**
      * Looks up a class entry in a constant pool.
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @return a metaspace Klass for a resolved method entry, a metaspace Symbol otherwise (with
@@ -144,7 +144,7 @@
 
     /**
      * Looks up a method entry in a constant pool.
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @return a metaspace Method for a resolved method entry, 0 otherwise
@@ -154,12 +154,12 @@
     /**
      * Looks up a field entry in a constant pool and attempts to resolve it. The values returned in
      * {@code info} are:
-     * 
+     *
      * <pre>
      *     [(int) flags,   // only valid if field is resolved
      *      (int) offset]  // only valid if field is resolved
      * </pre>
-     * 
+     *
      * @param metaspaceConstantPool metaspace constant pool pointer
      * @param cpi constant pool index
      * @param info an array in which the details of the field are returned
@@ -221,7 +221,7 @@
 
     /**
      * Installs the result of a compilation into the code cache.
-     * 
+     *
      * @param compiledCode the result of a compilation
      * @param code the details of the installed CodeBlob are written to this object
      * @return the outcome of the installation as a {@link CodeInstallResult}.
@@ -230,7 +230,7 @@
 
     /**
      * Notifies the VM of statistics for a completed compilation.
-     * 
+     *
      * @param id the identifier of the compilation
      * @param method the method compiled
      * @param osr specifies if the compilation was for on-stack-replacement
@@ -257,7 +257,7 @@
     /**
      * Gets the metaspace Method object corresponding to a given {@link Class} object and slot
      * number.
-     * 
+     *
      * @param holder method holder
      * @param slot slot number of the method
      * @return the metaspace Method
@@ -282,7 +282,11 @@
 
     String getFileName(HotSpotResolvedJavaType method);
 
-    Object readUnsafeUncompressedPointer(Object o, long displacement);
+    Class<?> getJavaMirror(long metaspaceKlass);
+
+    NodeClass getNodeClass(Class<?> c);
+
+    void setNodeClass(Class<?> c, NodeClass nodeClass);
 
     long readUnsafeKlassPointer(Object o);
 
@@ -290,7 +294,7 @@
 
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
-     * 
+     *
      * @param metaspaceMethod the metaspace Method object
      */
     void reprofile(long metaspaceMethod);
@@ -311,13 +315,13 @@
 
     /**
      * Gets the names of the supported GPU architectures.
-     * 
+     *
      * @return a comma separated list of names
      */
     String getGPUs();
 
     /**
-     * 
+     *
      * @param metaspaceMethod the method to check
      * @param entryBCI
      * @param level the compilation level
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Apr 10 00:01:30 2014 +0200
@@ -24,6 +24,7 @@
 package com.oracle.graal.hotspot.bridge;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -141,7 +142,13 @@
     public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
 
     @Override
-    public native Object readUnsafeUncompressedPointer(Object o, long displacement);
+    public native Class<?> getJavaMirror(long metaspaceKlass);
+
+    @Override
+    public native NodeClass getNodeClass(Class<?> c);
+
+    @Override
+    public native void setNodeClass(Class<?> c, NodeClass nodeClass);
 
     @Override
     public native long readUnsafeKlassPointer(Object o);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Thu Apr 10 00:01:30 2014 +0200
@@ -23,29 +23,30 @@
 package com.oracle.graal.hotspot.bridge;
 
 import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
 
 /**
- * A fast-path for {@link NodeClass} retrieval using {@link HotSpotResolvedObjectType}.
+ * Direct access to the {@code InstanceKlass::_graal_node_class} field.
  */
 class FastNodeClassRegistry extends NodeClass.Registry {
 
-    @SuppressWarnings("unused")
-    static void initialize() {
-        new FastNodeClassRegistry();
+    private final CompilerToVM vm;
+
+    public FastNodeClassRegistry(CompilerToVM vm) {
+        this.vm = vm;
     }
 
-    private static HotSpotResolvedObjectType type(Class<? extends Node> key) {
-        return (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(key);
+    @SuppressWarnings("unused")
+    static void initialize(CompilerToVM vm) {
+        new FastNodeClassRegistry(vm);
     }
 
     @Override
     public NodeClass get(Class<? extends Node> key) {
-        return type(key).getNodeClass();
+        return vm.getNodeClass(key);
     }
 
     @Override
     protected void registered(Class<? extends Node> key, NodeClass value) {
-        type(key).setNodeClass(value);
+        vm.setNodeClass(key, value);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Apr 10 00:01:30 2014 +0200
@@ -144,7 +144,7 @@
 
     public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
-        FastNodeClassRegistry.initialize();
+        FastNodeClassRegistry.initialize(runtime.getCompilerToVM());
 
         bootstrapRunning = bootstrapEnabled;
 
@@ -250,7 +250,7 @@
 
     /**
      * Take action related to entering a new execution phase.
-     * 
+     *
      * @param phase the execution phase being entered
      */
     protected void phaseTransition(String phase) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Thu Apr 10 00:01:30 2014 +0200
@@ -105,8 +105,15 @@
                 Object o = null;
                 if (baseConstant.getKind() == Kind.Object) {
                     o = unsafe.getObject(base, displacement);
+                } else if (baseConstant instanceof HotSpotMetaspaceConstant) {
+                    Object metaspaceObject = HotSpotMetaspaceConstant.getMetaspaceObject(baseConstant);
+                    if (metaspaceObject instanceof HotSpotResolvedObjectType && initialDisplacement == runtime.getConfig().classMirrorOffset) {
+                        o = ((HotSpotResolvedObjectType) metaspaceObject).mirror();
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere();
+                    }
                 } else {
-                    o = runtime.getCompilerToVM().readUnsafeUncompressedPointer(base, displacement);
+                    throw GraalInternalError.shouldNotReachHere();
                 }
                 return HotSpotObjectConstant.forObject(o);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Apr 10 00:01:30 2014 +0200
@@ -48,11 +48,6 @@
      */
     private final Class<?> javaClass;
 
-    /**
-     * Used for implemented a lazy binding from a {@link Node} type to a {@link NodeClass} value.
-     */
-    private NodeClass nodeClass;
-
     private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
     private HashMap<Long, HotSpotResolvedJavaMethod> methodCache;
     private HotSpotResolvedJavaField[] instanceFields;
@@ -79,7 +74,7 @@
      */
     public static ResolvedJavaType fromMetaspaceKlass(long metaspaceKlass) {
         assert metaspaceKlass != 0;
-        Class javaClass = (Class) runtime().getCompilerToVM().readUnsafeUncompressedPointer(null, metaspaceKlass + runtime().getConfig().classMirrorOffset);
+        Class javaClass = runtime().getCompilerToVM().getJavaMirror(metaspaceKlass);
         assert javaClass != null;
         return fromClass(javaClass);
     }
@@ -750,20 +745,6 @@
         return HotSpotObjectConstant.forObject(Array.newInstance(mirror(), length));
     }
 
-    /**
-     * @return the {@link NodeClass} value (which may be {@code null}) associated with this type
-     */
-    public NodeClass getNodeClass() {
-        return nodeClass;
-    }
-
-    /**
-     * Sets the {@link NodeClass} value associated with this type.
-     */
-    public void setNodeClass(NodeClass nodeClass) {
-        this.nodeClass = nodeClass;
-    }
-
     @Override
     public String toString() {
         String simpleName;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Thu Apr 10 00:01:30 2014 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011, 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.replacements;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.nodes.PiNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Substitutions for improving the performance of {@link NodeClass#get}.
+ */
+@ClassSubstitution(NodeClass.class)
+public class HotSpotNodeClassSubstitutions {
+
+    /**
+     * A macro node for calls to {@link NodeClass#get(Class)}. It can use the compiler's knowledge
+     * about node classes to replace itself with a constant value for a constant {@link Class}
+     * parameter.
+     */
+    public static class NodeClassGetNode extends PureFunctionMacroNode {
+
+        public NodeClassGetNode(Invoke invoke) {
+            super(invoke);
+        }
+
+        @Override
+        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
+            if (param.isNull() || ImmutableCode.getValue()) {
+                return null;
+            }
+            return HotSpotObjectConstant.forObject(NodeClass.get((Class<?>) HotSpotObjectConstant.asObject(param)));
+        }
+    }
+
+    @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class)
+    @MethodSubstitution(isStatic = true)
+    public static NodeClass get(Class<?> c) {
+        Word klass = loadWordFromObject(c, klassOffset());
+        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
+        if (nc != null) {
+            return nc;
+        }
+        return get(c);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Thu Apr 10 00:01:30 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, 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.replacements;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.nodes.PiNode.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.word.*;
+
+@ClassSubstitution(Node.class)
+public class HotSpotNodeSubstitutions {
+
+    /**
+     * Partial substitution of {@link Node#getNodeClass()} that returns the value of the
+     * InstanceKlass::_graal_node_class C++ field if it is non-null.
+     */
+    @MethodSubstitution(isStatic = false)
+    public static NodeClass getNodeClass(final Node thisObj) {
+        Word klass = loadHub(thisObj);
+        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
+        if (nc != null) {
+            return nc;
+        }
+        return getNodeClass(thisObj);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Apr 10 00:01:30 2014 +0200
@@ -556,6 +556,13 @@
         return config().arrayKlassOffset;
     }
 
+    public static final LocationIdentity KLASS_NODE_CLASS = new NamedLocationIdentity("KlassNodeClass");
+
+    @Fold
+    public static int klassNodeClassOffset() {
+        return config().klassNodeClassOffset;
+    }
+
     @Fold
     public static int classMirrorOffset() {
         return config().classMirrorOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Thu Apr 10 00:01:30 2014 +0200
@@ -42,7 +42,8 @@
         replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         replacements.registerSubstitutions(CRC32Substitutions.class);
         replacements.registerSubstitutions(ReflectionSubstitutions.class);
-        replacements.registerSubstitutions(NodeClassSubstitutions.class);
+        replacements.registerSubstitutions(HotSpotNodeClassSubstitutions.class);
+        replacements.registerSubstitutions(HotSpotNodeSubstitutions.class);
         replacements.registerSubstitutions(CompositeValueClassSubstitutions.class);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NodeClassSubstitutions.java	Wed Apr 09 23:48:22 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2011, 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.replacements;
-
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * Substitutions for improving the performance of some critical methods in {@link NodeClass}
- * methods.
- */
-@ClassSubstitution(NodeClass.class)
-public class NodeClassSubstitutions {
-
-    /**
-     * A macro node for calls to {@link NodeClass#get(Class)}. It can use the compiler's knowledge
-     * about node classes to replace itself with a constant value for a constant {@link Class}
-     * parameter.
-     */
-    public static class NodeClassGetNode extends PureFunctionMacroNode {
-
-        public NodeClassGetNode(Invoke invoke) {
-            super(invoke);
-        }
-
-        @Override
-        protected Constant evaluate(Constant param, MetaAccessProvider metaAccess) {
-            if (param.isNull() || ImmutableCode.getValue()) {
-                return null;
-            }
-            return HotSpotObjectConstant.forObject(NodeClass.get((Class<?>) HotSpotObjectConstant.asObject(param)));
-        }
-    }
-
-    @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class)
-    private static native NodeClass get(Class<?> c);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Apr 09 23:48:22 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu Apr 10 00:01:30 2014 +0200
@@ -108,6 +108,10 @@
         return piCast(object, toType, true, true);
     }
 
+    public static <T> T piCastExact(Object object, @ConstantNodeParameter Class<T> toType) {
+        return piCast(object, toType, true, false);
+    }
+
     public static <T> T piCast(Object object, @ConstantNodeParameter Class<T> toType) {
         return piCast(object, toType, false, false);
     }
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 09 23:48:22 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Apr 10 00:01:30 2014 +0200
@@ -727,11 +727,21 @@
   HotSpotInstalledCode::set_codeBlob(hotspotInstalledCode, 0);
 C2V_END
 
+C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv *env, jobject, jlong metaspace_klass))
+  Klass* klass = asKlass(metaspace_klass);
+  return JNIHandles::make_local(klass->java_mirror());
+C2V_END
 
-C2V_VMENTRY(jobject, readUnsafeUncompressedPointer, (JNIEnv *env, jobject, jobject o, jlong offset))
-  oop resolved_o = JNIHandles::resolve(o);
-  address addr = ((address)resolved_o) + offset;
-  return JNIHandles::make_local(*((oop*)addr));
+C2V_VMENTRY(jobject, getNodeClass, (JNIEnv *env, jobject, jobject java_class_handle))
+  oop java_class = JNIHandles::resolve(java_class_handle);
+  InstanceKlass* iklass = (InstanceKlass*) java_lang_Class::as_Klass(java_class);
+  return JNIHandles::make_local(iklass->graal_node_class());
+C2V_END
+
+C2V_VMENTRY(void, setNodeClass, (JNIEnv *env, jobject, jobject java_class_handle, jobject value))
+  oop java_class = JNIHandles::resolve(java_class_handle);
+  InstanceKlass* iklass = (InstanceKlass*) java_lang_Class::as_Klass(java_class);
+  iklass->set_graal_node_class(JNIHandles::resolve(value));
 C2V_END
 
 C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o))
@@ -787,6 +797,7 @@
 #define HS_COMPILED_CODE      "Lcom/oracle/graal/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG             "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
 #define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
+#define NODE_CLASS            "Lcom/oracle/graal/graph/NodeClass;"
 #define METASPACE_KLASS       "J"
 #define METASPACE_METHOD      "J"
 #define METASPACE_METHOD_DATA "J"
@@ -835,7 +846,9 @@
   {CC"getLocalVariableTableLength",                  CC"("METASPACE_METHOD")I",                                        FN_PTR(getLocalVariableTableLength)},
   {CC"reprofile",                                    CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
   {CC"invalidateInstalledCode",                      CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
-  {CC"readUnsafeUncompressedPointer",                CC"("OBJECT"J)"OBJECT,                                            FN_PTR(readUnsafeUncompressedPointer)},
+  {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
+  {CC"getNodeClass",                                 CC"("CLASS")"NODE_CLASS,                                          FN_PTR(getNodeClass)},
+  {CC"setNodeClass",                                 CC"("CLASS NODE_CLASS")V",                                        FN_PTR(setNodeClass)},
   {CC"readUnsafeKlassPointer",                       CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
   {CC"collectCounters",                              CC"()[J",                                                         FN_PTR(collectCounters)},
   {CC"getGPUs",                                      CC"()"STRING,                                                     FN_PTR(getGPUs)},
--- a/src/share/vm/graal/vmStructs_graal.hpp	Wed Apr 09 23:48:22 2014 +0200
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Thu Apr 10 00:01:30 2014 +0200
@@ -31,9 +31,10 @@
 #include "graal/graalEnv.hpp"
 
 #define VM_STRUCTS_GRAAL(nonstatic_field, static_field)                       \
-  nonstatic_field(ThreadShadow, _pending_deoptimization, int)                 \
-  nonstatic_field(ThreadShadow, _pending_failed_speculation, oop)             \
-  nonstatic_field(MethodData,   _graal_node_count, int)                       \
+  nonstatic_field(InstanceKlass, _graal_node_class, oop)                      \
+  nonstatic_field(ThreadShadow,  _pending_deoptimization, int)                \
+  nonstatic_field(ThreadShadow,  _pending_failed_speculation, oop)            \
+  nonstatic_field(MethodData,    _graal_node_count, int)                      \
 
 #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type)                   \
 
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Apr 09 23:48:22 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Apr 10 00:01:30 2014 +0200
@@ -288,6 +288,9 @@
   set_init_state(InstanceKlass::allocated);
   set_init_thread(NULL);
   set_reference_type(rt);
+#ifdef GRAAL
+  set_graal_node_class(NULL);
+#endif
   set_oop_map_cache(NULL);
   set_jni_ids(NULL);
   set_osr_nmethods_head(NULL);
@@ -317,6 +320,12 @@
   set_layout_helper(Klass::instance_layout_helper(0, true));
 }
 
+#ifdef GRAAL
+void InstanceKlass::oops_do(OopClosure* cl) {
+  Klass::oops_do(cl);
+  cl->do_oop(adr_graal_node_class());
+}
+#endif
 
 void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
                                        Array<Method*>* methods) {
@@ -2254,6 +2263,10 @@
   }
   init_implementor();
 
+#ifdef GRAAL
+  set_graal_node_class(NULL);
+#endif
+
   constants()->remove_unshareable_info();
 
   for (int i = 0; i < methods()->length(); i++) {
--- a/src/share/vm/oops/instanceKlass.hpp	Wed Apr 09 23:48:22 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.hpp	Thu Apr 10 00:01:30 2014 +0200
@@ -241,6 +241,10 @@
   Thread*         _init_thread;          // Pointer to current thread doing initialization (to handle recusive initialization)
   int             _vtable_len;           // length of Java vtable (in words)
   int             _itable_len;           // length of Java itable (in words)
+#ifdef GRAAL
+  // com/oracle/graal/graph/NodeClass instance mirroring this class
+  oop             _graal_node_class;
+#endif
   OopMapCache*    volatile _oop_map_cache;   // OopMapCache for all methods in the klass (allocated lazily)
   MemberNameTable* _member_names;        // Member names
   JNIid*          _jni_ids;              // First JNI identifier for static fields in this class
@@ -745,6 +749,16 @@
   void call_class_initializer(TRAPS);
   void set_initialization_state_and_notify(ClassState state, TRAPS);
 
+#ifdef GRAAL
+  // Graal com.oracle.graal.graph.NodeClass mirror
+  oop graal_node_class()           { return _graal_node_class;               }
+  void set_graal_node_class(oop m) { klass_oop_store(&_graal_node_class, m); }
+  oop* adr_graal_node_class()      { return (oop*)&this->_graal_node_class;  }
+
+  // GC support
+  virtual void oops_do(OopClosure* cl);
+#endif
+
   // OopMapCache support
   OopMapCache* oop_map_cache()               { return _oop_map_cache; }
   void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; }