Mercurial > hg > graal-jvmci-8
diff src/share/vm/compiler/compileBroker.cpp @ 1930:2d26b0046e0d
Merge.
author | Thomas Wuerthinger <wuerthinger@ssw.jku.at> |
---|---|
date | Tue, 30 Nov 2010 14:53:30 +0100 |
parents | 5571b97fc1ec d5d065957597 |
children | 48bbaead8b6c |
line wrap: on
line diff
--- a/src/share/vm/compiler/compileBroker.cpp Mon Nov 29 18:32:30 2010 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Nov 30 14:53:30 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -123,20 +123,12 @@ int CompileBroker::_sum_nmethod_size = 0; int CompileBroker::_sum_nmethod_code_size = 0; -CompileQueue* CompileBroker::_method_queue = NULL; +CompileQueue* CompileBroker::_c2_method_queue = NULL; +CompileQueue* CompileBroker::_c1_method_queue = NULL; CompileTask* CompileBroker::_task_free_list = NULL; GrowableArray<CompilerThread*>* CompileBroker::_method_threads = NULL; -// CompileTaskWrapper -// -// Assign this task to the current thread. Deallocate the task -// when the compilation is complete. -class CompileTaskWrapper : StackObj { -public: - CompileTaskWrapper(CompileTask* task); - ~CompileTaskWrapper(); -}; CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { CompilerThread* thread = CompilerThread::current(); @@ -246,6 +238,12 @@ bool_to_str(_is_complete), bool_to_str(_is_success)); } + +void CompileTask::print_compilation(outputStream *st, methodOop method, char* method_name) { + nmethod::print_compilation(st, method_name,/*title*/ NULL, method, + is_blocking(), compile_id(), osr_bci(), comp_level()); +} + // ------------------------------------------------------------------ // CompileTask::print_line_on_error // @@ -258,32 +256,13 @@ // void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { methodOop method = (methodOop)JNIHandles::resolve(_method); - // print compiler name st->print("%s:", CompileBroker::compiler(comp_level())->name()); - - // print compilation number - st->print("%3d", compile_id()); - - // print method attributes - const bool is_osr = osr_bci() != CompileBroker::standard_entry_bci; - { const char blocking_char = is_blocking() ? 'b' : ' '; - const char compile_type = is_osr ? '%' : ' '; - const char sync_char = method->is_synchronized() ? 's' : ' '; - const char exception_char = method->has_exception_handler() ? '!' : ' '; - const char tier_char = - is_highest_tier_compile(comp_level()) ? ' ' : ('0' + comp_level()); - st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, tier_char); + char* method_name = NULL; + if (method != NULL) { + method_name = method->name_and_sig_as_C_string(buf, buflen); } - - // Use buf to get method name and signature - if (method != NULL) st->print("%s", method->name_and_sig_as_C_string(buf, buflen)); - - // print osr_bci if any - if (is_osr) st->print(" @ %d", osr_bci()); - - // print method size - st->print_cr(" (%d bytes)", method->code_size()); + print_compilation(st, method, method_name); } // ------------------------------------------------------------------ @@ -298,32 +277,7 @@ // print compiler name if requested if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler(comp_level())->name()); - - // print compilation number - tty->print("%3d", compile_id()); - - // print method attributes - const bool is_osr = osr_bci() != CompileBroker::standard_entry_bci; - { const char blocking_char = is_blocking() ? 'b' : ' '; - const char compile_type = is_osr ? '%' : ' '; - const char sync_char = method->is_synchronized() ? 's' : ' '; - const char exception_char = method->has_exception_handler() ? '!' : ' '; - const char tier_char = - is_highest_tier_compile(comp_level()) ? ' ' : ('0' + comp_level()); - tty->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, tier_char); - } - - // print method name - method->print_short_name(tty); - - // print osr_bci if any - if (is_osr) tty->print(" @ %d", osr_bci()); - - // print method size - tty->print(" (%d bytes)", method->code_size()); - - // invocation count - tty->print_cr(" %d invocations", _hot_count); + print_compilation(tty, method(), NULL); } @@ -402,7 +356,7 @@ // <task_done ... stamp='1.234'> </task> nmethod* nm = code(); log->begin_elem("task_done success='%d' nmsize='%d' count='%d'", - _is_success, nm == NULL ? 0 : nm->instructions_size(), + _is_success, nm == NULL ? 0 : nm->content_size(), method->invocation_count()); int bec = method->backedge_count(); if (bec != 0) log->print(" backedge_count='%d'", bec); @@ -430,6 +384,7 @@ assert(lock()->owned_by_self(), "must own lock"); task->set_next(NULL); + task->set_prev(NULL); if (_last == NULL) { // The compile queue is empty. @@ -440,8 +395,10 @@ // Append the task to the queue. assert(_last->next() == NULL, "not last"); _last->set_next(task); + task->set_prev(_last); _last = task; } + ++_size; // Mark the method as being in the compile queue. ((methodOop)JNIHandles::resolve(task->method_handle()))->set_queued_for_compilation(); @@ -455,39 +412,62 @@ } // Notify CompilerThreads that a task is available. - lock()->notify(); + lock()->notify_all(); } - // ------------------------------------------------------------------ // CompileQueue::get // // Get the next CompileTask from a CompileQueue CompileTask* CompileQueue::get() { + NMethodSweeper::possibly_sweep(); + MutexLocker locker(lock()); - // Wait for an available CompileTask. while (_first == NULL) { // There is no work to be done right now. Wait. - lock()->wait(); + if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() || CodeCache::needs_flushing())) { + // During the emergency sweeping periods, wake up and sweep occasionally + bool timedout = lock()->wait(!Mutex::_no_safepoint_check_flag, NmethodSweepCheckInterval*1000); + if (timedout) { + MutexUnlocker ul(lock()); + // When otherwise not busy, run nmethod sweeping + NMethodSweeper::possibly_sweep(); + } + } else { + // During normal operation no need to wake up on timer + lock()->wait(); + } + } + CompileTask* task = CompilationPolicy::policy()->select_task(this); + remove(task); + return task; +} + +void CompileQueue::remove(CompileTask* task) +{ + assert(lock()->owned_by_self(), "must own lock"); + if (task->prev() != NULL) { + task->prev()->set_next(task->next()); + } else { + // max is the first element + assert(task == _first, "Sanity"); + _first = task->next(); } - CompileTask* task = _first; - - // Update queue first and last - _first =_first->next(); - if (_first == NULL) { - _last = NULL; + if (task->next() != NULL) { + task->next()->set_prev(task->prev()); + } else { + // max is the last element + assert(task == _last, "Sanity"); + _last = task->prev(); } // (tw) Immediately set compiling flag. JavaThread::current()->as_CompilerThread()->set_compiling(true); - - return task; - + --_size; } - // ------------------------------------------------------------------ // CompileQueue::print void CompileQueue::print() { @@ -614,10 +594,12 @@ _last_method_compiled[0] = '\0'; // Set the interface to the current compiler(s). + int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple); + int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization); #ifdef COMPILER1 if (UseC1X) { _compilers[0] = new C1XCompiler(); - } else { + } else if (c1_count > 0) { _compilers[0] = new Compiler(); } #ifndef COMPILER2 @@ -626,19 +608,24 @@ #endif // COMPILER1 #ifdef COMPILER2 - _compilers[1] = new C2Compiler(); -#ifndef COMPILER1 - _compilers[0] = _compilers[1]; + if (c2_count > 0) { + _compilers[1] = new C2Compiler(); + } +#endif // COMPILER2 + +#ifdef SHARK +#if defined(COMPILER1) || defined(COMPILER2) +#error "Can't use COMPILER1 or COMPILER2 with shark" #endif -#endif // COMPILER2 + _compilers[0] = new SharkCompiler(); + _compilers[1] = _compilers[0]; +#endif // Initialize the CompileTask free list _task_free_list = NULL; // Start the CompilerThreads - init_compiler_threads(compiler_count()); - - + init_compiler_threads(c1_count, c2_count); // totalTime performance counter is always created as it is required // by the implementation of java.lang.management.CompilationMBean. { @@ -826,23 +813,38 @@ // CompileBroker::init_compiler_threads // // Initialize the compilation queue -void CompileBroker::init_compiler_threads(int compiler_count) { +void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; + assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); + 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); + } - _method_queue = new CompileQueue("MethodQueue", MethodCompileQueue_lock); + int compiler_count = c1_compiler_count + c2_compiler_count; + _method_threads = new (ResourceObj::C_HEAP) GrowableArray<CompilerThread*>(compiler_count, true); char name_buffer[256]; - int i; - for (i = 0; i < compiler_count; i++) { + for (int i = 0; i < c2_compiler_count; i++) { // Create a name for our thread. - sprintf(name_buffer, "CompilerThread%d", i); + sprintf(name_buffer, "C2 CompilerThread%d", i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); - - CompilerThread* new_thread = make_compiler_thread(name_buffer, _method_queue, counters, 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); @@ -852,7 +854,9 @@ // ------------------------------------------------------------------ // CompileBroker::is_idle bool CompileBroker::is_idle() { - if (!_method_queue->is_empty()) { + 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(); @@ -915,6 +919,7 @@ return; } + // If this method is already in the compile queue, then // we do not block the current thread. if (compilation_is_in_queue(method, osr_bci)) { @@ -932,10 +937,11 @@ // Outputs from the following MutexLocker block: CompileTask* task = NULL; bool blocking = false; + CompileQueue* queue = compile_queue(comp_level); // Acquire our lock. { - MutexLocker locker(_method_queue->lock(), THREAD); + MutexLocker locker(queue->lock(), THREAD); if (Thread::current()->is_Compiler_thread() && CompilerThread::current()->is_compiling() && !BackgroundCompilation) { @@ -1008,7 +1014,7 @@ // and in that case it's best to protect both the testing (here) of // these bits, and their updating (here and elsewhere) under a // common lock. - task = create_compile_task(_method_queue, + task = create_compile_task(queue, compile_id, method, osr_bci, comp_level, hot_method, hot_count, comment, @@ -1022,6 +1028,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, + int comp_level, methodHandle hot_method, int hot_count, const char* comment, TRAPS) { // make sure arguments make sense @@ -1030,26 +1037,9 @@ assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods"); assert(!instanceKlass::cast(method->method_holder())->is_not_initialized(), "method holder must be initialized"); - int comp_level = CompilationPolicy::policy()->compilation_level(method, osr_bci); - -#ifdef TIERED - if (TieredCompilation && StressTieredRuntime) { - static int flipper = 0; - if (is_even(flipper++)) { - comp_level = CompLevel_fast_compile; - } else { - comp_level = CompLevel_full_optimization; - } + if (!TieredCompilation) { + comp_level = CompLevel_highest_tier; } -#ifdef SPARC - // QQQ FIX ME - // C2 only returns long results in G1 and c1 doesn't understand so disallow c2 - // compiles of long results - if (TieredCompilation && method()->result_type() == T_LONG) { - comp_level = CompLevel_fast_compile; - } -#endif // SPARC -#endif // TIERED // return quickly if possible @@ -1063,12 +1053,10 @@ if (osr_bci == InvocationEntryBci) { // standard compilation nmethod* method_code = method->code(); - if (method_code != NULL -#ifdef TIERED - && ( method_code->is_compiled_by_c2() || comp_level == CompLevel_fast_compile ) -#endif // TIERED - ) { - return method_code; + if (method_code != NULL) { + if (compilation_is_complete(method, osr_bci, comp_level)) { + return method_code; + } } if (method->is_not_compilable(comp_level)) return NULL; @@ -1084,10 +1072,11 @@ // osr compilation #ifndef TIERED // seems like an assert of dubious value - assert(comp_level == CompLevel_full_optimization, + assert(comp_level == CompLevel_highest_tier, "all OSR compiles are assumed to be at a single compilation lavel"); #endif // TIERED - nmethod* nm = method->lookup_osr_nmethod_for(osr_bci); + // We accept a higher level osr method + nmethod* nm = method->lookup_osr_nmethod_for(osr_bci, comp_level, false); if (nm != NULL) return nm; if (method->is_not_osr_compilable()) return NULL; } @@ -1134,8 +1123,7 @@ // If the compiler is shut off due to code cache flushing or otherwise, // fail out now so blocking compiles dont hang the java thread if (!should_compile_new_jobs() || (UseCodeCacheFlushing && CodeCache::needs_flushing())) { - method->invocation_counter()->decay(); - method->backedge_counter()->decay(); + CompilationPolicy::policy()->delay_compilation(method()); return NULL; } @@ -1151,7 +1139,8 @@ } // return requested nmethod - return osr_bci == InvocationEntryBci ? method->code() : method->lookup_osr_nmethod_for(osr_bci); + // We accept a higher level osr method + return osr_bci == InvocationEntryBci ? method->code() : method->lookup_osr_nmethod_for(osr_bci, comp_level, false); } @@ -1167,7 +1156,7 @@ if (method->is_not_osr_compilable()) { return true; } else { - nmethod* result = method->lookup_osr_nmethod_for(osr_bci); + nmethod* result = method->lookup_osr_nmethod_for(osr_bci, comp_level, true); return (result != NULL); } } else { @@ -1176,15 +1165,7 @@ } else { nmethod* result = method->code(); if (result == NULL) return false; -#ifdef TIERED - if (comp_level == CompLevel_fast_compile) { - // At worst the code is from c1 - return true; - } - // comp level must be full opt - return result->is_compiled_by_c2(); -#endif // TIERED - return true; + return comp_level == result->comp_level(); } } } @@ -1202,11 +1183,10 @@ // versa). This can be remedied by a full queue search to disambiguate // cases. If it is deemed profitible, this may be done. bool CompileBroker::compilation_is_in_queue(methodHandle method, - int osr_bci) { + int osr_bci) { return method->queued_for_compilation(); } - // ------------------------------------------------------------------ // CompileBroker::compilation_is_prohibited // @@ -1214,11 +1194,9 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level) { bool is_native = method->is_native(); // Some compilers may not support the compilation of natives. - // QQQ this needs some work ought to only record not compilable at - // the specified level if (is_native && (!CICompileNatives || !compiler(comp_level)->supports_native())) { - method->set_not_compilable_quietly(); + method->set_not_compilable_quietly(comp_level); return true; } @@ -1257,7 +1235,7 @@ // compilations may be numbered separately from regular compilations // if certain debugging flags are used. uint CompileBroker::assign_compile_id(methodHandle method, int osr_bci) { - assert(_method_queue->lock()->owner() == JavaThread::current(), + assert(MethodCompileQueue_lock->owner() == Thread::current(), "must hold the compilation queue lock"); bool is_osr = (osr_bci != standard_entry_bci); assert(!method->is_native(), "no longer compile natives"); @@ -1711,7 +1689,6 @@ #endif } - // ------------------------------------------------------------------ // CompileBroker::handle_full_code_cache // @@ -1720,21 +1697,20 @@ void CompileBroker::handle_full_code_cache() { UseInterpreter = true; if (UseCompiler || AlwaysCompileLoopMethods ) { - CompilerThread* thread = CompilerThread::current(); - CompileLog* log = thread->log(); - if (log != NULL) { - log->begin_elem("code_cache_full"); - log->stamp(); - log->end_elem(); + if (xtty != NULL) { + xtty->begin_elem("code_cache_full"); + xtty->stamp(); + xtty->end_elem(); } - #ifndef PRODUCT - warning("CodeCache is full. Compiler has been disabled"); + warning("CodeCache is full. Compiler has been disabled."); + warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); +#ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { before_exit(JavaThread::current()); exit_globals(); // will delete tty vm_direct_exit(CompileTheWorld ? 0 : 1); } - #endif +#endif if (UseCodeCacheFlushing) { NMethodSweeper::handle_full_code_cache(true); } else { @@ -1916,13 +1892,13 @@ } // Collect counts of successful compilations - _sum_nmethod_size += code->total_size(); - _sum_nmethod_code_size += code->code_size(); + _sum_nmethod_size += code->total_size(); + _sum_nmethod_code_size += code->insts_size(); _total_compile_count++; if (UsePerfData) { - _perf_sum_nmethod_size->inc(code->total_size()); - _perf_sum_nmethod_code_size->inc(code->code_size()); + _perf_sum_nmethod_size->inc( code->total_size()); + _perf_sum_nmethod_code_size->inc(code->insts_size()); _perf_total_compile_count->inc(); } @@ -1952,12 +1928,12 @@ CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count); tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count); - if (compiler(CompLevel_fast_compile)) { - compiler(CompLevel_fast_compile)->print_timers(); - if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) - compiler(CompLevel_highest_tier)->print_timers(); + if (compiler(CompLevel_simple) != NULL) { + compiler(CompLevel_simple)->print_timers(); } - + if (compiler(CompLevel_full_optimization) != NULL) { + compiler(CompLevel_full_optimization)->print_timers(); + } tty->cr(); int tcb = CompileBroker::_sum_osr_bytes_compiled + CompileBroker::_sum_standard_bytes_compiled; tty->print_cr(" Total compiled bytecodes : %6d bytes", tcb);