summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2017-06-12 18:37:19 -0700
committer Andreas Gampe <agampe@google.com> 2017-06-13 11:35:45 -0700
commit850a0fe2fc0dc1fdea40a6147762876547b3ebb3 (patch)
tree46a3026ea3a47681fc7a4ae5d9271577074b2ba8
parent6db6b4d276435cd18a516c84c33e5b3351f5bd3b (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.cc43
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,