diff options
author | 2017-06-12 18:37:19 -0700 | |
---|---|---|
committer | 2017-06-13 11:35:45 -0700 | |
commit | 850a0fe2fc0dc1fdea40a6147762876547b3ebb3 (patch) | |
tree | 46a3026ea3a47681fc7a4ae5d9271577074b2ba8 | |
parent | 6db6b4d276435cd18a516c84c33e5b3351f5bd3b (diff) |
ART: Add GetStackTrace fast-path
Add a fast-path closure that fills stack frames directly into the
provided buffer, avoiding an intermediate vector and its allocations,
as well as a memcpy.
This only works when collecting stack frames from the top (start >= 0),
which is a common case.
Bug: 62065987
Test: m test-art-host
Change-Id: I8f0d34b3d18f70f4699ed8bdec2c88ca4c96cd4f
-rw-r--r-- | runtime/openjdkjvmti/ti_stack.cc | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/runtime/openjdkjvmti/ti_stack.cc b/runtime/openjdkjvmti/ti_stack.cc index 184fd804d0..550b97272d 100644 --- a/runtime/openjdkjvmti/ti_stack.cc +++ b/runtime/openjdkjvmti/ti_stack.cc @@ -178,6 +178,33 @@ static jvmtiError TranslateFrameVector(const std::vector<jvmtiFrameInfo>& frames return ERR(NONE); } +struct GetStackTraceDirectClosure : public art::Closure { + public: + GetStackTraceDirectClosure(jvmtiFrameInfo* frame_buffer_, size_t start, size_t stop) + : frame_buffer(frame_buffer_), + start_input(start), + stop_input(stop), + index(0) { + DCHECK_GE(start_input, 0u); + } + + void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { + auto frames_fn = [&](jvmtiFrameInfo info) { + frame_buffer[index] = info; + ++index; + }; + auto visitor = MakeStackTraceVisitor(self, start_input, stop_input, frames_fn); + visitor.WalkStack(/* include_transitions */ false); + } + + jvmtiFrameInfo* frame_buffer; + + const size_t start_input; + const size_t stop_input; + + size_t index = 0; +}; + static jvmtiError GetThread(JNIEnv* env, jthread java_thread, art::Thread** thread) { if (java_thread == nullptr) { *thread = art::Thread::Current(); @@ -235,8 +262,20 @@ jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, return ERR(NONE); } - GetStackTraceVectorClosure closure(start_depth >= 0 ? static_cast<size_t>(start_depth) : 0, - start_depth >= 0 ? static_cast<size_t>(max_frame_count) : 0); + if (start_depth >= 0) { + // Fast path: Regular order of stack trace. Fill into the frame_buffer directly. + GetStackTraceDirectClosure closure(frame_buffer, + static_cast<size_t>(start_depth), + static_cast<size_t>(max_frame_count)); + thread->RequestSynchronousCheckpoint(&closure); + *count_ptr = static_cast<jint>(closure.index); + if (closure.index < static_cast<size_t>(start_depth)) { + return ERR(ILLEGAL_ARGUMENT); + } + return ERR(NONE); + } + + GetStackTraceVectorClosure closure(0, 0); thread->RequestSynchronousCheckpoint(&closure); return TranslateFrameVector(closure.frames, |