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

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
