// 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_or_bytecode_(Object::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())) {
    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;
  };

  const Code& code() const { return Code::Cast(code_or_bytecode_); }
  const Bytecode& bytecode() const { return Bytecode::Cast(code_or_bytecode_); }

  Zone* zone_;
  DartFrameIterator sync_frames_;

  StackFrame* sync_frame_;
  AwaiterFrame awaiter_frame_;

  bool* encountered_async_catch_error_;

  Closure& closure_;
  Object& code_or_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] = {};

  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()) {
        code_or_bytecode_ = sync_frame_->LookupDartBytecode();
        if (!bytecode().IsSharedBytecodeStub()) {
          const uword pc_offset = sync_frame_->pc() - bytecode().PayloadStart();
          handle_frame({sync_frame_, code_or_bytecode_, pc_offset,
                        Object::null_closure()});
        }
      } else {
        code_or_bytecode_ = sync_frame_->LookupDartCode();
        const uword pc_offset = sync_frame_->pc() - code().PayloadStart();
        handle_frame({sync_frame_, code_or_bytecode_, pc_offset,
                      Object::null_closure()});
      }
    }
    sync_frame_ = sync_frames_.NextFrame();
  }

  const StackTraceUtils::Frame gap_frame = {
      nullptr, StubCode::AsynchronousGapMarker(),
      /*pc_offset=*/0, Object::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;
      }

#if defined(DART_DYNAMIC_MODULES)
      if (pc == StubCode::ResumeInterpreter().EntryPoint()) {
        code_or_bytecode_ = Interpreter::Current()->GetSuspendedLocation(
            SuspendState::Cast(awaiter_frame_.next), &pc_offset);
        ASSERT(!bytecode().IsNull());
      } else {
#endif  // defined(DART_DYNAMIC_MODULES)
        code_or_bytecode_ =
            SuspendState::Cast(awaiter_frame_.next).GetCodeObject();
        pc_offset = pc - code().PayloadStart();
#if defined(DART_DYNAMIC_MODULES)
      }
#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).
      pc_offset = StackTraceUtils::kFutureListenerPcOffset;
#if defined(DART_DYNAMIC_MODULES)
      // Interpreted implicit closure functions are implemented using a
      // shared stub, so the target cannot be retrieved from the bytecode
      // object alone. Instead, retrieve the parent function and act as if
      // it is awaiting the value directly so the proper name is reported.
      //
      // This is done as a separate step because interpreted implicit closure
      // functions can be created for compiled functions in the AOT runtime.
      // This approach also mimics the way that StackFrame::ToCString() handles
      // future listeners that are compiled implicit static methods.
      if (function_.IsInterpreted() && function_.IsImplicitClosureFunction()) {
        function_ = function_.parent_function();
      }
      if (function_.IsInterpreted()) {
        code_or_bytecode_ = function_.GetBytecode();
        ASSERT(!bytecode().IsSharedBytecodeStub());
      } else {
#endif  // defined(DART_DYNAMIC_MODULES)
        code_or_bytecode_ = function_.EnsureHasCode();
        RELEASE_ASSERT(!code().IsNull());
#if defined(DART_DYNAMIC_MODULES)
      }
#endif  // defined(DART_DYNAMIC_MODULES)
    }

    handle_frame(gap_frame);
    handle_frame(
        {nullptr, code_or_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 false;  // Do not hide this 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
