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() {
*** 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);
--- 896,907 ----
_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 ****
--- 964,974 ----
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
--- 976,1026 ----
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,
--- 1033,1042 ----
*** 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
--- 1534,1642 ----
// 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->is_state_failed()) {
+ disable_compilation_forever();
+ // If compiler initialization failed, no compiler thread that is specific to a
+ // particular compiler runtime will ever start to compile methods.
+
+ // Tiered: 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.
+
+ if (comp->should_perform_shutdown()) {
+ 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;
+ }
+ }
+ warning("Initialization of %s failed -- shutting down compiler(s)", comp->name());
+
+ // Free buffer blob, if allocated
+ if (thread->get_buffer_blob() != NULL) {
+ CodeCache::free(thread->get_buffer_blob());
+ }
+
+ // Set state to shut down
+ comp->set_shut_down();
+
+ // Delete compiler runtimes
+ MutexLocker mu(MethodCompileQueue_lock, thread);
+ 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;
+ }
+
+ return false;
+ }
+
+ // C1 specific check
+ if ((comp->is_c1()) && (thread->get_buffer_blob() == NULL)) {
+ warning("Initialization of %s thread failed", comp->name());
+ return false;
+ }
+
+ return true;
+ }
+
// ------------------------------------------------------------------
// 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,1596 ****
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
--- 1661,1681 ----
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
*** 1640,1653 ****
// 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.
void CompileBroker::init_compiler_thread_log() {
--- 1725,1736 ----