chromium/v8/src/debug/debug.cc

// Copyright 2012 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.h"

#include <memory>
#include <optional>

#include "src/api/api-inl.h"
#include "src/base/platform/mutex.h"
#include "src/builtins/builtins.h"
#include "src/codegen/compilation-cache.h"
#include "src/codegen/compiler.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/common/message-template.h"
#include "src/debug/debug-evaluate.h"
#include "src/debug/liveedit.h"
#include "src/deoptimizer/deoptimizer.h"
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
#include "src/execution/protectors-inl.h"
#include "src/execution/v8threads.h"
#include "src/handles/global-handles-inl.h"
#include "src/heap/heap-inl.h"  // For NextDebuggingId.
#include "src/init/bootstrapper.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/logging/counters.h"
#include "src/logging/runtime-call-stats-scope.h"
#include "src/objects/api-callbacks-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/js-generator-inl.h"
#include "src/objects/js-promise-inl.h"
#include "src/objects/slots.h"
#include "src/snapshot/embedded/embedded-data.h"

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

namespace v8 {
namespace internal {

class Debug::TemporaryObjectsTracker : public HeapObjectAllocationTracker {};

Debug::Debug(Isolate* isolate)
    :{}

Debug::~Debug() {}

BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
                                       JavaScriptFrame* frame) {}

bool BreakLocation::IsPausedInJsFunctionEntry(JavaScriptFrame* frame) {}

MaybeHandle<FixedArray> Debug::CheckBreakPointsForLocations(
    Handle<DebugInfo> debug_info, std::vector<BreakLocation>& break_locations,
    bool* has_break_points) {}

void BreakLocation::AllAtCurrentStatement(
    Handle<DebugInfo> debug_info, JavaScriptFrame* frame,
    std::vector<BreakLocation>* result_out) {}

Tagged<JSGeneratorObject> BreakLocation::GetGeneratorObjectForSuspendedFrame(
    JavaScriptFrame* frame) const {}

int BreakLocation::BreakIndexFromCodeOffset(
    Handle<DebugInfo> debug_info, DirectHandle<AbstractCode> abstract_code,
    int offset) {}

bool BreakLocation::HasBreakPoint(Isolate* isolate,
                                  Handle<DebugInfo> debug_info) const {}

debug::BreakLocationType BreakLocation::type() const {}

BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
    :{}

int BreakIterator::BreakIndexFromPosition(int source_position) {}

void BreakIterator::Next() {}

DebugBreakType BreakIterator::GetDebugBreakType() {}

void BreakIterator::SkipToPosition(int position) {}

void BreakIterator::SetDebugBreak() {}

void BreakIterator::ClearDebugBreak() {}

BreakLocation BreakIterator::GetBreakLocation() {}

Isolate* BreakIterator::isolate() {}

// Threading support.
void Debug::ThreadInit() {}

char* Debug::ArchiveDebug(char* storage) {}

char* Debug::RestoreDebug(char* storage) {}

int Debug::ArchiveSpacePerThread() {}

void Debug::Iterate(RootVisitor* v) {}

char* Debug::Iterate(RootVisitor* v, char* thread_storage) {}

void Debug::Iterate(RootVisitor* v, ThreadLocal* thread_local_data) {}

void DebugInfoCollection::Insert(Tagged<SharedFunctionInfo> sfi,
                                 Tagged<DebugInfo> debug_info) {}

bool DebugInfoCollection::Contains(Tagged<SharedFunctionInfo> sfi) const {}

std::optional<Tagged<DebugInfo>> DebugInfoCollection::Find(
    Tagged<SharedFunctionInfo> sfi) const {}

void DebugInfoCollection::DeleteSlow(Tagged<SharedFunctionInfo> sfi) {}

Tagged<DebugInfo> DebugInfoCollection::EntryAsDebugInfo(size_t index) const {}

void DebugInfoCollection::DeleteIndex(size_t index) {}

void Debug::Unload() {}

debug::DebugDelegate::ActionAfterInstrumentation
Debug::OnInstrumentationBreak() {}

void Debug::Break(JavaScriptFrame* frame,
                  DirectHandle<JSFunction> break_target) {}

bool Debug::IsBreakOnInstrumentation(Handle<DebugInfo> debug_info,
                                     const BreakLocation& location) {}

bool Debug::IsBreakOnDebuggerStatement(
    DirectHandle<SharedFunctionInfo> function, const BreakLocation& location) {}

// Find break point objects for this location, if any, and evaluate them.
// Return an array of break point objects that evaluated true, or an empty
// handle if none evaluated true.
// has_break_points will be true, if there is any (non-instrumentation)
// breakpoint.
MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
                                                BreakLocation* location,
                                                bool* has_break_points) {}

bool Debug::IsMutedAtAnyBreakLocation(
    DirectHandle<SharedFunctionInfo> function,
    const std::vector<BreakLocation>& locations) {}

#if V8_ENABLE_WEBASSEMBLY
void Debug::SetMutedWasmLocation(DirectHandle<Script> script, int position) {}

bool Debug::IsMutedAtWasmLocation(Tagged<Script> script, int position) {}
#endif  // V8_ENABLE_WEBASSEMBLY

namespace {

// Convenience helper for easier std::optional translation.
bool ToHandle(Isolate* isolate, std::optional<Tagged<DebugInfo>> debug_info,
              Handle<DebugInfo>* out) {}

}  // namespace

// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(DirectHandle<BreakPoint> break_point,
                            bool is_break_at_entry) {}

bool Debug::SetBreakpoint(Handle<SharedFunctionInfo> shared,
                          DirectHandle<BreakPoint> break_point,
                          int* source_position) {}

bool Debug::SetBreakPointForScript(Handle<Script> script,
                                   DirectHandle<String> condition,
                                   int* source_position, int* id) {}

int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
                                 int source_position) {}

void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {}

void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {}

void Debug::ClearBreakPoint(DirectHandle<BreakPoint> break_point) {}

int Debug::GetFunctionDebuggingId(DirectHandle<JSFunction> function) {}

bool Debug::SetBreakpointForFunction(Handle<SharedFunctionInfo> shared,
                                     DirectHandle<String> condition, int* id,
                                     BreakPointKind kind) {}

void Debug::RemoveBreakpoint(int id) {}

#if V8_ENABLE_WEBASSEMBLY
void Debug::SetInstrumentationBreakpointForWasmScript(Handle<Script> script,
                                                      int* id) {}

void Debug::RemoveBreakpointForWasmScript(DirectHandle<Script> script, int id) {}

void Debug::RecordWasmScriptWithBreakpoints(Handle<Script> script) {}
#endif  // V8_ENABLE_WEBASSEMBLY

// Clear out all the debug break code.
void Debug::ClearAllBreakPoints() {}

void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
                             bool returns_only) {}

void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {}

bool Debug::IsBreakOnException(ExceptionBreakType type) {}

MaybeHandle<FixedArray> Debug::GetHitBreakPoints(
    DirectHandle<DebugInfo> debug_info, int position, bool* has_break_points) {}

void Debug::SetBreakOnNextFunctionCall() {}

void Debug::ClearBreakOnNextFunctionCall() {}

void Debug::PrepareStepIn(DirectHandle<JSFunction> function) {}

void Debug::PrepareStepInSuspendedGenerator() {}

void Debug::PrepareStepOnThrow() {}

void Debug::PrepareStep(StepAction step_action) {}

// Simple function for returning the source positions for active break points.
// static
Handle<Object> Debug::GetSourceBreakLocations(
    Isolate* isolate, DirectHandle<SharedFunctionInfo> shared) {}

void Debug::ClearStepping() {}

// Clears all the one-shot break points that are currently set. Normally this
// function is called each time a break point is hit as one shot break points
// are used to support stepping.
void Debug::ClearOneShot() {}

void Debug::ClearMutedLocation() {}

void Debug::SetMutedLocation(DirectHandle<SharedFunctionInfo> function,
                             const BreakLocation& location) {}

namespace {
class DiscardBaselineCodeVisitor : public ThreadVisitor {};
}  // namespace

void Debug::DiscardBaselineCode(Tagged<SharedFunctionInfo> shared) {}

void Debug::DiscardAllBaselineCode() {}

void Debug::DeoptimizeFunction(DirectHandle<SharedFunctionInfo> shared) {}

void Debug::PrepareFunctionForDebugExecution(
    DirectHandle<SharedFunctionInfo> shared) {}

namespace {

bool IsJSFunctionAndNeedsTrampoline(Isolate* isolate,
                                    Tagged<Object> maybe_function) {}

}  // namespace

void Debug::InstallDebugBreakTrampoline() {}

namespace {
void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
                            int end_position,
                            std::vector<BreakLocation>* locations) {}

bool CompileTopLevel(Isolate* isolate, Handle<Script> script,
                     MaybeHandle<SharedFunctionInfo>* result = nullptr) {}
}  // namespace

bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
                                   int end_position, bool restrict_to_function,
                                   std::vector<BreakLocation>* locations) {}

class SharedFunctionInfoFinder {};

namespace {
Tagged<SharedFunctionInfo> FindSharedFunctionInfoCandidate(
    int position, DirectHandle<Script> script, Isolate* isolate) {}
}  // namespace

Handle<SharedFunctionInfo> Debug::FindClosestSharedFunctionInfoFromPosition(
    int position, Handle<Script> script,
    Handle<SharedFunctionInfo> outer_shared) {}

bool Debug::FindSharedFunctionInfosIntersectingRange(
    Handle<Script> script, int start_position, int end_position,
    std::vector<Handle<SharedFunctionInfo>>* intersecting_shared) {}

MaybeHandle<SharedFunctionInfo> Debug::GetTopLevelWithRecompile(
    Handle<Script> script, bool* did_compile) {}

// We need to find a SFI for a literal that may not yet have been compiled yet,
// and there may not be a JSFunction referencing it. Find the SFI closest to
// the given position, compile it to reveal possible inner SFIs and repeat.
// While we are at this, also ensure code with debug break slots so that we do
// not have to compile a SFI without JSFunction, which is paifu for those that
// cannot be compiled without context (need to find outer compilable SFI etc.)
Handle<Object> Debug::FindInnermostContainingFunctionInfo(Handle<Script> script,
                                                          int position) {}

// Ensures the debug information is present for shared.
bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) {}

void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) {}

Handle<DebugInfo> Debug::GetOrCreateDebugInfo(
    DirectHandle<SharedFunctionInfo> shared) {}

void Debug::InstallCoverageInfo(DirectHandle<SharedFunctionInfo> shared,
                                Handle<CoverageInfo> coverage_info) {}

void Debug::RemoveAllCoverageInfos() {}

void Debug::ClearAllDebuggerHints() {}

void Debug::ClearAllDebugInfos(const DebugInfoClearFunction& clear_function) {}

void Debug::RemoveBreakInfoAndMaybeFree(DirectHandle<DebugInfo> debug_info) {}

bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {}

Handle<FixedArray> Debug::GetLoadedScripts() {}

std::optional<Tagged<DebugInfo>> Debug::TryGetDebugInfo(
    Tagged<SharedFunctionInfo> sfi) {}

bool Debug::HasDebugInfo(Tagged<SharedFunctionInfo> sfi) {}

bool Debug::HasCoverageInfo(Tagged<SharedFunctionInfo> sfi) {}

bool Debug::HasBreakInfo(Tagged<SharedFunctionInfo> sfi) {}

bool Debug::BreakAtEntry(Tagged<SharedFunctionInfo> sfi) {}

std::optional<Tagged<Object>> Debug::OnThrow(Handle<Object> exception) {}

void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {}

bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {}

void Debug::OnException(Handle<Object> exception,
                        MaybeHandle<JSPromise> promise,
                        v8::debug::ExceptionType exception_type) {}

void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit,
                         StepAction lastStepAction,
                         v8::debug::BreakReasons break_reasons) {}

namespace {
debug::Location GetDebugLocation(DirectHandle<Script> script,
                                 int source_position) {}
}  // namespace

bool Debug::IsBlackboxed(DirectHandle<SharedFunctionInfo> shared) {}

bool Debug::ShouldBeSkipped() {}

bool Debug::AllFramesOnStackAreBlackboxed() {}

bool Debug::CanBreakAtEntry(DirectHandle<SharedFunctionInfo> shared) {}

bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
                            bool preview, bool allow_top_frame_live_editing,
                            debug::LiveEditResult* result) {}

void Debug::OnCompileError(DirectHandle<Script> script) {}

void Debug::OnAfterCompile(DirectHandle<Script> script) {}

void Debug::ProcessCompileEvent(bool has_compile_error,
                                DirectHandle<Script> script) {}

int Debug::CurrentFrameCount() {}

void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) {}

void Debug::UpdateState() {}

void Debug::UpdateHookOnFunctionCall() {}

void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode,
                             v8::debug::BreakReasons break_reasons) {}

#ifdef DEBUG
void Debug::PrintBreakLocation() {}
#endif  // DEBUG

DebugScope::DebugScope(Debug* debug)
    :{}

void DebugScope::set_terminate_on_resume() {}

base::TimeDelta DebugScope::ElapsedTimeSinceCreation() {}

DebugScope::~DebugScope() {}

ReturnValueScope::ReturnValueScope(Debug* debug) :{}

ReturnValueScope::~ReturnValueScope() {}

void Debug::UpdateDebugInfosForExecutionMode() {}

void Debug::SetTerminateOnResume() {}

void Debug::StartSideEffectCheckMode() {}

void Debug::StopSideEffectCheckMode() {}

void Debug::ApplySideEffectChecks(DirectHandle<DebugInfo> debug_info) {}

void Debug::ClearSideEffectChecks(DirectHandle<DebugInfo> debug_info) {}

bool Debug::PerformSideEffectCheck(Handle<JSFunction> function,
                                   Handle<Object> receiver) {}

Handle<Object> Debug::return_value_handle() {}

void Debug::PrepareBuiltinForSideEffectCheck(Isolate* isolate, Builtin id) {}

bool Debug::PerformSideEffectCheckForAccessor(
    DirectHandle<AccessorInfo> accessor_info, Handle<Object> receiver,
    AccessorComponent component) {}

void Debug::IgnoreSideEffectsOnNextCallTo(
    Handle<FunctionTemplateInfo> function) {}

bool Debug::PerformSideEffectCheckForCallback(
    Handle<FunctionTemplateInfo> function) {}

bool Debug::PerformSideEffectCheckForInterceptor(
    Handle<InterceptorInfo> interceptor_info) {}

bool Debug::PerformSideEffectCheckAtBytecode(InterpretedFrame* frame) {}

bool Debug::PerformSideEffectCheckForObject(Handle<Object> object) {}

void Debug::SetTemporaryObjectTrackingDisabled(bool disabled) {}

bool Debug::GetTemporaryObjectTrackingDisabled() const {}

void Debug::PrepareRestartFrame(JavaScriptFrame* frame,
                                int inlined_frame_index) {}

void Debug::NotifyDebuggerPausedEventSent() {}

}  // namespace internal
}  // namespace v8