Files
sdk/runtime/vm/stack_trace.h
T
John McCutchan a0ee5b24db Track async causal stack traces
This CL improves the stack traces that accompany exceptions. Whenever an
async function is entered, we remember how we got there. This is similar
in spirit to package:stack_trace but the implementation is more efficient
and memory usage can be more easily reasoned about.

Tracking causal stack traces:

- [x] Upon entry to an async function, capture the synchronous stack trace prefix and store it into the closure.
- [x] Upon entry to an async* function, capture the synchronous stack trace prefix and store it into the closure.
- [x] Before returning from an async function, clear the Thread's asynchronous stack trace.
- [x] After resuming an async function, load the sychronous stack trace prefix into the Thread.
- [x] Filter stack traces to remove async machinery.

Service protocol changes:

- [x] Send causal async stack trace.

Observatory changes:

- [x] Display causal async stack trace below async functions.

Fixes https://github.com/dart-lang/sdk/issues/27661

R=asiva@google.com, rmacnak@google.com

Comparisons: https://docs.google.com/a/google.com/document/d/10r6jEqr8OCiDZ4y9SYU_uOimcHiOGAZMly2ghTErALI/edit?usp=sharing
Review-Url: https://codereview.chromium.org/2646443005 .
2017-02-09 15:39:44 -08:00

56 lines
2.0 KiB
C++

// 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.
#ifndef RUNTIME_VM_STACK_TRACE_H_
#define RUNTIME_VM_STACK_TRACE_H_
#include "vm/allocation.h"
#include "vm/flag_list.h"
#include "vm/object.h"
namespace dart {
DECLARE_FLAG(bool, show_invisible_frames);
class StackTraceUtils : public AllStatic {
public:
/// Counts the number of stack frames.
/// Skips over the first |skip_frames|.
/// If |async_function| is not null, stops at the function that has
/// |async_function| as its parent.
static intptr_t CountFrames(
Thread* thread,
int skip_frames,
const Function& async_function,
bool count_invisible_frames = FLAG_show_invisible_frames);
/// Collects |count| frames into |code_array| and |pc_offset_array|.
/// Writing begins at |array_offset|.
/// Skips over the first |skip_frames|.
/// Returns the number of frames collected.
static intptr_t 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 = FLAG_show_invisible_frames);
/// If |thread| has no async_stack_trace, does nothing.
/// Populates |async_function| with the top function of the async stack
/// trace. Populates |async_stack_trace|, |async_code_array|, and
/// |async_pc_offset_array| with the thread's async_stack_trace.
/// Returns the length of the asynchronous stack trace.
static intptr_t ExtractAsyncStackTraceInfo(Thread* thread,
Function* async_function,
StackTrace* async_stack_trace,
Array* async_code_array,
Array* async_pc_offset_array);
};
} // namespace dart
#endif // RUNTIME_VM_STACK_TRACE_H_