diff src/share/vm/compiler/compileBroker.cpp @ 1783:d5d065957597

6953144: Tiered compilation Summary: Infrastructure for tiered compilation support (interpreter + c1 + c2) for 32 and 64 bit. Simple tiered policy implementation. Reviewed-by: kvn, never, phh, twisti
author iveresov
date Fri, 03 Sep 2010 17:51:07 -0700
parents 3e8fbc61cee8
children 2d26b0046e0d 22ef3370343b
line wrap: on
line diff
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Sep 02 11:40:02 2010 -0700
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Sep 03 17:51:07 2010 -0700
@@ -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,29 +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_cr(" (%d bytes)", method->code_size());
+  print_compilation(tty, method(), NULL);
 }
 
 
@@ -427,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.
@@ -437,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();
@@ -452,10 +412,9 @@
   }
 
   // Notify CompilerThreads that a task is available.
-  lock()->notify();
+  lock()->notify_all();
 }
 
-
 // ------------------------------------------------------------------
 // CompileQueue::get
 //
@@ -464,7 +423,6 @@
   NMethodSweeper::possibly_sweep();
 
   MutexLocker locker(lock());
-
   // Wait for an available CompileTask.
   while (_first == NULL) {
     // There is no work to be done right now.  Wait.
@@ -481,20 +439,32 @@
       lock()->wait();
     }
   }
-
-  CompileTask* task = _first;
+  CompileTask* task = CompilationPolicy::policy()->select_task(this);
+  remove(task);
+  return task;
+}
 
-  // Update queue first and last
-  _first =_first->next();
-  if (_first == NULL) {
-    _last = NULL;
+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();
   }
 
-  return task;
-
+  if (task->next() != NULL) {
+    task->next()->set_prev(task->prev());
+  } else {
+    // max is the last element
+    assert(task == _last, "Sanity");
+    _last = task->prev();
+  }
+  --_size;
 }
 
-
 // ------------------------------------------------------------------
 // CompileQueue::print
 void CompileQueue::print() {
@@ -545,7 +515,6 @@
   }
 }
 
-
 // ------------------------------------------------------------------
 // CompileBroker::compilation_init
 //
@@ -554,18 +523,18 @@
   _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
-  _compilers[0] = new Compiler();
-#ifndef COMPILER2
-  _compilers[1] = _compilers[0];
-#endif
+  if (c1_count > 0) {
+    _compilers[0] = new Compiler();
+  }
 #endif // COMPILER1
 
 #ifdef COMPILER2
-  _compilers[1] = new C2Compiler();
-#ifndef COMPILER1
-  _compilers[0] = _compilers[1];
-#endif
+  if (c2_count > 0) {
+    _compilers[1] = new C2Compiler();
+  }
 #endif // COMPILER2
 
 #ifdef SHARK
@@ -580,9 +549,7 @@
   _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.
   {
@@ -770,23 +737,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);
@@ -796,7 +778,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();
@@ -859,6 +843,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)) {
@@ -876,10 +861,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);
 
     // Make sure the method has not slipped into the queues since
     // last we checked; note that those checks were "fast bail-outs".
@@ -945,7 +931,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,
@@ -959,6 +945,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
@@ -967,26 +954,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
 
@@ -1000,12 +970,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;
 
@@ -1021,10 +989,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;
   }
@@ -1071,8 +1040,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;
   }
 
@@ -1088,7 +1056,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);
 }
 
 
@@ -1104,7 +1073,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 {
@@ -1113,15 +1082,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();
     }
   }
 }
@@ -1139,11 +1100,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
 //
@@ -1151,11 +1111,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;
   }
 
@@ -1194,7 +1152,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");
@@ -1643,7 +1601,6 @@
 #endif
 }
 
-
 // ------------------------------------------------------------------
 // CompileBroker::handle_full_code_cache
 //
@@ -1883,12 +1840,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);