| 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..ee7ba3be339b7e20caa20efe9f915c8de41ce3bf
|
| --- /dev/null
|
| +++ b/runtime/vm/stack_trace.cc
|
| @@ -0,0 +1,113 @@
|
| +// Copyright (c) 2015, 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(int skip_frames,
|
| + const Function& async_function,
|
| + bool count_invisible_frames) {
|
| + 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();
|
| + Function& function = Function::Handle();
|
| + 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())) {
|
| + // We have hit the sentinel, stop.
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + frame = frames.NextFrame();
|
| + }
|
| + // We hit the sentinel.
|
| + ASSERT(async_function_is_null ||
|
| + (async_function.raw() == function.parent_function()));
|
| + return frame_count;
|
| +}
|
| +
|
| +
|
| +intptr_t StackTraceUtils::CollectFrames(const Array& code_array,
|
| + const Array& pc_offset_array,
|
| + intptr_t array_offset,
|
| + intptr_t count,
|
| + int skip_frames,
|
| + bool collect_invisible_frames) {
|
| + StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
|
| + StackFrame* frame = frames.NextFrame();
|
| + ASSERT(frame != NULL); // We expect to find a dart invocation frame.
|
| + Function& function = Function::Handle();
|
| + Code& code = Code::Handle();
|
| + Smi& offset = Smi::Handle();
|
| + intptr_t collected_frames_count = 0;
|
| + while ((frame != NULL) && (count > 0)) {
|
| + 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++;
|
| + count--;
|
| + }
|
| + }
|
| + }
|
| + frame = frames.NextFrame();
|
| + }
|
| + return collected_frames_count;
|
| +}
|
| +
|
| +
|
| +intptr_t StackTraceUtils::ExtractAsyncStackTraceInfo(
|
| + Thread* thread,
|
| + Function* async_function,
|
| + Array* async_code_array,
|
| + Array* async_pc_offset_array) {
|
| + if (thread->async_stack_trace() == StackTrace::null()) {
|
| + return 0;
|
| + }
|
| + 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
|
|
|