// 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_trace.h"

#include "vm/dart_api_impl.h"
#include "vm/object_store.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

namespace {

// Keep in sync with:
// - _StreamController._STATE_SUBSCRIBED.
const intptr_t k_StreamController__STATE_SUBSCRIBED = 1;
// - _StreamController._STATE_SUBSCRIPTION_MASK.
const intptr_t k_StreamController__STATE_SUBSCRIPTION_MASK = 3;
// - _StreamController._STATE_ADDSTREAM.
const intptr_t k_StreamController__STATE_ADDSTREAM = 8;
// - _BufferingStreamSubscription._STATE_HAS_ERROR_HANDLER.
const intptr_t k_BufferingStreamSubscription__STATE_HAS_ERROR_HANDLER = 1 << 5;
// - _Future._stateIgnoreError
const intptr_t k_Future__stateIgnoreError = 1;
// - _FutureListener.stateThen.
const intptr_t k_FutureListener_stateThen = 1;
// - _FutureListener.stateCatchError.
const intptr_t k_FutureListener_stateCatchError = 2;
// - _FutureListener.stateWhenComplete.
const intptr_t k_FutureListener_stateWhenComplete = 8;
// - sdk/lib/async/future_impl.dart:_FutureListener.maskAwait.
const intptr_t k_FutureListener_maskAwait = 16;

bool WasPreviouslySuspended(const Function& function,
                            const Object& suspend_state_var) {
  if (!suspend_state_var.IsSuspendState()) {
    return false;
  }
  if (function.IsAsyncFunction()) {
    // Error callback is set after both 'then' and 'error' callbacks are
    // registered with the Zone. Callback registration may query
    // stack trace and should still collect the synchronous stack trace.
    return SuspendState::Cast(suspend_state_var).error_callback() !=
           Object::null();
  } else if (function.IsAsyncGenerator()) {
    return true;
  } else {
    UNREACHABLE();
  }
}

bool TryGetAwaiterLink(const Closure& closure, Object* link) {
  *link = Object::null();
  const auto& function = Function::Handle(closure.function());
  const auto awaiter_link = function.awaiter_link();
  if (awaiter_link.depth != ClosureData::kNoAwaiterLinkDepth) {
    if (function.IsImplicitClosureFunction()) {
      ASSERT(awaiter_link.depth == 0 && awaiter_link.index == 0);
      *link = closure.GetImplicitClosureReceiver();
      return true;
    }

    auto& context = Context::Handle(closure.GetContext());
    intptr_t depth = awaiter_link.depth;
    while (depth-- > 0) {
      context = context.parent();
    }

    *link = context.At(awaiter_link.index);
    return true;
  }
  return false;
}

// Unwinder which starts by unwinding the synchronous portion of the stack
// until it reaches a frame which has an asynchronous awaiter (e.g. an
// activation of the async function which has a listener attached to the
// corresponding Future object) and then unwinds through the chain
// of awaiters.
class AsyncAwareStackUnwinder : public ValueObject {
 public:
  explicit AsyncAwareStackUnwinder(Thread* thread,
                                   bool* encountered_async_catch_error)
      : zone_(thread->zone()),
        sync_frames_(thread, StackFrameIterator::kNoCrossThreadIteration),
        sync_frame_(nullptr),
        awaiter_frame_{Closure::Handle(zone_), Object::Handle(zone_)},
        encountered_async_catch_error_(encountered_async_catch_error),
        closure_(Closure::Handle(zone_)),
        code_(Code::Handle(zone_)),
        bytecode_(Bytecode::Handle(zone_)),
        context_(Context::Handle(zone_)),
        function_(Function::Handle(zone_)),
        parent_function_(Function::Handle(zone_)),
        object_(Object::Handle(zone_)),
        result_future_(Object::Handle(zone_)),
        suspend_state_(SuspendState::Handle(zone_)),
        controller_(Object::Handle(zone_)),
        subscription_(Object::Handle(zone_)),
        stream_iterator_(Object::Handle(zone_)),
        async_lib_(Library::Handle(zone_, Library::AsyncLibrary())),
        null_closure_(Closure::Handle(zone_)),
        null_code_(Code::Handle(zone_)),
        null_bytecode_(Bytecode::Handle(zone_)) {
    if (encountered_async_catch_error_ != nullptr) {
      *encountered_async_catch_error_ = false;
    }
  }

  void Unwind(intptr_t skip_frames,
              std::function<void(const StackTraceUtils::Frame&)> handle_frame);

 private:
  bool HandleSynchronousFrame();

  void UnwindAwaiterFrame();

  // Returns either the `onData` or the Future awaiter.
  ObjectPtr FindCallerInAsyncStarStreamController(
      const Object& async_star_stream_controller);

  void InitializeAwaiterFrameFromSuspendState();

  void InitializeAwaiterFrameFromFutureListener(const Object& listener);

  void UnwindToAwaiter();

  // |frame.next| is a |_Future| instance. Unwind to the next frame.
  void UnwindFrameToFutureListener();

  // |frame.next| is an |_SyncStreamController| instance.
  void UnwindFrameToStreamController();

  // Follow awaiter-links from the given closure until the first
  // non-closure awaiter-link is encountered.
  //
  // |link| will contain the first non-closure awaiter-link or `null`.
  // |closure| will be updated to point to the last closure in the chain.
  void FollowAwaiterLinks(Closure* closure, Object* link);

  // Update |awaiter_frame| by unwinding awaiter links of the current closure.
  void ComputeNextFrameFromAwaiterLink();

  ObjectPtr GetReceiver() const;

  // Returns |true| if propagating an error to the listeners of this `_Future`
  // will always encounter an error handler. Future handles error iff:
  //
  // * It has no listeners and is marked as ignoring errors
  // * All of its listeners either have an error handler or corresponding
  //   result future handles error.
  //
  // Note: this ignores simple error forwarding/rethrow which occurs in `await`
  // or patterns like `fut.then(onError: c.completeError)`.
  bool WillFutureHandleError(const Object& future, intptr_t depth = 0);

  void MarkAsHandlingAsyncError() const {
    if (ShouldComputeIfAsyncErrorIsHandled()) {
      *encountered_async_catch_error_ = true;
    }
  }

  bool ShouldComputeIfAsyncErrorIsHandled() const {
    return encountered_async_catch_error_ != nullptr &&
           !*encountered_async_catch_error_;
  }

#define USED_CLASS_LIST(V)                                                     \
  V(_AsyncStarStreamController)                                                \
  V(_BufferingStreamSubscription)                                              \
  V(_Completer)                                                                \
  V(_AsyncCompleter)                                                           \
  V(_SyncCompleter)                                                            \
  V(_ControllerSubscription)                                                   \
  V(_Future)                                                                   \
  V(_FutureListener)                                                           \
  V(_StreamController)                                                         \
  V(_StreamIterator)                                                           \
  V(_SyncStreamController)                                                     \
  V(_StreamControllerAddStreamState)                                           \
  V(_AddStreamState)

  enum ClassId {
#define DECLARE_CONSTANT(symbol) k##symbol,
    USED_CLASS_LIST(DECLARE_CONSTANT)
#undef DECLARE_CONSTANT
  };

#define USED_FIELD_LIST(V)                                                     \
  V(_AsyncStarStreamController, asyncStarBody)                                 \
  V(_AsyncStarStreamController, controller)                                    \
  V(_BufferingStreamSubscription, _onData)                                     \
  V(_BufferingStreamSubscription, _onDone)                                     \
  V(_BufferingStreamSubscription, _onError)                                    \
  V(_BufferingStreamSubscription, _state)                                      \
  V(_Completer, future)                                                        \
  V(_Future, _resultOrListeners)                                               \
  V(_Future, _state)                                                           \
  V(_FutureListener, callback)                                                 \
  V(_FutureListener, result)                                                   \
  V(_FutureListener, state)                                                    \
  V(_FutureListener, _nextListener)                                            \
  V(_StreamController, _state)                                                 \
  V(_StreamController, _varData)                                               \
  V(_StreamControllerAddStreamState, _varData)                                 \
  V(_StreamIterator, _hasValue)                                                \
  V(_StreamIterator, _stateData)                                               \
  V(_AddStreamState, addStreamFuture)

  enum FieldId {
#define DECLARE_CONSTANT(class_symbol, field_symbol)                           \
  k##class_symbol##_##field_symbol,
    USED_FIELD_LIST(DECLARE_CONSTANT)
#undef DECLARE_CONSTANT
  };

#define PLUS_ONE(...) +1
  static constexpr intptr_t kUsedClassCount = 0 USED_CLASS_LIST(PLUS_ONE);
  static constexpr intptr_t kUsedFieldCount = 0 USED_FIELD_LIST(PLUS_ONE);
#undef PLUS_ONE

#define DECLARE_GETTER(symbol)                                                 \
  const Class& symbol() {                                                      \
    auto& cls = classes_[k##symbol];                                           \
    if (cls == nullptr) {                                                      \
      cls = &Class::Handle(                                                    \
          zone_, async_lib_.LookupClassAllowPrivate(Symbols::symbol()));       \
      ASSERT(!cls->IsNull());                                                  \
    }                                                                          \
    return *cls;                                                               \
  }
  USED_CLASS_LIST(DECLARE_GETTER)
#undef DECLARE_GETTER

#define DECLARE_GETTER(class_symbol, field_symbol)                             \
  ObjectPtr Get##class_symbol##_##field_symbol(const Object& obj) {            \
    auto& field = fields_[k##class_symbol##_##field_symbol];                   \
    if (field == nullptr) {                                                    \
      field = &Field::Handle(zone_, class_symbol().LookupFieldAllowPrivate(    \
                                        Symbols::field_symbol()));             \
      ASSERT(!field->IsNull());                                                \
    }                                                                          \
    return Instance::Cast(obj).GetField(*field);                               \
  }
  USED_FIELD_LIST(DECLARE_GETTER)
#undef DECLARE_GETTER

  struct AwaiterFrame {
    Closure& closure;
    Object& next;
  };

  Zone* zone_;
  DartFrameIterator sync_frames_;

  StackFrame* sync_frame_;
  AwaiterFrame awaiter_frame_;

  bool* encountered_async_catch_error_;

  Closure& closure_;
  Code& code_;
  Bytecode& bytecode_;
  Context& context_;
  Function& function_;
  Function& parent_function_;
  Object& object_;
  Object& result_future_;
  SuspendState& suspend_state_;

  Object& controller_;
  Object& subscription_;
  Object& stream_iterator_;

  const Library& async_lib_;
  Class* classes_[kUsedClassCount] = {};
  Field* fields_[kUsedFieldCount] = {};

  const Closure& null_closure_;
  const Code& null_code_;
  const Bytecode& null_bytecode_;

  DISALLOW_COPY_AND_ASSIGN(AsyncAwareStackUnwinder);
};

void AsyncAwareStackUnwinder::Unwind(
    intptr_t skip_frames,
    std::function<void(const StackTraceUtils::Frame&)> handle_frame) {
  // First skip the given number of synchronous frames.
  sync_frame_ = sync_frames_.NextFrame();
  while (skip_frames > 0 && sync_frame_ != nullptr) {
    sync_frame_ = sync_frames_.NextFrame();
    skip_frames--;
  }

  // Continue unwinding synchronous portion of the stack looking for
  // a synchronous frame which has an awaiter.
  while (sync_frame_ != nullptr && awaiter_frame_.closure.IsNull()) {
    const bool was_handled = HandleSynchronousFrame();
    if (!was_handled) {
      if (sync_frame_->is_interpreted()) {
        bytecode_ = sync_frame_->LookupDartBytecode();
        if (bytecode_.function() != Function::null()) {
          const uword pc_offset = sync_frame_->pc() - bytecode_.PayloadStart();
          handle_frame(
              {sync_frame_, null_code_, bytecode_, pc_offset, null_closure_});
        }
      } else {
        code_ = sync_frame_->LookupDartCode();
        const uword pc_offset = sync_frame_->pc() - code_.PayloadStart();
        handle_frame(
            {sync_frame_, code_, null_bytecode_, pc_offset, null_closure_});
      }
    }
    sync_frame_ = sync_frames_.NextFrame();
  }

  const StackTraceUtils::Frame gap_frame = {
      nullptr, StubCode::AsynchronousGapMarker(), null_bytecode_,
      /*pc_offset=*/0, null_closure_};

  // Traverse awaiter frames.
  bool any_async = false;
  for (; !awaiter_frame_.closure.IsNull(); UnwindToAwaiter()) {
    function_ = awaiter_frame_.closure.function();
    if (function_.IsNull()) {
      continue;
    }

    any_async = true;
    uword pc_offset;
    if (awaiter_frame_.next.IsSuspendState()) {
      const uword pc = SuspendState::Cast(awaiter_frame_.next).pc();
      if (pc == 0) {
        // Async function is already resumed.
        continue;
      }

      code_ = SuspendState::Cast(awaiter_frame_.next).GetCodeObject();
      pc_offset = pc - code_.PayloadStart();
    } else {
      // This is an asynchronous continuation represented by a closure which
      // will handle successful completion. This function is not yet executing
      // so we have to use artificial marker offset (1).
      code_ = function_.EnsureHasCode();
      RELEASE_ASSERT(!code_.IsNull());
      pc_offset =
          (function_.entry_point() + StackTraceUtils::kFutureListenerPcOffset) -
          code_.PayloadStart();
    }

    handle_frame(gap_frame);
    handle_frame(
        {nullptr, code_, null_bytecode_, pc_offset, awaiter_frame_.closure});
  }

  if (any_async) {
    handle_frame(gap_frame);
  }
}

ObjectPtr AsyncAwareStackUnwinder::GetReceiver() const {
  return *(reinterpret_cast<ObjectPtr*>(sync_frame_->GetCallerSp()) +
           function_.num_fixed_parameters() - 1);
}

bool AsyncAwareStackUnwinder::HandleSynchronousFrame() {
  function_ = sync_frame_->LookupDartFunction();
  if (function_.IsNull()) {
    return false;
  }

  // This is an invocation of an `async` or `async*` function.
  if (function_.IsAsyncFunction() || function_.IsAsyncGenerator()) {
    InitializeAwaiterFrameFromSuspendState();
    return false;
  }

  // This is an invocation of a closure which has a variable marked
  // with `@pragma('vm:awaiter-link')` which points to the awaiter.
  if (function_.HasAwaiterLink()) {
    object_ = GetReceiver();
    if (object_.IsClosure() &&
        TryGetAwaiterLink(Closure::Cast(object_), &awaiter_frame_.next)) {
      if (awaiter_frame_.next.IsSuspendState()) {
        awaiter_frame_.closure ^= object_.ptr();
        return true;  // Hide this frame from the stack trace.
      } else if (awaiter_frame_.next.GetClassId() == _Future().id()) {
        UnwindFrameToFutureListener();
        return false;  // Do not hide this from the stack trace.
      }
    }
  }

  // This is `_FutureListener.handleValue(...)` invocation.
  if (function_.recognized_kind() ==
      MethodRecognizer::kFutureListenerHandleValue) {
    object_ = GetReceiver();
    InitializeAwaiterFrameFromFutureListener(object_);
    UnwindToAwaiter();
    return true;  // Hide this frame from the stack trace.
  }

  return false;
}

void AsyncAwareStackUnwinder::InitializeAwaiterFrameFromSuspendState() {
  if (function_.IsAsyncFunction() || function_.IsAsyncGenerator()) {
    // Check if we reached a resumed asynchronous function. In this case we
    // are going to start following async frames after we emit this frame.
    object_ = *reinterpret_cast<ObjectPtr*>(LocalVarAddress(
        sync_frame_->fp(), runtime_frame_layout.FrameSlotForVariableIndex(
                               SuspendState::kSuspendStateVarIndex)));

    awaiter_frame_.closure = Closure::null();
    if (WasPreviouslySuspended(function_, object_)) {
      awaiter_frame_.next = object_.ptr();
      UnwindToAwaiter();
    }
  }
}

void AsyncAwareStackUnwinder::UnwindToAwaiter() {
  do {
    UnwindAwaiterFrame();
  } while (awaiter_frame_.closure.IsNull() && !awaiter_frame_.next.IsNull());
}

void AsyncAwareStackUnwinder::FollowAwaiterLinks(Closure* closure,
                                                 Object* link) {
  *link = Object::null();
  while (!closure->IsNull() && TryGetAwaiterLink(*closure, link) &&
         link->IsClosure()) {
    *closure ^= link->ptr();
  }
}

void AsyncAwareStackUnwinder::ComputeNextFrameFromAwaiterLink() {
  FollowAwaiterLinks(&awaiter_frame_.closure, &object_);
  if (!object_.IsNull()) {
    awaiter_frame_.next = object_.ptr();
  }
}

void AsyncAwareStackUnwinder::UnwindAwaiterFrame() {
  if (awaiter_frame_.next.IsSuspendState()) {
    awaiter_frame_.next =
        SuspendState::Cast(awaiter_frame_.next).function_data();
  } else if (awaiter_frame_.next.GetClassId() == _SyncCompleter().id() ||
             awaiter_frame_.next.GetClassId() == _AsyncCompleter().id()) {
    awaiter_frame_.next = Get_Completer_future(awaiter_frame_.next);
  }

  if (awaiter_frame_.next.GetClassId() == _AsyncStarStreamController().id()) {
    awaiter_frame_.next =
        Get_AsyncStarStreamController_controller(awaiter_frame_.next);
  }

  if (awaiter_frame_.next.GetClassId() == _Future().id()) {
    UnwindFrameToFutureListener();
  } else if (awaiter_frame_.next.GetClassId() == _SyncStreamController().id()) {
    UnwindFrameToStreamController();
    ComputeNextFrameFromAwaiterLink();
  } else {
    awaiter_frame_.closure = Closure::null();
    awaiter_frame_.next = Object::null();
  }
}

void AsyncAwareStackUnwinder::UnwindFrameToFutureListener() {
  object_ = Get_Future__resultOrListeners(awaiter_frame_.next);
  if (object_.GetClassId() == _FutureListener().id()) {
    InitializeAwaiterFrameFromFutureListener(object_);
  } else {
    if (ShouldComputeIfAsyncErrorIsHandled()) {
      // Check if error on this future was ignored through |Future.ignore|.
      const auto state =
          Smi::Value(Smi::RawCast(Get_Future__state(awaiter_frame_.next)));
      if ((state & k_Future__stateIgnoreError) != 0) {
        MarkAsHandlingAsyncError();
      }
    }

    awaiter_frame_.closure = Closure::null();
    awaiter_frame_.next = Object::null();
  }
}

bool AsyncAwareStackUnwinder::WillFutureHandleError(const Object& future,
                                                    intptr_t depth /* = 0 */) {
  if (depth > 100 || future.GetClassId() != _Future().id()) {
    return true;  // Conservative.
  }

  if (Get_Future__resultOrListeners(future) == Object::null()) {
    // No listeners: check if future is simply ignoring errors.
    const auto state = Smi::Value(Smi::RawCast(Get_Future__state(future)));
    return (state & k_Future__stateIgnoreError) != 0;
  }

  for (auto& listener = Object::Handle(Get_Future__resultOrListeners(future));
       listener.GetClassId() == _FutureListener().id();
       listener = Get_FutureListener__nextListener(listener)) {
    const auto state =
        Smi::Value(Smi::RawCast(Get_FutureListener_state(listener)));
    if ((state & k_FutureListener_stateCatchError) == 0 &&
        !WillFutureHandleError(
            Object::Handle(Get_FutureListener_result(listener)), depth + 1)) {
      return false;
    }
  }

  return true;
}

void AsyncAwareStackUnwinder::InitializeAwaiterFrameFromFutureListener(
    const Object& listener) {
  if (listener.GetClassId() != _FutureListener().id()) {
    awaiter_frame_.closure = Closure::null();
    awaiter_frame_.next = Object::null();
    return;
  }

  const auto state =
      Smi::Value(Smi::RawCast(Get_FutureListener_state(listener)));
  if (state == k_FutureListener_stateThen ||
      state == k_FutureListener_stateCatchError ||
      state == k_FutureListener_stateWhenComplete ||
      state ==
          (k_FutureListener_stateThen | k_FutureListener_stateCatchError) ||
      state == (k_FutureListener_stateThen | k_FutureListener_stateCatchError |
                k_FutureListener_maskAwait)) {
    result_future_ = Get_FutureListener_result(listener);
  } else {
    result_future_ = Object::null();
  }
  awaiter_frame_.closure =
      Closure::RawCast(Get_FutureListener_callback(listener));
  awaiter_frame_.next = result_future_.ptr();

  ComputeNextFrameFromAwaiterLink();

  if (ShouldComputeIfAsyncErrorIsHandled() && !result_future_.IsNull() &&
      result_future_.ptr() != awaiter_frame_.next.ptr()) {
    // We have unwound through closure rather than followed result future, this
    // can be caused by unwinding through `await` or code like
    // `fut.whenComplete(c.complete)`. If the current future does not
    // catch the error then the error will be forwarded into result_future_.
    // Check if result_future_ handles it and set
    // encountered_async_catch_error_ respectively.
    if ((state & k_FutureListener_stateCatchError) == 0 &&
        WillFutureHandleError(result_future_)) {
      MarkAsHandlingAsyncError();
    }
  }

  // If the Future has catchError callback attached through either
  // `Future.catchError` or `Future.then(..., onError: ...)` then we should
  // treat this listener as a catch all exception handler. However we should
  // ignore the case when these callbacks are simply forwarding errors into a
  // suspended async function, because it will be represented by its own async
  // frame.
  //
  // However if we fail to unwind this frame (e.g. because there is some
  // Zone wrapping callbacks and obstructing unwinding) then we conservatively
  // treat this error handler as handling all errors to prevent user
  // unfriendly situations where debugger stops on handled exceptions.
  if ((state & k_FutureListener_stateCatchError) != 0 &&
      ((state & k_FutureListener_maskAwait) == 0 ||
       !awaiter_frame_.next.IsSuspendState())) {
    MarkAsHandlingAsyncError();
  }
}

void AsyncAwareStackUnwinder::UnwindFrameToStreamController() {
  controller_ = awaiter_frame_.next.ptr();

  // Clear the frame.
  awaiter_frame_.closure = Closure::null();
  awaiter_frame_.next = Object::null();

  const auto state =
      Smi::Value(Smi::RawCast(Get_StreamController__state(controller_)));

  if ((state & k_StreamController__STATE_SUBSCRIPTION_MASK) !=
      k_StreamController__STATE_SUBSCRIBED) {
    return;
  }

  subscription_ = Get_StreamController__varData(controller_);
  if ((state & k_StreamController__STATE_ADDSTREAM) != 0) {
    subscription_ = Get_StreamControllerAddStreamState__varData(subscription_);
  }

  closure_ ^= Get_BufferingStreamSubscription__onData(subscription_);

  const auto subscription_state = Smi::Value(
      Smi::RawCast(Get_BufferingStreamSubscription__state(subscription_)));

  const auto has_error_handler =
      ((subscription_state &
        k_BufferingStreamSubscription__STATE_HAS_ERROR_HANDLER) != 0);

  // If this is not the "_StreamIterator._onData" tear-off, we return the
  // callback we found.
  function_ = closure_.function();
  if (function_.IsImplicitClosureFunction()) {
    // Handle `await for` case. In this case onData is calling
    // _StreamIterator._onData which then notifies awaiter by completing
    // _StreamIterator.moveNextFuture.
    if (function_.Owner() == _StreamIterator().ptr()) {
      // All implicit closure functions (tear-offs) have the "this" receiver
      // captured in the context.
      stream_iterator_ = closure_.GetImplicitClosureReceiver();

      if (stream_iterator_.GetClassId() != _StreamIterator().id()) {
        UNREACHABLE();
      }

      // If `_hasValue` is true then the `StreamIterator._stateData` field
      // contains the iterator's value. In that case we cannot unwind anymore.
      //
      // Notice: With correct async* semantics this may never be true: the
      // async* generator should only be invoked to produce a value if there's
      // an in-progress `await streamIterator.moveNext()` call. Once such call
      // has finished the async* generator should be paused/yielded until the
      // next such call - and being paused/yielded means it should not appear
      // in stack traces.
      //
      // See dartbug.com/48695.
      if (Get_StreamIterator__hasValue(stream_iterator_) ==
          Object::bool_true().ptr()) {
        if (has_error_handler) {
          MarkAsHandlingAsyncError();
        }
        return;
      }

      // If we have an await'er for `await streamIterator.moveNext()` we
      // continue unwinding there.
      //
      // Notice: With correct async* semantics this may always contain a Future
      // See also comment above as well as dartbug.com/48695.
      object_ = Get_StreamIterator__stateData(stream_iterator_);
      if (object_.GetClassId() == _Future().id()) {
        awaiter_frame_.next = object_.ptr();
      } else {
        if (has_error_handler) {
          MarkAsHandlingAsyncError();
        }
      }
      return;
    }

    // Handle `yield*` case. Here one stream controller will be forwarding
    // to another one. If the destination controller is
    // _AsyncStarStreamController, then we should make sure to reflect
    // its asyncStarBody in the stack trace.
    if (function_.Owner() == _StreamController().ptr()) {
      // Get the controller to which we are forwarding and check if it is
      // in the ADD_STREAM state.
      object_ = closure_.GetImplicitClosureReceiver();
      const auto state =
          Smi::Value(Smi::RawCast(Get_StreamController__state(object_)));
      if ((state & k_StreamController__STATE_ADDSTREAM) != 0) {
        // Get to the addStreamFuture - if this is yield* internals we
        // will be able to get original _AsyncStarStreamController from
        // handler attached to that future.
        object_ = Get_StreamController__varData(object_);
        object_ = Get_AddStreamState_addStreamFuture(object_);
        object_ = Get_Future__resultOrListeners(object_);
        if (object_.GetClassId() == _FutureListener().id()) {
          const auto state =
              Smi::Value(Smi::RawCast(Get_FutureListener_state(object_)));
          if (state == k_FutureListener_stateThen) {
            auto& handler = Closure::Handle(
                Closure::RawCast(Get_FutureListener_callback(object_)));
            FollowAwaiterLinks(&handler, &object_);
            if (object_.GetClassId() == _AsyncStarStreamController().id()) {
              awaiter_frame_.closure = Closure::RawCast(
                  Get_AsyncStarStreamController_asyncStarBody(object_));
              return;
            }
          }
        }
      }
    }
  }

  awaiter_frame_.closure = closure_.ptr();

  bool found_awaiter_link_in_sibling_handler = false;

  if (!function_.HasAwaiterLink()) {
    // If we don't have awaiter-link in the `onData` handler, try checking
    // if either onError or onDone have an awaiter link.
    closure_ ^= Get_BufferingStreamSubscription__onError(subscription_);
    function_ = closure_.function();
    found_awaiter_link_in_sibling_handler = function_.HasAwaiterLink();
  }

  if (!function_.HasAwaiterLink()) {
    closure_ ^= Get_BufferingStreamSubscription__onDone(subscription_);
    function_ = closure_.function();
    found_awaiter_link_in_sibling_handler = function_.HasAwaiterLink();
  }

  if (has_error_handler || found_awaiter_link_in_sibling_handler) {
    FollowAwaiterLinks(&closure_, &object_);
  }

  if (has_error_handler && object_.GetClassId() != _Future().id() &&
      object_.GetClassId() != _SyncStreamController().id()) {
    MarkAsHandlingAsyncError();
  }

  if (found_awaiter_link_in_sibling_handler) {
    if (object_.GetClassId() == _AsyncStarStreamController().id() ||
        object_.GetClassId() == _SyncStreamController().id()) {
      // We can continue unwinding from here.
      awaiter_frame_.closure = closure_.ptr();
    } else {
      awaiter_frame_.next = object_.ptr();
    }
  }
}

}  // namespace

bool StackTraceUtils::IsPossibleAwaiterLink(const Class& cls) {
  if (cls.library() != Library::AsyncLibrary()) {
    return false;
  }

  String& class_name = String::Handle();
  const auto is_class = [&](const String& name) {
    class_name = cls.Name();
    return String::EqualsIgnoringPrivateKey(class_name, name);
  };

  return is_class(Symbols::_AsyncStarStreamController()) ||
         is_class(Symbols::_SyncStreamController()) ||
         is_class(Symbols::_StreamController()) ||
         is_class(Symbols::_Completer()) ||
         is_class(Symbols::_AsyncCompleter()) ||
         is_class(Symbols::_SyncCompleter()) || is_class(Symbols::_Future());
}

bool StackTraceUtils::IsNeededForAsyncAwareUnwinding(const Function& function) {
  // If this is a closure function which specifies an awaiter-link then
  // we need to retain both function and the corresponding code.
  if (function.HasAwaiterLink()) {
    return true;
  }

  if (function.recognized_kind() ==
      MethodRecognizer::kFutureListenerHandleValue) {
    return true;
  }

  return false;
}

void StackTraceUtils::CollectFrames(
    Thread* thread,
    int skip_frames,
    const std::function<void(const StackTraceUtils::Frame&)>& handle_frame,
    bool* has_async_catch_error /* = null */) {
  AsyncAwareStackUnwinder it(thread, has_async_catch_error);
  it.Unwind(skip_frames, handle_frame);
}

bool StackTraceUtils::GetSuspendState(const Closure& closure,
                                      Object* suspend_state) {
  if (TryGetAwaiterLink(closure, suspend_state)) {
    return suspend_state->IsSuspendState();
  }
  return false;
}

}  // namespace dart
