# HG changeset patch # User Doug Simon # Date 1417697290 -3600 # Node ID c2da0aa9e675604470b2cd7ad89be83ce5a00259 # Parent c307546c7b0a3e5d3074b9cf391c71b473037d1e# Parent 20e498cfa409cb1a42bf705dd7fba81bddfb9907 Merge. diff -r 20e498cfa409 -r c2da0aa9e675 graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java --- a/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Thu Dec 04 12:13:27 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Thu Dec 04 13:48:10 2014 +0100 @@ -26,19 +26,31 @@ import java.net.*; /** - * Utility to create a separate class loader for loading classes in {@code graal.jar} and - * {@code graal-truffle.jar}. + * Utility to create and register a separate class loader for loading Graal classes (i.e., those in + * {@code graal.jar} and {@code graal-truffle.jar}). */ public class Factory { /** + * Copy of the {@code UseGraalClassLoader} VM option. Set by the VM before the static + * initializer is called. + */ + private static boolean useGraalClassLoader; + + /** + * Registers the Graal class loader in the VM. + */ + private static native void init(ClassLoader loader); + + static { + init(useGraalClassLoader ? newClassLoader() : null); + } + + /** * Creates a new class loader for loading classes in {@code graal.jar} and - * {@code graal-truffle.jar} - * - * Called from the VM. + * {@code graal-truffle.jar}. */ - @SuppressWarnings("unused") - private static ClassLoader newClassLoader() throws MalformedURLException { + private static ClassLoader newClassLoader() { URL[] urls = {getGraalJarUrl("graal"), getGraalJarUrl("graal-truffle")}; ClassLoader parent = null; return URLClassLoader.newInstance(urls, parent); @@ -47,7 +59,7 @@ /** * Gets the URL for {@code base.jar}. */ - private static URL getGraalJarUrl(String base) throws MalformedURLException { + private static URL getGraalJarUrl(String base) { File file = new File(System.getProperty("java.home")); for (String name : new String[]{"lib", base + ".jar"}) { file = new File(file, name); @@ -57,6 +69,10 @@ throw new InternalError(file + " does not exist"); } - return file.toURI().toURL(); + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + throw new InternalError(e); + } } } diff -r 20e498cfa409 -r c2da0aa9e675 mx/mx_graal.py --- a/mx/mx_graal.py Thu Dec 04 12:13:27 2014 +0100 +++ b/mx/mx_graal.py Thu Dec 04 13:48:10 2014 +0100 @@ -2271,13 +2271,14 @@ assert exists(findbugsJar) nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')] outputDirs = map(mx._cygpathU2W, [p.output_dir() for p in nonTestProjects]) + javaCompliance = max([p.javaCompliance for p in nonTestProjects]) findbugsResults = join(_graal_home, 'findbugs.results') cmd = ['-jar', mx._cygpathU2W(findbugsJar), '-textui', '-low', '-maxRank', '15'] if sys.stdout.isatty(): cmd.append('-progress') cmd = cmd + ['-auxclasspath', mx._separatedCygpathU2W(mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects])), '-output', mx._cygpathU2W(findbugsResults), '-exitcode'] + args + outputDirs - exitcode = mx.run_java(cmd, nonZeroIsFatal=False) + exitcode = mx.run_java(cmd, nonZeroIsFatal=False, javaConfig=mx.java(javaCompliance)) if exitcode != 0: with open(findbugsResults) as fp: mx.log(fp.read()) diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Dec 04 13:48:10 2014 +0100 @@ -96,6 +96,10 @@ oop SystemDictionary::graal_loader() { return _graal_loader; } +void SystemDictionary::init_graal_loader(oop loader) { + assert(UseGraalClassLoader == (loader != NULL), "must be"); + _graal_loader = loader; +} #endif // lazily initialized klass variables @@ -1931,18 +1935,6 @@ } } -#ifdef GRAAL -void SystemDictionary::initialize_preloaded_graal_classes(TRAPS) { - assert(WK_KLASS(Node_klass) == NULL, "preloaded Graal classes should only be initialized once"); - if (UseGraalClassLoader) { - _graal_loader = GraalRuntime::compute_graal_class_loader(CHECK); - } - - WKID scan = FIRST_GRAAL_WKID; - initialize_wk_klasses_through(LAST_GRAAL_WKID, scan, CHECK); -} -#endif - // Tells if a given klass is a box (wrapper class, such as java.lang.Integer). // If so, returns the basic type it holds. If not, returns T_OBJECT. BasicType SystemDictionary::box_klass_type(Klass* k) { diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Dec 04 13:48:10 2014 +0100 @@ -185,7 +185,7 @@ \ /* Support for Graal */ \ do_klass(BitSet_klass, java_util_BitSet, Opt ) \ - /* Graal classes */ \ + /* Graal classes. These are loaded on-demand. */ \ GRAAL_ONLY(do_klass(Node_klass, com_oracle_graal_graph_Node, Graal)) \ GRAAL_ONLY(do_klass(NodeClass_klass, com_oracle_graal_graph_NodeClass, Graal)) \ GRAAL_ONLY(do_klass(HotSpotCompiledCode_klass, com_oracle_graal_hotspot_HotSpotCompiledCode, Graal)) \ @@ -537,6 +537,8 @@ // Returns the Graal loader. This will be NULL if !UseGraalClassLoader // in which case it's equivalent to the boot loader static oop graal_loader(); + // Sets the Graal loader. This is called at most once. + static void init_graal_loader(oop loader); #endif // Compute the default system loader @@ -704,10 +706,6 @@ public: static bool is_ext_class_loader(Handle class_loader); -#ifdef GRAAL - static void initialize_preloaded_graal_classes(TRAPS); -#endif - private: static Klass* find_shared_class(Symbol* class_name); diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Dec 04 13:48:10 2014 +0100 @@ -291,7 +291,6 @@ \ /* Support for Graal */ \ template(java_util_BitSet, "java/util/BitSet") \ - GRAAL_ONLY(template(com_oracle_graal_compiler_CompilerThread, "com/oracle/graal/compiler/CompilerThread")) \ GRAAL_ONLY(template(com_oracle_graal_graph_Node, "com/oracle/graal/graph/Node")) \ GRAAL_ONLY(template(com_oracle_graal_graph_NodeClass, "com/oracle/graal/graph/NodeClass")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotGraalRuntime, "com/oracle/graal/hotspot/HotSpotGraalRuntime")) \ diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Thu Dec 04 13:48:10 2014 +0100 @@ -115,6 +115,7 @@ return; } + GraalRuntime::ensure_graal_class_loader_is_initialized(); HandleMark hm; ResourceMark rm; JavaValue result(T_VOID); diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Thu Dec 04 13:48:10 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; diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Thu Dec 04 13:48:10 2014 +0100 @@ -127,6 +127,11 @@ public: + /** + * Ensures that the Graal class loader is initialized and the well known Graal classes are loaded. + */ + static void ensure_graal_class_loader_is_initialized(); + static void initialize_natives(JNIEnv *env, jclass c2vmClass); static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_initialized; } @@ -200,11 +205,6 @@ */ static Klass* load_required_class(Symbol* name); - /** - * Creates a separate class loader for classes in graal.jar and graal-truffle.jar. - */ - static oop compute_graal_class_loader(TRAPS); - static BufferBlob* initialize_buffer_blob(); /** diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/prims/nativeLookup.cpp Thu Dec 04 13:48:10 2014 +0100 @@ -127,6 +127,7 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL + void JNICALL JVM_InitGraalClassLoader(JNIEnv *env, jclass c, jobject loader); void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass compilerToVMClass); jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c); @@ -148,6 +149,7 @@ { 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_hotspot_loader_Factory_init", NULL, FN_PTR(JVM_InitGraalClassLoader) }, { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, diff -r 20e498cfa409 -r c2da0aa9e675 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Dec 04 12:13:27 2014 +0100 +++ b/src/share/vm/runtime/thread.cpp Thu Dec 04 13:48:10 2014 +0100 @@ -3686,11 +3686,6 @@ // set_init_completed has just been called, causing exceptions not to be shortcut // anymore. We call vm_exit_during_initialization directly instead. SystemDictionary::compute_java_system_loader(THREAD); -#ifdef GRAAL - if (!HAS_PENDING_EXCEPTION) { - SystemDictionary::initialize_preloaded_graal_classes(THREAD); - } -#endif if (HAS_PENDING_EXCEPTION) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); }