8058564: Tiered compilation performance drop in PIT
authoriveresov
Wed, 17 Sep 2014 21:15:03 -0700
changeset 26799 0c349e16bbe8
parent 26797 b89b8ffec1f0
child 26800 ed8ab32a293d
8058564: Tiered compilation performance drop in PIT Summary: Ensure MethodCounters are created before method is enqueued for compilation Reviewed-by: kvn, drchase, jiangli
hotspot/src/share/vm/compiler/compileBroker.cpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/runtime/sweeper.cpp
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Sep 17 06:05:41 2014 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Sep 17 21:15:03 2014 -0700
@@ -1206,6 +1206,12 @@
     return;
   }
 
+  if (TieredCompilation) {
+    // Tiered policy requires MethodCounters to exist before adding a method to
+    // the queue. Create if we don't have them yet.
+    method->get_method_counters(thread);
+  }
+
   // Outputs from the following MutexLocker block:
   CompileTask* task     = NULL;
   bool         blocking = false;
--- a/hotspot/src/share/vm/oops/method.cpp	Wed Sep 17 06:05:41 2014 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Sep 17 21:15:03 2014 -0700
@@ -93,7 +93,7 @@
   set_hidden(false);
   set_dont_inline(false);
   set_method_data(NULL);
-  set_method_counters(NULL);
+  clear_method_counters();
   set_vtable_index(Method::garbage_vtable_index);
 
   // Fix and bury in Method*
@@ -117,7 +117,7 @@
   MetadataFactory::free_metadata(loader_data, method_data());
   set_method_data(NULL);
   MetadataFactory::free_metadata(loader_data, method_counters());
-  set_method_counters(NULL);
+  clear_method_counters();
   // The nmethod will be gone when we get here.
   if (code() != NULL) _code = NULL;
 }
@@ -395,9 +395,7 @@
   methodHandle mh(m);
   ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
   MethodCounters* counters = MethodCounters::allocate(loader_data, CHECK_NULL);
-  if (mh->method_counters() == NULL) {
-    mh->set_method_counters(counters);
-  } else {
+  if (!mh->init_method_counters(counters)) {
     MetadataFactory::free_metadata(loader_data, counters);
   }
   return mh->method_counters();
@@ -859,7 +857,7 @@
   assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?");
 
   set_method_data(NULL);
-  set_method_counters(NULL);
+  clear_method_counters();
 }
 
 // Called when the method_holder is getting linked. Setup entrypoints so the method
--- a/hotspot/src/share/vm/oops/method.hpp	Wed Sep 17 06:05:41 2014 +0000
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Sep 17 21:15:03 2014 -0700
@@ -333,11 +333,13 @@
     return _method_counters;
   }
 
-  void set_method_counters(MethodCounters* counters) {
-    // The store into method must be released. On platforms without
-    // total store order (TSO) the reference may become visible before
-    // the initialization of data otherwise.
-    OrderAccess::release_store_ptr((volatile void *)&_method_counters, counters);
+  void clear_method_counters() {
+    _method_counters = NULL;
+  }
+
+  bool init_method_counters(MethodCounters* counters) {
+    // Try to install a pointer to MethodCounters, return true on success.
+    return Atomic::cmpxchg_ptr(counters, (volatile void*)&_method_counters, NULL) == NULL;
   }
 
 #ifdef TIERED
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Sep 17 06:05:41 2014 +0000
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Sep 17 21:15:03 2014 -0700
@@ -616,12 +616,7 @@
       // The stack-scanning low-cost detection may not see the method was used (which can happen for
       // flat profiles). Check the age counter for possible data.
       if (UseCodeAging && make_not_entrant && (nm->is_compiled_by_c2() || nm->is_compiled_by_c1())) {
-        MethodCounters* mc = nm->method()->method_counters();
-        if (mc == NULL) {
-          // Sometimes we can get here without MethodCounters. For example if we run with -Xcomp.
-          // Try to allocate them.
-          mc = nm->method()->get_method_counters(Thread::current());
-        }
+        MethodCounters* mc = nm->method()->get_method_counters(Thread::current());
         if (mc != NULL) {
           // Snapshot the value as it's changed concurrently
           int age = mc->nmethod_age();