hotspot/src/share/vm/ci/ciMethod.cpp
changeset 6453 970dc585ab63
parent 6418 6671edbd230e
child 6744 dd08c62a68c7
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Sep 02 11:40:02 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Fri Sep 03 17:51:07 2010 -0700
@@ -49,7 +49,8 @@
   _handler_count      = h_m()->exception_table()->length() / 4;
   _uses_monitors      = h_m()->access_flags().has_monitor_bytecodes();
   _balanced_monitors  = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
-  _is_compilable      = !h_m()->is_not_compilable();
+  _is_c1_compilable   = !h_m()->is_not_c1_compilable();
+  _is_c2_compilable   = !h_m()->is_not_c2_compilable();
   // Lazy fields, filled in on demand.  Require allocation.
   _code               = NULL;
   _exception_handlers = NULL;
@@ -61,11 +62,12 @@
 #endif // COMPILER2 || SHARK
 
   ciEnv *env = CURRENT_ENV;
-  if (env->jvmti_can_hotswap_or_post_breakpoint() && _is_compilable) {
+  if (env->jvmti_can_hotswap_or_post_breakpoint() && can_be_compiled()) {
     // 6328518 check hotswap conditions under the right lock.
     MutexLocker locker(Compile_lock);
     if (Dependencies::check_evol_method(h_m()) != NULL) {
-      _is_compilable = false;
+      _is_c1_compilable = false;
+      _is_c2_compilable = false;
     }
   } else {
     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
@@ -93,7 +95,7 @@
   _signature = new (env->arena()) ciSignature(_holder, sig_symbol);
   _method_data = NULL;
   // Take a snapshot of these values, so they will be commensurate with the MDO.
-  if (ProfileInterpreter) {
+  if (ProfileInterpreter || TieredCompilation) {
     int invcnt = h_m()->interpreter_invocation_count();
     // if the value overflowed report it as max int
     _interpreter_invocation_count = invcnt < 0 ? max_jint : invcnt ;
@@ -437,11 +439,26 @@
         // In addition, virtual call sites have receiver type information
         int receivers_count_total = 0;
         int morphism = 0;
+        // Precompute morphism for the possible fixup
         for (uint i = 0; i < call->row_limit(); i++) {
           ciKlass* receiver = call->receiver(i);
           if (receiver == NULL)  continue;
-          morphism += 1;
-          int rcount = call->receiver_count(i);
+          morphism++;
+        }
+        int epsilon = 0;
+        if (TieredCompilation && ProfileInterpreter) {
+          // Interpreter and C1 treat final and special invokes differently.
+          // C1 will record a type, whereas the interpreter will just
+          // increment the count. Detect this case.
+          if (morphism == 1 && count > 0) {
+            epsilon = count;
+            count = 0;
+          }
+        }
+        for (uint i = 0; i < call->row_limit(); i++) {
+          ciKlass* receiver = call->receiver(i);
+          if (receiver == NULL)  continue;
+          int rcount = call->receiver_count(i) + epsilon;
           if (rcount == 0) rcount = 1; // Should be valid value
           receivers_count_total += rcount;
           // Add the receiver to result data.
@@ -687,10 +704,17 @@
 // invocation counts in methods.
 int ciMethod::scale_count(int count, float prof_factor) {
   if (count > 0 && method_data() != NULL) {
-    int current_mileage = method_data()->current_mileage();
-    int creation_mileage = method_data()->creation_mileage();
-    int counter_life = current_mileage - creation_mileage;
+    int counter_life;
     int method_life = interpreter_invocation_count();
+    if (TieredCompilation) {
+      // In tiered the MDO's life is measured directly, so just use the snapshotted counters
+      counter_life = MAX2(method_data()->invocation_count(), method_data()->backedge_count());
+    } else {
+      int current_mileage = method_data()->current_mileage();
+      int creation_mileage = method_data()->creation_mileage();
+      counter_life = current_mileage - creation_mileage;
+    }
+
     // counter_life due to backedge_counter could be > method_life
     if (counter_life > method_life)
       counter_life = method_life;
@@ -778,7 +802,8 @@
   Thread* my_thread = JavaThread::current();
   methodHandle h_m(my_thread, get_methodOop());
 
-  if (Tier1UpdateMethodData && is_tier1_compile(env->comp_level())) {
+  // Create an MDO for the inlinee
+  if (TieredCompilation && is_c1_compile(env->comp_level())) {
     build_method_data(h_m);
   }
 
@@ -885,7 +910,11 @@
 // Have previous compilations of this method succeeded?
 bool ciMethod::can_be_compiled() {
   check_is_loaded();
-  return _is_compilable;
+  ciEnv* env = CURRENT_ENV;
+  if (is_c1_compile(env->comp_level())) {
+    return _is_c1_compilable;
+  }
+  return _is_c2_compilable;
 }
 
 // ------------------------------------------------------------------
@@ -895,8 +924,13 @@
 void ciMethod::set_not_compilable() {
   check_is_loaded();
   VM_ENTRY_MARK;
-  _is_compilable = false;
-  get_methodOop()->set_not_compilable();
+  ciEnv* env = CURRENT_ENV;
+  if (is_c1_compile(env->comp_level())) {
+    _is_c1_compilable = false;
+  } else {
+    _is_c2_compilable = false;
+  }
+  get_methodOop()->set_not_compilable(env->comp_level());
 }
 
 // ------------------------------------------------------------------
@@ -910,7 +944,8 @@
 bool ciMethod::can_be_osr_compiled(int entry_bci) {
   check_is_loaded();
   VM_ENTRY_MARK;
-  return !get_methodOop()->access_flags().is_not_osr_compilable();
+  ciEnv* env = CURRENT_ENV;
+  return !get_methodOop()->is_not_osr_compilable(env->comp_level());
 }
 
 // ------------------------------------------------------------------
@@ -920,6 +955,14 @@
   return get_methodOop()->code() != NULL;
 }
 
+int ciMethod::comp_level() {
+  check_is_loaded();
+  VM_ENTRY_MARK;
+  nmethod* nm = get_methodOop()->code();
+  if (nm != NULL) return nm->comp_level();
+  return 0;
+}
+
 // ------------------------------------------------------------------
 // ciMethod::instructions_size
 //
@@ -928,18 +971,13 @@
 // junk like exception handler, stubs, and constant table, which are
 // not highly relevant to an inlined method.  So we use the more
 // specific accessor nmethod::insts_size.
-int ciMethod::instructions_size() {
+int ciMethod::instructions_size(int comp_level) {
   GUARDED_VM_ENTRY(
     nmethod* code = get_methodOop()->code();
-    // if there's no compiled code or the code was produced by the
-    // tier1 profiler return 0 for the code size.  This should
-    // probably be based on the compilation level of the nmethod but
-    // that currently isn't properly recorded.
-    if (code == NULL ||
-        (TieredCompilation && code->compiler() != NULL && code->compiler()->is_c1())) {
-      return 0;
+    if (code != NULL && (comp_level == CompLevel_any || comp_level == code->comp_level())) {
+      return code->code_end() - code->verified_entry_point();
     }
-    return code->insts_end() - code->verified_entry_point();
+    return 0;
   )
 }