// Copyright (c) 2013, 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 "lib/stacktrace.h"
#include "vm/bootstrap_natives.h"
#include "vm/debugger.h"
#include "vm/exceptions.h"
#include "vm/native_entry.h"
#include "vm/object_store.h"
#include "vm/runtime_entry.h"
#include "vm/stack_frame.h"
#include "vm/stack_trace.h"

namespace dart {

DECLARE_FLAG(bool, show_invisible_frames);

static RawStackTrace* CurrentSyncStackTrace(Thread* thread,
                                            intptr_t skip_frames = 1) {
  Zone* zone = thread->zone();
  const Function& null_function = Function::ZoneHandle(zone);

  // Determine how big the stack trace is.
  const intptr_t stack_trace_length =
      StackTraceUtils::CountFrames(thread, skip_frames, null_function);

  // Allocate once.
  const Array& code_array =
      Array::ZoneHandle(zone, Array::New(stack_trace_length));
  const Array& pc_offset_array =
      Array::ZoneHandle(zone, Array::New(stack_trace_length));

  // Collect the frames.
  const intptr_t collected_frames_count = StackTraceUtils::CollectFrames(
      thread, code_array, pc_offset_array, 0, stack_trace_length, skip_frames);

  ASSERT(collected_frames_count == stack_trace_length);

  return StackTrace::New(code_array, pc_offset_array);
}

static RawStackTrace* CurrentStackTrace(
    Thread* thread,
    bool for_async_function,
    intptr_t skip_frames = 1,
    bool causal_async_stacks = FLAG_causal_async_stacks) {
  if (!causal_async_stacks) {
    // Return the synchronous stack trace.
    return CurrentSyncStackTrace(thread, skip_frames);
  }

  Zone* zone = thread->zone();
  Code& code = Code::ZoneHandle(zone);
  Smi& offset = Smi::ZoneHandle(zone);
  Function& async_function = Function::ZoneHandle(zone);
  StackTrace& async_stack_trace = StackTrace::ZoneHandle(zone);
  Array& async_code_array = Array::ZoneHandle(zone);
  Array& async_pc_offset_array = Array::ZoneHandle(zone);

  StackTraceUtils::ExtractAsyncStackTraceInfo(
      thread, &async_function, &async_stack_trace, &async_code_array,
      &async_pc_offset_array);

  // Determine the size of the stack trace.
  const intptr_t extra_frames = for_async_function ? 1 : 0;
  const intptr_t synchronous_stack_trace_length =
      StackTraceUtils::CountFrames(thread, skip_frames, async_function);

  const intptr_t capacity = synchronous_stack_trace_length +
                            extra_frames;  // For the asynchronous gap.

  // Allocate memory for the stack trace.
  const Array& code_array = Array::ZoneHandle(zone, Array::New(capacity));
  const Array& pc_offset_array = Array::ZoneHandle(zone, Array::New(capacity));

  intptr_t write_cursor = 0;
  if (for_async_function) {
    // Place the asynchronous gap marker at the top of the stack trace.
    code = StubCode::AsynchronousGapMarker_entry()->code();
    ASSERT(!code.IsNull());
    offset = Smi::New(0);
    code_array.SetAt(write_cursor, code);
    pc_offset_array.SetAt(write_cursor, offset);
    write_cursor++;
  }

  // Append the synchronous stack trace.
  const intptr_t collected_frames_count = StackTraceUtils::CollectFrames(
      thread, code_array, pc_offset_array, write_cursor,
      synchronous_stack_trace_length, skip_frames);

  write_cursor += collected_frames_count;

  ASSERT(write_cursor == capacity);

  return StackTrace::New(code_array, pc_offset_array, async_stack_trace);
}

RawStackTrace* GetStackTraceForException() {
  Thread* thread = Thread::Current();
  return CurrentStackTrace(thread, false, 0);
}

DEFINE_NATIVE_ENTRY(StackTrace_current, 0) {
  return CurrentStackTrace(thread, false);
}

DEFINE_NATIVE_ENTRY(StackTrace_asyncStackTraceHelper, 1) {
  if (!FLAG_causal_async_stacks) {
    return Object::null();
  }
#if !defined(PRODUCT)
  GET_NATIVE_ARGUMENT(Closure, async_op, arguments->NativeArgAt(0));
  Debugger* debugger = isolate->debugger();
  if (debugger != NULL) {
    debugger->MaybeAsyncStepInto(async_op);
  }
#endif
  return CurrentStackTrace(thread, true);
}

DEFINE_NATIVE_ENTRY(StackTrace_clearAsyncThreadStackTrace, 0) {
  thread->clear_async_stack_trace();
  return Object::null();
}

DEFINE_NATIVE_ENTRY(StackTrace_setAsyncThreadStackTrace, 1) {
  if (!FLAG_causal_async_stacks) {
    return Object::null();
  }

  GET_NON_NULL_NATIVE_ARGUMENT(StackTrace, stack_trace,
                               arguments->NativeArgAt(0));
  thread->set_async_stack_trace(stack_trace);
  return Object::null();
}

static void AppendFrames(const GrowableObjectArray& code_list,
                         const GrowableObjectArray& pc_offset_list,
                         int skip_frames) {
  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                            Thread::Current(),
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
  Code& code = Code::Handle();
  Smi& offset = Smi::Handle();
  while (frame != NULL) {
    if (frame->IsDartFrame()) {
      if (skip_frames > 0) {
        skip_frames--;
      } else {
        code = frame->LookupDartCode();
        offset = Smi::New(frame->pc() - code.PayloadStart());
        code_list.Add(code);
        pc_offset_list.Add(offset);
      }
    }
    frame = frames.NextFrame();
  }
}

// Creates a StackTrace object from the current stack.
//
// Skips the first skip_frames Dart frames.
const StackTrace& GetCurrentStackTrace(int skip_frames) {
  const GrowableObjectArray& code_list =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  const GrowableObjectArray& pc_offset_list =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  AppendFrames(code_list, pc_offset_list, skip_frames);
  const Array& code_array = Array::Handle(Array::MakeFixedLength(code_list));
  const Array& pc_offset_array =
      Array::Handle(Array::MakeFixedLength(pc_offset_list));
  const StackTrace& stacktrace =
      StackTrace::Handle(StackTrace::New(code_array, pc_offset_array));
  return stacktrace;
}

}  // namespace dart
