// 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/stack_frame.h"
#include "vm/symbols.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/frontend/bytecode_reader.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {

// Keep in sync with
// sdk/lib/async/stream_controller.dart:_StreamController._STATE_SUBSCRIBED.
const intptr_t kStreamController_StateSubscribed = 1;

RawClosure* FindClosureInFrame(RawObject** last_object_in_caller,
                               const Function& function,
                               bool is_interpreted) {
  NoSafepointScope nsp;

  // The callee has function signature
  //   :async_op([result, exception, stack])
  // So we are guaranteed to
  //   a) have only tagged arguments on the stack until we find the :async_op
  //      closure, and
  //   b) find the async closure.
  auto& closure = Closure::Handle();
  for (intptr_t i = 0; i < 4; i++) {
    // KBC builds the stack upwards instead of the usual downwards stack.
    RawObject* arg = last_object_in_caller[(is_interpreted ? -i : i)];
    if (arg->IsHeapObject() && arg->GetClassId() == kClosureCid) {
      closure = Closure::RawCast(arg);
      if (closure.function() == function.raw()) {
        return closure.raw();
      }
    }
  }
  UNREACHABLE();
}

// Find current yield index from async closure.
// Async closures contains a variable, :await_jump_var that holds the index into
// async wrapper.
intptr_t GetYieldIndex(const Closure& receiver_closure) {
  const auto& function = Function::Handle(receiver_closure.function());
  if (!function.IsAsyncClosure() && !function.IsAsyncGenClosure()) {
    return RawPcDescriptors::kInvalidYieldIndex;
  }
  const auto& await_jump_var =
      Object::Handle(Context::Handle(receiver_closure.context())
                         .At(Context::kAwaitJumpVarIndex));
  ASSERT(await_jump_var.IsSmi());
  return Smi::Cast(await_jump_var).Value();
}

intptr_t FindPcOffset(const PcDescriptors& pc_descs, intptr_t yield_index) {
  if (yield_index == RawPcDescriptors::kInvalidYieldIndex) {
    return 0;
  }
  PcDescriptors::Iterator iter(pc_descs, RawPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    if (iter.YieldIndex() == yield_index) {
      return iter.PcOffset();
    }
  }
  UNREACHABLE();  // If we cannot find it we have a bug.
}

#if !defined(DART_PRECOMPILED_RUNTIME)
intptr_t FindPcOffset(const Bytecode& bytecode, intptr_t yield_index) {
  if (yield_index == RawPcDescriptors::kInvalidYieldIndex) {
    return 0;
  }
  if (!bytecode.HasSourcePositions()) {
    return 0;
  }
  intptr_t last_yield_point = 0;
  kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
                                               bytecode);
  while (iter.MoveNext()) {
    if (iter.IsYieldPoint()) {
      last_yield_point++;
    }
    if (last_yield_point == yield_index) {
      return iter.PcOffset();
    }
  }
  UNREACHABLE();  // If we cannot find it we have a bug.
}
#endif

// Helper class for finding the closure of the caller.
// This is done via the _AsyncAwaitCompleter which holds a
// FutureResultOrListeners which in turn holds a callback.
class CallerClosureFinder {
 public:
  // Instance caches library and field references.
  // This way we don't have to do the look-ups for every frame in the stack.
  explicit CallerClosureFinder(Zone* zone)
      : receiver_context_(Context::Handle(zone)),
        receiver_function_(Function::Handle(zone)),
        context_entry_(Object::Handle(zone)),
        is_sync(Object::Handle(zone)),
        future_(Object::Handle(zone)),
        listener_(Object::Handle(zone)),
        callback_(Object::Handle(zone)),
        controller_(Object::Handle(zone)),
        state_(Object::Handle(zone)),
        var_data_(Object::Handle(zone)),
        callback_instance_(Object::Handle(zone)),
        future_impl_class(Class::Handle(zone)),
        async_await_completer_class(Class::Handle(zone)),
        future_listener_class(Class::Handle(zone)),
        async_start_stream_controller_class(Class::Handle(zone)),
        stream_controller_class(Class::Handle(zone)),
        async_stream_controller_class(Class::Handle(zone)),
        controller_subscription_class(Class::Handle(zone)),
        buffering_stream_subscription_class(Class::Handle(zone)),
        stream_iterator_class(Class::Handle(zone)),
        completer_is_sync_field(Field::Handle(zone)),
        completer_future_field(Field::Handle(zone)),
        future_result_or_listeners_field(Field::Handle(zone)),
        callback_field(Field::Handle(zone)),
        controller_controller_field(Field::Handle(zone)),
        var_data_field(Field::Handle(zone)),
        state_field(Field::Handle(zone)),
        on_data_field(Field::Handle(zone)),
        state_data_field(Field::Handle(zone)) {
    const auto& async_lib = Library::Handle(zone, Library::AsyncLibrary());
    // Look up classes:
    // - async:
    future_impl_class =
        async_lib.LookupClassAllowPrivate(Symbols::FutureImpl());
    ASSERT(!future_impl_class.IsNull());
    async_await_completer_class =
        async_lib.LookupClassAllowPrivate(Symbols::_AsyncAwaitCompleter());
    ASSERT(!async_await_completer_class.IsNull());
    future_listener_class =
        async_lib.LookupClassAllowPrivate(Symbols::_FutureListener());
    ASSERT(!future_listener_class.IsNull());
    // - async*:
    async_start_stream_controller_class = async_lib.LookupClassAllowPrivate(
        Symbols::_AsyncStarStreamController());
    ASSERT(!async_start_stream_controller_class.IsNull());
    stream_controller_class =
        async_lib.LookupClassAllowPrivate(Symbols::_StreamController());
    ASSERT(!stream_controller_class.IsNull());
    async_stream_controller_class =
        async_lib.LookupClassAllowPrivate(Symbols::_AsyncStreamController());
    ASSERT(!async_stream_controller_class.IsNull());
    controller_subscription_class =
        async_lib.LookupClassAllowPrivate(Symbols::_ControllerSubscription());
    ASSERT(!controller_subscription_class.IsNull());
    buffering_stream_subscription_class = async_lib.LookupClassAllowPrivate(
        Symbols::_BufferingStreamSubscription());
    ASSERT(!buffering_stream_subscription_class.IsNull());
    stream_iterator_class =
        async_lib.LookupClassAllowPrivate(Symbols::_StreamIterator());
    ASSERT(!stream_iterator_class.IsNull());

    // Look up fields:
    // - async:
    completer_is_sync_field =
        async_await_completer_class.LookupFieldAllowPrivate(Symbols::isSync());
    ASSERT(!completer_is_sync_field.IsNull());
    completer_future_field =
        async_await_completer_class.LookupFieldAllowPrivate(Symbols::_future());
    ASSERT(!completer_future_field.IsNull());
    future_result_or_listeners_field =
        future_impl_class.LookupFieldAllowPrivate(
            Symbols::_resultOrListeners());
    ASSERT(!future_result_or_listeners_field.IsNull());
    callback_field =
        future_listener_class.LookupFieldAllowPrivate(Symbols::callback());
    ASSERT(!callback_field.IsNull());
    // - async*:
    controller_controller_field =
        async_start_stream_controller_class.LookupFieldAllowPrivate(
            Symbols::controller());
    ASSERT(!controller_controller_field.IsNull());
    state_field =
        stream_controller_class.LookupFieldAllowPrivate(Symbols::_state());
    ASSERT(!state_field.IsNull());
    var_data_field =
        stream_controller_class.LookupFieldAllowPrivate(Symbols::_varData());
    ASSERT(!var_data_field.IsNull());
    on_data_field = buffering_stream_subscription_class.LookupFieldAllowPrivate(
        Symbols::_onData());
    ASSERT(!on_data_field.IsNull());
    state_data_field =
        stream_iterator_class.LookupFieldAllowPrivate(Symbols::_stateData());
    ASSERT(!state_data_field.IsNull());
  }

  RawClosure* GetCallerInFutureImpl(const Object& future_) {
    ASSERT(!future_.IsNull());
    ASSERT(future_.GetClassId() == future_impl_class.id());

    listener_ =
        Instance::Cast(future_).GetField(future_result_or_listeners_field);
    if (listener_.GetClassId() != future_listener_class.id()) {
      return Closure::null();
    }

    callback_ = Instance::Cast(listener_).GetField(callback_field);
    // This happens for e.g.: await f().catchError(..);
    if (callback_.IsNull()) {
      return Closure::null();
    }
    ASSERT(callback_.IsClosure());

    return Closure::Cast(callback_).raw();
  }

  RawClosure* FindCallerInAsyncClosure(const Context& receiver_context) {
    context_entry_ = receiver_context.At(Context::kAsyncCompleterIndex);
    ASSERT(context_entry_.IsInstance());
    ASSERT(context_entry_.GetClassId() == async_await_completer_class.id());

    const Instance& completer = Instance::Cast(context_entry_);
    future_ = completer.GetField(completer_future_field);
    return GetCallerInFutureImpl(future_);
  }

  RawClosure* FindCallerInAsyncGenClosure(const Context& receiver_context) {
    context_entry_ = receiver_context.At(Context::kControllerIndex);
    ASSERT(context_entry_.IsInstance());
    ASSERT(context_entry_.GetClassId() ==
           async_start_stream_controller_class.id());

    const Instance& controller = Instance::Cast(context_entry_);
    controller_ = controller.GetField(controller_controller_field);
    ASSERT(!controller_.IsNull());
    ASSERT(controller_.GetClassId() == async_stream_controller_class.id());

    state_ = Instance::Cast(controller_).GetField(state_field);
    ASSERT(state_.IsSmi());
    if (Smi::Cast(state_).Value() != kStreamController_StateSubscribed) {
      return Closure::null();
    }

    // _StreamController._varData
    var_data_ = Instance::Cast(controller_).GetField(var_data_field);
    ASSERT(var_data_.GetClassId() == controller_subscription_class.id());

    // _ControllerSubscription<T>/_BufferingStreamSubscription.<T>_onData
    callback_ = Instance::Cast(var_data_).GetField(on_data_field);
    ASSERT(callback_.IsClosure());

    // If this is not the "_StreamIterator._onData" tear-off, we return the
    // callback we found.
    receiver_function_ = Closure::Cast(callback_).function();
    if (!receiver_function_.IsImplicitInstanceClosureFunction() ||
        receiver_function_.Owner() != stream_iterator_class.raw()) {
      return Closure::Cast(callback_).raw();
    }

    // All implicit closure functions (tear-offs) have the "this" receiver
    // captured.
    receiver_context_ = Closure::Cast(callback_).context();
    ASSERT(receiver_context_.num_variables() == 1);
    callback_instance_ = receiver_context_.At(0);
    ASSERT(callback_instance_.IsInstance());

    // If the async* stream is await-for'd:
    if (callback_instance_.GetClassId() == stream_iterator_class.id()) {
      // _StreamIterator._stateData
      future_ = Instance::Cast(callback_instance_).GetField(state_data_field);
      return GetCallerInFutureImpl(future_);
    }

    UNREACHABLE();  // If no onData is found we have a bug.
  }

  RawClosure* FindCaller(const Closure& receiver_closure) {
    receiver_function_ = receiver_closure.function();
    receiver_context_ = receiver_closure.context();

    if (receiver_function_.IsAsyncClosure()) {
      return FindCallerInAsyncClosure(receiver_context_);
    } else if (receiver_function_.IsAsyncGenClosure()) {
      return FindCallerInAsyncGenClosure(receiver_context_);
    }

    return Closure::null();
  }

  bool IsRunningAsync(const Closure& receiver_closure) {
    receiver_function_ = receiver_closure.function();
    receiver_context_ = receiver_closure.context();

    // The async* functions are never started synchronously, they start running
    // after the first `listen()` call to its returned `Stream`.
    if (receiver_function_.IsAsyncGenClosure()) {
      return true;
    }
    ASSERT(receiver_function_.IsAsyncClosure());

    context_entry_ = receiver_context_.At(Context::kAsyncCompleterIndex);
    ASSERT(context_entry_.IsInstance());
    ASSERT(context_entry_.GetClassId() == async_await_completer_class.id());

    const Instance& completer = Instance::Cast(context_entry_);
    is_sync = completer.GetField(completer_is_sync_field);
    ASSERT(!is_sync.IsNull());
    ASSERT(is_sync.IsBool());
    // _AsyncAwaitCompleter.isSync indicates whether the future should be
    // completed async. or sync., based on whether it has yielded yet.
    // isSync is true when the :async_op is running async.
    return Bool::Cast(is_sync).value();
  }

 private:
  Context& receiver_context_;
  Function& receiver_function_;

  Object& context_entry_;
  Object& is_sync;
  Object& future_;
  Object& listener_;
  Object& callback_;
  Object& controller_;
  Object& state_;
  Object& var_data_;
  Object& callback_instance_;

  Class& future_impl_class;
  Class& async_await_completer_class;
  Class& future_listener_class;
  Class& async_start_stream_controller_class;
  Class& stream_controller_class;
  Class& async_stream_controller_class;
  Class& controller_subscription_class;
  Class& buffering_stream_subscription_class;
  Class& stream_iterator_class;

  Field& completer_is_sync_field;
  Field& completer_future_field;
  Field& future_result_or_listeners_field;
  Field& callback_field;
  Field& controller_controller_field;
  Field& var_data_field;
  Field& state_field;
  Field& on_data_field;
  Field& state_data_field;
};

void StackTraceUtils::CollectFramesLazy(
    Thread* thread,
    const GrowableObjectArray& code_array,
    const GrowableObjectArray& pc_offset_array,
    int skip_frames,
    std::function<void(StackFrame*)>* on_sync_frames,
    bool* has_async) {
  if (has_async != nullptr) {
    *has_async = false;
  }
  Zone* zone = thread->zone();
  DartFrameIterator frames(thread, StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();

  // If e.g. the isolate is paused before executing anything, we might not get
  // any frames at all. Bail:
  if (frame == nullptr) {
    return;
  }

  auto& function = Function::Handle(zone);
  auto& code = Code::Handle(zone);
  auto& bytecode = Bytecode::Handle(zone);
  auto& offset = Smi::Handle(zone);

  auto& closure = Closure::Handle(zone);
  CallerClosureFinder caller_closure_finder(zone);
  auto& pc_descs = PcDescriptors::Handle();

  for (; frame != nullptr; frame = frames.NextFrame()) {
    if (skip_frames > 0) {
      skip_frames--;
      continue;
    }

    if (frame->is_interpreted()) {
      bytecode = frame->LookupDartBytecode();
      ASSERT(!bytecode.IsNull());
      function = bytecode.function();
      if (function.IsNull()) {
        continue;
      }
      RELEASE_ASSERT(function.raw() == frame->LookupDartFunction());
    } else {
      function = frame->LookupDartFunction();
    }

    // Add the current synchronous frame.
    if (frame->is_interpreted()) {
      code_array.Add(bytecode);
      const intptr_t pc_offset = frame->pc() - bytecode.PayloadStart();
      ASSERT(pc_offset >= 0 && pc_offset <= bytecode.Size());
      offset = Smi::New(pc_offset);
    } else {
      code = frame->LookupDartCode();
      ASSERT(function.raw() == code.function());
      code_array.Add(code);
      offset = Smi::New(frame->pc() - code.PayloadStart());
    }
    pc_offset_array.Add(offset);
    if (on_sync_frames != nullptr) {
      (*on_sync_frames)(frame);
    }

    // Either continue the loop (sync-async case) or find all await'ers and
    // return.
    if (!function.IsNull() &&
        (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
      if (has_async != nullptr) {
        *has_async = true;
      }

      // Next, look up caller's closure on the stack and walk backwards through
      // the yields.
      RawObject** last_caller_obj = reinterpret_cast<RawObject**>(
          frame->GetCallerSp());
      closure = FindClosureInFrame(last_caller_obj, function,
                                   frame->is_interpreted());

      // If this async function hasn't yielded yet, we're still dealing with a
      // normal stack. Continue to next frame as usual.
      if (!caller_closure_finder.IsRunningAsync(closure)) {
        continue;
      }

      // Inject async suspension marker.
      code_array.Add(StubCode::AsynchronousGapMarker());
      offset = Smi::New(0);
      pc_offset_array.Add(offset);

      // Skip: Already handled this frame's function above.
      closure = caller_closure_finder.FindCaller(closure);

      for (; !closure.IsNull();
           closure = caller_closure_finder.FindCaller(closure)) {
        function = closure.function();
        // In hot-reload-test-mode we sometimes have to do this:
        if (!function.HasCode() && !function.HasBytecode()) {
          function.EnsureHasCode();
        }
        if (function.HasBytecode()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
          bytecode = function.bytecode();
          code_array.Add(bytecode);
          offset = Smi::New(FindPcOffset(bytecode, GetYieldIndex(closure)));
#else
          UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
        } else if (function.HasCode()) {
          code = function.CurrentCode();
          code_array.Add(code);
          pc_descs = code.pc_descriptors();
          offset = Smi::New(FindPcOffset(pc_descs, GetYieldIndex(closure)));
        } else {
          UNREACHABLE();
        }
        ASSERT(offset.Value() >= 0);
        pc_offset_array.Add(offset);

        // Inject async suspension marker.
        code_array.Add(StubCode::AsynchronousGapMarker());
        offset = Smi::New(0);
        pc_offset_array.Add(offset);
      }

      // Ignore the rest of the stack; already unwound all async calls.
      return;
    }
  }

  return;
}

// Count the number of frames that are on the stack.
intptr_t StackTraceUtils::CountFrames(Thread* thread,
                                      int skip_frames,
                                      const Function& async_function,
                                      bool* sync_async_end) {
  Zone* zone = thread->zone();
  intptr_t frame_count = 0;
  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
  Function& function = Function::Handle(zone);
  Code& code = Code::Handle(zone);
  Bytecode& bytecode = Bytecode::Handle(zone);
  String& function_name = String::Handle(zone);
  const bool async_function_is_null = async_function.IsNull();
  int sync_async_gap_frames = -1;
  ASSERT(async_function_is_null || sync_async_end != NULL);
  for (; frame != NULL && sync_async_gap_frames != 0;
       frame = frames.NextFrame()) {
    if (!frame->IsDartFrame()) {
      continue;
    }
    if (skip_frames > 0) {
      skip_frames--;
      continue;
    }
    if (frame->is_interpreted()) {
      bytecode = frame->LookupDartBytecode();
      function = bytecode.function();
    } else {
      code = frame->LookupDartCode();
      function = code.function();
    }
    if (function.IsNull()) continue;
    if (sync_async_gap_frames > 0) {
      function_name = function.QualifiedScrubbedName();
      if (!CheckAndSkipAsync(&sync_async_gap_frames, function_name)) {
        *sync_async_end = false;
        return frame_count;
      }
    } else {
      frame_count++;
    }
    if (!async_function_is_null &&
        (async_function.raw() == function.parent_function())) {
      sync_async_gap_frames = kSyncAsyncFrameGap;
    }
  }
  if (!async_function_is_null) {
    *sync_async_end = sync_async_gap_frames == 0;
  }
  return frame_count;
}

intptr_t StackTraceUtils::CollectFrames(Thread* thread,
                                        const Array& code_array,
                                        const Array& pc_offset_array,
                                        intptr_t array_offset,
                                        intptr_t count,
                                        int skip_frames) {
  Zone* zone = thread->zone();
  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
  Function& function = Function::Handle(zone);
  Code& code = Code::Handle(zone);
  Bytecode& bytecode = Bytecode::Handle(zone);
  Smi& offset = Smi::Handle(zone);
  intptr_t collected_frames_count = 0;
  for (; (frame != NULL) && (collected_frames_count < count);
       frame = frames.NextFrame()) {
    if (!frame->IsDartFrame()) {
      continue;
    }
    if (skip_frames > 0) {
      skip_frames--;
      continue;
    }
    if (frame->is_interpreted()) {
      bytecode = frame->LookupDartBytecode();
      function = bytecode.function();
      if (function.IsNull()) {
        continue;
      }
      offset = Smi::New(frame->pc() - bytecode.PayloadStart());
      code_array.SetAt(array_offset, bytecode);
    } else {
      code = frame->LookupDartCode();
      offset = Smi::New(frame->pc() - code.PayloadStart());
      code_array.SetAt(array_offset, code);
    }
    pc_offset_array.SetAt(array_offset, offset);
    array_offset++;
    collected_frames_count++;
  }
  return collected_frames_count;
}

intptr_t StackTraceUtils::ExtractAsyncStackTraceInfo(
    Thread* thread,
    Function* async_function,
    StackTrace* async_stack_trace_out,
    Array* async_code_array,
    Array* async_pc_offset_array) {
  if (thread->async_stack_trace() == StackTrace::null()) {
    return 0;
  }
  *async_stack_trace_out = thread->async_stack_trace();
  ASSERT(!async_stack_trace_out->IsNull());
  const StackTrace& async_stack_trace =
      StackTrace::Handle(thread->async_stack_trace());
  const intptr_t async_stack_trace_length = async_stack_trace.Length();
  // At least two entries (0: gap marker, 1: async function).
  ASSERT(async_stack_trace_length >= 2);
  // Validate the structure of this stack trace.
  *async_code_array = async_stack_trace.code_array();
  ASSERT(!async_code_array->IsNull());
  *async_pc_offset_array = async_stack_trace.pc_offset_array();
  ASSERT(!async_pc_offset_array->IsNull());
  // We start with the asynchronous gap marker.
  ASSERT(async_code_array->At(0) != Code::null());
  ASSERT(async_code_array->At(0) == StubCode::AsynchronousGapMarker().raw());
  const Object& code_object = Object::Handle(async_code_array->At(1));
  if (code_object.IsCode()) {
    *async_function = Code::Cast(code_object).function();
  } else {
    ASSERT(code_object.IsBytecode());
    *async_function = Bytecode::Cast(code_object).function();
  }
  ASSERT(!async_function->IsNull());
  ASSERT(async_function->IsAsyncFunction() ||
         async_function->IsAsyncGenerator());
  return async_stack_trace_length;
}

}  // namespace dart
