// 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/deoptimizer/deoptimizer.h"
#include "src/execution/frames-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/sandbox/check.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/debug/debug-wasm-objects.h"
#endif  // V8_ENABLE_WEBASSEMBLY

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();
  script_ = Cast<Script>(summary.script());
  receiver_ = summary.receiver();

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

#if V8_ENABLE_WEBASSEMBLY
  JavaScriptFrame* js_frame =
      frame->is_javascript() ? javascript_frame() : nullptr;
  DCHECK(js_frame || frame->is_wasm());
#else
  JavaScriptFrame* js_frame = javascript_frame();
#endif  // V8_ENABLE_WEBASSEMBLY
  is_optimized_ = js_frame && js_frame->is_optimized();

  // 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 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_);
}

DirectHandle<String> FrameInspector::GetFunctionName() {
#if V8_ENABLE_WEBASSEMBLY
  if (IsWasm()) {
#if V8_ENABLE_DRUMBRAKE
    if (IsWasmInterpreter()) {
      auto wasm_frame = WasmInterpreterEntryFrame::cast(frame_);
      auto instance_data =
          handle(wasm_frame->trusted_instance_data(), isolate_);
      return GetWasmFunctionDebugName(
          isolate_, instance_data,
          wasm_frame->function_index(inlined_frame_index_));
    }
#endif  // V8_ENABLE_DRUMBRAKE
    auto wasm_frame = WasmFrame::cast(frame_);
    auto instance_data = handle(wasm_frame->trusted_instance_data(), isolate_);
    int top_func_index = FrameSummary::Get(wasm_frame, inlined_frame_index_)
                             .AsWasm()
                             .function_index();
    return GetWasmFunctionDebugName(isolate_, instance_data, top_func_index);
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  return JSFunction::GetDebugName(isolate_, function_);
}

#if V8_ENABLE_WEBASSEMBLY
bool FrameInspector::IsWasm() { return frame_->is_wasm(); }
#if V8_ENABLE_DRUMBRAKE
bool FrameInspector::IsWasmInterpreter() {
  return frame_->is_wasm_interpreter_entry();
}
#endif  // V8_ENABLE_DRUMBRAKE
#endif  // V8_ENABLE_WEBASSEMBLY

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

bool FrameInspector::ParameterIsShadowedByContextLocal(
    DirectHandle<ScopeInfo> info, DirectHandle<String> parameter_name) {
  return info->ContextSlotIndex(*parameter_name) != -1;
}

RedirectActiveFunctions::RedirectActiveFunctions(
    Isolate* isolate, Tagged<SharedFunctionInfo> shared, Mode mode)
    : shared_(shared), mode_(mode) {
  DCHECK(shared->HasBytecodeArray());
  DCHECK(shared->HasDebugInfo(isolate));
}

void RedirectActiveFunctions::VisitThread(Isolate* isolate,
                                          ThreadLocalTop* top) {
  Tagged<DebugInfo> debug_info = shared_->GetDebugInfo(isolate);
  Tagged<BytecodeArray> original_bytecode =
      debug_info->OriginalBytecodeArray(isolate);
  Tagged<BytecodeArray> debug_bytecode =
      debug_info->DebugBytecodeArray(isolate);

  for (JavaScriptStackFrameIterator it(isolate, top); !it.done();
       it.Advance()) {
    JavaScriptFrame* frame = it.frame();
    // Skip live-edited frames, they'll be restarted from scratch anyway.
    if (isolate->debug()->ShouldRestartFrame(frame->id())) continue;
    Tagged<JSFunction> function = frame->function();
    if (!frame->is_interpreted()) continue;
    if (function->shared() != shared_) continue;
    InterpretedFrame* interpreted_frame =
        reinterpret_cast<InterpretedFrame*>(frame);

    if (mode_ == Mode::kUseDebugBytecode) {
      SBXCHECK_EQ(interpreted_frame->GetBytecodeArray(), original_bytecode);
      interpreted_frame->PatchBytecodeArray(debug_bytecode);
    } else {
      SBXCHECK_EQ(interpreted_frame->GetBytecodeArray(), debug_bytecode);
      interpreted_frame->PatchBytecodeArray(original_bytecode);
    }
  }
}

}  // namespace internal
}  // namespace v8
