// 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;
    bytecode_ = Bytecode::null();
    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();

#if defined(DART_DYNAMIC_MODULES)
      if (pc == StubCode::ResumeInterpreter().EntryPoint()) {
        bytecode_ = Interpreter::Current()->GetSuspendedLocation(
            SuspendState::Cast(awaiter_frame_.next), &pc_offset);
        ASSERT(!bytecode_.IsNull());
        code_ = Code::null();
      }
#endif  // defined(DART_DYNAMIC_MODULES)
    } 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).
#if defined(DART_DYNAMIC_MODULES)
      if (function_.HasBytecode()) {
        bytecode_ = function_.GetBytecode();
        code_ = Code::null();
        pc_offset = StackTraceUtils::kFutureListenerPcOffset;
      } else {
#endif  // defined(DART_DYNAMIC_MODULES)
        code_ = function_.EnsureHasCode();
        RELEASE_ASSERT(!code_.IsNull());
        pc_offset = (function_.entry_point() +
                     StackTraceUtils::kFutureListenerPcOffset) -
                    code_.PayloadStart();
#if defined(DART_DYNAMIC_MODULES)
      }
#endif  // defined(DART_DYNAMIC_MODULES)
    }

    handle_frame(gap_frame);
    handle_frame(
        {nullptr, code_, 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
