# HG changeset patch # User dcubed # Date 1309404538 25200 # Node ID 88dce6a60ac8102c3716bdd7efda0e01597ace87 # Parent d425748f2203937ae7396d3409b0727503cde8a9 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 diff -r d425748f2203 -r 88dce6a60ac8 src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Thu Jun 23 20:31:43 2011 -0700 +++ b/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);