8#include <unordered_map>
39using ImportExportKey = std::pair<ImportExportKindCode, uint32_t>;
41enum ReturnLocation { kAfterBreakpoint, kAfterWasmCall };
43Address FindNewPC(WasmFrame* frame, WasmCode* wasm_code,
int byte_offset,
44 ReturnLocation return_location) {
45 base::Vector<const uint8_t> new_pos_table = wasm_code->source_positions();
51 WasmCode* old_code = frame->wasm_code();
52 int pc_offset =
static_cast<int>(frame->pc() - old_code->instruction_start());
53 base::Vector<const uint8_t> old_pos_table = old_code->source_positions();
54 SourcePositionTableIterator old_it(old_pos_table);
56 while (!old_it.done() && old_it.code_offset() <
pc_offset) {
57 call_offset = old_it.code_offset();
61 int call_instruction_size =
pc_offset - call_offset;
67 SourcePositionTableIterator it(new_pos_table);
68 while (!it.done() && it.source_position().ScriptOffset() != byte_offset) {
71 if (return_location == kAfterBreakpoint) {
72 while (!it.is_statement()) it.Advance();
73 DCHECK_EQ(byte_offset, it.source_position().ScriptOffset());
74 return wasm_code->instruction_start() + it.code_offset() +
75 call_instruction_size;
78 DCHECK_EQ(kAfterWasmCall, return_location);
81 code_offset = it.code_offset();
83 }
while (!it.done() && it.source_position().ScriptOffset() == byte_offset);
84 return wasm_code->instruction_start() + code_offset + call_instruction_size;
92 for (
auto& entry :
entries_) entry.Print(os);
97 os << std::setw(6) << std::hex <<
pc_offset_ << std::dec <<
" stack height "
100 os <<
" " << value.type.name() <<
":";
101 switch (value.storage) {
103 os <<
"const#" << value.i32_const;
106 os <<
"reg#" << value.reg_code;
109 os <<
"stack#" << value.stack_offset;
125 result += entry.EstimateCurrentMemoryConsumption();
145 Address debug_break_fp,
Isolate* isolate) {
148 fp, debug_break_fp, isolate);
156 return stack_height - num_locals;
160 Address debug_break_fp,
Isolate* isolate) {
164 if (num_locals + index >= value_count)
return {};
166 num_locals + index, fp, debug_break_fp, isolate);
171 auto*
module = native_module_->module();
172 return module->functions[scope.code->index()];
180 const auto& function =
182 int offset = frame->position() - function.code.offset();
183 if (std::binary_search(breakpoints.
begin(), breakpoints.
end(),
offset)) {
194#if !V8_ENABLE_DRUMBRAKE
195 if (it.done() || !it.is_wasm())
return 0;
198 if (it.done() || !it.is_wasm() || it.is_wasm_interpreter_entry()) {
202 auto* wasm_frame = WasmFrame::cast(it.frame());
203 if (
static_cast<int>(wasm_frame->function_index()) != func_index)
return 0;
204 return DeadBreakpoint(wasm_frame, breakpoints);
209 int dead_breakpoint) {
218 for (
auto begin = cached_debugging_code_.begin(), it = begin,
219 end = cached_debugging_code_.end();
221 if (it->func_index == func_index &&
222 it->breakpoint_offsets.as_vector() == offsets &&
223 it->dead_breakpoint == dead_breakpoint) {
225 for (; it != begin; --it) std::iter_swap(it, it - 1);
240 FunctionBody body{function->sig, function->code.offset(),
241 wire_bytes.
begin() + function->code.offset(),
242 wire_bytes.
begin() + function->code.end_offset(),
244 std::unique_ptr<DebugSideTable> debug_sidetable;
251 Zone validation_zone(wasm::GetWasmEngine()->allocator(),
ZONE_NAME);
254 env.
module, &unused_detected_features, body);
258 validation_result.
error().message().c_str());
259 env.
module->set_function_validated(func_index);
264 .set_func_index(func_index)
265 .set_for_debugging(for_debugging)
266 .set_breakpoints(offsets)
267 .set_dead_breakpoint(dead_breakpoint)
268 .set_debug_sidetable(generate_debug_sidetable ? &debug_sidetable
272 if (!
result.succeeded())
FATAL(
"Liftoff compilation failed");
273 DCHECK_EQ(generate_debug_sidetable, debug_sidetable !=
nullptr);
280 if (generate_debug_sidetable) {
282 DCHECK_EQ(0, debug_side_tables_.count(new_code));
283 debug_side_tables_.emplace(new_code, std::move(debug_sidetable));
287 cached_debugging_code_.insert(
288 cached_debugging_code_.begin(),
290 dead_breakpoint, new_code});
294 if (cached_debugging_code_.size() > kMaxCachedDebuggingCode) {
297 WasmCodeRefScope::AddRef(cached_debugging_code_.back().code);
298 cached_debugging_code_.back().code->DecRefOnLiveCode();
299 cached_debugging_code_.pop_back();
301 DCHECK_GE(kMaxCachedDebuggingCode, cached_debugging_code_.size());
324 std::vector<int> all_breakpoints = FindAllBreakpoints(func_index);
326 auto& isolate_data = per_isolate_data_[
isolate];
327 std::vector<int>& breakpoints =
328 isolate_data.breakpoints_per_function[func_index];
329 auto insertion_point =
330 std::lower_bound(breakpoints.begin(), breakpoints.end(),
offset);
331 if (insertion_point != breakpoints.end() && *insertion_point ==
offset) {
335 breakpoints.insert(insertion_point,
offset);
337 DCHECK(std::is_sorted(all_breakpoints.begin(), all_breakpoints.end()));
339 insertion_point = std::lower_bound(all_breakpoints.begin(),
340 all_breakpoints.end(),
offset);
341 bool breakpoint_exists =
342 insertion_point != all_breakpoints.end() && *insertion_point ==
offset;
347 if (breakpoint_exists) {
350 all_breakpoints.insert(insertion_point,
offset);
351 int dead_breakpoint =
352 DeadBreakpoint(func_index, base::VectorOf(all_breakpoints), isolate);
353 new_code = RecompileLiftoffWithBreakpoints(
354 func_index, base::VectorOf(all_breakpoints), dead_breakpoint);
356 UpdateReturnAddresses(isolate, new_code, isolate_data.stepping_frame);
361 std::set<int> breakpoints;
362 for (
auto& data : per_isolate_data_) {
363 auto it = data.second.breakpoints_per_function.find(func_index);
364 if (it == data.second.breakpoints_per_function.end())
continue;
365 for (
int offset : it->second) breakpoints.insert(
offset);
367 return {breakpoints.begin(), breakpoints.end()};
372 int dead_breakpoint) {
377 WasmCode* new_code = RecompileLiftoffWithBreakpoints(
378 func_index, breakpoints, dead_breakpoint);
379 UpdateReturnAddresses(isolate, new_code, stepping_frame);
387 constexpr int kFloodingBreakpoints[] = {0};
388 DCHECK(frame->wasm_code()->is_liftoff());
391 WasmCode* new_code = RecompileLiftoffWithBreakpoints(
392 frame->function_index(), base::ArrayVector(kFloodingBreakpoints), 0);
393 UpdateReturnAddress(frame, new_code, return_location);
395 per_isolate_data_[frame->isolate()].stepping_frame = frame->id();
400 int func_index = frame->function_index();
402 native_module->
module()->functions[func_index].code;
405 return isolate->debug()->IsFunctionBlackboxed(script, func_code.
offset(),
412 if (!code->is_liftoff())
return false;
413 if (IsAtReturn(frame))
return false;
414 FloodWithBreakpoints(frame, kAfterBreakpoint);
421 if (!code->is_liftoff())
return;
422 FloodWithBreakpoints(frame, kAfterWasmCall);
431 auto* code = frame->wasm_code();
433 int func_index = code->index();
434 std::vector<int> breakpoints = FindAllBreakpoints(func_index);
435 int dead_breakpoint = DeadBreakpoint(frame, base::VectorOf(breakpoints));
436 WasmCode* new_code = RecompileLiftoffWithBreakpoints(
437 func_index, base::VectorOf(breakpoints), dead_breakpoint);
438 UpdateReturnAddress(frame, new_code, kAfterBreakpoint);
443 auto it = per_isolate_data_.find(isolate);
444 if (it != per_isolate_data_.end()) it->second.stepping_frame =
NO_ID;
449 if (isolate->debug()->last_step_action() == StepInto)
return true;
451 auto it = per_isolate_data_.find(isolate);
452 return it != per_isolate_data_.end() &&
453 it->second.stepping_frame == frame->id();
465 const auto& function =
native_module_->module()->functions[func_index];
468 auto& isolate_data = per_isolate_data_[
isolate];
469 std::vector<int>& breakpoints =
470 isolate_data.breakpoints_per_function[func_index];
472 auto insertion_point =
473 std::lower_bound(breakpoints.begin(), breakpoints.end(),
offset);
474 if (insertion_point == breakpoints.end())
return;
475 if (*insertion_point !=
offset)
return;
476 breakpoints.erase(insertion_point);
478 std::vector<int> remaining = FindAllBreakpoints(func_index);
480 DCHECK(std::is_sorted(remaining.begin(), remaining.end()));
481 if (std::binary_search(remaining.begin(), remaining.end(),
offset))
return;
482 int dead_breakpoint =
483 DeadBreakpoint(func_index, base::VectorOf(remaining), isolate);
484 UpdateBreakpoints(func_index, base::VectorOf(remaining), isolate,
485 isolate_data.stepping_frame, dead_breakpoint);
490 for (
auto* code : codes) {
491 debug_side_tables_.erase(code);
497 auto it = debug_side_tables_.find(code);
498 return it == debug_side_tables_.end() ?
nullptr : it->second.get();
502 const std::vector<int>& remaining) {
503 DCHECK(std::is_sorted(remaining.begin(), remaining.end()));
504 for (
int offset : removed) {
506 if (!std::binary_search(remaining.begin(), remaining.end(),
offset)) {
519 auto per_isolate_data_it = per_isolate_data_.find(isolate);
520 if (per_isolate_data_it == per_isolate_data_.end())
return;
521 std::unordered_map<int, std::vector<int>> removed_per_function =
522 std::move(per_isolate_data_it->second.breakpoints_per_function);
523 per_isolate_data_.erase(per_isolate_data_it);
524 for (
auto& entry : removed_per_function) {
525 int func_index = entry.first;
526 std::vector<int>& removed = entry.second;
527 std::vector<int> remaining = FindAllBreakpoints(func_index);
528 if (HasRemovedBreakpoints(removed, remaining)) {
529 RecompileLiftoffWithBreakpoints(func_index, base::VectorOf(remaining),
543 for (
const auto& [code, table] : debug_side_tables_) {
544 result += table->EstimateCurrentMemoryConsumption();
551 result += code.breakpoint_offsets.size() *
sizeof(int);
554 for (
const auto& [isolate, data] : per_isolate_data_) {
557 for (
const auto& [idx, breakpoints] : data.breakpoints_per_function) {
562 if (
v8_flags.trace_wasm_offheap_memory) {
573 pc_offset(static_cast<int>(
pc - code->instruction_start())),
574 debug_side_table(code->is_inspectable()
575 ? debug_info->GetDebugSideTable(code)
577 debug_side_table_entry(debug_side_table
580 DCHECK_IMPLIES(code->is_inspectable(), debug_side_table_entry !=
nullptr);
593 DCHECK(code->is_inspectable());
598 auto it = debug_side_tables_.find(code);
599 if (it != debug_side_tables_.end())
return it->second.get();
603 std::unique_ptr<DebugSideTable> debug_side_table =
611 auto& slot = debug_side_tables_[
code];
612 if (slot !=
nullptr)
return slot.get();
613 slot = std::move(debug_side_table);
625 int index, Address stack_frame_base,
626 Address debug_break_fp,
Isolate* isolate)
const {
628 debug_side_table->
FindValue(debug_side_table_entry, index);
629 if (value->is_constant()) {
635 if (value->is_register()) {
636 auto reg = LiftoffRegister::from_liftoff_code(value->reg_code);
638 return debug_break_fp +
639 WasmDebugBreakFrameConstants::GetPushedGpRegisterOffset(
642 if (
reg.is_gp_pair()) {
644 uint32_t low_word = ReadUnalignedValue<uint32_t>(gp_addr(
reg.low_gp()));
646 ReadUnalignedValue<uint32_t>(gp_addr(
reg.high_gp()));
647 return WasmValue((uint64_t{high_word} << 32) | low_word);
651 return WasmValue(ReadUnalignedValue<uint32_t>(gp_addr(
reg.gp())));
652 }
else if (value->type ==
kWasmI64) {
653 return WasmValue(ReadUnalignedValue<uint64_t>(gp_addr(
reg.gp())));
654 }
else if (value->type.is_reference()) {
660 return WasmValue(obj, value->module->canonical_type(value->type));
667#ifdef V8_TARGET_ARCH_ARM
668 int code =
reg.is_fp_pair() ?
reg.low_fp().code() :
reg.fp().code();
670 int code =
reg.fp().code();
672 Address spilled_addr =
674 WasmDebugBreakFrameConstants::GetPushedFpRegisterOffset(code);
676 return WasmValue(ReadUnalignedValue<float>(spilled_addr));
677 }
else if (value->type ==
kWasmF64) {
678 return WasmValue(ReadUnalignedValue<double>(spilled_addr));
688 Address stack_address = stack_frame_base - value->stack_offset;
689 switch (value->type.kind()) {
691 return WasmValue(ReadUnalignedValue<int32_t>(stack_address));
693 return WasmValue(ReadUnalignedValue<int64_t>(stack_address));
695 return WasmValue(ReadUnalignedValue<float>(stack_address));
697 return WasmValue(ReadUnalignedValue<double>(stack_address));
705 return WasmValue(obj, value->module->canonical_type(value->type));
724 ReturnLocation return_location = kAfterBreakpoint;
726 it.Advance(), return_location = kAfterWasmCall) {
728 if (it.frame()->id() == stepping_frame)
continue;
729#if !V8_ENABLE_DRUMBRAKE
730 if (!it.is_wasm())
continue;
733 if (!it.is_wasm() || it.is_wasm_interpreter_entry())
continue;
735 WasmFrame* frame = WasmFrame::cast(it.frame());
736 if (frame->native_module() != new_code->
native_module())
continue;
737 if (frame->function_index() != new_code->
index())
continue;
738 if (!frame->wasm_code()->is_liftoff())
continue;
739 UpdateReturnAddress(frame, new_code, return_location);
744 ReturnLocation return_location) {
748 DCHECK(frame->wasm_code()->is_liftoff());
749 Address new_pc = FindNewPC(frame, new_code, frame->generated_code_offset(),
752 int old_position = frame->position();
754#if V8_TARGET_ARCH_X64
755 if (frame->wasm_code()->for_debugging()) {
756 base::Memory<Address>(frame->fp() - kOSRTargetOffset) = new_pc;
759 PointerAuthentication::ReplacePC(frame->pc_address(), new_pc,
763 DCHECK_EQ(old_position, frame->position());
771 if (opcode == kExprReturn)
return true;
773 int func_index = frame->function_index();
775 return static_cast<size_t>(
position) == code.end_offset() - 1;
795 std::unordered_map<const WasmCode*, std::unique_ptr<DebugSideTable>>
805 static constexpr size_t kMaxCachedDebuggingCode = 3;
824 return impl_->GetNumLocals(
pc, isolate);
829 return impl_->GetLocalValue(local,
pc, fp, debug_break_fp, isolate);
833 return impl_->GetStackDepth(
pc, isolate);
838 return impl_->GetStackValue(index,
pc, fp, debug_break_fp, isolate);
843 return impl_->GetFunctionAtAddress(
pc, isolate);
848 impl_->SetBreakpoint(func_index,
offset, current_isolate);
852 return impl_->IsFrameBlackboxed(frame);
856 return impl_->PrepareStep(frame);
860 impl_->PrepareStepOutTo(frame);
864 impl_->ClearStepping(isolate);
870 return impl_->IsStepping(frame);
875 impl_->RemoveBreakpoint(func_index,
offset, current_isolate);
879 impl_->RemoveDebugSideTables(code);
884 return impl_->GetDebugSideTableIfExists(code);
888 return impl_->RemoveIsolate(isolate);
892 return impl_->EstimateCurrentMemoryConsumption();
904 int offset_in_func) {
906 wasm::BodyLocalDecls locals;
908 const wasm::WasmFunction& func =
909 native_module->
module()->functions[func_index];
910 wasm::BytecodeIterator iterator(module_start + func.code.offset(),
911 module_start + func.code.end_offset(),
914 if (offset_in_func < 0)
return 0;
915 for (; iterator.has_next(); iterator.next()) {
916 if (iterator.pc_offset() <
static_cast<uint32_t
>(offset_in_func))
continue;
918 return static_cast<int>(iterator.pc_offset());
924 if (script->break_on_entry() == enabled)
return;
926 script->set_break_on_entry(enabled);
929 script->wasm_weak_instance_list();
931 for (
int i = 0;
i < weak_instance_list->length(); ++
i) {
932 if (weak_instance_list->Get(
i).
IsCleared())
continue;
935 instance->trusted_data(isolate)->set_break_on_entry(enabled);
947 int func_index = GetContainingWasmFunction(module, *
position);
948 if (func_index < 0)
return false;
952 int breakable_offset = FindNextBreakablePosition(script->wasm_native_module(),
953 func_index, offset_in_func);
954 if (breakable_offset == 0)
return false;
958 breakable_offset, break_point);
968 SetBreakOnEntryFlag(*script,
true);
975 if (func_index < 0)
return false;
976 int offset_in_func = 0;
978 int breakable_offset = FindNextBreakablePosition(script->wasm_native_module(),
979 func_index, offset_in_func);
980 if (breakable_offset == 0)
return false;
982 breakable_offset, break_point);
1009int GetBreakpointPos(
Isolate* isolate,
1011 if (IsUndefined(break_point_info_or_undef, isolate))
return kMaxInt;
1015int FindBreakpointInfoInsertPos(
Isolate* isolate,
1016 DirectHandle<FixedArray> breakpoint_infos,
1024 int right = breakpoint_infos->length();
1025 while (right - left > 1) {
1026 int mid = left + (right - left) / 2;
1028 if (GetBreakpointPos(isolate, mid_obj) <=
position) {
1035 int left_pos = GetBreakpointPos(isolate, breakpoint_infos->get(left));
1036 return left_pos <
position ? left + 1 : left;
1044 if (!script->has_wasm_breakpoint_infos())
return false;
1050 int pos = FindBreakpointInfoInsertPos(isolate, breakpoint_infos,
position);
1053 if (
pos == breakpoint_infos->length())
return false;
1060 if (info->GetBreakPointCount(isolate) == 0) {
1062 for (
int i =
pos;
i < breakpoint_infos->length() - 1;
i++) {
1064 breakpoint_infos->set(
i, entry);
1065 if (IsUndefined(entry, isolate))
break;
1068 breakpoint_infos->set(breakpoint_infos->length() - 1,
1075 SetBreakOnEntryFlag(*script,
false);
1080 int func_index = GetContainingWasmFunction(module,
position);
1090 int breakpoint_id) {
1091 if (!script->has_wasm_breakpoint_infos()) {
1098 DCHECK_LT(0, breakpoint_infos->length());
1100 for (
int i = 0, e = breakpoint_infos->length();
i < e; ++
i) {
1102 if (IsUndefined(*obj, isolate)) {
1109 .ToHandle(&breakpoint)) {
1110 DCHECK(breakpoint->id() == breakpoint_id);
1112 script, breakpoint_info->source_position(), breakpoint);
1120 script->set_wasm_breakpoint_infos(
1122 SetBreakOnEntryFlag(script,
false);
1130 if (script->has_wasm_breakpoint_infos()) {
1131 breakpoint_infos =
direct_handle(script->wasm_breakpoint_infos(), isolate);
1135 script->set_wasm_breakpoint_infos(*breakpoint_infos);
1139 FindBreakpointInfoInsertPos(isolate, breakpoint_infos,
position);
1143 if (insert_pos < breakpoint_infos->
length() &&
1144 GetBreakpointPos(isolate, breakpoint_infos->get(insert_pos)) ==
1153 bool need_realloc = !IsUndefined(
1154 breakpoint_infos->get(breakpoint_infos->length() - 1), isolate);
1157 new_breakpoint_infos = isolate->factory()->NewFixedArray(
1159 script->set_wasm_breakpoint_infos(*new_breakpoint_infos);
1161 for (
int i = 0;
i < insert_pos; ++
i)
1162 new_breakpoint_infos->set(
i, breakpoint_infos->get(
i));
1166 for (
int i = breakpoint_infos->length() - 1;
i >= insert_pos; --
i) {
1168 if (IsUndefined(entry, isolate))
continue;
1169 new_breakpoint_infos->set(
i + 1, entry);
1174 isolate->factory()->NewBreakPointInfo(
position);
1178 new_breakpoint_infos->set(insert_pos, *breakpoint_info);
1185 std::vector<v8::debug::BreakLocation>* locations) {
1189 const std::vector<wasm::WasmFunction>& functions =
module->functions;
1191 if (
start.GetLineNumber() != 0 ||
start.GetColumnNumber() < 0 ||
1193 (
end.GetLineNumber() != 0 ||
end.GetColumnNumber() < 0 ||
1194 end.GetColumnNumber() <
start.GetColumnNumber())))
1201 int start_func_index =
1202 GetNearestWasmFunction(module,
start.GetColumnNumber());
1203 if (start_func_index < 0)
return false;
1204 uint32_t start_offset =
start.GetColumnNumber();
1206 uint32_t end_offset;
1208 if (
end.IsEmpty()) {
1210 end_func_index =
static_cast<uint32_t
>(functions.size() - 1);
1211 end_offset = functions[end_func_index].code.end_offset();
1214 end_offset =
end.GetColumnNumber();
1215 end_func_index = GetNearestWasmFunction(module, end_offset);
1216 DCHECK_GE(end_func_index, start_func_index);
1219 if (start_func_index == end_func_index &&
1220 start_offset > functions[end_func_index].code.end_offset())
1225 for (
int func_idx = start_func_index; func_idx <= end_func_index;
1236 uint32_t total_offset = func.
code.
offset() + iterator.pc_offset();
1237 if (total_offset >= end_offset) {
1241 if (total_offset < start_offset)
continue;
1253 if (break_point->condition()->length() == 0)
return true;
1259 const int inlined_jsframe_index = 0;
1260 const bool throw_on_side_effect =
false;
1262 throw_on_side_effect)
1264 isolate->clear_exception();
1276 if (!script->has_wasm_breakpoint_infos())
return {};
1281 FindBreakpointInfoInsertPos(isolate, breakpoint_infos,
position);
1282 if (insert_pos >= breakpoint_infos->length())
return {};
1286 if (IsUndefined(*maybe_breakpoint_info, isolate))
return {};
1288 if (breakpoint_info->source_position() !=
position)
return {};
1291 if (!IsFixedArray(*break_points)) {
1295 isolate->debug()->SetMutedWasmLocation(script,
position);
1299 isolate->debug()->ClearMutedLocation();
1301 isolate->factory()->NewFixedArray(1);
1302 break_points_hit->set(0, *break_points);
1303 return break_points_hit;
1308 isolate->factory()->NewFixedArray(array->length());
1309 int break_points_hit_count = 0;
1310 for (
int i = 0;
i < array->
length(); ++
i) {
1313 if (CheckBreakPoint(isolate, break_point, frame_id)) {
1314 break_points_hit->set(break_points_hit_count++, *break_point);
1317 if (break_points_hit_count == 0)
return {};
1318 break_points_hit->RightTrim(isolate, break_points_hit_count);
1319 return break_points_hit;
constexpr size_t size() const
constexpr T * begin() const
constexpr T * end() const
static void SetBreakPoint(Isolate *isolate, DirectHandle< BreakPointInfo > info, DirectHandle< BreakPoint > break_point)
static void ClearBreakPoint(Isolate *isolate, DirectHandle< BreakPointInfo > info, DirectHandle< BreakPoint > break_point)
static MaybeDirectHandle< BreakPoint > GetBreakPointById(Isolate *isolate, DirectHandle< BreakPointInfo > info, int breakpoint_id)
static V8_EXPORT_PRIVATE MaybeDirectHandle< Object > Local(Isolate *isolate, StackFrameId frame_id, int inlined_jsframe_index, DirectHandle< String > source, bool throw_on_side_effect)
static const int kInstrumentationId
Isolate * isolate() const
static V8_INLINE Isolate * Current()
static V8_EXPORT_PRIVATE bool BooleanValue(Tagged< Object > obj, IsolateT *isolate)
constexpr bool IsCleared() const
bool GetHeapObject(Tagged< HeapObject > *result) const
static MaybeDirectHandle< FixedArray > CheckBreakPoints(Isolate *, DirectHandle< Script >, int position, StackFrameId stack_frame_id)
static V8_EXPORT_PRIVATE bool GetPossibleBreakpoints(wasm::NativeModule *native_module, const debug::Location &start, const debug::Location &end, std::vector< debug::BreakLocation > *locations)
static V8_EXPORT_PRIVATE bool SetBreakPointOnFirstBreakableForFunction(DirectHandle< Script >, int function_index, DirectHandle< BreakPoint > break_point)
static V8_EXPORT_PRIVATE bool SetBreakPointForFunction(DirectHandle< Script >, int function_index, int breakable_offset, DirectHandle< BreakPoint > break_point)
static V8_EXPORT_PRIVATE void SetInstrumentationBreakpoint(DirectHandle< Script >, DirectHandle< BreakPoint > break_point)
static void ClearAllBreakpoints(Tagged< Script >)
static V8_EXPORT_PRIVATE bool ClearBreakPoint(DirectHandle< Script >, int position, DirectHandle< BreakPoint > break_point)
static V8_EXPORT_PRIVATE bool ClearBreakPointById(DirectHandle< Script >, int breakpoint_id)
static V8_EXPORT_PRIVATE bool SetBreakPoint(DirectHandle< Script >, int *position, DirectHandle< BreakPoint > break_point)
static constexpr int kOnEntryBreakpointPosition
static void AddBreakpointToInfo(DirectHandle< Script >, int position, DirectHandle< BreakPoint > break_point)
WasmCode * RecompileLiftoffWithBreakpoints(int func_index, base::Vector< const int > offsets, int dead_breakpoint)
bool PrepareStep(WasmFrame *frame)
std::vector< CachedDebuggingCode > cached_debugging_code_
void FloodWithBreakpoints(WasmFrame *frame, ReturnLocation return_location)
std::unordered_map< Isolate *, PerIsolateDebugData > per_isolate_data_
void UpdateReturnAddresses(Isolate *isolate, WasmCode *new_code, StackFrameId stepping_frame)
WasmValue GetStackValue(int index, Address pc, Address fp, Address debug_break_fp, Isolate *isolate)
void UpdateBreakpoints(int func_index, base::Vector< int > breakpoints, Isolate *isolate, StackFrameId stepping_frame, int dead_breakpoint)
base::Mutex debug_side_tables_mutex_
DebugInfoImpl & operator=(const DebugInfoImpl &)=delete
const WasmFunction & GetFunctionAtAddress(Address pc, Isolate *isolate)
WasmValue GetLocalValue(int local, Address pc, Address fp, Address debug_break_fp, Isolate *isolate)
int DeadBreakpoint(int func_index, base::Vector< const int > breakpoints, Isolate *isolate)
int GetStackDepth(Address pc, Isolate *isolate)
DebugInfoImpl(NativeModule *native_module)
const DebugSideTable * GetDebugSideTable(WasmCode *code)
std::vector< int > FindAllBreakpoints(int func_index)
bool IsStepping(WasmFrame *frame)
static bool HasRemovedBreakpoints(const std::vector< int > &removed, const std::vector< int > &remaining)
void RemoveDebugSideTables(base::Vector< WasmCode *const > codes)
void UpdateReturnAddress(WasmFrame *frame, WasmCode *new_code, ReturnLocation return_location)
void ClearStepping(Isolate *isolate)
int DeadBreakpoint(WasmFrame *frame, base::Vector< const int > breakpoints)
std::unordered_map< const WasmCode *, std::unique_ptr< DebugSideTable > > debug_side_tables_
void RemoveIsolate(Isolate *isolate)
DebugInfoImpl(const DebugInfoImpl &)=delete
bool IsAtReturn(WasmFrame *frame)
void ClearStepping(WasmFrame *frame)
void PrepareStepOutTo(WasmFrame *frame)
void SetBreakpoint(int func_index, int offset, Isolate *isolate)
int GetNumLocals(Address pc, Isolate *isolate)
bool IsFrameBlackboxed(WasmFrame *frame)
NativeModule *const native_module_
WasmValue GetValue(const DebugSideTable *debug_side_table, const DebugSideTable::Entry *debug_side_table_entry, int index, Address stack_frame_base, Address debug_break_fp, Isolate *isolate) const
void RemoveBreakpoint(int func_index, int position, Isolate *isolate)
DebugSideTable * GetDebugSideTableIfExists(const WasmCode *code) const
size_t EstimateCurrentMemoryConsumption() const
WasmValue GetLocalValue(int local, Address pc, Address fp, Address debug_break_fp, Isolate *isolate)
void RemoveIsolate(Isolate *)
void ClearStepping(Isolate *)
void PrepareStepOutTo(WasmFrame *)
DebugInfo(NativeModule *)
size_t EstimateCurrentMemoryConsumption() const
bool PrepareStep(WasmFrame *)
void RemoveBreakpoint(int func_index, int offset, Isolate *current_isolate)
const wasm::WasmFunction & GetFunctionAtAddress(Address pc, Isolate *isolate)
std::unique_ptr< DebugInfoImpl > impl_
WasmValue GetStackValue(int index, Address pc, Address fp, Address debug_break_fp, Isolate *isolate)
int GetStackDepth(Address pc, Isolate *isolate)
bool IsFrameBlackboxed(WasmFrame *frame)
int GetNumLocals(Address pc, Isolate *isolate)
DebugSideTable * GetDebugSideTableIfExists(const WasmCode *) const
void RemoveDebugSideTables(base::Vector< WasmCode *const >)
void SetBreakpoint(int func_index, int offset, Isolate *current_isolate)
bool IsStepping(WasmFrame *)
size_t EstimateCurrentMemoryConsumption() const
std::vector< Value > changed_values_
void Print(std::ostream &) const
DebugSideTable(int num_locals, std::vector< Entry > entries)
std::vector< Entry > entries_
const Entry::Value * FindValue(const Entry *entry, int stack_index) const
size_t EstimateCurrentMemoryConsumption() const
void Print(std::ostream &) const
const WasmModule * module() const
base::Vector< const uint8_t > wire_bytes() const
DebugInfo * GetDebugInfo()
const WasmError & error() const &
NativeModule * native_module() const
bool is_inspectable() const
AccountingAllocator * allocator()
static constexpr bool IsBreakable(WasmOpcode)
uint32_t end_offset() const
Handle< SharedFunctionInfo > info
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr
ZoneVector< RpoNumber > & result
std::vector< Value > changed_values_
std::shared_ptr< NativeModule > native_module_
WasmCodeManager * GetWasmCodeManager()
constexpr IndependentValueType kWasmF32
constexpr IndependentValueType kWasmI32
WasmCompilationResult ExecuteLiftoffCompilation(CompilationEnv *env, const FunctionBody &func_body, const LiftoffOptions &compiler_options)
std::unique_ptr< DebugSideTable > GenerateLiftoffDebugSideTable(const WasmCode *code)
size_t ContentSize(const std::vector< T > &vector)
DecodeResult ValidateFunctionBody(Zone *zone, WasmEnabledFeatures enabled, const WasmModule *module, WasmDetectedFeatures *detected, const FunctionBody &body)
WasmEngine * GetWasmEngine()
constexpr IndependentValueType kWasmS128
constexpr IndependentValueType kWasmF64
constexpr IndependentValueType kWasmI64
void PrintF(const char *format,...)
Tagged(T object) -> Tagged< T >
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
constexpr int kSystemPointerSize
V8_EXPORT_PRIVATE FlagValues v8_flags
JSArrayBuffer::IsDetachableBit is_shared
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK_LE(v1, v2)
#define CHECK_WITH_MSG(condition, message)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define UPDATE_WHEN_CLASS_CHANGES(classname, size)
const WasmEnabledFeatures enabled_features
const WasmModule *const module
base::OwnedVector< const int > breakpoint_offsets
bool is_inspectable() const
const DebugSideTable::Entry * debug_side_table_entry
wasm::WasmCodeRefScope wasm_code_ref_scope
FrameInspectionScope(DebugInfoImpl *debug_info, Address pc, Isolate *isolate)
const DebugSideTable * debug_side_table
std::unordered_map< int, std::vector< int > > breakpoints_per_function
#define V8_UNLIKELY(condition)