diff src/share/vm/graal/graalRuntime.cpp @ 18614:c307546c7b0a

made initialization of the Graal class loader and well known Graal classes lazy
author Doug Simon <doug.simon@oracle.com>
date Thu, 04 Dec 2014 13:42:56 +0100
parents ab47ef2f2207
children 0aec14bcf006
line wrap: on
line diff
--- a/src/share/vm/graal/graalRuntime.cpp	Thu Dec 04 13:41:59 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Dec 04 13:42:56 2014 +0100
@@ -49,6 +49,8 @@
   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"));
 
+  ensure_graal_class_loader_is_initialized();
+
   JavaThread* THREAD = JavaThread::current();
   {
     ThreadToNativeFromVM trans(THREAD);
@@ -656,6 +658,13 @@
   return value;
 JRT_END
 
+// private static void Factory.init()
+JVM_ENTRY(void, JVM_InitGraalClassLoader(JNIEnv *env, jclass c, jobject loader_handle))
+  SystemDictionary::init_graal_loader(JNIHandles::resolve(loader_handle));
+  SystemDictionary::WKID scan = SystemDictionary::FIRST_GRAAL_WKID;
+  SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_GRAAL_WKID, scan, CHECK);
+JVM_END
+
 // private static GraalRuntime Graal.initializeRuntime()
 JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c))
   return GraalRuntime::get_HotSpotGraalRuntime_jobject();
@@ -748,6 +757,36 @@
   return result;
 JVM_END
 
+
+void GraalRuntime::ensure_graal_class_loader_is_initialized() {
+  // This initialization code is guarded by a static pointer to the Factory class.
+  // Once it is non-null, the Graal class loader and well know Graal classes are
+  // guaranteed to have been initialized. By going through the static
+  // initializer of Factory, we can rely on class initialization semantics to
+  // synchronize threads racing to do the initialization.
+  static Klass* _FactoryKlass = NULL;
+  if (_FactoryKlass == NULL) {
+    Thread* THREAD = Thread::current();
+    TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", CHECK_ABORT);
+    KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      abort_on_pending_exception(PENDING_EXCEPTION, "Graal classes are not available");
+    }
+    TempNewSymbol field_name = SymbolTable::new_symbol("useGraalClassLoader", CHECK_ABORT);
+
+    fieldDescriptor field_desc;
+    if (klass->find_field(field_name, vmSymbols::bool_signature(), &field_desc) == NULL) {
+      ResourceMark rm;
+      fatal(err_msg("Invalid layout of %s at %s", field_name->as_C_string(), klass->external_name()));
+    }
+    InstanceKlass* ik = InstanceKlass::cast(klass());
+    address addr = ik->static_field_addr(field_desc.offset() - InstanceMirrorKlass::offset_of_static_fields());
+    *((jboolean *) addr) = (jboolean) UseGraalClassLoader;
+    klass->initialize(CHECK_ABORT);
+    _FactoryKlass = klass();
+  }
+}
+
 jint GraalRuntime::check_arguments(TRAPS) {
   KlassHandle nullHandle;
   parse_arguments(nullHandle, THREAD);
@@ -800,6 +839,7 @@
 }
 
 void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) {
+  ensure_graal_class_loader_is_initialized();
   char first = arg[0];
   char* name;
   size_t name_len;
@@ -1017,17 +1057,6 @@
                           thread);
 }
 
-oop GraalRuntime::compute_graal_class_loader(TRAPS) {
-  assert(UseGraalClassLoader, "must be");
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", CHECK_NULL);
-  KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
-
-  TempNewSymbol getClassLoader = SymbolTable::new_symbol("newClassLoader", CHECK_NULL);
-  JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result, klass, getClassLoader, vmSymbols::void_classloader_signature(), CHECK_NULL);
-  return (oop) result.get_jobject();
-}
-
 void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) {
   Thread* THREAD = Thread::current();
   CLEAR_PENDING_EXCEPTION;