6951623: 3/3 possible performance problems in FollowReferences() and GetObjectsWithTags()
authordcubed
Wed, 29 Jun 2011 20:28:58 -0700
changeset 10229 7b358d5def21
parent 10228 e5e1539de725
child 10230 648477032920
6951623: 3/3 possible performance problems in FollowReferences() and GetObjectsWithTags() Summary: Call collect_stack_roots() before collect_simple_roots() as an optimization. Reviewed-by: ysr, dsamersoff, dcubed Contributed-by: ashok.srinivasa.murthy@oracle.com
hotspot/src/share/vm/prims/jvmtiTagMap.cpp
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Jun 23 20:31:43 2011 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Wed Jun 29 20:28:58 2011 -0700
@@ -3034,7 +3034,8 @@
 }
 
 
-// collects all simple (non-stack) roots.
+// Collects all simple (non-stack) roots except for threads;
+// threads are handled in collect_stack_roots() as an optimization.
 // if there's a heap root callback provided then the callback is
 // invoked for each simple root.
 // if an object reference callback is provided then all simple
@@ -3065,16 +3066,7 @@
     return false;
   }
 
-  // Threads
-  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
-    oop threadObj = thread->threadObj();
-    if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
-      bool cont = CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD, threadObj);
-      if (!cont) {
-        return false;
-      }
-    }
-  }
+  // threads are now handled in collect_stack_roots()
 
   // Other kinds of roots maintained by HotSpot
   // Many of these won't be visible but others (such as instances of important
@@ -3186,13 +3178,20 @@
 }
 
 
-// collects all stack roots - for each thread it walks the execution
+// Collects the simple roots for all threads and collects all
+// stack roots - for each thread it walks the execution
 // stack to find all references and local JNI refs.
 inline bool VM_HeapWalkOperation::collect_stack_roots() {
   JNILocalRootsClosure blk;
   for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
     oop threadObj = thread->threadObj();
     if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
+      // Collect the simple root for this thread before we
+      // collect its stack roots
+      if (!CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD,
+                                               threadObj)) {
+        return false;
+      }
       if (!collect_stack_roots(thread, &blk)) {
         return false;
       }
@@ -3251,8 +3250,12 @@
     // to reset.
     ObjectMarker::set_needs_reset(false);
 
+    // Calling collect_stack_roots() before collect_simple_roots()
+    // can result in a big performance boost for an agent that is
+    // focused on analyzing references in the thread stacks.
+    if (!collect_stack_roots()) return;
+
     if (!collect_simple_roots()) return;
-    if (!collect_stack_roots()) return;
 
     // no early return so enable heap traversal to reset the mark bits
     ObjectMarker::set_needs_reset(true);