# HG changeset patch # User mdoerr # Date 1571680696 -7200 # Node ID 7bbaa3c416e7e35247eaf1f9234e24555712101b # Parent dc1899bb84c0af6059f8b88526a537755123584c 8230459: Test failed to resume JVMCI CompilerThread Reviewed-by: dholmes, kvn diff -r dc1899bb84c0 -r 7bbaa3c416e7 src/hotspot/share/compiler/compileBroker.cpp --- a/src/hotspot/share/compiler/compileBroker.cpp Wed Nov 13 17:24:53 2019 +0800 +++ b/src/hotspot/share/compiler/compileBroker.cpp Mon Oct 21 19:58:16 2019 +0200 @@ -299,7 +299,7 @@ /** * Check if a CompilerThread can be removed and update count if requested. */ -static bool can_remove(CompilerThread *ct, bool do_it) { +bool CompileBroker::can_remove(CompilerThread *ct, bool do_it) { assert(UseDynamicNumberOfCompilerThreads, "or shouldn't be here"); if (!ReduceNumberOfCompilerThreads) return false; @@ -313,13 +313,32 @@ // Keep thread alive for at least some time. if (ct->idle_time_millis() < (c1 ? 500 : 100)) return false; +#if INCLUDE_JVMCI + if (compiler->is_jvmci()) { + // Handles for JVMCI thread objects may get released concurrently. + if (do_it) { + assert(CompileThread_lock->owner() == ct, "must be holding lock"); + } else { + // Skip check if it's the last thread and let caller check again. + return true; + } + } +#endif + // We only allow the last compiler thread of each type to get removed. - jobject last_compiler = c1 ? CompileBroker::compiler1_object(compiler_count - 1) - : CompileBroker::compiler2_object(compiler_count - 1); + jobject last_compiler = c1 ? compiler1_object(compiler_count - 1) + : compiler2_object(compiler_count - 1); if (ct->threadObj() == JNIHandles::resolve_non_null(last_compiler)) { if (do_it) { assert_locked_or_safepoint(CompileThread_lock); // Update must be consistent. compiler->set_num_compiler_threads(compiler_count - 1); +#if INCLUDE_JVMCI + if (compiler->is_jvmci()) { + // Old j.l.Thread object can die when no longer referenced elsewhere. + JNIHandles::destroy_global(compiler2_object(compiler_count - 1)); + _compiler2_objects[compiler_count - 1] = NULL; + } +#endif } return true; } @@ -426,7 +445,7 @@ if (UseDynamicNumberOfCompilerThreads && _first == NULL) { // Still nothing to compile. Give caller a chance to stop this thread. - if (can_remove(CompilerThread::current(), false)) return NULL; + if (CompileBroker::can_remove(CompilerThread::current(), false)) return NULL; } } @@ -842,10 +861,15 @@ char name_buffer[256]; for (int i = 0; i < _c2_count; i++) { + jobject thread_handle = NULL; + // Create all j.l.Thread objects for C1 and C2 threads here, but only one + // for JVMCI compiler which can create further ones on demand. + JVMCI_ONLY(if (!UseJVMCICompiler || !UseDynamicNumberOfCompilerThreads || i == 0) {) // Create a name for our thread. sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); Handle thread_oop = create_thread_oop(name_buffer, CHECK); - jobject thread_handle = JNIHandles::make_global(thread_oop); + thread_handle = JNIHandles::make_global(thread_oop); + JVMCI_ONLY(}) _compiler2_objects[i] = thread_handle; _compiler2_logs[i] = NULL; @@ -912,6 +936,39 @@ (int)(available_cc_np / (128*K))); for (int i = old_c2_count; i < new_c2_count; i++) { +#if INCLUDE_JVMCI + if (UseJVMCICompiler) { + // Native compiler threads as used in C1/C2 can reuse the j.l.Thread + // objects as their existence is completely hidden from the rest of + // the VM (and those compiler threads can't call Java code to do the + // creation anyway). For JVMCI we have to create new j.l.Thread objects + // as they are visible and we can see unexpected thread lifecycle + // transitions if we bind them to new JavaThreads. + if (!THREAD->can_call_java()) break; + char name_buffer[256]; + sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); + Handle thread_oop; + { + // We have to give up the lock temporarily for the Java calls. + MutexUnlocker mu(CompileThread_lock); + thread_oop = create_thread_oop(name_buffer, THREAD); + } + if (HAS_PENDING_EXCEPTION) { + if (TraceCompilerThreads) { + ResourceMark rm; + tty->print_cr("JVMCI compiler thread creation failed:"); + PENDING_EXCEPTION->print(); + } + CLEAR_PENDING_EXCEPTION; + break; + } + // Check if another thread has beaten us during the Java calls. + if (_compilers[1]->num_compiler_threads() != i) break; + jobject thread_handle = JNIHandles::make_global(thread_oop); + assert(compiler2_object(i) == NULL, "Old one must be released!"); + _compiler2_objects[i] = thread_handle; + } +#endif JavaThread *ct = make_thread(compiler2_object(i), _c2_compile_queue, _compilers[1], CHECK); if (ct == NULL) break; _compilers[1]->set_num_compiler_threads(i + 1); diff -r dc1899bb84c0 -r 7bbaa3c416e7 src/hotspot/share/compiler/compileBroker.hpp --- a/src/hotspot/share/compiler/compileBroker.hpp Wed Nov 13 17:24:53 2019 +0800 +++ b/src/hotspot/share/compiler/compileBroker.hpp Mon Oct 21 19:58:16 2019 +0200 @@ -395,6 +395,8 @@ return _compiler2_objects[idx]; } + static bool can_remove(CompilerThread *ct, bool do_it); + static CompileLog* get_log(CompilerThread* ct); static int get_total_compile_count() { return _total_compile_count; }