blob: ce560b5d53111b4bd6b11d63c44dda62e83c19d3 [file]
// Copyright 2017 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.
#ifndef V8_OBJECTS_DEBUG_OBJECTS_H_
#define V8_OBJECTS_DEBUG_OBJECTS_H_
#include <memory>
#include "src/base/bit-field.h"
#include "src/objects/fixed-array.h"
#include "src/objects/objects.h"
#include "src/objects/struct.h"
#include "src/objects/trusted-pointer.h"
#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-limits.h"
#endif // V8_ENABLE_WEBASSEMBLY
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class DebugInfo;
class BreakPoint;
class BreakPointInfo;
class StackFrameInfo;
class StackTraceInfo;
class DebugScriptScopeInfo;
class BytecodeArray;
class StructBodyDescriptor;
// The DebugInfo class holds additional information for a function being
// debugged.
V8_OBJECT class DebugInfo : public ExposedTrustedObject {
public:
// Bit positions in |flags|.
using HasBreakInfoBit = base::BitField<bool, 0, 1, uint32_t>;
using PreparedForDebugExecutionBit = HasBreakInfoBit::Next<bool, 1>;
using HasCoverageInfoBit = PreparedForDebugExecutionBit::Next<bool, 1>;
using BreakAtEntryBit = HasCoverageInfoBit::Next<bool, 1>;
using CanBreakAtEntryBit = BreakAtEntryBit::Next<bool, 1>;
using DebugExecutionModeBit = CanBreakAtEntryBit::Next<bool, 1>;
enum Flag : uint32_t {
kNone = 0,
kHasBreakInfo = HasBreakInfoBit::kMask,
kPreparedForDebugExecution = PreparedForDebugExecutionBit::kMask,
kHasCoverageInfo = HasCoverageInfoBit::kMask,
kBreakAtEntry = BreakAtEntryBit::kMask,
kCanBreakAtEntry = CanBreakAtEntryBit::kMask,
kDebugExecutionMode = DebugExecutionModeBit::kMask,
};
using Flags = base::Flags<Flag>;
static constexpr int kFlagCount = 6;
// DebugInfo can be detached from the SharedFunctionInfo iff it is empty.
bool IsEmpty() const;
// --- Debug execution ---
// -----------------------
enum ExecutionMode : uint8_t {
kBreakpoints = 0,
kSideEffects = kDebugExecutionMode
};
// Returns current debug execution mode. Debug execution mode defines by
// applied to bytecode patching. False for breakpoints, true for side effect
// checks.
ExecutionMode DebugExecutionMode() const;
void SetDebugExecutionMode(ExecutionMode value);
// Specifies whether the associated function has an instrumented bytecode
// array. If so, OriginalBytecodeArray returns the non-instrumented bytecode,
// and DebugBytecodeArray returns the instrumented bytecode.
inline bool HasInstrumentedBytecodeArray();
inline Tagged<BytecodeArray> OriginalBytecodeArray(Isolate* isolate);
inline Tagged<BytecodeArray> DebugBytecodeArray(Isolate* isolate);
DECL_PROTECTED_POINTER_ACCESSORS(original_bytecode_array, BytecodeArray)
DECL_RELEASE_ACQUIRE_PROTECTED_POINTER_ACCESSORS(original_bytecode_array,
BytecodeArray)
DECL_PROTECTED_POINTER_ACCESSORS(debug_bytecode_array, BytecodeArray)
DECL_RELEASE_ACQUIRE_PROTECTED_POINTER_ACCESSORS(debug_bytecode_array,
BytecodeArray)
// --- Break points ---
// --------------------
bool HasBreakInfo() const;
// Clears all fields related to break points.
V8_EXPORT_PRIVATE void ClearBreakInfo(Isolate* isolate);
// Accessors to flag whether to break before entering the function.
// This is used to break for functions with no source, e.g. builtins.
void SetBreakAtEntry();
void ClearBreakAtEntry();
bool BreakAtEntry() const;
// Check if there is a break point at a source position.
bool HasBreakPoint(Isolate* isolate, int source_position);
// Attempt to clear a break point. Return true if successful.
static bool ClearBreakPoint(Isolate* isolate,
DirectHandle<DebugInfo> debug_info,
DirectHandle<BreakPoint> break_point);
// Set a break point.
static void SetBreakPoint(Isolate* isolate,
DirectHandle<DebugInfo> debug_info,
int source_position,
DirectHandle<BreakPoint> break_point);
// Get the break point objects for a source position.
DirectHandle<Object> GetBreakPoints(Isolate* isolate, int source_position);
// Find the break point info holding this break point object.
static DirectHandle<Object> FindBreakPointInfo(
Isolate* isolate, DirectHandle<DebugInfo> debug_info,
DirectHandle<BreakPoint> break_point);
// Get the number of break points for this function.
uint32_t GetBreakPointCount(Isolate* isolate);
// Returns whether we should be able to break before entering the function.
// This is true for functions with no source, e.g. builtins.
bool CanBreakAtEntry() const;
// --- Debugger hint flags ---
// ---------------------------
// Indicates that the function should be skipped during stepping.
inline bool debug_is_blackboxed() const;
inline void set_debug_is_blackboxed(bool value);
// Indicates that |debug_is_blackboxed| has been computed and set.
inline bool computed_debug_is_blackboxed() const;
inline void set_computed_debug_is_blackboxed(bool value);
// Indicates the side effect state.
inline int side_effect_state() const;
inline void set_side_effect_state(int value);
enum SideEffectState {
kNotComputed = 0,
kHasSideEffects = 1,
kRequiresRuntimeChecks = 2,
kHasNoSideEffect = 3,
};
SideEffectState GetSideEffectState(Isolate* isolate);
// Id assigned to the function for debugging.
// This could also be implemented as a weak hash table.
inline int debugging_id() const;
inline void set_debugging_id(int value);
// Bit positions in |debugger_hints|.
using SideEffectStateBits = base::BitField<int32_t, 0, 2, uint32_t>;
using DebugIsBlackboxedBit = SideEffectStateBits::Next<bool, 1>;
using ComputedDebugIsBlackboxedBit = DebugIsBlackboxedBit::Next<bool, 1>;
using DebuggingIdBits = ComputedDebugIsBlackboxedBit::Next<int32_t, 20>;
static const int kNoDebuggingId = 0;
// --- Block Coverage ---
// ----------------------
bool HasCoverageInfo() const;
// Clears all fields related to block coverage.
void ClearCoverageInfo(Isolate* isolate);
static const int kEstimatedNofBreakPointsInFunction = 4;
DECL_PRINTER(DebugInfo)
DECL_VERIFIER(DebugInfo)
class BodyDescriptor;
inline Tagged<SharedFunctionInfo> shared() const;
inline void set_shared(Tagged<SharedFunctionInfo> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline int debugger_hints() const;
inline void set_debugger_hints(int value);
inline Tagged<FixedArray> break_points() const;
inline void set_break_points(Tagged<FixedArray> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Flags flags(RelaxedLoadTag) const;
inline void set_flags(Flags value, RelaxedStoreTag);
inline Tagged<UnionOf<CoverageInfo, Undefined>> coverage_info() const;
inline void set_coverage_info(Tagged<UnionOf<CoverageInfo, Undefined>> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
private:
// Get the break point info object for a source position.
Tagged<Object> GetBreakPointInfo(Isolate* isolate, int source_position);
public:
TaggedMember<SharedFunctionInfo> shared_;
TaggedMember<Smi> debugger_hints_;
TaggedMember<FixedArray> break_points_;
TaggedMember<Smi> flags_;
TaggedMember<UnionOf<CoverageInfo, Undefined>> coverage_info_;
ProtectedTaggedMember<UnionOf<BytecodeArray, Zero>> original_bytecode_array_;
ProtectedTaggedMember<UnionOf<BytecodeArray, Zero>> debug_bytecode_array_;
} V8_OBJECT_END;
// The BreakPointInfo class holds information for break points set in a
// function. The DebugInfo object holds a BreakPointInfo object for each code
// position with one or more break points.
V8_OBJECT class BreakPointInfo : public Struct {
public:
// Accessors
inline int source_position() const;
inline void set_source_position(int value);
inline Tagged<UnionOf<FixedArray, BreakPoint, Undefined>> break_points()
const;
inline void set_break_points(
Tagged<UnionOf<FixedArray, BreakPoint, Undefined>> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Removes a break point.
static void ClearBreakPoint(Isolate* isolate,
DirectHandle<BreakPointInfo> info,
DirectHandle<BreakPoint> break_point);
// Set a break point.
static void SetBreakPoint(Isolate* isolate, DirectHandle<BreakPointInfo> info,
DirectHandle<BreakPoint> break_point);
// Check if break point info has this break point.
static bool HasBreakPoint(Isolate* isolate, DirectHandle<BreakPointInfo> info,
DirectHandle<BreakPoint> break_point);
// Check if break point info has break point with this id.
static MaybeDirectHandle<BreakPoint> GetBreakPointById(
Isolate* isolate, DirectHandle<BreakPointInfo> info, int breakpoint_id);
// Get the number of break points for this code offset.
uint32_t GetBreakPointCount(Isolate* isolate);
int GetStatementPosition(Handle<DebugInfo> debug_info);
using BodyDescriptor = StructBodyDescriptor;
DECL_PRINTER(BreakPointInfo)
DECL_VERIFIER(BreakPointInfo)
TaggedMember<Smi> source_position_;
TaggedMember<UnionOf<FixedArray, BreakPoint, Undefined>> break_points_;
} V8_OBJECT_END;
// Layout of a single slot within CoverageInfo.
struct CoverageInfoSlot {
int32_t start_source_position;
int32_t end_source_position;
int32_t block_count;
int32_t padding;
static const int kSize;
};
static_assert(sizeof(CoverageInfoSlot) == 16);
inline constexpr int CoverageInfoSlot::kSize = sizeof(CoverageInfoSlot);
// Holds information related to block code coverage.
V8_OBJECT class CoverageInfo : public HeapObject {
public:
inline int32_t slot_count() const;
inline void set_slot_count(int32_t value);
inline int32_t slots_start_source_position(int i) const;
inline void set_slots_start_source_position(int i, int32_t value);
inline int32_t slots_end_source_position(int i) const;
inline void set_slots_end_source_position(int i, int32_t value);
inline int32_t slots_block_count(int i) const;
inline void set_slots_block_count(int i, int32_t value);
inline int32_t slots_padding(int i) const;
inline void set_slots_padding(int i, int32_t value);
void InitializeSlot(int slot_index, int start_pos, int end_pos);
void ResetBlockCount(int slot_index);
// Computes the size for a CoverageInfo instance of a given length.
static constexpr int SizeFor(int slot_count);
inline int AllocatedSize() const;
// Print debug info.
void CoverageInfoPrint(std::ostream& os,
std::unique_ptr<char[]> function_name = nullptr);
DECL_VERIFIER(CoverageInfo)
class BodyDescriptor; // GC visitor.
// Description of layout within each slot.
using Slot = CoverageInfoSlot;
int32_t slot_count_;
FLEXIBLE_ARRAY_MEMBER(CoverageInfoSlot, slots);
} V8_OBJECT_END;
constexpr int CoverageInfo::SizeFor(int slot_count) {
return OBJECT_POINTER_ALIGN(OFFSET_OF_DATA_START(CoverageInfo) +
slot_count * sizeof(CoverageInfoSlot));
}
// Holds breakpoint related information. This object is used by inspector.
V8_OBJECT class BreakPoint : public Struct {
public:
// Accessors
inline int id() const;
inline void set_id(int value);
inline Tagged<String> condition() const;
inline void set_condition(Tagged<String> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
using BodyDescriptor = StructBodyDescriptor;
DECL_PRINTER(BreakPoint)
DECL_VERIFIER(BreakPoint)
TaggedMember<Smi> id_;
TaggedMember<String> condition_;
} V8_OBJECT_END;
V8_OBJECT class StackFrameInfo : public Struct {
public:
static int GetSourcePosition(DirectHandle<StackFrameInfo> info);
// The script for the stack frame.
inline Tagged<Script> script() const;
// The bytecode offset or source position for the stack frame.
inline int bytecode_offset_or_source_position() const;
inline void set_bytecode_offset_or_source_position(int value);
// Indicates that the frame corresponds to a 'new' invocation.
inline bool is_constructor() const;
inline void set_is_constructor(bool value);
inline Tagged<UnionOf<SharedFunctionInfo, Script>> shared_or_script() const;
inline void set_shared_or_script(
Tagged<UnionOf<SharedFunctionInfo, Script>> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Tagged<String> function_name() const;
inline void set_function_name(Tagged<String> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline int flags() const;
inline void set_flags(int value);
// Bit positions in |flags|.
using IsConstructorBit = base::BitField<bool, 0, 1, uint32_t>;
using BodyDescriptor = StructBodyDescriptor;
DECL_VERIFIER(StackFrameInfo)
DECL_PRINTER(StackFrameInfo)
TaggedMember<UnionOf<SharedFunctionInfo, Script>> shared_or_script_;
TaggedMember<String> function_name_;
TaggedMember<Smi> flags_;
TaggedMember<Smi> bytecode_offset_or_source_position_;
#if V8_ENABLE_WEBASSEMBLY
// Wasm wire byte offsets are 0-indexed instruction positions within a module
// buffer of max size kV8MaxWasmModuleSize (1 GiB). The maximum possible
// offset is kV8MaxWasmModuleSize - 1, which fits exactly within a signed
// 31-bit Smi.
static_assert(wasm::kV8MaxWasmModuleSize - 1 <= Smi::kMaxValue);
#endif // V8_ENABLE_WEBASSEMBLY
} V8_OBJECT_END;
V8_OBJECT class StackTraceInfo : public Struct {
public:
// Accessors
inline int id() const;
inline void set_id(int value);
inline Tagged<FixedArray> frames() const;
inline void set_frames(Tagged<FixedArray> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Access to the stack frames.
int length() const;
Tagged<StackFrameInfo> get(int index) const;
// Dispatched behavior.
DECL_VERIFIER(StackTraceInfo)
DECL_PRINTER(StackTraceInfo)
using BodyDescriptor = StructBodyDescriptor;
TaggedMember<Smi> id_;
TaggedMember<FixedArray> frames_;
} V8_OBJECT_END;
V8_OBJECT class ErrorStackData : public Struct {
public:
inline bool HasFormattedStack() const;
inline Tagged<JSAny> formatted_stack() const;
inline void set_formatted_stack(Tagged<JSAny> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline bool HasRawDataForCallSiteInfos() const;
inline Tagged<FixedArray> raw_data_for_call_site_infos() const;
inline void set_raw_data_for_call_site_infos(
Tagged<FixedArray> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Tagged<UnionOf<FixedArray, JSAny>>
raw_data_for_call_site_infos_or_formatted_stack() const;
inline void set_raw_data_for_call_site_infos_or_formatted_stack(
Tagged<UnionOf<FixedArray, JSAny>> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Tagged<StackTraceInfo> stack_trace() const;
inline void set_stack_trace(Tagged<StackTraceInfo> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
DECL_VERIFIER(ErrorStackData)
DECL_PRINTER(ErrorStackData)
using BodyDescriptor = StructBodyDescriptor;
TaggedMember<UnionOf<FixedArray, JSAny>>
raw_data_for_call_site_infos_or_formatted_stack_;
TaggedMember<StackTraceInfo> stack_trace_;
} V8_OBJECT_END;
// DebugScriptScopeInfo holds the serialized scope tree of a Script for the
// debugger. It caches lexical scope information (scopes, variables, positions)
// to avoid reparsing the script on every pause or inspection step.
//
// The exact encoding of the data in `numeric_data` is described in
// src/debug/debug-scope-info.cc.
V8_OBJECT class DebugScriptScopeInfo : public Struct {
public:
inline Tagged<ByteArray> numeric_data() const;
inline void set_numeric_data(Tagged<ByteArray> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Tagged<FixedArray> string_table() const;
inline void set_string_table(Tagged<FixedArray> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
DECL_VERIFIER(DebugScriptScopeInfo)
DECL_PRINTER(DebugScriptScopeInfo)
using BodyDescriptor = StructBodyDescriptor;
TaggedMember<ByteArray> numeric_data_;
TaggedMember<FixedArray> string_table_;
} V8_OBJECT_END;
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_DEBUG_OBJECTS_H_