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
--- 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);