// Copyright 2016 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 <unordered_map>

#include "src/assert-scope.h"
#include "src/base/optional.h"
#include "src/codegen/assembler-inl.h"
#include "src/compiler/wasm-compiler.h"
#include "src/debug/debug-scopes.h"
#include "src/debug/debug.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/utils/identity-map.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/zone/accounting-allocator.h"

namespace v8 {
namespace internal {
namespace wasm {

namespace {

template <bool internal, typename... Args>
Handle<String> PrintFToOneByteString(Isolate* isolate, const char* format,
                                     Args... args) {
  // Maximum length of a formatted value name ("arg#%d", "local#%d",
  // "global#%d", i32 constants, i64 constants), including null character.
  static constexpr int kMaxStrLen = 21;
  EmbeddedVector<char, kMaxStrLen> value;
  int len = SNPrintF(value, format, args...);
  CHECK(len > 0 && len < value.length());
  Vector<const uint8_t> name =
      Vector<const uint8_t>::cast(value.SubVector(0, len));
  return internal
             ? isolate->factory()->InternalizeString(name)
             : isolate->factory()->NewStringFromOneByte(name).ToHandleChecked();
}

Handle<Object> WasmValueToValueObject(Isolate* isolate, WasmValue value) {
  switch (value.type()) {
    case kWasmI32:
      if (Smi::IsValid(value.to<int32_t>()))
        return handle(Smi::FromInt(value.to<int32_t>()), isolate);
      return PrintFToOneByteString<false>(isolate, "%d", value.to<int32_t>());
    case kWasmI64: {
      int64_t i64 = value.to<int64_t>();
      int32_t i32 = static_cast<int32_t>(i64);
      if (i32 == i64 && Smi::IsValid(i32))
        return handle(Smi::FromIntptr(i32), isolate);
      return PrintFToOneByteString<false>(isolate, "%" PRId64, i64);
    }
    case kWasmF32:
      return isolate->factory()->NewNumber(value.to<float>());
    case kWasmF64:
      return isolate->factory()->NewNumber(value.to<double>());
    case kWasmAnyRef:
      return value.to_anyref();
    default:
      UNIMPLEMENTED();
      return isolate->factory()->undefined_value();
  }
}

MaybeHandle<String> GetLocalName(Isolate* isolate,
                                 Handle<WasmDebugInfo> debug_info,
                                 int func_index, int local_index) {
  DCHECK_LE(0, func_index);
  DCHECK_LE(0, local_index);
  if (!debug_info->has_locals_names()) {
    Handle<WasmModuleObject> module_object(
        debug_info->wasm_instance().module_object(), isolate);
    Handle<FixedArray> locals_names = DecodeLocalNames(isolate, module_object);
    debug_info->set_locals_names(*locals_names);
  }

  Handle<FixedArray> locals_names(debug_info->locals_names(), isolate);
  if (func_index >= locals_names->length() ||
      locals_names->get(func_index).IsUndefined(isolate)) {
    return {};
  }

  Handle<FixedArray> func_locals_names(
      FixedArray::cast(locals_names->get(func_index)), isolate);
  if (local_index >= func_locals_names->length() ||
      func_locals_names->get(local_index).IsUndefined(isolate)) {
    return {};
  }
  return handle(String::cast(func_locals_names->get(local_index)), isolate);
}

class InterpreterHandle {
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(InterpreterHandle);
  Isolate* isolate_;
  const WasmModule* module_;
  WasmInterpreter interpreter_;
  StepAction next_step_action_ = StepNone;
  int last_step_stack_depth_ = 0;
  std::unordered_map<Address, uint32_t> activations_;

  uint32_t StartActivation(Address frame_pointer) {
    WasmInterpreter::Thread* thread = interpreter_.GetThread(0);
    uint32_t activation_id = thread->StartActivation();
    DCHECK_EQ(0, activations_.count(frame_pointer));
    activations_.insert(std::make_pair(frame_pointer, activation_id));
    return activation_id;
  }

  void FinishActivation(Address frame_pointer, uint32_t activation_id) {
    WasmInterpreter::Thread* thread = interpreter_.GetThread(0);
    thread->FinishActivation(activation_id);
    DCHECK_EQ(1, activations_.count(frame_pointer));
    activations_.erase(frame_pointer);
  }

  std::pair<uint32_t, uint32_t> GetActivationFrameRange(
      WasmInterpreter::Thread* thread, Address frame_pointer) {
    DCHECK_EQ(1, activations_.count(frame_pointer));
    uint32_t activation_id = activations_.find(frame_pointer)->second;
    uint32_t num_activations = static_cast<uint32_t>(activations_.size() - 1);
    uint32_t frame_base = thread->ActivationFrameBase(activation_id);
    uint32_t frame_limit = activation_id == num_activations
                               ? thread->GetFrameCount()
                               : thread->ActivationFrameBase(activation_id + 1);
    DCHECK_LE(frame_base, frame_limit);
    DCHECK_LE(frame_limit, thread->GetFrameCount());
    return {frame_base, frame_limit};
  }

  static ModuleWireBytes GetBytes(WasmDebugInfo debug_info) {
    // Return raw pointer into heap. The WasmInterpreter will make its own copy
    // of this data anyway, and there is no heap allocation in-between.
    NativeModule* native_module =
        debug_info.wasm_instance().module_object().native_module();
    return ModuleWireBytes{native_module->wire_bytes()};
  }

 public:
  InterpreterHandle(Isolate* isolate, Handle<WasmDebugInfo> debug_info)
      : isolate_(isolate),
        module_(debug_info->wasm_instance().module_object().module()),
        interpreter_(isolate, module_, GetBytes(*debug_info),
                     handle(debug_info->wasm_instance(), isolate)) {}

  WasmInterpreter* interpreter() { return &interpreter_; }
  const WasmModule* module() const { return module_; }

  void PrepareStep(StepAction step_action) {
    next_step_action_ = step_action;
    last_step_stack_depth_ = CurrentStackDepth();
  }

  void ClearStepping() { next_step_action_ = StepNone; }

  int CurrentStackDepth() {
    DCHECK_EQ(1, interpreter()->GetThreadCount());
    return interpreter()->GetThread(0)->GetFrameCount();
  }

  // Returns true if exited regularly, false if a trap/exception occurred and
  // was not handled inside this activation. In the latter case, a pending
  // exception will have been set on the isolate.
  bool Execute(Handle<WasmInstanceObject> instance_object,
               Address frame_pointer, uint32_t func_index,
               Vector<WasmValue> argument_values,
               Vector<WasmValue> return_values) {
    DCHECK_GE(module()->functions.size(), func_index);
    FunctionSig* sig = module()->functions[func_index].sig;
    DCHECK_EQ(sig->parameter_count(), argument_values.size());
    DCHECK_EQ(sig->return_count(), return_values.size());

    uint32_t activation_id = StartActivation(frame_pointer);

    WasmCodeRefScope code_ref_scope;
    WasmInterpreter::Thread* thread = interpreter_.GetThread(0);
    thread->InitFrame(&module()->functions[func_index],
                      argument_values.begin());
    bool finished = false;
    while (!finished) {
      // TODO(clemensh): Add occasional StackChecks.
      WasmInterpreter::State state = ContinueExecution(thread);
      switch (state) {
        case WasmInterpreter::State::PAUSED:
          NotifyDebugEventListeners(thread);
          break;
        case WasmInterpreter::State::FINISHED:
          // Perfect, just break the switch and exit the loop.
          finished = true;
          break;
        case WasmInterpreter::State::TRAPPED: {
          MessageTemplate message_id =
              WasmOpcodes::TrapReasonToMessageId(thread->GetTrapReason());
          Handle<Object> exception =
              isolate_->factory()->NewWasmRuntimeError(message_id);
          auto result = thread->RaiseException(isolate_, exception);
          if (result == WasmInterpreter::Thread::HANDLED) break;
          // If no local handler was found, we fall-thru to {STOPPED}.
          DCHECK_EQ(WasmInterpreter::State::STOPPED, thread->state());
          V8_FALLTHROUGH;
        }
        case WasmInterpreter::State::STOPPED:
          // An exception happened, and the current activation was unwound
          // without hitting a local exception handler. All that remains to be
          // done is finish the activation and let the exception propagate.
          DCHECK_EQ(thread->ActivationFrameBase(activation_id),
                    thread->GetFrameCount());
          DCHECK(isolate_->has_pending_exception());
          FinishActivation(frame_pointer, activation_id);
          return false;
        // RUNNING should never occur here.
        case WasmInterpreter::State::RUNNING:
        default:
          UNREACHABLE();
      }
    }

    // Copy back the return value.
    DCHECK_GE(kV8MaxWasmFunctionReturns, sig->return_count());
    // TODO(wasm): Handle multi-value returns.
    DCHECK_EQ(1, kV8MaxWasmFunctionReturns);
    if (sig->return_count()) {
      return_values[0] = thread->GetReturnValue(0);
    }

    FinishActivation(frame_pointer, activation_id);

    return true;
  }

  WasmInterpreter::State ContinueExecution(WasmInterpreter::Thread* thread) {
    switch (next_step_action_) {
      case StepNone:
        return thread->Run();
      case StepIn:
        return thread->Step();
      case StepOut:
        thread->AddBreakFlags(WasmInterpreter::BreakFlag::AfterReturn);
        return thread->Run();
      case StepNext: {
        int stack_depth = thread->GetFrameCount();
        if (stack_depth == last_step_stack_depth_) return thread->Step();
        thread->AddBreakFlags(stack_depth > last_step_stack_depth_
                                  ? WasmInterpreter::BreakFlag::AfterReturn
                                  : WasmInterpreter::BreakFlag::AfterCall);
        return thread->Run();
      }
      default:
        UNREACHABLE();
    }
  }

  Handle<WasmInstanceObject> GetInstanceObject() {
    StackTraceFrameIterator it(isolate_);
    WasmInterpreterEntryFrame* frame =
        WasmInterpreterEntryFrame::cast(it.frame());
    Handle<WasmInstanceObject> instance_obj(frame->wasm_instance(), isolate_);
    // Check that this is indeed the instance which is connected to this
    // interpreter.
    DCHECK_EQ(this, Managed<InterpreterHandle>::cast(
                        instance_obj->debug_info().interpreter_handle())
                        .raw());
    return instance_obj;
  }

  void NotifyDebugEventListeners(WasmInterpreter::Thread* thread) {
    // Enter the debugger.
    DebugScope debug_scope(isolate_->debug());

    // Check whether we hit a breakpoint.
    if (isolate_->debug()->break_points_active()) {
      Handle<WasmModuleObject> module_object(
          GetInstanceObject()->module_object(), isolate_);
      int position = GetTopPosition(module_object);
      Handle<FixedArray> breakpoints;
      if (WasmModuleObject::CheckBreakPoints(isolate_, module_object, position)
              .ToHandle(&breakpoints)) {
        // We hit one or several breakpoints. Clear stepping, notify the
        // listeners and return.
        ClearStepping();
        isolate_->debug()->OnDebugBreak(breakpoints);
        return;
      }
    }

    // We did not hit a breakpoint, so maybe this pause is related to stepping.
    bool hit_step = false;
    switch (next_step_action_) {
      case StepNone:
        break;
      case StepIn:
        hit_step = true;
        break;
      case StepOut:
        hit_step = thread->GetFrameCount() < last_step_stack_depth_;
        break;
      case StepNext: {
        hit_step = thread->GetFrameCount() == last_step_stack_depth_;
        break;
      }
      default:
        UNREACHABLE();
    }
    if (!hit_step) return;
    ClearStepping();
    isolate_->debug()->OnDebugBreak(isolate_->factory()->empty_fixed_array());
  }

  int GetTopPosition(Handle<WasmModuleObject> module_object) {
    DCHECK_EQ(1, interpreter()->GetThreadCount());
    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
    DCHECK_LT(0, thread->GetFrameCount());

    auto frame = thread->GetFrame(thread->GetFrameCount() - 1);
    return module_object->GetFunctionOffset(frame->function()->func_index) +
           frame->pc();
  }

  std::vector<std::pair<uint32_t, int>> GetInterpretedStack(
      Address frame_pointer) {
    DCHECK_EQ(1, interpreter()->GetThreadCount());
    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);

    std::pair<uint32_t, uint32_t> frame_range =
        GetActivationFrameRange(thread, frame_pointer);

    std::vector<std::pair<uint32_t, int>> stack;
    stack.reserve(frame_range.second - frame_range.first);
    for (uint32_t fp = frame_range.first; fp < frame_range.second; ++fp) {
      auto frame = thread->GetFrame(fp);
      stack.emplace_back(frame->function()->func_index, frame->pc());
    }
    return stack;
  }

  WasmInterpreter::FramePtr GetInterpretedFrame(Address frame_pointer,
                                                int idx) {
    DCHECK_EQ(1, interpreter()->GetThreadCount());
    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);

    std::pair<uint32_t, uint32_t> frame_range =
        GetActivationFrameRange(thread, frame_pointer);
    DCHECK_LE(0, idx);
    DCHECK_GT(frame_range.second - frame_range.first, idx);

    return thread->GetFrame(frame_range.first + idx);
  }

  uint64_t NumInterpretedCalls() {
    DCHECK_EQ(1, interpreter()->GetThreadCount());
    return interpreter()->GetThread(0)->NumInterpretedCalls();
  }

  Handle<JSObject> GetGlobalScopeObject(InterpretedFrame* frame,
                                        Handle<WasmDebugInfo> debug_info) {
    Isolate* isolate = isolate_;
    Handle<WasmInstanceObject> instance(debug_info->wasm_instance(), isolate);

    Handle<JSObject> global_scope_object =
        isolate_->factory()->NewJSObjectWithNullProto();
    if (instance->has_memory_object()) {
      Handle<String> name =
          isolate_->factory()->InternalizeString(StaticCharVector("memory"));
      Handle<JSArrayBuffer> memory_buffer(
          instance->memory_object().array_buffer(), isolate_);
      Handle<JSTypedArray> uint8_array = isolate_->factory()->NewJSTypedArray(
          kExternalUint8Array, memory_buffer, 0, memory_buffer->byte_length());
      JSObject::SetOwnPropertyIgnoreAttributes(global_scope_object, name,
                                               uint8_array, NONE)
          .Assert();
    }

    DCHECK_EQ(1, interpreter()->GetThreadCount());
    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);

    uint32_t global_count = thread->GetGlobalCount();
    if (global_count > 0) {
      Handle<JSObject> globals_obj =
          isolate_->factory()->NewJSObjectWithNullProto();
      Handle<String> globals_name =
          isolate_->factory()->InternalizeString(StaticCharVector("globals"));
      JSObject::SetOwnPropertyIgnoreAttributes(global_scope_object,
                                               globals_name, globals_obj, NONE)
          .Assert();

      for (uint32_t i = 0; i < global_count; ++i) {
        const char* label = "global#%d";
        Handle<String> name = PrintFToOneByteString<true>(isolate_, label, i);
        WasmValue value = thread->GetGlobalValue(i);
        Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
        JSObject::SetOwnPropertyIgnoreAttributes(globals_obj, name, value_obj,
                                                 NONE)
            .Assert();
      }
    }

    return global_scope_object;
  }

  Handle<JSObject> GetLocalScopeObject(InterpretedFrame* frame,
                                       Handle<WasmDebugInfo> debug_info) {
    Isolate* isolate = isolate_;

    Handle<JSObject> local_scope_object =
        isolate_->factory()->NewJSObjectWithNullProto();
    // Fill parameters and locals.
    int num_params = frame->GetParameterCount();
    int num_locals = frame->GetLocalCount();
    DCHECK_LE(num_params, num_locals);
    if (num_locals > 0) {
      Handle<JSObject> locals_obj =
          isolate_->factory()->NewJSObjectWithNullProto();
      Handle<String> locals_name =
          isolate_->factory()->InternalizeString(StaticCharVector("locals"));
      JSObject::SetOwnPropertyIgnoreAttributes(local_scope_object, locals_name,
                                               locals_obj, NONE)
          .Assert();
      for (int i = 0; i < num_locals; ++i) {
        MaybeHandle<String> name =
            GetLocalName(isolate, debug_info, frame->function()->func_index, i);
        if (name.is_null()) {
          // Parameters should come before locals in alphabetical ordering, so
          // we name them "args" here.
          const char* label = i < num_params ? "arg#%d" : "local#%d";
          name = PrintFToOneByteString<true>(isolate_, label, i);
        }
        WasmValue value = frame->GetLocalValue(i);
        Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
        JSObject::SetOwnPropertyIgnoreAttributes(
            locals_obj, name.ToHandleChecked(), value_obj, NONE)
            .Assert();
      }
    }

    // Fill stack values.
    int stack_count = frame->GetStackHeight();
    // Use an object without prototype instead of an Array, for nicer displaying
    // in DevTools. For Arrays, the length field and prototype is displayed,
    // which does not make too much sense here.
    Handle<JSObject> stack_obj =
        isolate_->factory()->NewJSObjectWithNullProto();
    Handle<String> stack_name =
        isolate_->factory()->InternalizeString(StaticCharVector("stack"));
    JSObject::SetOwnPropertyIgnoreAttributes(local_scope_object, stack_name,
                                             stack_obj, NONE)
        .Assert();
    for (int i = 0; i < stack_count; ++i) {
      WasmValue value = frame->GetStackValue(i);
      Handle<Object> value_obj = WasmValueToValueObject(isolate_, value);
      JSObject::SetOwnElementIgnoreAttributes(
          stack_obj, static_cast<uint32_t>(i), value_obj, NONE)
          .Assert();
    }
    return local_scope_object;
  }
};

}  // namespace

}  // namespace wasm

namespace {

wasm::InterpreterHandle* GetOrCreateInterpreterHandle(
    Isolate* isolate, Handle<WasmDebugInfo> debug_info) {
  Handle<Object> handle(debug_info->interpreter_handle(), isolate);
  if (handle->IsUndefined(isolate)) {
    // Use the maximum stack size to estimate the maximum size of the
    // interpreter. The interpreter keeps its own stack internally, and the size
    // of the stack should dominate the overall size of the interpreter. We
    // multiply by '2' to account for the growing strategy for the backing store
    // of the stack.
    size_t interpreter_size = FLAG_stack_size * KB * 2;
    handle = Managed<wasm::InterpreterHandle>::Allocate(
        isolate, interpreter_size, isolate, debug_info);
    debug_info->set_interpreter_handle(*handle);
  }

  return Handle<Managed<wasm::InterpreterHandle>>::cast(handle)->raw();
}

wasm::InterpreterHandle* GetInterpreterHandle(WasmDebugInfo debug_info) {
  Object handle_obj = debug_info.interpreter_handle();
  DCHECK(!handle_obj.IsUndefined());
  return Managed<wasm::InterpreterHandle>::cast(handle_obj).raw();
}

wasm::InterpreterHandle* GetInterpreterHandleOrNull(WasmDebugInfo debug_info) {
  Object handle_obj = debug_info.interpreter_handle();
  if (handle_obj.IsUndefined()) return nullptr;
  return Managed<wasm::InterpreterHandle>::cast(handle_obj).raw();
}

}  // namespace

Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) {
  DCHECK(!instance->has_debug_info());
  Factory* factory = instance->GetIsolate()->factory();
  Handle<WasmDebugInfo> debug_info = Handle<WasmDebugInfo>::cast(
      factory->NewStruct(WASM_DEBUG_INFO_TYPE, AllocationType::kOld));
  debug_info->set_wasm_instance(*instance);
  instance->set_debug_info(*debug_info);
  return debug_info;
}

wasm::WasmInterpreter* WasmDebugInfo::SetupForTesting(
    Handle<WasmInstanceObject> instance_obj) {
  Handle<WasmDebugInfo> debug_info = WasmDebugInfo::New(instance_obj);
  Isolate* isolate = instance_obj->GetIsolate();
  // Use the maximum stack size to estimate the maximum size of the interpreter.
  // The interpreter keeps its own stack internally, and the size of the stack
  // should dominate the overall size of the interpreter. We multiply by '2' to
  // account for the growing strategy for the backing store of the stack.
  size_t interpreter_size = FLAG_stack_size * KB * 2;
  auto interp_handle = Managed<wasm::InterpreterHandle>::Allocate(
      isolate, interpreter_size, isolate, debug_info);
  debug_info->set_interpreter_handle(*interp_handle);
  return interp_handle->raw()->interpreter();
}

void WasmDebugInfo::SetBreakpoint(Handle<WasmDebugInfo> debug_info,
                                  int func_index, int offset) {
  Isolate* isolate = debug_info->GetIsolate();
  auto* handle = GetOrCreateInterpreterHandle(isolate, debug_info);
  RedirectToInterpreter(debug_info, Vector<int>(&func_index, 1));
  const wasm::WasmFunction* func = &handle->module()->functions[func_index];
  handle->interpreter()->SetBreakpoint(func, offset, true);
}

void WasmDebugInfo::RedirectToInterpreter(Handle<WasmDebugInfo> debug_info,
                                          Vector<int> func_indexes) {
  Isolate* isolate = debug_info->GetIsolate();
  // Ensure that the interpreter is instantiated.
  GetOrCreateInterpreterHandle(isolate, debug_info);
  Handle<WasmInstanceObject> instance(debug_info->wasm_instance(), isolate);
  wasm::NativeModule* native_module = instance->module_object().native_module();
  const wasm::WasmModule* module = instance->module();

  // We may modify the wasm jump table.
  wasm::NativeModuleModificationScope native_module_modification_scope(
      native_module);

  for (int func_index : func_indexes) {
    DCHECK_LE(0, func_index);
    DCHECK_GT(module->functions.size(), func_index);
    // Note that this is just a best effort check. Multiple threads can still
    // race at redirecting the same function to the interpreter, which is OK.
    if (native_module->IsRedirectedToInterpreter(func_index)) continue;

    wasm::WasmCodeRefScope code_ref_scope;
    wasm::WasmCompilationResult result = compiler::CompileWasmInterpreterEntry(
        isolate->wasm_engine(), native_module->enabled_features(), func_index,
        module->functions[func_index].sig);
    std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode(
        func_index, result.code_desc, result.frame_slot_count,
        result.tagged_parameter_slots, std::move(result.protected_instructions),
        std::move(result.source_positions), wasm::WasmCode::kInterpreterEntry,
        wasm::ExecutionTier::kInterpreter);
    native_module->PublishCode(std::move(wasm_code));
    DCHECK(native_module->IsRedirectedToInterpreter(func_index));
  }
}

void WasmDebugInfo::PrepareStep(StepAction step_action) {
  GetInterpreterHandle(*this)->PrepareStep(step_action);
}

// static
bool WasmDebugInfo::RunInterpreter(Isolate* isolate,
                                   Handle<WasmDebugInfo> debug_info,
                                   Address frame_pointer, int func_index,
                                   Vector<wasm::WasmValue> argument_values,
                                   Vector<wasm::WasmValue> return_values) {
  DCHECK_LE(0, func_index);
  auto* handle = GetOrCreateInterpreterHandle(isolate, debug_info);
  Handle<WasmInstanceObject> instance(debug_info->wasm_instance(), isolate);
  return handle->Execute(instance, frame_pointer,
                         static_cast<uint32_t>(func_index), argument_values,
                         return_values);
}

std::vector<std::pair<uint32_t, int>> WasmDebugInfo::GetInterpretedStack(
    Address frame_pointer) {
  return GetInterpreterHandle(*this)->GetInterpretedStack(frame_pointer);
}

wasm::WasmInterpreter::FramePtr WasmDebugInfo::GetInterpretedFrame(
    Address frame_pointer, int idx) {
  return GetInterpreterHandle(*this)->GetInterpretedFrame(frame_pointer, idx);
}

uint64_t WasmDebugInfo::NumInterpretedCalls() {
  auto* handle = GetInterpreterHandleOrNull(*this);
  return handle ? handle->NumInterpretedCalls() : 0;
}

// static
Handle<JSObject> WasmDebugInfo::GetGlobalScopeObject(
    Handle<WasmDebugInfo> debug_info, Address frame_pointer, int frame_index) {
  auto* interp_handle = GetInterpreterHandle(*debug_info);
  auto frame = interp_handle->GetInterpretedFrame(frame_pointer, frame_index);
  return interp_handle->GetGlobalScopeObject(frame.get(), debug_info);
}

// static
Handle<JSObject> WasmDebugInfo::GetLocalScopeObject(
    Handle<WasmDebugInfo> debug_info, Address frame_pointer, int frame_index) {
  auto* interp_handle = GetInterpreterHandle(*debug_info);
  auto frame = interp_handle->GetInterpretedFrame(frame_pointer, frame_index);
  return interp_handle->GetLocalScopeObject(frame.get(), debug_info);
}

// static
Handle<JSFunction> WasmDebugInfo::GetCWasmEntry(
    Handle<WasmDebugInfo> debug_info, wasm::FunctionSig* sig) {
  Isolate* isolate = debug_info->GetIsolate();
  DCHECK_EQ(debug_info->has_c_wasm_entries(),
            debug_info->has_c_wasm_entry_map());
  if (!debug_info->has_c_wasm_entries()) {
    auto entries = isolate->factory()->NewFixedArray(4, AllocationType::kOld);
    debug_info->set_c_wasm_entries(*entries);
    size_t map_size = 0;  // size estimate not so important here.
    auto managed_map = Managed<wasm::SignatureMap>::Allocate(isolate, map_size);
    debug_info->set_c_wasm_entry_map(*managed_map);
  }
  Handle<FixedArray> entries(debug_info->c_wasm_entries(), isolate);
  wasm::SignatureMap* map = debug_info->c_wasm_entry_map().raw();
  int32_t index = map->Find(*sig);
  if (index == -1) {
    index = static_cast<int32_t>(map->FindOrInsert(*sig));
    if (index == entries->length()) {
      entries = isolate->factory()->CopyFixedArrayAndGrow(
          entries, entries->length(), AllocationType::kOld);
      debug_info->set_c_wasm_entries(*entries);
    }
    DCHECK(entries->get(index).IsUndefined(isolate));
    Handle<Code> new_entry_code =
        compiler::CompileCWasmEntry(isolate, sig).ToHandleChecked();
    Handle<WasmExportedFunctionData> function_data =
        Handle<WasmExportedFunctionData>::cast(isolate->factory()->NewStruct(
            WASM_EXPORTED_FUNCTION_DATA_TYPE, AllocationType::kOld));
    function_data->set_wrapper_code(*new_entry_code);
    function_data->set_instance(debug_info->wasm_instance());
    function_data->set_jump_table_offset(-1);
    function_data->set_function_index(-1);
    Handle<String> name =
        isolate->factory()->InternalizeString(StaticCharVector("c-wasm-entry"));
    NewFunctionArgs args = NewFunctionArgs::ForWasm(
        name, function_data, isolate->sloppy_function_map());
    Handle<JSFunction> new_entry = isolate->factory()->NewFunction(args);
    new_entry->set_context(debug_info->wasm_instance().native_context());
    new_entry->shared().set_internal_formal_parameter_count(
        compiler::CWasmEntryParameters::kNumParameters);
    entries->set(index, *new_entry);
  }
  return handle(JSFunction::cast(entries->get(index)), isolate);
}

}  // namespace internal
}  // namespace v8
