changeset 15603:b7fb36e57da8

made Graal initialization be driven from Java to simplify sequencing and synchronization
author Doug Simon <doug.simon@oracle.com>
date Mon, 12 May 2014 23:27:07 +0200
parents c73df62cbaee
children d556971b409c
files CHANGELOG.md graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.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.truffle.api/src/com/oracle/truffle/api/Truffle.java src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp src/share/vm/prims/jni.cpp src/share/vm/prims/nativeLookup.cpp
diffstat 11 files changed, 121 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Mon May 12 22:37:26 2014 +0200
+++ b/CHANGELOG.md	Mon May 12 23:27:07 2014 +0200
@@ -2,7 +2,7 @@
 
 ## `tip`
 ### Graal
-* ...
+* Made initialization of Graal runtime lazy in hosted mode.
 
 ### Truffle
 * ...
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon May 12 22:37:26 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon May 12 23:27:07 2014 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*;
+import static sun.reflect.Reflection.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -54,9 +55,26 @@
  */
 public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider, StackIntrospection {
 
-    private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime();
+    private static final HotSpotGraalRuntime instance;
+
+    /**
+     * Initializes the native part of the Graal runtime.
+     */
+    private static native void init(Class<?> compilerToVMClass);
+
     static {
+        init(CompilerToVMImpl.class);
+
+        // The options must be processed before any code using them...
+        HotSpotOptions.initialize();
+
+        // ... including code in the constructor
+        instance = new HotSpotGraalRuntime();
+
+        // Why deferred initialization? See comment in completeInitialization().
         instance.completeInitialization();
+
+        registerFieldsToFilter(HotSpotGraalRuntime.class, "instance");
     }
 
     /**
@@ -75,10 +93,6 @@
         return instance;
     }
 
-    static {
-        Reflection.registerFieldsToFilter(HotSpotGraalRuntime.class, "instance");
-    }
-
     /**
      * Do deferred initialization.
      */
@@ -104,6 +118,8 @@
 
         this.vmToCompiler = toCompiler;
         this.compilerToVm = toVM;
+
+        this.vmToCompiler.startRuntime();
     }
 
     // Options must not be directly declared in HotSpotGraalRuntime - see VerifyOptionsPhase
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon May 12 22:37:26 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon May 12 23:27:07 2014 +0200
@@ -87,7 +87,7 @@
             try {
                 for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) {
                     if (!line.startsWith("#")) {
-                        if (!setOption(line)) {
+                        if (!parseOption(line, null)) {
                             throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions);
                         }
                     }
@@ -98,14 +98,39 @@
         }
     }
 
+    /**
+     * Gets the Graal specific options specified to HotSpot (e.g., on the command line).
+     *
+     * @param timeCompilations (out) true if the CITime or CITimeEach HotSpot VM options are set
+     */
+    private static native String[] getVMOptions(boolean[] timeCompilations);
+
     static {
         initializeOptions();
         loadOptionOverrides();
+
+        boolean[] timeCompilations = {false};
+        for (String option : getVMOptions(timeCompilations)) {
+            if (!parseOption(option, null)) {
+                throw new InternalError("Invalid Graal option \"-G:" + option + "\"");
+            }
+        }
+
+        if (timeCompilations[0] || PrintCompRate.getValue() != 0) {
+            unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes");
+            unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime");
+        }
+        assert !Debug.Initialization.isDebugInitialized() : "The class " + Debug.class.getName() + " must not be initialized before the Graal runtime has been initialized. " +
+                        "This can be fixed by placing a call to " + Graal.class.getName() + ".runtime() on the path that triggers initialization of " + Debug.class.getName();
+        if (areDebugScopePatternsEnabled()) {
+            System.setProperty(Debug.Initialization.INITIALIZER_PROPERTY_NAME, "true");
+        }
     }
 
-    // Called from VM code
-    public static boolean setOption(String option) {
-        return parseOption(option, null);
+    /**
+     * Ensures {@link HotSpotOptions} is initialized.
+     */
+    public static void initialize() {
     }
 
     interface OptionConsumer {
@@ -238,24 +263,6 @@
     }
 
     /**
-     * Called from VM code once all Graal command line options have been processed by
-     * {@link #setOption(String)}.
-     *
-     * @param timeCompilations true if the CITime or CITimeEach HotSpot VM options are set
-     */
-    public static void finalizeOptions(boolean timeCompilations) {
-        if (timeCompilations || PrintCompRate.getValue() != 0) {
-            unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes");
-            unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime");
-        }
-        assert !Debug.Initialization.isDebugInitialized() : "The class " + Debug.class.getName() + " must not be initialized before the Graal runtime has been initialized. " +
-                        "This can be fixed by placing a call to " + Graal.class.getName() + ".runtime() on the path that triggers initialization of " + Debug.class.getName();
-        if (areDebugScopePatternsEnabled()) {
-            System.setProperty(Debug.Initialization.INITIALIZER_PROPERTY_NAME, "true");
-        }
-    }
-
-    /**
      * Wraps some given text to one or more lines of a given maximum width.
      *
      * @param text text to wrap
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon May 12 22:37:26 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon May 12 23:27:07 2014 +0200
@@ -30,7 +30,7 @@
  */
 public interface VMToCompiler {
 
-    void startRuntime() throws Throwable;
+    void startRuntime();
 
     void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon May 12 22:37:26 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon May 12 23:27:07 2014 +0200
@@ -142,7 +142,7 @@
         this.runtime = runtime;
     }
 
-    public void startRuntime() throws Throwable {
+    public void startRuntime() {
 
         if (LogFile.getValue() != null) {
             try {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Mon May 12 22:37:26 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Mon May 12 23:27:07 2014 +0200
@@ -33,7 +33,14 @@
 
     private static final TruffleRuntime RUNTIME;
 
-    private static native TruffleRuntime initializeRuntime();
+    /**
+     * Creates a new {@link TruffleRuntime} instance if the runtime has a specialized
+     * implementation.
+     *
+     * @throws UnsatisfiedLinkError if the runtime does not have a specialized implementation of
+     *             {@link TruffleRuntime}
+     */
+    private static native TruffleRuntime createRuntime();
 
     public static TruffleRuntime getRuntime() {
         return RUNTIME;
@@ -42,7 +49,7 @@
     static {
         TruffleRuntime runtime;
         try {
-            runtime = initializeRuntime();
+            runtime = createRuntime();
         } catch (UnsatisfiedLinkError e) {
             runtime = new DefaultTruffleRuntime();
         }
--- a/src/share/vm/graal/graalCompiler.cpp	Mon May 12 22:37:26 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon May 12 23:27:07 2014 +0200
@@ -48,8 +48,6 @@
     return;
   }
 
-  GraalRuntime::initialize();
-
   BufferBlob* buffer_blob = GraalRuntime::initialize_buffer_blob();
   if (!UseGraalCompilationQueue) {
     // This path is used for initialization both by the native queue and the graal queue
@@ -68,7 +66,11 @@
     bool bootstrap = UseGraalCompilationQueue && (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal);
     VMToCompiler::startCompiler(bootstrap);
     _started = true;
+
+    // Graal is considered as application code so we need to
+    // stop the VM deferring compilation now.
     CompilationPolicy::completed_vm_startup();
+
     if (bootstrap) {
       // Avoid -Xcomp and -Xbatch problems by turning on interpreter and background compilation for bootstrapping.
       FlagSetting a(UseInterpreter, true);
--- a/src/share/vm/graal/graalRuntime.cpp	Mon May 12 22:37:26 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon May 12 23:27:07 2014 +0200
@@ -37,97 +37,30 @@
 #include "utilities/debug.hpp"
 
 address GraalRuntime::_external_deopt_i2c_entry = NULL;
-volatile GraalRuntime::State GraalRuntime::_state = uninitialized;
-Thread* GraalRuntime::_initializingThread = NULL;
 
-bool GraalRuntime::should_perform_init() {
-  JavaThread* THREAD = JavaThread::current();
-  if (_state != initialized) {
-    if (THREAD == _initializingThread) {
-      return false;
-    }
-    MutexLocker locker(GraalInitialization_lock);
-    if (_state == uninitialized) {
-      _state = initializing;
-      _initializingThread = THREAD;
-      return true;
-    } else {
-      while (_state == initializing) {
-        GraalInitialization_lock->wait();
-      }
-    }
-  }
-  return false;
-}
-
-void GraalRuntime::initialize() {
-  if (!should_perform_init()) {
-    return;
-  }
-
+void GraalRuntime::initialize_natives(JNIEnv *env, jclass c2vmClass) {
   uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
   uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
   AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"));
   NOT_LP64(error("check TLAB allocation code for address space conflicts"));
 
   JavaThread* THREAD = JavaThread::current();
-  ThreadToNativeFromVM trans(THREAD);
-  TRACE_graal_1("GraalRuntime::initialize");
-
-  JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment();
-  jclass klass = env->FindClass("com/oracle/graal/hotspot/bridge/CompilerToVMImpl");
-  if (klass == NULL) {
-    tty->print_cr("graal CompilerToVMImpl class not found");
-    vm_abort(false);
-  }
-  env->RegisterNatives(klass, CompilerToVM_methods, CompilerToVM_methods_count());
-
-  ResourceMark rm;
-  HandleMark hm;
   {
-    GRAAL_VM_ENTRY_MARK;
-    check_pending_exception("Could not register natives");
-  }
+    ThreadToNativeFromVM trans(THREAD);
 
-  graal_compute_offsets();
-
-  // Ensure _non_oop_bits is initialized
-  Universe::non_oop_word();
-
-  {
-    GRAAL_VM_ENTRY_MARK;
+    ResourceMark rm;
     HandleMark hm;
-    VMToCompiler::initOptions();
-    for (int i = 0; i < Arguments::num_graal_args(); ++i) {
-      const char* arg = Arguments::graal_args_array()[i];
-      Handle option = java_lang_String::create_from_str(arg, THREAD);
-      jboolean result = VMToCompiler::setOption(option);
-      if (!result) {
-        tty->print_cr("Invalid option for graal: -G:%s", arg);
-        vm_abort(false);
-      }
-    }
-    VMToCompiler::finalizeOptions(CITime || CITimeEach);
+
+    graal_compute_offsets();
 
     _external_deopt_i2c_entry = create_external_deopt_i2c();
 
-    VMToCompiler::startRuntime();
-
-    {
-      MutexLocker locker(GraalInitialization_lock);
-      _state = initialized;
-      _initializingThread = NULL;
-    }
+    // Ensure _non_oop_bits is initialized
+    Universe::non_oop_word();
 
-#if !defined(PRODUCT) && !defined(COMPILERGRAAL)
-    // In COMPILERGRAAL, we want to allow GraalBootstrap
-    // to happen first so GraalCompiler::initialize()
-    // duplicates the following code.
-    if (CompileTheWorld) {
-      VMToCompiler::compileTheWorld();
-    }
-#endif
+    env->RegisterNatives(c2vmClass, CompilerToVM_methods, CompilerToVM_methods_count());
   }
+  check_pending_exception("Could not register natives");
 }
 
 BufferBlob* GraalRuntime::initialize_buffer_blob() {
@@ -703,14 +636,32 @@
   }
 JRT_END
 
-// JVM_InitializeGraalRuntime
-JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass))
-  GraalRuntime::initialize();
+// private static GraalRuntime Graal.initializeRuntime()
+JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c))
   return VMToCompiler::get_HotSpotGraalRuntime_jobject();
 JVM_END
 
-// JVM_InitializeTruffleRuntime
-JVM_ENTRY(jobject, JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass))
-  GraalRuntime::initialize();
+// private static TruffleRuntime Truffle.createRuntime()
+JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c))
   return JNIHandles::make_local(VMToCompiler::create_HotSpotTruffleRuntime()());
 JVM_END
+
+// private static void HotSpotGraalRuntime.init(Class compilerToVMClass)
+JVM_ENTRY(void, JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass c2vmClass))
+  GraalRuntime::initialize_natives(env, c2vmClass);
+JVM_END
+
+// private static String[] HotSpotOptions.getVMOptions(boolean[] timeCompilations)
+JVM_ENTRY(jobject, JVM_GetGraalOptions(JNIEnv *env, jclass c, jobject timeCompilations))
+  HandleMark hm;
+  int numOptions = Arguments::num_graal_args();
+  objArrayOop options = oopFactory::new_objArray(SystemDictionary::String_klass(),
+      numOptions, CHECK_NULL);
+  objArrayHandle optionsHandle(THREAD, options);
+  for (int i = 0; i < numOptions; i++) {
+    Handle option = java_lang_String::create_from_str(Arguments::graal_args_array()[i], CHECK_NULL);
+    optionsHandle->obj_at_put(i, option());
+  }
+  ((typeArrayOop) JNIHandles::resolve(timeCompilations))->bool_at_put(0, CITime || CITimeEach);
+  return JNIHandles::make_local(THREAD, optionsHandle());
+JVM_END
--- a/src/share/vm/graal/graalRuntime.hpp	Mon May 12 22:37:26 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Mon May 12 23:27:07 2014 +0200
@@ -33,14 +33,9 @@
 
   static address   _external_deopt_i2c_entry;
 
-  enum State { uninitialized, initializing, initialized };
-  static volatile State _state;
-  static Thread* _initializingThread;
-  static bool should_perform_init();
-
  public:
 
-  static /*synchronized*/ void initialize();
+  static void initialize_natives(JNIEnv *env, jclass c2vmClass);
   static BufferBlob* initialize_buffer_blob();
   static BasicType kindToBasicType(jchar ch);
   static address create_external_deopt_i2c();
--- a/src/share/vm/prims/jni.cpp	Mon May 12 22:37:26 2014 +0200
+++ b/src/share/vm/prims/jni.cpp	Mon May 12 23:27:07 2014 +0200
@@ -35,6 +35,7 @@
 #include "utilities/macros.hpp"
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
+#include "graal/graalVMToCompiler.hpp"
 #endif
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
@@ -5210,7 +5211,19 @@
   #endif
 
     // Check if we should compile all classes on bootclasspath
+#ifdef GRAAL
+#ifndef COMPILERGRAAL
+    if (CompileTheWorld) {
+      // Graal is considered as application code so we need to
+      // stop the VM deferring compilation now.
+      CompilationPolicy::completed_vm_startup();
+
+      VMToCompiler::compileTheWorld();
+    }
+#endif
+#else
     if (CompileTheWorld) ClassLoader::compile_the_world();
+#endif
     if (ReplayCompiles) ciReplay::replay(thread);
 
     // Some platforms (like Win*) need a wrapper around these test
--- a/src/share/vm/prims/nativeLookup.cpp	Mon May 12 22:37:26 2014 +0200
+++ b/src/share/vm/prims/nativeLookup.cpp	Mon May 12 23:27:07 2014 +0200
@@ -124,8 +124,10 @@
   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
 #ifdef GRAAL
-  jobject JNICALL JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass);
-  jobject JNICALL JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass);
+  void    JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass);
+  jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c);
+  jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c);
+  jobject JNICALL JVM_GetGraalOptions(JNIEnv *env, jclass hotspotOptionsClass, jobject timeCompilations);
 #endif
 }
 
@@ -138,8 +140,10 @@
   { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
 #ifdef GRAAL
-  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_InitializeGraalRuntime)      },
-  { CC"Java_com_oracle_truffle_api_Truffle_initializeRuntime",     NULL, FN_PTR(JVM_InitializeTruffleRuntime)    },
+  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime)             },
+  { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",         NULL, FN_PTR(JVM_CreateTruffleRuntime)        },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init",    NULL, FN_PTR(JVM_InitializeGraalNatives)      },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_getVMOptions", NULL, FN_PTR(JVM_GetGraalOptions)             },
 #endif
 };