// 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_)),
        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_)) {
    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_;
  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_;

  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) {
      code_ = sync_frame_->LookupDartCode();
      const uword pc_offset = sync_frame_->pc() - code_.PayloadStart();
      handle_frame({sync_frame_, code_, pc_offset, null_closure_});
    }
    sync_frame_ = sync_frames_.NextFrame();
  }

  const StackTraceUtils::Frame gap_frame = {nullptr,
                                            StubCode::AsynchronousGapMarker(),
                                            /*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_, 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() &&
        StackTraceUtils::GetSuspendState(Closure::Cast(object_),
                                         &awaiter_frame_.next)) {
      awaiter_frame_.closure ^= object_.ptr();
      return true;  // Hide this frame 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
