Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1358)

Unified Diff: runtime/vm/stack_trace.cc

Issue 2646443005: Track async causal stack traces (Closed)
Patch Set: rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/stack_trace.h ('k') | runtime/vm/stub_code.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/stack_trace.cc
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0168e3bc74c92c498fcc73b2a296d60ecfb0e4f1
--- /dev/null
+++ b/runtime/vm/stack_trace.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/stack_frame.h"
+#include "vm/stack_trace.h"
+
+namespace dart {
+
+// Count the number of frames that are on the stack.
+intptr_t StackTraceUtils::CountFrames(Thread* thread,
+ int skip_frames,
+ const Function& async_function,
+ bool count_invisible_frames) {
+ Zone* zone = thread->zone();
+ intptr_t frame_count = 0;
+ StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
+ StackFrame* frame = frames.NextFrame();
+ ASSERT(frame != NULL); // We expect to find a dart invocation frame.
+ Code& code = Code::Handle(zone);
+ Function& function = Function::Handle(zone);
+ const bool async_function_is_null = async_function.IsNull();
+ while (frame != NULL) {
+ if (frame->IsDartFrame()) {
+ if (skip_frames > 0) {
+ skip_frames--;
+ } else {
+ code = frame->LookupDartCode();
+ function = code.function();
+ if (function.is_visible() || count_invisible_frames) {
+ frame_count++;
+ }
+ if (!async_function_is_null &&
+ (async_function.raw() == function.parent_function())) {
+ return frame_count;
+ }
+ }
+ }
+ frame = frames.NextFrame();
+ }
+ // We hit the sentinel.
+ ASSERT(async_function_is_null);
+ return frame_count;
+}
+
+
+intptr_t StackTraceUtils::CollectFrames(Thread* thread,
+ const Array& code_array,
+ const Array& pc_offset_array,
+ intptr_t array_offset,
+ intptr_t count,
+ int skip_frames,
+ bool collect_invisible_frames) {
+ Zone* zone = thread->zone();
+ StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
+ StackFrame* frame = frames.NextFrame();
+ ASSERT(frame != NULL); // We expect to find a dart invocation frame.
+ Function& function = Function::Handle(zone);
+ Code& code = Code::Handle(zone);
+ Smi& offset = Smi::Handle(zone);
+ intptr_t collected_frames_count = 0;
+ while ((frame != NULL) && (collected_frames_count < count)) {
+ if (frame->IsDartFrame()) {
+ if (skip_frames > 0) {
+ skip_frames--;
+ } else {
+ code = frame->LookupDartCode();
+ function = code.function();
+ if (function.is_visible() || collect_invisible_frames) {
+ offset = Smi::New(frame->pc() - code.PayloadStart());
+ code_array.SetAt(array_offset, code);
+ pc_offset_array.SetAt(array_offset, offset);
+ array_offset++;
+ collected_frames_count++;
+ }
+ }
+ }
+ frame = frames.NextFrame();
+ }
+ return collected_frames_count;
+}
+
+
+intptr_t StackTraceUtils::ExtractAsyncStackTraceInfo(
+ Thread* thread,
+ Function* async_function,
+ StackTrace* async_stack_trace_out,
+ Array* async_code_array,
+ Array* async_pc_offset_array) {
+ if (thread->async_stack_trace() == StackTrace::null()) {
+ return 0;
+ }
+ *async_stack_trace_out = thread->async_stack_trace();
+ ASSERT(!async_stack_trace_out->IsNull());
+ const StackTrace& async_stack_trace =
+ StackTrace::Handle(thread->async_stack_trace());
+ const intptr_t async_stack_trace_length = async_stack_trace.Length();
+ // At least two entries (0: gap marker, 1: async function).
+ ASSERT(async_stack_trace_length >= 2);
+ // Validate the structure of this stack trace.
+ *async_code_array = async_stack_trace.code_array();
+ ASSERT(!async_code_array->IsNull());
+ *async_pc_offset_array = async_stack_trace.pc_offset_array();
+ ASSERT(!async_pc_offset_array->IsNull());
+ // We start with the asynchronous gap marker.
+ ASSERT(async_code_array->At(0) != Code::null());
+ ASSERT(async_code_array->At(0) ==
+ StubCode::AsynchronousGapMarker_entry()->code());
+ const Code& code = Code::Handle(Code::RawCast(async_code_array->At(1)));
+ *async_function = code.function();
+ ASSERT(!async_function->IsNull());
+ ASSERT(async_function->IsAsyncFunction() ||
+ async_function->IsAsyncGenerator());
+ return async_stack_trace_length;
+}
+
+} // namespace dart
« no previous file with comments | « runtime/vm/stack_trace.h ('k') | runtime/vm/stub_code.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698