|  | // 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 <functional> | 
|  |  | 
|  | #include "vm/allocation.h" | 
|  | #include "vm/flag_list.h" | 
|  | #include "vm/object.h" | 
|  | #include "vm/symbols.h" | 
|  |  | 
|  | namespace dart { | 
|  |  | 
|  | class StackTraceUtils : public AllStatic { | 
|  | public: | 
|  | static constexpr uword kFutureListenerPcOffset = 1; | 
|  |  | 
|  | struct Frame { | 
|  | // Corresponding on stack frame or |nullptr| if this is an awaiter frame | 
|  | // or a gap. | 
|  | StackFrame* frame; | 
|  |  | 
|  | // Code object corresponding to this frame. | 
|  | const Code& code; | 
|  |  | 
|  | // Bytecode object corresponding to this frame. | 
|  | const Bytecode& bytecode; | 
|  |  | 
|  | // Offset into the code object corresponding to this frame. | 
|  | // | 
|  | // Will be set to |kFutureListenerPcOffset| if this frame corresponds to | 
|  | // future listener that is not yet executing. | 
|  | uword pc_offset; | 
|  |  | 
|  | // Closure corresponding to the awaiter frame or |null| if this is | 
|  | // a synchronous frame or a gap. | 
|  | const Closure& closure; | 
|  | }; | 
|  |  | 
|  | // Returns |true| if this function is needed to correctly unwind through | 
|  | // awaiter chains. This means AOT compiler should retain |Function| object, | 
|  | // its signature and the corresponding |Code| object (so that we could | 
|  | // perform the reverse lookup). | 
|  | static bool IsNeededForAsyncAwareUnwinding(const Function& function); | 
|  |  | 
|  | // Returns |true| if the given class might serve as an awaiter-link when | 
|  | // unwinding an awaiter chain. | 
|  | // | 
|  | // This is used to eagerly mark tear-offs of methods on this class | 
|  | // as having an awaiter-link. | 
|  | static bool IsPossibleAwaiterLink(const Class& cls); | 
|  |  | 
|  | /// Collects all frames on the current stack until an async/async* frame is | 
|  | /// hit which has yielded before (i.e. is not in sync-async case). | 
|  | /// | 
|  | /// From there on finds the closure of the async/async* frame and starts | 
|  | /// traversing the listeners. | 
|  | static void CollectFrames( | 
|  | Thread* thread, | 
|  | int skip_frames, | 
|  | const std::function<void(const Frame&)>& handle_frame, | 
|  | bool* has_async_catch_error = nullptr); | 
|  |  | 
|  | // If |closure| has an awaiter-link pointing to the |SuspendState| | 
|  | // the return that object. | 
|  | static bool GetSuspendState(const Closure& closure, Object* suspend_state); | 
|  | }; | 
|  |  | 
|  | }  // namespace dart | 
|  |  | 
|  | #endif  // RUNTIME_VM_STACK_TRACE_H_ |