src/share/vm/compiler/compileBroker.cpp

Print this page

        

*** 184,194 **** CompileQueue* CompileBroker::_c2_method_queue = NULL; CompileQueue* CompileBroker::_c1_method_queue = NULL; CompileTask* CompileBroker::_task_free_list = NULL; ! GrowableArray<CompilerThread*>* CompileBroker::_method_threads = NULL; class CompilationLog : public StringEventLog { public: CompilationLog() : StringEventLog("Compilation events") { --- 184,194 ---- CompileQueue* CompileBroker::_c2_method_queue = NULL; CompileQueue* CompileBroker::_c1_method_queue = NULL; CompileTask* CompileBroker::_task_free_list = NULL; ! GrowableArray<CompilerThread*>* CompileBroker::_compiler_threads = NULL; class CompilationLog : public StringEventLog { public: CompilationLog() : StringEventLog("Compilation events") {
*** 585,597 **** log->mark_file_end(); } - // ------------------------------------------------------------------ - // CompileQueue::add - // // Add a CompileTask to a CompileQueue void CompileQueue::add(CompileTask* task) { assert(lock()->owned_by_self(), "must own lock"); task->set_next(NULL); --- 585,594 ----
*** 624,633 **** --- 621,640 ---- // Notify CompilerThreads that a task is available. lock()->notify_all(); } + void CompileQueue::delete_all() { + assert(lock()->owned_by_self(), "must own lock"); + if (_first != NULL) { + for (CompileTask* task = _first; task != NULL; task = task->next()) { + delete task; + } + _first = NULL; + } + } + // ------------------------------------------------------------------ // CompileQueue::get // // Get the next CompileTask from a CompileQueue CompileTask* CompileQueue::get() {
*** 638,647 **** --- 645,659 ---- // having no compile jobs: First, we compiled everything we wanted. Second, // we ran out of code cache so compilation has been disabled. In the latter // case we perform code cache sweeps to free memory such that we can re-enable // compilation. while (_first == NULL) { + // Exit loop if compilation is disabled forever + if (CompileBroker::is_compilation_disabled_forever()) { + return NULL; + } + if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs()) { // Wait a certain amount of time to possibly do another sweep. // We must wait until stack scanning has happened so that we can // transition a method's state from 'not_entrant' to 'zombie'. long wait_time = NmethodSweepCheckInterval * 1000;
*** 662,674 **** // (i.e., there is enough free space in the code cache) there is // no need to invoke the sweeper. As a result, the hotness of methods // remains unchanged. This behavior is desired, since we want to keep // the stable state, i.e., we do not want to evict methods from the // code cache if it is unnecessary. ! lock()->wait(); } } CompileTask* task = CompilationPolicy::policy()->select_task(this); remove(task); return task; } --- 674,691 ---- // (i.e., there is enough free space in the code cache) there is // no need to invoke the sweeper. As a result, the hotness of methods // remains unchanged. This behavior is desired, since we want to keep // the stable state, i.e., we do not want to evict methods from the // code cache if it is unnecessary. ! lock()->wait(!Mutex::_no_safepoint_check_flag, 5*1000); } } + + if (CompileBroker::is_compilation_disabled_forever()) { + return NULL; + } + CompileTask* task = CompilationPolicy::policy()->select_task(this); remove(task); return task; }
*** 889,902 **** _initialized = true; } ! ! // ------------------------------------------------------------------ ! // CompileBroker::make_compiler_thread ! CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, TRAPS) { CompilerThread* compiler_thread = NULL; Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_0); --- 906,917 ---- _initialized = true; } ! CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, ! AbstractCompiler* comp, TRAPS) { CompilerThread* compiler_thread = NULL; Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_0);
*** 959,968 **** --- 974,984 ---- os::set_native_priority(compiler_thread, native_prio); java_lang_Thread::set_daemon(thread_oop()); compiler_thread->set_threadObj(thread_oop()); + compiler_thread->set_compiler(comp); Threads::add(compiler_thread); Thread::start(compiler_thread); } // Let go of Threads_lock before yielding
*** 970,1020 **** return compiler_thread; } - // ------------------------------------------------------------------ - // CompileBroker::init_compiler_threads - // - // Initialize the compilation queue void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; #if !defined(ZERO) && !defined(SHARK) assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); #endif // !ZERO && !SHARK if (c2_compiler_count > 0) { _c2_method_queue = new CompileQueue("C2MethodQueue", MethodCompileQueue_lock); } if (c1_compiler_count > 0) { _c1_method_queue = new CompileQueue("C1MethodQueue", MethodCompileQueue_lock); } int compiler_count = c1_compiler_count + c2_compiler_count; ! _method_threads = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true); char name_buffer[256]; for (int i = 0; i < c2_compiler_count; i++) { // Create a name for our thread. sprintf(name_buffer, "C2 CompilerThread%d", i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); ! CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, CHECK); ! _method_threads->append(new_thread); } for (int i = c2_compiler_count; i < compiler_count; i++) { // Create a name for our thread. sprintf(name_buffer, "C1 CompilerThread%d", i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); ! CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, CHECK); ! _method_threads->append(new_thread); } if (UsePerfData) { ! PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, ! compiler_count, CHECK); } } // Set the methods on the stack as on_stack so that redefine classes doesn't --- 986,1036 ---- return compiler_thread; } void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; #if !defined(ZERO) && !defined(SHARK) assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); #endif // !ZERO && !SHARK + // Initialize the compilation queue if (c2_compiler_count > 0) { _c2_method_queue = new CompileQueue("C2MethodQueue", MethodCompileQueue_lock); + _compilers[1]->set_num_compiler_threads(c2_compiler_count); } if (c1_compiler_count > 0) { _c1_method_queue = new CompileQueue("C1MethodQueue", MethodCompileQueue_lock); + _compilers[0]->set_num_compiler_threads(c1_compiler_count); } int compiler_count = c1_compiler_count + c2_compiler_count; ! _compiler_threads = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true); char name_buffer[256]; for (int i = 0; i < c2_compiler_count; i++) { // Create a name for our thread. sprintf(name_buffer, "C2 CompilerThread%d", i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); ! // Shark and C2 ! CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, _compilers[1], CHECK); ! _compiler_threads->append(new_thread); } for (int i = c2_compiler_count; i < compiler_count; i++) { // Create a name for our thread. sprintf(name_buffer, "C1 CompilerThread%d", i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); ! // C1 ! CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, _compilers[0], CHECK); ! _compiler_threads->append(new_thread); } if (UsePerfData) { ! PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, compiler_count, CHECK); } } // Set the methods on the stack as on_stack so that redefine classes doesn't
*** 1027,1057 **** _c1_method_queue->mark_on_stack(); } } // ------------------------------------------------------------------ - // CompileBroker::is_idle - bool CompileBroker::is_idle() { - if (_c2_method_queue != NULL && !_c2_method_queue->is_empty()) { - return false; - } else if (_c1_method_queue != NULL && !_c1_method_queue->is_empty()) { - return false; - } else { - int num_threads = _method_threads->length(); - for (int i=0; i<num_threads; i++) { - if (_method_threads->at(i)->task() != NULL) { - return false; - } - } - - // No pending or active compilations. - return true; - } - } - - - // ------------------------------------------------------------------ // CompileBroker::compile_method // // Request compilation of a method. void CompileBroker::compile_method_base(methodHandle method, int osr_bci, --- 1043,1052 ----
*** 1549,1566 **** // waiting on a CompileTask, we know that no one else will // be using this CompileTask; we can free it. free_task(task); } // ------------------------------------------------------------------ // CompileBroker::compiler_thread_loop // // The main loop run by a CompilerThread. void CompileBroker::compiler_thread_loop() { CompilerThread* thread = CompilerThread::current(); CompileQueue* queue = thread->queue(); - // For the thread that initializes the ciObjectFactory // this resource mark holds all the shared objects ResourceMark rm; // First thread to get here will initialize the compiler interface --- 1544,1661 ---- // waiting on a CompileTask, we know that no one else will // be using this CompileTask; we can free it. free_task(task); } + // Initialize compiler thread(s) + compiler object(s). + bool CompileBroker::init_compiler_runtime() { + CompilerThread* thread = CompilerThread::current(); + AbstractCompiler* comp = thread->compiler(); + // Final sanity check - the compiler object must exist + guarantee(comp != NULL, "Compiler object must exist"); + + int system_dictionary_modification_counter; + { + MutexLocker locker(Compile_lock, thread); + system_dictionary_modification_counter = SystemDictionary::number_of_modifications(); + } + + { + // Must switch to native to allocate ci_env + ThreadToNativeFromVM ttn(thread); + ciEnv ci_env(NULL, system_dictionary_modification_counter); + // Cache Jvmti state + ci_env.cache_jvmti_state(); + // Cache DTrace flags + ci_env.cache_dtrace_flags(); + + // Switch back to VM state to to compiler initialization + ThreadInVMfromNative tv(thread); + ResetNoHandleMark rnhm; + + if (!comp->is_shark()) { + // Perform per-thread and global initializations + comp->initialize(); + } + } + + if (comp->should_exit()) { + disable_compilation_forever(); + // If compiler initialization failed, no compiler thread that is specific to a + // particular compiler runtime will ever start to compile methods. + + shutdown_compiler_runtime(comp, thread); + return false; + } + + // C1 specific check + if ((comp->is_c1()) && (thread->get_buffer_blob() == NULL)) { + warning("Initialization of %s thread failed (no space to run compilers)", thread->name()); + return false; + } + + return true; + } + + // If C1 and/or C2 initialization failed, we shut down all compilation. + // We do this to keep things simple. This can be changed if it ever turns out to be + // a problem. + void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread) { + // Free buffer blob, if allocated + if (thread->get_buffer_blob() != NULL) { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::free(thread->get_buffer_blob()); + } + + if (comp->should_perform_shutdown()) { + // There are two reasons for shutting down the compiler + // 1) compiler runtime initialization failed + // 2) The code cache is full and the following flag is set: -XX:-UseCodeCacheFlushing + warning("Shutting down compiler %s (no space to run compilers)", comp->name()); + + // Only one thread per compiler runtime object enters here + // Set state to shut down + comp->set_shut_down(); + + MutexLocker mu(MethodCompileQueue_lock, thread); + CompileQueue* queue; + if (_c1_method_queue != NULL) { + _c1_method_queue->delete_all(); + queue = _c1_method_queue; + _c1_method_queue = NULL; + delete _c1_method_queue; + } + + if (_c2_method_queue != NULL) { + _c2_method_queue->delete_all(); + queue = _c2_method_queue; + _c2_method_queue = NULL; + delete _c2_method_queue; + } + + // We could delete compiler runtimes also. However, there are references to + // the compiler runtime(s) (e.g., nmethod::is_compiled_by_c1()) which then + // fail. This can be done later if necessary. + /*if ((comp->is_c1()) && (_compilers[0] != NULL)) { + delete _compilers[0]; + _compilers[0] = NULL; + } + + if ((comp->is_c2()) && (_compilers[1] != NULL)) { + delete _compilers[1]; + _compilers[1] = NULL; + }*/ + } + } + // ------------------------------------------------------------------ // CompileBroker::compiler_thread_loop // // The main loop run by a CompilerThread. void CompileBroker::compiler_thread_loop() { CompilerThread* thread = CompilerThread::current(); CompileQueue* queue = thread->queue(); // For the thread that initializes the ciObjectFactory // this resource mark holds all the shared objects ResourceMark rm; // First thread to get here will initialize the compiler interface
*** 1585,1605 **** os::current_process_id()); log->stamp(); log->end_elem(); } ! while (true) { ! { // We need this HandleMark to avoid leaking VM handles. HandleMark hm(thread); if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { // the code cache is really full handle_full_code_cache(); } CompileTask* task = queue->get(); // Give compiler threads an extra quanta. They tend to be bursty and // this helps the compiler to finish up the job. if( CompilerThreadHintNoPreempt ) os::hint_no_preempt(); --- 1680,1712 ---- os::current_process_id()); log->stamp(); log->end_elem(); } ! // If compiler thread/runtime initialization fails, exit the compiler thread ! if (!init_compiler_runtime()) { ! return; ! } ! ! // Poll for new compilation tasks as long as the JVM runs. Compilation ! // should only be disabled if something went wrong while initializing the ! // compiler runtimes. This, in turn, should not happen. The only known case ! // when compiler runtime initialization fails is if there is not enough free ! // space in the code cache to generate the necessary stubs, etc. ! while (!is_compilation_disabled_forever()) { // We need this HandleMark to avoid leaking VM handles. HandleMark hm(thread); if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { // the code cache is really full handle_full_code_cache(); } CompileTask* task = queue->get(); + if (task == NULL) { + continue; + } // Give compiler threads an extra quanta. They tend to be bursty and // this helps the compiler to finish up the job. if( CompilerThreadHintNoPreempt ) os::hint_no_preempt();
*** 1640,1652 **** // After compilation is disabled, remove remaining methods from queue method->clear_queued_for_compilation(); } } } - } - } // ------------------------------------------------------------------ // CompileBroker::init_compiler_thread_log // // Set up state required by +LogCompilation. --- 1747,1760 ---- // After compilation is disabled, remove remaining methods from queue method->clear_queued_for_compilation(); } } } + // Shut down compiler runtime + shutdown_compiler_runtime(thread->compiler(), thread); + } // ------------------------------------------------------------------ // CompileBroker::init_compiler_thread_log // // Set up state required by +LogCompilation.
*** 1954,1965 **** if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) { NMethodSweeper::log_sweep("disable_compiler"); NMethodSweeper::possibly_sweep(); } } else { ! UseCompiler = false; ! AlwaysCompileLoopMethods = false; } } codecache_print(/* detailed= */ true); } --- 2062,2072 ---- if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) { NMethodSweeper::log_sweep("disable_compiler"); NMethodSweeper::possibly_sweep(); } } else { ! disable_compilation_forever(); } } codecache_print(/* detailed= */ true); }