changeset 15106:6876a4599b7e

create NodeClass for each Node subclass during class initialization of the latter
author Doug Simon <doug.simon@oracle.com>
date Tue, 15 Apr 2014 13:34:29 +0200
parents 4833806209f2
children 1bf700e19e84 de406a971984
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.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/VMToCompiler.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/HotSpotResolvedJavaField.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 src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalVMToCompiler.cpp src/share/vm/graal/graalVMToCompiler.hpp src/share/vm/oops/instanceKlass.cpp
diffstat 16 files changed, 57 insertions(+), 178 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Apr 15 13:34:29 2014 +0200
@@ -26,7 +26,6 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
@@ -36,7 +35,7 @@
 import com.oracle.graal.graph.spi.*;
 
 /**
- * Lazily associated metadata for every {@link Node} type. The metadata includes:
+ * Metadata for every {@link Node} type. The metadata includes:
  * <ul>
  * <li>The offsets of fields annotated with {@link Input} and {@link Successor} as well as methods
  * for iterating over such fields.</li>
@@ -45,72 +44,7 @@
  */
 public final class NodeClass extends FieldIntrospection {
 
-    /**
-     * Maps {@link Class} values (for {@link Node} types) to {@link NodeClass} values.
-     *
-     * Only a single Registry instance can be created. If a runtime creates a specialized registry,
-     * it must do so before the class initializer of {@link NodeClass} is executed.
-     */
-    public static class Registry {
-
-        private static Registry instance;
-
-        /**
-         * Gets the singleton {@link Registry} instance, creating it first if necessary.
-         */
-        static synchronized Registry instance() {
-            if (instance == null) {
-                return new Registry();
-            }
-            return instance;
-        }
-
-        protected Registry() {
-            assert instance == null : "exactly one registry can be created";
-            instance = this;
-        }
-
-        /**
-         * @return the {@link NodeClass} value for {@code key} or {@code null} if no such mapping
-         *         exists
-         */
-        protected NodeClass get(Class<? extends Node> key) {
-            return (NodeClass) allClasses.get(key);
-        }
-
-        /**
-         * Same as {@link #get(Class)} except that a {@link NodeClass} is created if no such mapping
-         * exists. The creation of a {@link NodeClass} must be serialized as
-         * {@link NodeClass#NodeClass(Class)} accesses both {@link FieldIntrospection#allClasses}
-         * and {@link NodeClass#nextIterableId}.
-         * <p>
-         * The fact that {@link ConcurrentHashMap#put} {@link ConcurrentHashMap#get} are used should
-         * make the double-checked locking idiom work in the way {@link NodeClass#get(Class)} uses
-         * this method and {@link #get(Class)}.
-         */
-        final synchronized NodeClass make(Class<? extends Node> key) {
-            NodeClass value = (NodeClass) allClasses.get(key);
-            if (value == null) {
-                value = new NodeClass(key);
-                Object old = allClasses.putIfAbsent(key, value);
-                assert old == null;
-                registered(key, value);
-            }
-            return value;
-        }
-
-        /**
-         * Hook for a subclass to be notified of a new mapping added to the registry.
-         *
-         * @param key
-         * @param value
-         */
-        protected void registered(Class<? extends Node> key, NodeClass value) {
-
-        }
-    }
-
-    private static final Registry registry = Registry.instance();
+    private static final Object GetNodeClassLock = new Object();
 
     /**
      * Gets the {@link NodeClass} associated with a given {@link Class}.
@@ -118,11 +52,22 @@
     @SuppressWarnings("unchecked")
     public static NodeClass get(Class<?> c) {
         Class<? extends Node> key = (Class<? extends Node>) c;
-        NodeClass value = registry.get(key);
-        if (value != null) {
-            return value;
+        NodeClass value = (NodeClass) allClasses.get(key);
+        // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get}
+        // are used makes the double-checked locking idiom work.
+        if (value == null) {
+            // The creation of a NodeClass must be serialized as the NodeClass constructor accesses
+            // both FieldIntrospection.allClasses and NodeClass.nextIterableId.
+            synchronized (GetNodeClassLock) {
+                value = (NodeClass) allClasses.get(key);
+                if (value == null) {
+                    value = new NodeClass(key);
+                    Object old = allClasses.putIfAbsent(key, value);
+                    assert old == null : old + "   " + key;
+                }
+            }
         }
-        return registry.make(key);
+        return value;
     }
 
     public static final int NOT_ITERABLE = -1;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Apr 15 13:34:29 2014 +0200
@@ -284,8 +284,6 @@
 
     Class<?> getJavaMirror(long metaspaceKlass);
 
-    void setNodeClass(Class<?> c, NodeClass nodeClass);
-
     long readUnsafeKlassPointer(Object o);
 
     void doNotInlineOrCompile(long metaspaceMethod);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Apr 15 13:34:29 2014 +0200
@@ -24,7 +24,6 @@
 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.*;
 
@@ -145,9 +144,6 @@
     public native Class<?> getJavaMirror(long metaspaceKlass);
 
     @Override
-    public native void setNodeClass(Class<?> c, NodeClass nodeClass);
-
-    @Override
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Tue Apr 15 12:20:43 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2013, 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.bridge;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.replacements.*;
-
-/**
- * Updates the {@code InstanceKlass::_graal_node_class} field when a {@link NodeClass} is created so
- * that the {@link HotSpotNodeClassSubstitutions} and {@link HotSpotNodeSubstitutions}
- * intrinsifications can read it.
- */
-class FastNodeClassRegistry extends NodeClass.Registry {
-
-    private final CompilerToVM vm;
-
-    public FastNodeClassRegistry(CompilerToVM vm) {
-        this.vm = vm;
-    }
-
-    @SuppressWarnings("unused")
-    static void initialize(CompilerToVM vm) {
-        new FastNodeClassRegistry(vm);
-    }
-
-    @Override
-    protected void registered(Class<? extends Node> key, NodeClass value) {
-        vm.setNodeClass(key, value);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Tue Apr 15 13:34:29 2014 +0200
@@ -38,11 +38,7 @@
 
     void shutdownCompiler() throws Exception;
 
-    /**
-     * @param hostedOnly specifies if the Graal compiler is only being used in hosted mode (i.e., it
-     *            will never compile itself)
-     */
-    void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable;
+    void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
     void bootstrap() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Apr 15 13:34:29 2014 +0200
@@ -142,11 +142,7 @@
         this.runtime = runtime;
     }
 
-    public void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable {
-
-        if (!hostedOnly) {
-            FastNodeClassRegistry.initialize(runtime.getCompilerToVM());
-        }
+    public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         bootstrapRunning = bootstrapEnabled;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Apr 15 13:34:29 2014 +0200
@@ -174,8 +174,6 @@
 
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
-
-                fields.add(metaAccess.lookupJavaField(NodeClass.class.getDeclaredField("registry")));
             } catch (SecurityException | NoSuchFieldException e) {
                 throw new GraalInternalError(e);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Tue Apr 15 13:34:29 2014 +0200
@@ -22,8 +22,6 @@
  */
 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.*;
@@ -33,7 +31,6 @@
 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}.
@@ -61,15 +58,12 @@
         }
     }
 
+    /**
+     * NOTE: A {@link MethodSubstitution} similar to
+     * {@link HotSpotNodeSubstitutions#getNodeClass(Node)} is not possible here because there is no
+     * guarantee that {@code c} is initialized (accessing a Class literal in Java is not a class
+     * initialization barrier).
+     */
     @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);
-
-    }
+    public static native NodeClass get(Class<?> c);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Tue Apr 15 12:20:43 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Tue Apr 15 13:34:29 2014 +0200
@@ -33,16 +33,15 @@
 public class HotSpotNodeSubstitutions {
 
     /**
-     * Partial substitution of {@link Node#getNodeClass()} that returns the value of the
-     * {@code InstanceKlass::_graal_node_class} field if it is non-null.
+     * Gets the value of the {@code InstanceKlass::_graal_node_class} field from the InstanceKlass
+     * pointed to by {@code node}'s header.
      */
     @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);
+    public static NodeClass getNodeClass(final Node node) {
+        // HotSpot creates the NodeClass for each Node subclass while initializing it
+        // so we are guaranteed to read a non-null value here. The fact that NodeClass
+        // is final will automatically make the stamp of the PiNode exact.
+        Word klass = loadHub(node);
+        return piCastNonNull(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
     }
 }
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Tue Apr 15 13:34:29 2014 +0200
@@ -186,6 +186,9 @@
   /* Support for Graal */                                                                                                \
   do_klass(CompilerThread_klass,                  com_oracle_graal_compiler_CompilerThread,                     Opt) \
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
+  /* graal.graph */                                                                                                  \
+  do_klass(Node_klass,                            com_oracle_graal_graph_Node,                                  Opt) \
+  do_klass(NodeClass_klass,                       com_oracle_graal_graph_NodeClass,                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
   do_klass(HotSpotCompiledCode_Comment_klass,     com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,         Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Apr 15 13:34:29 2014 +0200
@@ -292,6 +292,9 @@
   /* Support for Graal */                                                                                                             \
   template(com_oracle_graal_compiler_CompilerThread,                 "com/oracle/graal/compiler/CompilerThread")                      \
   template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
+  /* graal.graph */                                                                                                                   \
+  template(com_oracle_graal_graph_Node,                              "com/oracle/graal/graph/Node")                                   \
+  template(com_oracle_graal_graph_NodeClass,                         "com/oracle/graal/graph/NodeClass")                              \
   /* graal.hotspot */                                                                                                                 \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Tue Apr 15 13:34:29 2014 +0200
@@ -101,12 +101,10 @@
       _external_deopt_i2c_entry = create_external_deopt_i2c();
 #ifdef COMPILERGRAAL
       bool bootstrap = FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal;
-      bool hostedOnly = false;
 #else
       bool bootstrap = false;
-      bool hostedOnly = true;
 #endif
-      VMToCompiler::startCompiler(bootstrap, hostedOnly);
+      VMToCompiler::startCompiler(bootstrap);
       _initialized = true;
       CompilationPolicy::completed_vm_startup();
       if (bootstrap) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Apr 15 13:34:29 2014 +0200
@@ -739,12 +739,6 @@
   return JNIHandles::make_local(klass->java_mirror());
 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))
   oop resolved_o = JNIHandles::resolve(o);
   jlong klass = (jlong)(address)resolved_o->klass();
@@ -1098,7 +1092,6 @@
   {CC"reprofile",                                    CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
   {CC"invalidateInstalledCode",                      CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
   {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
-  {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/graalVMToCompiler.cpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Tue Apr 15 13:34:29 2014 +0200
@@ -144,15 +144,13 @@
   }
 }
 
-void VMToCompiler::startCompiler(jboolean bootstrap_enabled, jboolean hosted_only) {
+void VMToCompiler::startCompiler(jboolean bootstrap_enabled) {
   JavaThread* THREAD = JavaThread::current();
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(instance());
   args.push_int(bootstrap_enabled);
-  args.push_int(hosted_only);
-  TempNewSymbol bool_bool_void = SymbolTable::new_symbol("(ZZ)V", CHECK);
-  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), bool_bool_void, &args, THREAD);
+  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::bool_void_signature(), &args, THREAD);
   check_pending_exception("Error while calling startCompiler");
 }
 
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Tue Apr 15 13:34:29 2014 +0200
@@ -66,8 +66,8 @@
   // public abstract void shutdownCompiler();
   static void shutdownCompiler();
   
-  // public abstract void startCompiler(boolean bootstrapEnabled, boolean hostedOnly);
-  static void startCompiler(jboolean bootstrap_enabled, jboolean hosted_only);
+  // public abstract void startCompiler(boolean bootstrapEnabled);
+  static void startCompiler(jboolean bootstrap_enabled);
   
   // public abstract void bootstrap();
   static void bootstrap();
--- a/src/share/vm/oops/instanceKlass.cpp	Tue Apr 15 12:20:43 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Tue Apr 15 13:34:29 2014 +0200
@@ -1201,6 +1201,18 @@
     JavaValue result(T_VOID);
     JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
   }
+
+#ifdef GRAAL
+  if (this_oop->class_loader() == NULL && this_oop->is_subtype_of(SystemDictionary::Node_klass())) {
+    if (this_oop() != SystemDictionary::Node_klass()) {
+      // Create the NodeClass for a Node subclass.
+      TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/Class;)Lcom/oracle/graal/graph/NodeClass;", CHECK);
+      JavaValue result(T_OBJECT);
+      JavaCalls::call_static(&result, SystemDictionary::NodeClass_klass(), vmSymbols::get_name(), sig, this_oop->java_mirror(), CHECK);
+      this_oop->set_graal_node_class((oop) result.get_jobject());
+    }
+  }
+#endif
 }