18const intptr_t k_StreamController__STATE_SUBSCRIBED = 1;
20const intptr_t k_StreamController__STATE_SUBSCRIPTION_MASK = 3;
22const intptr_t k_StreamController__STATE_ADDSTREAM = 8;
24const intptr_t k_BufferingStreamSubscription__STATE_HAS_ERROR_HANDLER = 1 << 5;
26const intptr_t k_Future__stateIgnoreError = 1;
28const intptr_t k_FutureListener_stateThen = 1;
30const intptr_t k_FutureListener_stateCatchError = 2;
32const intptr_t k_FutureListener_stateWhenComplete = 8;
34const intptr_t k_FutureListener_maskAwait = 16;
36bool WasPreviouslySuspended(
const Function&
function,
37 const Object& suspend_state_var) {
38 if (!suspend_state_var.IsSuspendState()) {
45 return SuspendState::Cast(suspend_state_var).error_callback() !=
47 }
else if (
function.IsAsyncGenerator()) {
54bool TryGetAwaiterLink(
const Closure&
closure, Object*
link) {
57 const auto awaiter_link =
function.awaiter_link();
59 if (
function.IsImplicitClosureFunction()) {
60 ASSERT(awaiter_link.depth == 0 && awaiter_link.index == 0);
66 intptr_t depth = awaiter_link.depth;
68 context = context.parent();
71 *
link = context.At(awaiter_link.index);
82class AsyncAwareStackUnwinder :
public ValueObject {
84 explicit AsyncAwareStackUnwinder(Thread* thread,
85 bool* encountered_async_catch_error)
86 : zone_(thread->zone()),
87 sync_frames_(thread, StackFrameIterator::kNoCrossThreadIteration),
89 awaiter_frame_{Closure::Handle(zone_), Object::Handle(zone_)},
90 encountered_async_catch_error_(encountered_async_catch_error),
91 closure_(Closure::Handle(zone_)),
92 code_(Code::Handle(zone_)),
93 context_(
Context::Handle(zone_)),
94 function_(Function::Handle(zone_)),
95 parent_function_(Function::Handle(zone_)),
96 object_(Object::Handle(zone_)),
97 result_future_(Object::Handle(zone_)),
98 suspend_state_(SuspendState::Handle(zone_)),
99 controller_(Object::Handle(zone_)),
100 subscription_(Object::Handle(zone_)),
101 stream_iterator_(Object::Handle(zone_)),
102 async_lib_(Library::Handle(zone_, Library::AsyncLibrary())),
103 null_closure_(Closure::Handle(zone_)) {
104 if (encountered_async_catch_error_ !=
nullptr) {
105 *encountered_async_catch_error_ =
false;
109 void Unwind(intptr_t skip_frames,
110 std::function<
void(
const StackTraceUtils::Frame&)> handle_frame);
113 bool HandleSynchronousFrame();
115 void UnwindAwaiterFrame();
118 ObjectPtr FindCallerInAsyncStarStreamController(
119 const Object& async_star_stream_controller);
121 void InitializeAwaiterFrameFromSuspendState();
123 void InitializeAwaiterFrameFromFutureListener(
const Object& listener);
125 void UnwindToAwaiter();
128 void UnwindFrameToFutureListener();
131 void UnwindFrameToStreamController();
138 void FollowAwaiterLinks(Closure*
closure, Object*
link);
141 void ComputeNextFrameFromAwaiterLink();
154 bool WillFutureHandleError(
const Object& future, intptr_t depth = 0);
156 void MarkAsHandlingAsyncError()
const {
157 if (ShouldComputeIfAsyncErrorIsHandled()) {
158 *encountered_async_catch_error_ =
true;
162 bool ShouldComputeIfAsyncErrorIsHandled()
const {
163 return encountered_async_catch_error_ !=
nullptr &&
164 !*encountered_async_catch_error_;
167#define USED_CLASS_LIST(V) \
168 V(_AsyncStarStreamController) \
169 V(_BufferingStreamSubscription) \
173 V(_ControllerSubscription) \
176 V(_StreamController) \
178 V(_SyncStreamController) \
179 V(_StreamControllerAddStreamState) \
183#define DECLARE_CONSTANT(symbol) k##symbol,
185#undef DECLARE_CONSTANT
188#define USED_FIELD_LIST(V) \
189 V(_AsyncStarStreamController, asyncStarBody) \
190 V(_AsyncStarStreamController, controller) \
191 V(_BufferingStreamSubscription, _onData) \
192 V(_BufferingStreamSubscription, _onDone) \
193 V(_BufferingStreamSubscription, _onError) \
194 V(_BufferingStreamSubscription, _state) \
195 V(_Completer, future) \
196 V(_Future, _resultOrListeners) \
198 V(_FutureListener, callback) \
199 V(_FutureListener, result) \
200 V(_FutureListener, state) \
201 V(_FutureListener, _nextListener) \
202 V(_StreamController, _state) \
203 V(_StreamController, _varData) \
204 V(_StreamControllerAddStreamState, _varData) \
205 V(_StreamIterator, _hasValue) \
206 V(_StreamIterator, _stateData) \
207 V(_AddStreamState, addStreamFuture)
210#define DECLARE_CONSTANT(class_symbol, field_symbol) \
211 k##class_symbol##_##field_symbol,
213#undef DECLARE_CONSTANT
216#define PLUS_ONE(...) +1
221#define DECLARE_GETTER(symbol) \
222 const Class& symbol() { \
223 auto& cls = classes_[k##symbol]; \
224 if (cls == nullptr) { \
225 cls = &Class::Handle( \
226 zone_, async_lib_.LookupClassAllowPrivate(Symbols::symbol())); \
227 ASSERT(!cls->IsNull()); \
234#define DECLARE_GETTER(class_symbol, field_symbol) \
235 ObjectPtr Get##class_symbol##_##field_symbol(const Object& obj) { \
236 auto& field = fields_[k##class_symbol##_##field_symbol]; \
237 if (field == nullptr) { \
238 field = &Field::Handle(zone_, class_symbol().LookupFieldAllowPrivate( \
239 Symbols::field_symbol())); \
240 ASSERT(!field->IsNull()); \
242 return Instance::Cast(obj).GetField(*field); \
247 struct AwaiterFrame {
253 DartFrameIterator sync_frames_;
255 StackFrame* sync_frame_;
256 AwaiterFrame awaiter_frame_;
258 bool* encountered_async_catch_error_;
264 Function& parent_function_;
266 Object& result_future_;
267 SuspendState& suspend_state_;
270 Object& subscription_;
271 Object& stream_iterator_;
273 const Library& async_lib_;
274 Class* classes_[kUsedClassCount] = {};
275 Field* fields_[kUsedFieldCount] = {};
277 const Closure& null_closure_;
282void AsyncAwareStackUnwinder::Unwind(
283 intptr_t skip_frames,
284 std::function<
void(
const StackTraceUtils::Frame&)> handle_frame) {
286 sync_frame_ = sync_frames_.NextFrame();
287 while (skip_frames > 0 && sync_frame_ !=
nullptr) {
288 sync_frame_ = sync_frames_.NextFrame();
294 while (sync_frame_ !=
nullptr && awaiter_frame_.closure.IsNull()) {
295 const bool was_handled = HandleSynchronousFrame();
297 code_ = sync_frame_->LookupDartCode();
298 const uword pc_offset = sync_frame_->pc() - code_.PayloadStart();
299 handle_frame({sync_frame_, code_, pc_offset, null_closure_});
301 sync_frame_ = sync_frames_.NextFrame();
304 const StackTraceUtils::Frame gap_frame = {
nullptr,
305 StubCode::AsynchronousGapMarker(),
309 bool any_async =
false;
310 for (; !awaiter_frame_.closure.IsNull(); UnwindToAwaiter()) {
311 function_ = awaiter_frame_.closure.function();
312 if (function_.IsNull()) {
318 if (awaiter_frame_.next.IsSuspendState()) {
319 const uword pc = SuspendState::Cast(awaiter_frame_.next).pc();
325 code_ = SuspendState::Cast(awaiter_frame_.next).GetCodeObject();
326 pc_offset = pc - code_.PayloadStart();
331 code_ = function_.EnsureHasCode();
335 code_.PayloadStart();
338 handle_frame(gap_frame);
339 handle_frame({
nullptr, code_, pc_offset, awaiter_frame_.closure});
343 handle_frame(gap_frame);
348 return *(
reinterpret_cast<ObjectPtr*
>(sync_frame_->GetCallerSp()) +
349 function_.num_fixed_parameters() - 1);
352bool AsyncAwareStackUnwinder::HandleSynchronousFrame() {
353 function_ = sync_frame_->LookupDartFunction();
354 if (function_.IsNull()) {
359 if (function_.IsAsyncFunction() || function_.IsAsyncGenerator()) {
360 InitializeAwaiterFrameFromSuspendState();
366 if (function_.HasAwaiterLink()) {
368 if (object_.IsClosure() &&
370 &awaiter_frame_.next)) {
371 awaiter_frame_.closure ^= object_.ptr();
377 if (function_.recognized_kind() ==
378 MethodRecognizer::kFutureListenerHandleValue) {
380 InitializeAwaiterFrameFromFutureListener(object_);
388void AsyncAwareStackUnwinder::InitializeAwaiterFrameFromSuspendState() {
389 if (function_.IsAsyncFunction() || function_.IsAsyncGenerator()) {
397 if (WasPreviouslySuspended(function_, object_)) {
398 awaiter_frame_.next = object_.ptr();
404void AsyncAwareStackUnwinder::UnwindToAwaiter() {
406 UnwindAwaiterFrame();
407 }
while (awaiter_frame_.closure.IsNull() && !awaiter_frame_.next.IsNull());
410void AsyncAwareStackUnwinder::FollowAwaiterLinks(Closure*
closure,
419void AsyncAwareStackUnwinder::ComputeNextFrameFromAwaiterLink() {
420 FollowAwaiterLinks(&awaiter_frame_.closure, &object_);
421 if (!object_.IsNull()) {
422 awaiter_frame_.next = object_.ptr();
426void AsyncAwareStackUnwinder::UnwindAwaiterFrame() {
427 if (awaiter_frame_.next.IsSuspendState()) {
428 awaiter_frame_.next =
429 SuspendState::Cast(awaiter_frame_.next).function_data();
430 }
else if (awaiter_frame_.next.GetClassId() == _SyncCompleter().
id() ||
431 awaiter_frame_.next.GetClassId() == _AsyncCompleter().
id()) {
432 awaiter_frame_.next = Get_Completer_future(awaiter_frame_.next);
435 if (awaiter_frame_.next.GetClassId() == _AsyncStarStreamController().
id()) {
436 awaiter_frame_.next =
437 Get_AsyncStarStreamController_controller(awaiter_frame_.next);
440 if (awaiter_frame_.next.GetClassId() == _Future().
id()) {
441 UnwindFrameToFutureListener();
442 }
else if (awaiter_frame_.next.GetClassId() == _SyncStreamController().
id()) {
443 UnwindFrameToStreamController();
444 ComputeNextFrameFromAwaiterLink();
451void AsyncAwareStackUnwinder::UnwindFrameToFutureListener() {
452 object_ = Get_Future__resultOrListeners(awaiter_frame_.next);
453 if (object_.GetClassId() == _FutureListener().
id()) {
454 InitializeAwaiterFrameFromFutureListener(object_);
456 if (ShouldComputeIfAsyncErrorIsHandled()) {
460 if ((
state & k_Future__stateIgnoreError) != 0) {
461 MarkAsHandlingAsyncError();
470bool AsyncAwareStackUnwinder::WillFutureHandleError(
const Object& future,
472 if (depth > 100 || future.GetClassId() != _Future().
id()) {
476 if (Get_Future__resultOrListeners(future) ==
Object::null()) {
479 return (
state & k_Future__stateIgnoreError) != 0;
482 for (
auto& listener =
Object::Handle(Get_Future__resultOrListeners(future));
483 listener.
GetClassId() == _FutureListener().
id();
484 listener = Get_FutureListener__nextListener(listener)) {
487 if ((
state & k_FutureListener_stateCatchError) == 0 &&
488 !WillFutureHandleError(
489 Object::Handle(Get_FutureListener_result(listener)), depth + 1)) {
497void AsyncAwareStackUnwinder::InitializeAwaiterFrameFromFutureListener(
498 const Object& listener) {
499 if (listener.GetClassId() != _FutureListener().
id()) {
507 if (
state == k_FutureListener_stateThen ||
508 state == k_FutureListener_stateCatchError ||
509 state == k_FutureListener_stateWhenComplete ||
511 (k_FutureListener_stateThen | k_FutureListener_stateCatchError) ||
512 state == (k_FutureListener_stateThen | k_FutureListener_stateCatchError |
513 k_FutureListener_maskAwait)) {
514 result_future_ = Get_FutureListener_result(listener);
518 awaiter_frame_.closure =
520 awaiter_frame_.next = result_future_.ptr();
522 ComputeNextFrameFromAwaiterLink();
524 if (ShouldComputeIfAsyncErrorIsHandled() && !result_future_.IsNull() &&
525 result_future_.ptr() != awaiter_frame_.next.ptr()) {
532 if ((
state & k_FutureListener_stateCatchError) == 0 &&
533 WillFutureHandleError(result_future_)) {
534 MarkAsHandlingAsyncError();
549 if ((
state & k_FutureListener_stateCatchError) != 0 &&
550 ((
state & k_FutureListener_maskAwait) == 0 ||
551 !awaiter_frame_.next.IsSuspendState())) {
552 MarkAsHandlingAsyncError();
556void AsyncAwareStackUnwinder::UnwindFrameToStreamController() {
557 controller_ = awaiter_frame_.next.ptr();
566 if ((
state & k_StreamController__STATE_SUBSCRIPTION_MASK) !=
567 k_StreamController__STATE_SUBSCRIBED) {
571 subscription_ = Get_StreamController__varData(controller_);
572 if ((
state & k_StreamController__STATE_ADDSTREAM) != 0) {
573 subscription_ = Get_StreamControllerAddStreamState__varData(subscription_);
576 closure_ ^= Get_BufferingStreamSubscription__onData(subscription_);
579 Smi::RawCast(Get_BufferingStreamSubscription__state(subscription_)));
581 const auto has_error_handler =
582 ((subscription_state &
583 k_BufferingStreamSubscription__STATE_HAS_ERROR_HANDLER) != 0);
587 function_ = closure_.function();
588 if (function_.IsImplicitClosureFunction()) {
592 if (function_.Owner() == _StreamIterator().ptr()) {
595 stream_iterator_ = closure_.GetImplicitClosureReceiver();
597 if (stream_iterator_.GetClassId() != _StreamIterator().id()) {
612 if (Get_StreamIterator__hasValue(stream_iterator_) ==
613 Object::bool_true().ptr()) {
614 if (has_error_handler) {
615 MarkAsHandlingAsyncError();
625 object_ = Get_StreamIterator__stateData(stream_iterator_);
626 if (object_.GetClassId() == _Future().
id()) {
627 awaiter_frame_.next = object_.ptr();
629 if (has_error_handler) {
630 MarkAsHandlingAsyncError();
640 if (function_.Owner() == _StreamController().ptr()) {
643 object_ = closure_.GetImplicitClosureReceiver();
646 if ((
state & k_StreamController__STATE_ADDSTREAM) != 0) {
650 object_ = Get_StreamController__varData(object_);
651 object_ = Get_AddStreamState_addStreamFuture(object_);
652 object_ = Get_Future__resultOrListeners(object_);
653 if (object_.GetClassId() == _FutureListener().
id()) {
656 if (
state == k_FutureListener_stateThen) {
659 FollowAwaiterLinks(&handler, &object_);
660 if (object_.GetClassId() == _AsyncStarStreamController().
id()) {
662 Get_AsyncStarStreamController_asyncStarBody(object_));
671 awaiter_frame_.closure = closure_.ptr();
673 bool found_awaiter_link_in_sibling_handler =
false;
675 if (!function_.HasAwaiterLink()) {
678 closure_ ^= Get_BufferingStreamSubscription__onError(subscription_);
679 function_ = closure_.function();
680 found_awaiter_link_in_sibling_handler = function_.HasAwaiterLink();
683 if (!function_.HasAwaiterLink()) {
684 closure_ ^= Get_BufferingStreamSubscription__onDone(subscription_);
685 function_ = closure_.function();
686 found_awaiter_link_in_sibling_handler = function_.HasAwaiterLink();
689 if (has_error_handler || found_awaiter_link_in_sibling_handler) {
690 FollowAwaiterLinks(&closure_, &object_);
693 if (has_error_handler && object_.GetClassId() != _Future().
id() &&
694 object_.GetClassId() != _SyncStreamController().
id()) {
695 MarkAsHandlingAsyncError();
698 if (found_awaiter_link_in_sibling_handler) {
699 if (object_.GetClassId() == _AsyncStarStreamController().
id() ||
700 object_.GetClassId() == _SyncStreamController().
id()) {
702 awaiter_frame_.closure = closure_.ptr();
704 awaiter_frame_.next = object_.ptr();
717 const auto is_class = [&](
const String&
name) {
722 return is_class(Symbols::_AsyncStarStreamController()) ||
723 is_class(Symbols::_SyncStreamController()) ||
724 is_class(Symbols::_StreamController()) ||
725 is_class(Symbols::_Completer()) ||
726 is_class(Symbols::_AsyncCompleter()) ||
727 is_class(Symbols::_SyncCompleter()) || is_class(Symbols::_Future());
738 MethodRecognizer::kFutureListenerHandleValue) {
749 bool* has_async_catch_error ) {
750 AsyncAwareStackUnwinder it(thread, has_async_catch_error);
751 it.Unwind(skip_frames, handle_frame);
756 if (TryGetAwaiterLink(
closure, suspend_state)) {
757 return suspend_state->IsSuspendState();
static float next(float f)
#define RELEASE_ASSERT(cond)
LibraryPtr library() const
static constexpr uint8_t kNoAwaiterLinkDepth
static LibraryPtr AsyncLibrary()
intptr_t GetClassId() const
static ObjectPtr RawCast(ObjectPtr obj)
static bool IsNeededForAsyncAwareUnwinding(const Function &function)
static bool GetSuspendState(const Closure &closure, Object *suspend_state)
static void CollectFrames(Thread *thread, int skip_frames, const std::function< void(const Frame &)> &handle_frame, bool *has_async_catch_error=nullptr)
static bool IsPossibleAwaiterLink(const Class &cls)
static constexpr uword kFutureListenerPcOffset
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
static constexpr intptr_t kSuspendStateVarIndex
Dart_NativeFunction function
def link(from_root, to_root)
const char *const class_name
FrameLayout runtime_frame_layout
static DART_FORCE_INLINE uword LocalVarAddress(uword fp, intptr_t index)
std::function< void()> closure
T * GetReceiver(Dart_NativeArguments args)
#define DECLARE_CONSTANT(symbol)
#define USED_CLASS_LIST(V)
#define USED_FIELD_LIST(V)
#define DECLARE_GETTER(symbol)
intptr_t FrameSlotForVariableIndex(intptr_t index) const