// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/debug/debug-frames.h"

#include "src/builtins/accessors.h"
#include "src/execution/frames-inl.h"
#include "src/wasm/wasm-objects-inl.h"

namespace v8 {
namespace internal {

FrameInspector::FrameInspector(CommonFrame* frame, int inlined_frame_index,
                               Isolate* isolate)
    : frame_(frame),
      inlined_frame_index_(inlined_frame_index),
      isolate_(isolate) {
  // Extract the relevant information from the frame summary and discard it.
  FrameSummary summary = FrameSummary::Get(frame, inlined_frame_index);
  summary.EnsureSourcePositionsAvailable();

  is_constructor_ = summary.is_constructor();
  source_position_ = summary.SourcePosition();
  function_name_ = summary.FunctionName();
  script_ = Handle<Script>::cast(summary.script());
  receiver_ = summary.receiver();

  if (summary.IsJavaScript()) {
    function_ = summary.AsJavaScript().function();
  }

  JavaScriptFrame* js_frame =
      frame->is_java_script() ? javascript_frame() : nullptr;
  DCHECK(js_frame || frame->is_wasm());
  has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
  is_optimized_ = frame_->is_optimized();
  is_interpreted_ = frame_->is_interpreted();

  // Calculate the deoptimized frame.
  if (is_optimized_) {
    DCHECK_NOT_NULL(js_frame);
    deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
        js_frame, inlined_frame_index, isolate));
  }
}

// Destructor needs to be defined in the .cc file, because it instantiates
// std::unique_ptr destructors but the types are not known in the header.
FrameInspector::~FrameInspector() = default;

JavaScriptFrame* FrameInspector::javascript_frame() {
  return frame_->is_arguments_adaptor() ? ArgumentsAdaptorFrame::cast(frame_)
                                        : JavaScriptFrame::cast(frame_);
}

Handle<Object> FrameInspector::GetParameter(int index) {
  if (is_optimized_) return deoptimized_frame_->GetParameter(index);
  DCHECK(IsJavaScript());
  return handle(javascript_frame()->GetParameter(index), isolate_);
}

Handle<Object> FrameInspector::GetExpression(int index) {
  return is_optimized_ ? deoptimized_frame_->GetExpression(index)
                       : handle(frame_->GetExpression(index), isolate_);
}

Handle<Object> FrameInspector::GetContext() {
  return deoptimized_frame_ ? deoptimized_frame_->GetContext()
                            : handle(frame_->context(), isolate_);
}

bool FrameInspector::IsWasm() { return frame_->is_wasm(); }

bool FrameInspector::IsJavaScript() { return frame_->is_java_script(); }

bool FrameInspector::ParameterIsShadowedByContextLocal(
    Handle<ScopeInfo> info, Handle<String> parameter_name) {
  VariableMode mode;
  InitializationFlag init_flag;
  MaybeAssignedFlag maybe_assigned_flag;
  IsStaticFlag is_static_flag;
  return ScopeInfo::ContextSlotIndex(*info, *parameter_name, &mode, &init_flag,
                                     &maybe_assigned_flag,
                                     &is_static_flag) != -1;
}

RedirectActiveFunctions::RedirectActiveFunctions(SharedFunctionInfo shared,
                                                 Mode mode)
    : shared_(shared), mode_(mode) {
  DCHECK(shared.HasBytecodeArray());
  if (mode == Mode::kUseDebugBytecode) {
    DCHECK(shared.HasDebugInfo());
  }
}

void RedirectActiveFunctions::VisitThread(Isolate* isolate,
                                          ThreadLocalTop* top) {
  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
    JavaScriptFrame* frame = it.frame();
    JSFunction function = frame->function();
    if (!frame->is_interpreted()) continue;
    if (function.shared() != shared_) continue;
    InterpretedFrame* interpreted_frame =
        reinterpret_cast<InterpretedFrame*>(frame);
    BytecodeArray bytecode = mode_ == Mode::kUseDebugBytecode
                                 ? shared_.GetDebugInfo().DebugBytecodeArray()
                                 : shared_.GetBytecodeArray();
    interpreted_frame->PatchBytecodeArray(bytecode);
  }
}

}  // namespace internal
}  // namespace v8
