7017434: Tiered needs to support reprofiling
authoriveresov
Wed, 09 Feb 2011 16:34:34 -0800
changeset 8322 8f11ba61239f
parent 8321 a416df5e4dad
child 8323 2f0378cd35f6
7017434: Tiered needs to support reprofiling Summary: Tiered needs to support proper method reprofiling after deopts. Reviewed-by: kvn
hotspot/src/share/vm/c1/c1_Compilation.cpp
hotspot/src/share/vm/oops/methodDataOop.cpp
hotspot/src/share/vm/oops/methodDataOop.hpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Tue Feb 08 16:12:16 2011 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Wed Feb 09 16:34:34 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -491,10 +491,11 @@
       // to start profiling on its own.
       _method->ensure_method_data();
     }
-  } else if (is_profiling() && _would_profile) {
+  } else if (is_profiling()) {
     ciMethodData *md = method->method_data_or_null();
-    assert(md != NULL, "Sanity");
-    md->set_would_profile(_would_profile);
+    if (md != NULL) {
+      md->set_would_profile(_would_profile);
+    }
   }
 }
 
--- a/hotspot/src/share/vm/oops/methodDataOop.cpp	Tue Feb 08 16:12:16 2011 -0800
+++ b/hotspot/src/share/vm/oops/methodDataOop.cpp	Wed Feb 09 16:34:34 2011 -0800
@@ -764,11 +764,13 @@
   if (TieredCompilation) {
     _invocation_counter.init();
     _backedge_counter.init();
+    _invocation_counter_start = 0;
+    _backedge_counter_start = 0;
     _num_loops = 0;
     _num_blocks = 0;
     _highest_comp_level = 0;
     _highest_osr_comp_level = 0;
-    _would_profile = false;
+    _would_profile = true;
   }
   set_creation_mileage(mileage_of(method()));
 
--- a/hotspot/src/share/vm/oops/methodDataOop.hpp	Tue Feb 08 16:12:16 2011 -0800
+++ b/hotspot/src/share/vm/oops/methodDataOop.hpp	Wed Feb 09 16:34:34 2011 -0800
@@ -1224,6 +1224,9 @@
   InvocationCounter _invocation_counter;
   // Same for backedges.
   InvocationCounter _backedge_counter;
+  // Counter values at the time profiling started.
+  int               _invocation_counter_start;
+  int               _backedge_counter_start;
   // Number of loops and blocks is computed when compiling the first
   // time with C1. It is used to determine if method is trivial.
   short             _num_loops;
@@ -1333,6 +1336,28 @@
     return backedge_counter()->count();
   }
 
+  int invocation_count_start() {
+    if (invocation_counter()->carry()) {
+      return 0;
+    }
+    return _invocation_counter_start;
+  }
+
+  int backedge_count_start() {
+    if (backedge_counter()->carry()) {
+      return 0;
+    }
+    return _backedge_counter_start;
+  }
+
+  int invocation_count_delta() { return invocation_count() - invocation_count_start(); }
+  int backedge_count_delta()   { return backedge_count()   - backedge_count_start();   }
+
+  void reset_start_counters() {
+    _invocation_counter_start = invocation_count();
+    _backedge_counter_start = backedge_count();
+  }
+
   InvocationCounter* invocation_counter()     { return &_invocation_counter; }
   InvocationCounter* backedge_counter()       { return &_backedge_counter;   }
 
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Tue Feb 08 16:12:16 2011 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Wed Feb 09 16:34:34 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, 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
@@ -28,6 +28,7 @@
 #include "runtime/arguments.hpp"
 #include "runtime/simpleThresholdPolicy.hpp"
 #include "runtime/simpleThresholdPolicy.inline.hpp"
+#include "code/scopeDesc.hpp"
 
 // Print an event.
 void SimpleThresholdPolicy::print_event(EventType type, methodHandle mh, methodHandle imh,
@@ -48,6 +49,18 @@
     break;
   case COMPILE:
     tty->print("compile");
+    break;
+  case KILL:
+    tty->print("kill");
+    break;
+  case UPDATE:
+    tty->print("update");
+    break;
+  case REPROFILE:
+    tty->print("reprofile");
+    break;
+  default:
+    tty->print("unknown");
   }
 
   tty->print(" level: %d ", level);
@@ -69,13 +82,17 @@
   if (type != COMPILE) {
     methodDataHandle mdh = mh->method_data();
     int mdo_invocations = 0, mdo_backedges = 0;
+    int mdo_invocations_start = 0, mdo_backedges_start = 0;
     if (mdh() != NULL) {
       mdo_invocations = mdh->invocation_count();
       mdo_backedges = mdh->backedge_count();
+      mdo_invocations_start = mdh->invocation_count_start();
+      mdo_backedges_start = mdh->backedge_count_start();
     }
-    tty->print(" total: %d,%d mdo: %d,%d",
+    tty->print(" total: %d,%d mdo: %d(%d),%d(%d)",
                invocation_count, backedge_count,
-               mdo_invocations, mdo_backedges);
+               mdo_invocations, mdo_invocations_start,
+               mdo_backedges, mdo_backedges_start);
     tty->print(" max levels: %d,%d",
                 mh->highest_comp_level(), mh->highest_osr_comp_level());
     if (inlinee_event) {
@@ -138,6 +155,20 @@
   return compile_queue->first();
 }
 
+void SimpleThresholdPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) {
+  for (ScopeDesc* sd = trap_scope;; sd = sd->sender()) {
+    if (PrintTieredEvents) {
+      methodHandle mh(sd->method());
+      print_event(REPROFILE, mh, mh, InvocationEntryBci, CompLevel_none);
+    }
+    methodDataOop mdo = sd->method()->method_data();
+    if (mdo != NULL) {
+      mdo->reset_start_counters();
+    }
+    if (sd->is_top()) break;
+  }
+}
+
 nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee,
                                       int branch_bci, int bci, CompLevel comp_level, TRAPS) {
   if (comp_level == CompLevel_none &&
@@ -254,46 +285,35 @@
 
 // Common transition function. Given a predicate determines if a method should transition to another level.
 CompLevel SimpleThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level) {
+  if (is_trivial(method)) return CompLevel_simple;
+
   CompLevel next_level = cur_level;
   int i = method->invocation_count();
   int b = method->backedge_count();
 
   switch(cur_level) {
   case CompLevel_none:
-    {
-      methodDataOop mdo = method->method_data();
-      if (mdo != NULL) {
-        int mdo_i = mdo->invocation_count();
-        int mdo_b = mdo->backedge_count();
-        // If we were at full profile level, would we switch to full opt?
-        if ((this->*p)(mdo_i, mdo_b, CompLevel_full_profile)) {
-          next_level = CompLevel_full_optimization;
-        }
-      }
-    }
-    if (next_level == cur_level && (this->*p)(i, b, cur_level)) {
-      if (is_trivial(method)) {
-        next_level = CompLevel_simple;
-      } else {
-        next_level = CompLevel_full_profile;
-      }
+    // If we were at full profile level, would we switch to full opt?
+    if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
+      next_level = CompLevel_full_optimization;
+    } else if ((this->*p)(i, b, cur_level)) {
+      next_level = CompLevel_full_profile;
     }
     break;
   case CompLevel_limited_profile:
   case CompLevel_full_profile:
-    if (is_trivial(method)) {
-      next_level = CompLevel_simple;
-    } else {
+    {
       methodDataOop mdo = method->method_data();
-      guarantee(mdo != NULL, "MDO should always exist");
-      if (mdo->would_profile()) {
-        int mdo_i = mdo->invocation_count();
-        int mdo_b = mdo->backedge_count();
-        if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+      if (mdo != NULL) {
+        if (mdo->would_profile()) {
+          int mdo_i = mdo->invocation_count_delta();
+          int mdo_b = mdo->backedge_count_delta();
+          if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+            next_level = CompLevel_full_optimization;
+          }
+        } else {
           next_level = CompLevel_full_optimization;
         }
-      } else {
-        next_level = CompLevel_full_optimization;
       }
     }
     break;
@@ -303,12 +323,6 @@
 
 // Determine if a method should be compiled with a normal entry point at a different level.
 CompLevel SimpleThresholdPolicy::call_event(methodOop method,  CompLevel cur_level) {
-  CompLevel highest_level = (CompLevel)method->highest_comp_level();
-  if (cur_level == CompLevel_none && highest_level > cur_level) {
-    // TODO: We may want to try to do more extensive reprofiling in this case.
-    return highest_level;
-  }
-
   CompLevel osr_level = (CompLevel) method->highest_osr_comp_level();
   CompLevel next_level = common(&SimpleThresholdPolicy::call_predicate, method, cur_level);
 
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Tue Feb 08 16:12:16 2011 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Wed Feb 09 16:34:34 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, 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
@@ -62,7 +62,7 @@
   void set_c1_count(int x) { _c1_count = x;    }
   void set_c2_count(int x) { _c2_count = x;    }
 
-  enum EventType { CALL, LOOP, COMPILE };
+  enum EventType { CALL, LOOP, COMPILE, KILL, UPDATE, REPROFILE };
   void print_event(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level);
   // Print policy-specific information if necessary
   virtual void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level) { }
@@ -103,7 +103,7 @@
   virtual void disable_compilation(methodOop method) { }
   // TODO: we should honour reprofiling requests in the future. Currently reprofiling
   // would happen but not to the extent we would ideally like.
-  virtual void reprofile(ScopeDesc* trap_scope, bool is_osr) { }
+  virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);
   virtual nmethod* event(methodHandle method, methodHandle inlinee,
                          int branch_bci, int bci, CompLevel comp_level, TRAPS);
   // Select task is called by CompileBroker. We should return a task or NULL.