5 #include "src/debug/debug.h" 8 #include <unordered_set> 10 #include "src/api-inl.h" 11 #include "src/arguments.h" 12 #include "src/assembler-inl.h" 13 #include "src/base/platform/mutex.h" 14 #include "src/bootstrapper.h" 15 #include "src/builtins/builtins.h" 16 #include "src/code-stubs.h" 17 #include "src/compilation-cache.h" 18 #include "src/compiler.h" 19 #include "src/counters.h" 20 #include "src/debug/debug-evaluate.h" 21 #include "src/debug/liveedit.h" 22 #include "src/deoptimizer.h" 23 #include "src/execution.h" 24 #include "src/frames-inl.h" 25 #include "src/global-handles.h" 26 #include "src/globals.h" 27 #include "src/interpreter/bytecode-array-accessor.h" 28 #include "src/interpreter/bytecode-array-iterator.h" 29 #include "src/interpreter/interpreter.h" 30 #include "src/isolate-inl.h" 32 #include "src/message-template.h" 33 #include "src/objects/api-callbacks-inl.h" 34 #include "src/objects/debug-objects-inl.h" 35 #include "src/objects/js-generator-inl.h" 36 #include "src/objects/js-promise-inl.h" 37 #include "src/objects/slots.h" 38 #include "src/snapshot/natives.h" 39 #include "src/snapshot/snapshot.h" 40 #include "src/wasm/wasm-objects-inl.h" 50 void AllocationEvent(
Address addr,
int)
override { objects_.insert(addr); }
53 if (from == to)
return;
54 base::MutexGuard guard(&mutex_);
55 auto it = objects_.find(from);
56 if (it == objects_.end()) {
68 if (obj->IsJSObject() &&
76 return objects_.find(obj->address()) != objects_.end();
80 std::unordered_set<Address> objects_;
87 hook_on_function_call_(false),
88 is_suppressed_(false),
89 break_disabled_(false),
90 break_points_active_(true),
91 break_on_exception_(false),
92 break_on_uncaught_exception_(false),
93 side_effect_check_failed_(false),
94 debug_info_list_(nullptr),
95 feature_tracker_(isolate),
100 Debug::~Debug() { DCHECK_NULL(debug_delegate_); }
103 JavaScriptFrame* frame) {
104 if (debug_info->CanBreakAtEntry()) {
105 return BreakLocation(Debug::kBreakAtEntryPosition, DEBUG_BREAK_AT_ENTRY);
107 auto summary = FrameSummary::GetTop(frame).AsJavaScript();
108 int offset = summary.code_offset();
109 Handle<AbstractCode> abstract_code = summary.abstract_code();
110 BreakIterator it(debug_info);
111 it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
112 return it.GetBreakLocation();
115 void BreakLocation::AllAtCurrentStatement(
116 Handle<DebugInfo> debug_info, JavaScriptFrame* frame,
117 std::vector<BreakLocation>* result_out) {
118 DCHECK(!debug_info->CanBreakAtEntry());
119 auto summary = FrameSummary::GetTop(frame).AsJavaScript();
120 int offset = summary.code_offset();
121 Handle<AbstractCode> abstract_code = summary.abstract_code();
122 if (abstract_code->IsCode()) offset = offset - 1;
123 int statement_position;
125 BreakIterator it(debug_info);
126 it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
127 statement_position = it.statement_position();
129 for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
130 if (it.statement_position() == statement_position) {
131 result_out->push_back(it.GetBreakLocation());
136 JSGeneratorObject* BreakLocation::GetGeneratorObjectForSuspendedFrame(
137 JavaScriptFrame* frame)
const {
139 DCHECK_GE(generator_obj_reg_index_, 0);
141 Object* generator_obj =
142 InterpretedFrame::cast(frame)->ReadInterpreterRegister(
143 generator_obj_reg_index_);
145 return JSGeneratorObject::cast(generator_obj);
148 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
149 Handle<AbstractCode> abstract_code,
152 int closest_break = 0;
153 int distance = kMaxInt;
154 DCHECK(0 <= offset && offset < abstract_code->Size());
155 for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
157 if (it.code_offset() <= offset && offset - it.code_offset() < distance) {
158 closest_break = it.break_index();
159 distance = offset - it.code_offset();
161 if (distance == 0)
break;
164 return closest_break;
167 bool BreakLocation::HasBreakPoint(Isolate* isolate,
168 Handle<DebugInfo> debug_info)
const {
170 if (!debug_info->HasBreakPoint(isolate, position_))
return false;
171 if (debug_info->CanBreakAtEntry()) {
172 DCHECK_EQ(Debug::kBreakAtEntryPosition, position_);
173 return debug_info->BreakAtEntry();
178 DCHECK(abstract_code_->IsBytecodeArray());
179 BreakIterator it(debug_info);
180 it.SkipToPosition(position_);
181 return it.code_offset() == code_offset_;
185 debug::BreakLocationType BreakLocation::type()
const {
187 case DEBUGGER_STATEMENT:
188 return debug::kDebuggerStatementBreakLocation;
189 case DEBUG_BREAK_SLOT_AT_CALL:
190 return debug::kCallBreakLocation;
191 case DEBUG_BREAK_SLOT_AT_RETURN:
192 return debug::kReturnBreakLocation;
195 case DEBUG_BREAK_SLOT_AT_SUSPEND:
197 return debug::kCommonBreakLocation;
201 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
202 : debug_info_(debug_info),
204 source_position_iterator_(
205 debug_info->DebugBytecodeArray()->SourcePositionTable()) {
206 position_ = debug_info->shared()->StartPosition();
207 statement_position_ = position_;
213 int BreakIterator::BreakIndexFromPosition(
int source_position) {
214 int distance = kMaxInt;
215 int closest_break = break_index();
217 int next_position = position();
218 if (source_position <= next_position &&
219 next_position - source_position < distance) {
220 closest_break = break_index();
221 distance = next_position - source_position;
223 if (distance == 0)
break;
227 return closest_break;
230 void BreakIterator::Next() {
231 DisallowHeapAllocation no_gc;
233 bool first = break_index_ == -1;
235 if (!first) source_position_iterator_.Advance();
238 position_ = source_position_iterator_.source_position().ScriptOffset();
239 if (source_position_iterator_.is_statement()) {
240 statement_position_ = position_;
242 DCHECK_LE(0, position_);
243 DCHECK_LE(0, statement_position_);
245 DebugBreakType type = GetDebugBreakType();
246 if (type != NOT_DEBUG_BREAK)
break;
251 DebugBreakType BreakIterator::GetDebugBreakType() {
252 BytecodeArray bytecode_array = debug_info_->OriginalBytecodeArray();
253 interpreter::Bytecode bytecode =
254 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
257 if (interpreter::Bytecodes::IsPrefixScalingBytecode(bytecode)) {
258 bytecode = interpreter::Bytecodes::FromByte(
259 bytecode_array->get(code_offset() + 1));
262 if (bytecode == interpreter::Bytecode::kDebugger) {
263 return DEBUGGER_STATEMENT;
264 }
else if (bytecode == interpreter::Bytecode::kReturn) {
265 return DEBUG_BREAK_SLOT_AT_RETURN;
266 }
else if (bytecode == interpreter::Bytecode::kSuspendGenerator) {
267 return DEBUG_BREAK_SLOT_AT_SUSPEND;
268 }
else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) {
269 return DEBUG_BREAK_SLOT_AT_CALL;
270 }
else if (source_position_iterator_.is_statement()) {
271 return DEBUG_BREAK_SLOT;
273 return NOT_DEBUG_BREAK;
277 void BreakIterator::SkipToPosition(
int position) {
278 BreakIterator it(debug_info_);
279 SkipTo(it.BreakIndexFromPosition(position));
282 void BreakIterator::SetDebugBreak() {
283 DebugBreakType debug_break_type = GetDebugBreakType();
284 if (debug_break_type == DEBUGGER_STATEMENT)
return;
285 HandleScope scope(isolate());
286 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
287 Handle<BytecodeArray> bytecode_array(debug_info_->DebugBytecodeArray(),
289 interpreter::BytecodeArrayAccessor(bytecode_array, code_offset())
293 void BreakIterator::ClearDebugBreak() {
294 DebugBreakType debug_break_type = GetDebugBreakType();
295 if (debug_break_type == DEBUGGER_STATEMENT)
return;
296 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
297 BytecodeArray bytecode_array = debug_info_->DebugBytecodeArray();
298 BytecodeArray original = debug_info_->OriginalBytecodeArray();
299 bytecode_array->set(code_offset(), original->get(code_offset()));
302 BreakLocation BreakIterator::GetBreakLocation() {
303 Handle<AbstractCode> code(
304 AbstractCode::cast(debug_info_->DebugBytecodeArray()), isolate());
305 DebugBreakType type = GetDebugBreakType();
306 int generator_object_reg_index = -1;
307 if (type == DEBUG_BREAK_SLOT_AT_SUSPEND) {
313 BytecodeArray bytecode_array = debug_info_->OriginalBytecodeArray();
314 interpreter::BytecodeArrayAccessor accessor(
315 handle(bytecode_array, isolate()), code_offset());
317 DCHECK_EQ(accessor.current_bytecode(),
318 interpreter::Bytecode::kSuspendGenerator);
319 interpreter::Register generator_obj_reg = accessor.GetRegisterOperand(0);
320 generator_object_reg_index = generator_obj_reg.index();
322 return BreakLocation(code, type, code_offset(), position_,
323 generator_object_reg_index);
326 Isolate* BreakIterator::isolate() {
return debug_info_->GetIsolate(); }
328 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
331 if (bitfield_ & mask)
return;
332 isolate_->counters()->debug_feature_usage()->AddSample(feature);
338 void Debug::ThreadInit() {
339 thread_local_.break_frame_id_ = StackFrame::NO_ID;
340 thread_local_.last_step_action_ = StepNone;
341 thread_local_.last_statement_position_ = kNoSourcePosition;
342 thread_local_.last_frame_count_ = -1;
343 thread_local_.fast_forward_to_return_ =
false;
344 thread_local_.ignore_step_into_function_ = Smi::kZero;
345 thread_local_.target_frame_count_ = -1;
346 thread_local_.return_value_ = Smi::kZero;
347 thread_local_.last_breakpoint_id_ = 0;
348 clear_suspended_generator();
349 thread_local_.restart_fp_ = kNullAddress;
350 base::Relaxed_Store(&thread_local_.current_debug_scope_,
351 static_cast<base::AtomicWord>(0));
352 thread_local_.break_on_next_function_call_ =
false;
353 UpdateHookOnFunctionCall();
357 char* Debug::ArchiveDebug(
char* storage) {
358 MemCopy(storage, reinterpret_cast<char*>(&thread_local_),
359 ArchiveSpacePerThread());
360 return storage + ArchiveSpacePerThread();
363 char* Debug::RestoreDebug(
char* storage) {
364 MemCopy(reinterpret_cast<char*>(&thread_local_), storage,
365 ArchiveSpacePerThread());
368 DebugScope debug_scope(
this);
374 if (thread_local_.last_step_action_ != StepNone) {
376 PrepareStep(thread_local_.last_step_action_);
379 return storage + ArchiveSpacePerThread();
382 int Debug::ArchiveSpacePerThread() {
return sizeof(ThreadLocal); }
384 void Debug::Iterate(RootVisitor* v) {
385 v->VisitRootPointer(Root::kDebug,
nullptr,
386 ObjectSlot(&thread_local_.return_value_));
387 v->VisitRootPointer(Root::kDebug,
nullptr,
388 ObjectSlot(&thread_local_.suspended_generator_));
389 v->VisitRootPointer(Root::kDebug,
nullptr,
390 ObjectSlot(&thread_local_.ignore_step_into_function_));
393 DebugInfoListNode::DebugInfoListNode(Isolate* isolate, DebugInfo* debug_info)
396 GlobalHandles* global_handles = isolate->global_handles();
397 debug_info_ = global_handles->Create(debug_info).location();
401 DebugInfoListNode::~DebugInfoListNode() {
402 if (debug_info_ ==
nullptr)
return;
403 GlobalHandles::Destroy(debug_info_);
404 debug_info_ =
nullptr;
407 void Debug::Unload() {
408 ClearAllBreakPoints();
410 RemoveAllCoverageInfos();
411 ClearAllDebuggerHints();
412 debug_delegate_ =
nullptr;
415 void Debug::Break(JavaScriptFrame* frame, Handle<JSFunction> break_target) {
417 LiveEdit::InitializeThreadLocal(
this);
420 if (break_disabled())
return;
423 DebugScope debug_scope(
this);
424 DisableBreak no_recursive_break(
this);
427 Handle<SharedFunctionInfo> shared(break_target->shared(), isolate_);
428 if (!EnsureBreakInfo(shared))
return;
429 PrepareFunctionForDebugExecution(shared);
431 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
434 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
437 MaybeHandle<FixedArray> break_points_hit =
438 CheckBreakPoints(debug_info, &location);
439 if (!break_points_hit.is_null() || break_on_next_function_call()) {
443 OnDebugBreak(!break_points_hit.is_null()
444 ? break_points_hit.ToHandleChecked()
445 : isolate_->factory()->empty_fixed_array());
450 if (location.IsDebugBreakAtEntry()) {
451 DCHECK(debug_info->BreakAtEntry());
455 DCHECK_NOT_NULL(frame);
458 StepAction step_action = last_step_action();
459 int current_frame_count = CurrentFrameCount();
460 int target_frame_count = thread_local_.target_frame_count_;
461 int last_frame_count = thread_local_.last_frame_count_;
465 if (thread_local_.fast_forward_to_return_) {
466 DCHECK(location.IsReturnOrSuspend());
468 if (current_frame_count > target_frame_count)
return;
470 PrepareStep(StepOut);
474 bool step_break =
false;
475 switch (step_action) {
480 if (current_frame_count > target_frame_count)
return;
485 if (current_frame_count > target_frame_count)
return;
489 if (location.IsSuspend()) {
490 DCHECK(!has_suspended_generator());
491 thread_local_.suspended_generator_ =
492 location.GetGeneratorObjectForSuspendedFrame(frame);
497 FrameSummary summary = FrameSummary::GetTop(frame);
498 step_break = step_break || location.IsReturn() ||
499 current_frame_count != last_frame_count ||
500 thread_local_.last_statement_position_ !=
501 summary.SourceStatementPosition();
511 OnDebugBreak(isolate_->factory()->empty_fixed_array());
514 PrepareStep(step_action);
522 MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
523 BreakLocation* location,
524 bool* has_break_points) {
525 bool has_break_points_to_check =
526 break_points_active_ && location->HasBreakPoint(isolate_, debug_info);
527 if (has_break_points) *has_break_points = has_break_points_to_check;
528 if (!has_break_points_to_check)
return {};
530 return Debug::GetHitBreakPoints(debug_info, location->position());
534 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
535 HandleScope scope(isolate_);
541 FrameSummary summary = FrameSummary::GetTop(frame);
542 DCHECK(!summary.IsWasm());
543 Handle<JSFunction>
function = summary.AsJavaScript().function();
544 if (!function->shared()->HasBreakInfo())
return false;
545 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo(), isolate_);
547 DebugScope debug_scope(
this);
548 std::vector<BreakLocation> break_locations;
549 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
550 bool has_break_points_at_all =
false;
551 for (
size_t i = 0;
i < break_locations.size();
i++) {
552 bool has_break_points;
553 MaybeHandle<FixedArray> check_result =
554 CheckBreakPoints(debug_info, &break_locations[
i], &has_break_points);
555 has_break_points_at_all |= has_break_points;
556 if (has_break_points && !check_result.is_null())
return false;
558 return has_break_points_at_all;
562 bool Debug::CheckBreakPoint(Handle<BreakPoint> break_point,
563 bool is_break_at_entry) {
564 HandleScope scope(isolate_);
566 if (!break_point->condition()->length())
return true;
567 Handle<String> condition(break_point->condition(), isolate_);
568 MaybeHandle<Object> maybe_result;
569 Handle<Object> result;
571 if (is_break_at_entry) {
572 maybe_result = DebugEvaluate::WithTopmostArguments(isolate_, condition);
576 const int inlined_jsframe_index = 0;
577 const bool throw_on_side_effect =
false;
579 DebugEvaluate::Local(isolate_, break_frame_id(), inlined_jsframe_index,
580 condition, throw_on_side_effect);
583 if (!maybe_result.ToHandle(&result)) {
584 if (isolate_->has_pending_exception()) {
585 isolate_->clear_pending_exception();
589 return result->BooleanValue(isolate_);
592 bool Debug::SetBreakPoint(Handle<JSFunction>
function,
593 Handle<BreakPoint> break_point,
594 int* source_position) {
595 HandleScope scope(isolate_);
598 Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
599 if (!EnsureBreakInfo(shared))
return false;
600 PrepareFunctionForDebugExecution(shared);
602 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
604 DCHECK_LE(0, *source_position);
607 *source_position = FindBreakablePosition(debug_info, *source_position);
608 DebugInfo::SetBreakPoint(isolate_, debug_info, *source_position, break_point);
610 DCHECK_LT(0, debug_info->GetBreakPointCount(isolate_));
612 ClearBreakPoints(debug_info);
613 ApplyBreakPoints(debug_info);
615 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
619 bool Debug::SetBreakPointForScript(Handle<Script> script,
620 Handle<String> condition,
621 int* source_position,
int*
id) {
622 *
id = ++thread_local_.last_breakpoint_id_;
623 Handle<BreakPoint> break_point =
624 isolate_->factory()->NewBreakPoint(*
id, condition);
625 if (script->type() == Script::TYPE_WASM) {
626 Handle<WasmModuleObject> module_object(
627 WasmModuleObject::cast(script->wasm_module_object()), isolate_);
628 return WasmModuleObject::SetBreakPoint(module_object, source_position,
632 HandleScope scope(isolate_);
635 Handle<Object> result =
636 FindSharedFunctionInfoInScript(script, *source_position);
637 if (result->IsUndefined(isolate_))
return false;
640 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
641 if (!EnsureBreakInfo(shared))
return false;
642 PrepareFunctionForDebugExecution(shared);
646 if (shared->StartPosition() > *source_position) {
647 *source_position = shared->StartPosition();
650 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
655 int breakable_position = FindBreakablePosition(debug_info, *source_position);
656 if (breakable_position < *source_position)
return false;
657 *source_position = breakable_position;
659 DebugInfo::SetBreakPoint(isolate_, debug_info, *source_position, break_point);
661 DCHECK_LT(0, debug_info->GetBreakPointCount(isolate_));
663 ClearBreakPoints(debug_info);
664 ApplyBreakPoints(debug_info);
666 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
670 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
671 int source_position) {
672 if (debug_info->CanBreakAtEntry()) {
673 return kBreakAtEntryPosition;
675 DCHECK(debug_info->HasInstrumentedBytecodeArray());
676 BreakIterator it(debug_info);
677 it.SkipToPosition(source_position);
678 return it.position();
682 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
683 DisallowHeapAllocation no_gc;
684 if (debug_info->CanBreakAtEntry()) {
685 debug_info->SetBreakAtEntry();
687 if (!debug_info->HasInstrumentedBytecodeArray())
return;
688 FixedArray break_points = debug_info->break_points();
689 for (
int i = 0;
i < break_points->length();
i++) {
690 if (break_points->get(
i)->IsUndefined(isolate_))
continue;
691 BreakPointInfo* info = BreakPointInfo::cast(break_points->get(
i));
692 if (info->GetBreakPointCount(isolate_) == 0)
continue;
693 DCHECK(debug_info->HasInstrumentedBytecodeArray());
694 BreakIterator it(debug_info);
695 it.SkipToPosition(info->source_position());
699 debug_info->SetDebugExecutionMode(DebugInfo::kBreakpoints);
702 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
703 if (debug_info->CanBreakAtEntry()) {
704 debug_info->ClearBreakAtEntry();
708 if (!debug_info->HasInstrumentedBytecodeArray() ||
709 !debug_info->HasBreakInfo()) {
713 DisallowHeapAllocation no_gc;
714 for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
715 it.ClearDebugBreak();
720 void Debug::ClearBreakPoint(Handle<BreakPoint> break_point) {
721 HandleScope scope(isolate_);
723 for (DebugInfoListNode* node = debug_info_list_; node !=
nullptr;
724 node = node->next()) {
725 if (!node->debug_info()->HasBreakInfo())
continue;
726 Handle<Object> result = DebugInfo::FindBreakPointInfo(
727 isolate_, node->debug_info(), break_point);
728 if (result->IsUndefined(isolate_))
continue;
729 Handle<DebugInfo> debug_info = node->debug_info();
730 if (DebugInfo::ClearBreakPoint(isolate_, debug_info, break_point)) {
731 ClearBreakPoints(debug_info);
732 if (debug_info->GetBreakPointCount(isolate_) == 0) {
733 RemoveBreakInfoAndMaybeFree(debug_info);
735 ApplyBreakPoints(debug_info);
742 int Debug::GetFunctionDebuggingId(Handle<JSFunction>
function) {
743 Handle<SharedFunctionInfo> shared = handle(function->shared(), isolate_);
744 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
745 int id = debug_info->debugging_id();
746 if (
id == DebugInfo::kNoDebuggingId) {
747 id = isolate_->heap()->NextDebuggingId();
748 debug_info->set_debugging_id(
id);
753 bool Debug::SetBreakpointForFunction(Handle<JSFunction>
function,
754 Handle<String> condition,
int*
id) {
755 *
id = ++thread_local_.last_breakpoint_id_;
756 Handle<BreakPoint> breakpoint =
757 isolate_->factory()->NewBreakPoint(*
id, condition);
758 int source_position = 0;
759 return SetBreakPoint(
function, breakpoint, &source_position);
762 void Debug::RemoveBreakpoint(
int id) {
763 Handle<BreakPoint> breakpoint = isolate_->factory()->NewBreakPoint(
764 id, isolate_->factory()->empty_string());
765 ClearBreakPoint(breakpoint);
769 void Debug::ClearAllBreakPoints() {
770 ClearAllDebugInfos([=](Handle<DebugInfo> info) {
771 ClearBreakPoints(info);
772 info->ClearBreakInfo(isolate_);
776 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
778 if (IsBlackboxed(shared))
return;
780 if (!EnsureBreakInfo(shared))
return;
781 PrepareFunctionForDebugExecution(shared);
783 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
785 DCHECK(debug_info->HasInstrumentedBytecodeArray());
786 for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
787 if (returns_only && !it.GetBreakLocation().IsReturnOrSuspend())
continue;
792 void Debug::ChangeBreakOnException(ExceptionBreakType type,
bool enable) {
793 if (type == BreakUncaughtException) {
794 break_on_uncaught_exception_ = enable;
796 break_on_exception_ = enable;
801 bool Debug::IsBreakOnException(ExceptionBreakType type) {
802 if (type == BreakUncaughtException) {
803 return break_on_uncaught_exception_;
805 return break_on_exception_;
809 MaybeHandle<FixedArray> Debug::GetHitBreakPoints(Handle<DebugInfo> debug_info,
811 Handle<Object> break_points = debug_info->GetBreakPoints(isolate_, position);
812 bool is_break_at_entry = debug_info->BreakAtEntry();
813 DCHECK(!break_points->IsUndefined(isolate_));
814 if (!break_points->IsFixedArray()) {
815 if (!CheckBreakPoint(Handle<BreakPoint>::cast(break_points),
816 is_break_at_entry)) {
819 Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
820 break_points_hit->set(0, *break_points);
821 return break_points_hit;
824 Handle<FixedArray> array(FixedArray::cast(*break_points), isolate_);
825 int num_objects = array->length();
826 Handle<FixedArray> break_points_hit =
827 isolate_->factory()->NewFixedArray(num_objects);
828 int break_points_hit_count = 0;
829 for (
int i = 0;
i < num_objects; ++
i) {
830 Handle<Object> break_point(array->get(
i), isolate_);
831 if (CheckBreakPoint(Handle<BreakPoint>::cast(break_point),
832 is_break_at_entry)) {
833 break_points_hit->set(break_points_hit_count++, *break_point);
836 if (break_points_hit_count == 0)
return {};
837 break_points_hit->Shrink(isolate_, break_points_hit_count);
838 return break_points_hit;
841 void Debug::SetBreakOnNextFunctionCall() {
848 thread_local_.break_on_next_function_call_ =
true;
849 UpdateHookOnFunctionCall();
852 void Debug::ClearBreakOnNextFunctionCall() {
853 thread_local_.break_on_next_function_call_ =
false;
854 UpdateHookOnFunctionCall();
857 void Debug::PrepareStepIn(Handle<JSFunction>
function) {
858 CHECK(last_step_action() >= StepIn || break_on_next_function_call());
859 if (ignore_events())
return;
860 if (in_debug_scope())
return;
861 if (break_disabled())
return;
862 Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
863 if (IsBlackboxed(shared))
return;
864 if (*
function == thread_local_.ignore_step_into_function_)
return;
865 thread_local_.ignore_step_into_function_ = Smi::kZero;
866 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
869 void Debug::PrepareStepInSuspendedGenerator() {
870 CHECK(has_suspended_generator());
871 if (ignore_events())
return;
872 if (in_debug_scope())
return;
873 if (break_disabled())
return;
874 thread_local_.last_step_action_ = StepIn;
875 UpdateHookOnFunctionCall();
876 Handle<JSFunction>
function(
877 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function(),
879 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
880 clear_suspended_generator();
883 void Debug::PrepareStepOnThrow() {
884 if (last_step_action() == StepNone)
return;
885 if (ignore_events())
return;
886 if (in_debug_scope())
return;
887 if (break_disabled())
return;
891 int current_frame_count = CurrentFrameCount();
894 JavaScriptFrameIterator it(isolate_);
896 JavaScriptFrame* frame = it.frame();
897 if (frame->LookupExceptionHandlerInTable(
nullptr,
nullptr) > 0)
break;
898 std::vector<SharedFunctionInfo*> infos;
899 frame->GetFunctions(&infos);
900 current_frame_count -= infos.size();
905 if (it.done())
return;
907 bool found_handler =
false;
910 for (; !it.done(); it.Advance()) {
911 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
912 if (last_step_action() == StepIn) {
914 Deoptimizer::DeoptimizeFunction(frame->function());
916 std::vector<FrameSummary> summaries;
917 frame->Summarize(&summaries);
918 for (
size_t i = summaries.size();
i != 0;
i--, current_frame_count--) {
919 const FrameSummary& summary = summaries[
i - 1];
920 if (!found_handler) {
924 if (summaries.size() > 1) {
925 Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
926 CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
927 HandlerTable table(code->GetBytecodeArray());
928 int code_offset = summary.code_offset();
929 HandlerTable::CatchPrediction prediction;
930 int index = table.LookupRange(code_offset,
nullptr, &prediction);
931 if (index > 0) found_handler =
true;
933 found_handler =
true;
940 if ((last_step_action() == StepNext || last_step_action() == StepOut) &&
941 current_frame_count > thread_local_.target_frame_count_) {
944 Handle<SharedFunctionInfo> info(
945 summary.AsJavaScript().function()->shared(), isolate_);
946 if (IsBlackboxed(info))
continue;
947 FloodWithOneShot(info);
955 void Debug::PrepareStep(StepAction step_action) {
956 HandleScope scope(isolate_);
958 DCHECK(in_debug_scope());
964 StackFrame::Id frame_id = break_frame_id();
966 if (frame_id == StackFrame::NO_ID)
return;
968 feature_tracker()->Track(DebugFeatureTracker::kStepping);
970 thread_local_.last_step_action_ = step_action;
972 StackTraceFrameIterator frames_it(isolate_, frame_id);
973 StandardFrame* frame = frames_it.frame();
976 if (frame->is_wasm()) {
978 if (frame->is_wasm_compiled())
return;
979 WasmInterpreterEntryFrame* wasm_frame =
980 WasmInterpreterEntryFrame::cast(frame);
981 wasm_frame->debug_info()->PrepareStep(step_action);
985 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
986 DCHECK(js_frame->function()->IsJSFunction());
989 auto summary = FrameSummary::GetTop(frame).AsJavaScript();
990 Handle<JSFunction>
function(summary.function());
991 Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
992 if (!EnsureBreakInfo(shared))
return;
993 PrepareFunctionForDebugExecution(shared);
995 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
997 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame);
1001 if (location.IsReturn() || (location.IsSuspend() && step_action == StepOut)) {
1004 if (last_step_action() == StepOut) {
1005 thread_local_.ignore_step_into_function_ = *
function;
1007 step_action = StepOut;
1008 thread_local_.last_step_action_ = StepIn;
1012 UpdateHookOnFunctionCall();
1015 if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut;
1017 thread_local_.last_statement_position_ =
1018 summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1019 int current_frame_count = CurrentFrameCount();
1020 thread_local_.last_frame_count_ = current_frame_count;
1022 clear_suspended_generator();
1024 switch (step_action) {
1030 thread_local_.last_statement_position_ = kNoSourcePosition;
1031 thread_local_.last_frame_count_ = -1;
1032 if (!location.IsReturnOrSuspend() && !IsBlackboxed(shared)) {
1035 thread_local_.target_frame_count_ = current_frame_count;
1036 thread_local_.fast_forward_to_return_ =
true;
1037 FloodWithOneShot(shared,
true);
1042 bool in_current_frame =
true;
1043 for (; !frames_it.done(); frames_it.Advance()) {
1045 if (frames_it.frame()->is_wasm())
continue;
1046 JavaScriptFrame* frame = JavaScriptFrame::cast(frames_it.frame());
1047 if (last_step_action() == StepIn) {
1049 Deoptimizer::DeoptimizeFunction(frame->function());
1051 HandleScope scope(isolate_);
1052 std::vector<Handle<SharedFunctionInfo>> infos;
1053 frame->GetFunctions(&infos);
1054 for (; !infos.empty(); current_frame_count--) {
1055 Handle<SharedFunctionInfo> info = infos.back();
1057 if (in_current_frame) {
1059 in_current_frame =
false;
1062 if (IsBlackboxed(info))
continue;
1063 FloodWithOneShot(info);
1064 thread_local_.target_frame_count_ = current_frame_count;
1071 thread_local_.target_frame_count_ = current_frame_count;
1075 FloodWithOneShot(shared);
1081 Handle<Object> Debug::GetSourceBreakLocations(
1082 Isolate* isolate, Handle<SharedFunctionInfo> shared) {
1083 if (!shared->HasBreakInfo()) {
1084 return isolate->factory()->undefined_value();
1087 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate);
1088 if (debug_info->GetBreakPointCount(isolate) == 0) {
1089 return isolate->factory()->undefined_value();
1091 Handle<FixedArray> locations = isolate->factory()->NewFixedArray(
1092 debug_info->GetBreakPointCount(isolate));
1094 for (
int i = 0;
i < debug_info->break_points()->length(); ++
i) {
1095 if (!debug_info->break_points()->get(
i)->IsUndefined(isolate)) {
1096 BreakPointInfo* break_point_info =
1097 BreakPointInfo::cast(debug_info->break_points()->get(
i));
1098 int break_points = break_point_info->GetBreakPointCount(isolate);
1099 if (break_points == 0)
continue;
1100 for (
int j = 0; j < break_points; ++j) {
1101 locations->set(count++,
1102 Smi::FromInt(break_point_info->source_position()));
1109 void Debug::ClearStepping() {
1113 thread_local_.last_step_action_ = StepNone;
1114 thread_local_.last_statement_position_ = kNoSourcePosition;
1115 thread_local_.ignore_step_into_function_ = Smi::kZero;
1116 thread_local_.fast_forward_to_return_ =
false;
1117 thread_local_.last_frame_count_ = -1;
1118 thread_local_.target_frame_count_ = -1;
1119 thread_local_.break_on_next_function_call_ =
false;
1120 UpdateHookOnFunctionCall();
1127 void Debug::ClearOneShot() {
1131 for (DebugInfoListNode* node = debug_info_list_; node !=
nullptr;
1132 node = node->next()) {
1133 Handle<DebugInfo> debug_info = node->debug_info();
1134 ClearBreakPoints(debug_info);
1135 ApplyBreakPoints(debug_info);
1143 DCHECK(shared->HasBytecodeArray());
1150 if (!frame->is_interpreted())
continue;
1151 if (function->shared() != shared_)
continue;
1154 BytecodeArray debug_copy = shared_->GetDebugInfo()->DebugBytecodeArray();
1155 interpreted_frame->PatchBytecodeArray(debug_copy);
1167 isolate_->AbortConcurrentOptimization(BlockingBehavior::kBlock);
1170 isolate_->heap()->PreciseCollectAllGarbage(
1171 Heap::kNoGCFlags, GarbageCollectionReason::kDebugger);
1173 bool found_something =
false;
1176 Code code = iterator.Next();
1177 if (code.is_null())
break;
1178 if (code->Inlines(*shared)) {
1179 code->set_marked_for_deoptimization(
true);
1180 found_something =
true;
1184 if (found_something) {
1186 Deoptimizer::DeoptimizeMarkedCode(isolate_);
1190 void Debug::PrepareFunctionForDebugExecution(
1191 Handle<SharedFunctionInfo> shared) {
1195 DCHECK(shared->is_compiled());
1196 DCHECK(shared->HasDebugInfo());
1197 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1198 if (debug_info->flags() & DebugInfo::kPreparedForDebugExecution)
return;
1201 Handle<Object> maybe_original_bytecode_array =
1202 isolate_->factory()->undefined_value();
1203 if (shared->HasBytecodeArray()) {
1204 Handle<BytecodeArray> original_bytecode_array =
1205 handle(shared->GetBytecodeArray(), isolate_);
1206 Handle<BytecodeArray> debug_bytecode_array =
1207 isolate_->factory()->CopyBytecodeArray(original_bytecode_array);
1208 debug_info->set_debug_bytecode_array(*debug_bytecode_array);
1209 shared->SetDebugBytecodeArray(*debug_bytecode_array);
1210 maybe_original_bytecode_array = original_bytecode_array;
1212 debug_info->set_original_bytecode_array(*maybe_original_bytecode_array);
1214 if (debug_info->CanBreakAtEntry()) {
1216 Deoptimizer::DeoptimizeAll(isolate_);
1217 InstallDebugBreakTrampoline();
1219 DeoptimizeFunction(shared);
1221 RedirectActiveFunctions redirect_visitor(*shared);
1222 redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1223 isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1225 debug_info->set_flags(debug_info->flags() |
1226 DebugInfo::kPreparedForDebugExecution);
1229 void Debug::InstallDebugBreakTrampoline() {
1233 HandleScope scope(isolate_);
1235 bool needs_to_use_trampoline =
false;
1237 bool needs_to_clear_ic =
false;
1238 for (DebugInfoListNode* current = debug_info_list_; current !=
nullptr;
1239 current = current->next()) {
1240 if (current->debug_info()->CanBreakAtEntry()) {
1241 needs_to_use_trampoline =
true;
1242 if (current->debug_info()->shared()->IsApiFunction()) {
1243 needs_to_clear_ic =
true;
1249 if (!needs_to_use_trampoline)
return;
1251 Handle<Code> trampoline = BUILTIN_CODE(isolate_, DebugBreakTrampoline);
1252 std::vector<Handle<JSFunction>> needs_compile;
1254 HeapIterator iterator(isolate_->heap());
1255 while (HeapObject* obj = iterator.next()) {
1256 if (needs_to_clear_ic && obj->IsFeedbackVector()) {
1257 FeedbackVector::cast(obj)->ClearSlots(isolate_);
1259 }
else if (obj->IsJSFunction()) {
1260 JSFunction* fun = JSFunction::cast(obj);
1261 SharedFunctionInfo* shared = fun->shared();
1262 if (!shared->HasDebugInfo())
continue;
1263 if (!shared->GetDebugInfo()->CanBreakAtEntry())
continue;
1264 if (!fun->is_compiled()) {
1265 needs_compile.push_back(handle(fun, isolate_));
1267 fun->set_code(*trampoline);
1274 for (Handle<JSFunction> fun : needs_compile) {
1275 Compiler::Compile(fun, Compiler::CLEAR_EXCEPTION);
1276 fun->set_code(*trampoline);
1281 template <
typename Iterator>
1282 void GetBreakablePositions(Iterator* it,
int start_position,
int end_position,
1283 std::vector<BreakLocation>* locations) {
1284 while (!it->Done()) {
1285 if (it->position() >= start_position && it->position() < end_position) {
1286 locations->push_back(it->GetBreakLocation());
1292 void FindBreakablePositions(Handle<DebugInfo> debug_info,
int start_position,
1294 std::vector<BreakLocation>* locations) {
1295 DCHECK(debug_info->HasInstrumentedBytecodeArray());
1296 BreakIterator it(debug_info);
1297 GetBreakablePositions(&it, start_position, end_position, locations);
1301 bool Debug::GetPossibleBreakpoints(Handle<Script> script,
int start_position,
1302 int end_position,
bool restrict_to_function,
1303 std::vector<BreakLocation>* locations) {
1304 if (restrict_to_function) {
1305 Handle<Object> result =
1306 FindSharedFunctionInfoInScript(script, start_position);
1307 if (result->IsUndefined(isolate_))
return false;
1310 Handle<SharedFunctionInfo> shared =
1311 Handle<SharedFunctionInfo>::cast(result);
1312 if (!EnsureBreakInfo(shared))
return false;
1313 PrepareFunctionForDebugExecution(shared);
1315 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
1316 FindBreakablePositions(debug_info, start_position, end_position, locations);
1321 HandleScope scope(isolate_);
1322 std::vector<Handle<SharedFunctionInfo>> candidates;
1323 SharedFunctionInfo::ScriptIterator iterator(isolate_, *script);
1324 for (SharedFunctionInfo* info = iterator.Next(); info !=
nullptr;
1325 info = iterator.Next()) {
1326 if (info->EndPosition() < start_position ||
1327 info->StartPosition() >= end_position) {
1330 if (!info->IsSubjectToDebugging())
continue;
1331 if (!info->is_compiled() && !info->allows_lazy_compilation())
continue;
1332 candidates.push_back(i::handle(info, isolate_));
1335 bool was_compiled =
false;
1336 for (
const auto& candidate : candidates) {
1338 DCHECK(candidate->allows_lazy_compilation());
1339 if (!candidate->is_compiled()) {
1340 if (!Compiler::Compile(candidate, Compiler::CLEAR_EXCEPTION)) {
1343 was_compiled =
true;
1346 if (!EnsureBreakInfo(candidate))
return false;
1347 PrepareFunctionForDebugExecution(candidate);
1349 if (was_compiled)
continue;
1351 for (
const auto& candidate : candidates) {
1352 CHECK(candidate->HasBreakInfo());
1353 Handle<DebugInfo> debug_info(candidate->GetDebugInfo(), isolate_);
1354 FindBreakablePositions(debug_info, start_position, end_position,
1365 : current_candidate_(
nullptr),
1366 current_candidate_closure_(
nullptr),
1367 current_start_position_(kNoSourcePosition),
1368 target_position_(target_position) {}
1371 if (!shared->IsSubjectToDebugging())
return;
1372 int start_position = shared->function_token_position();
1373 if (start_position == kNoSourcePosition) {
1374 start_position = shared->StartPosition();
1377 if (start_position > target_position_)
return;
1378 if (target_position_ > shared->EndPosition())
return;
1380 if (current_candidate_ !=
nullptr) {
1381 if (current_start_position_ == start_position &&
1382 shared->EndPosition() == current_candidate_->EndPosition()) {
1384 if (current_candidate_closure_ !=
nullptr && closure ==
nullptr)
return;
1388 if (!current_candidate_->is_toplevel() && shared->is_toplevel())
return;
1389 }
else if (start_position < current_start_position_ ||
1390 current_candidate_->EndPosition() < shared->EndPosition()) {
1395 current_start_position_ = start_position;
1396 current_candidate_ = shared;
1397 current_candidate_closure_ = closure;
1402 JSFunction* ResultClosure() {
return current_candidate_closure_; }
1407 int current_start_position_;
1408 int target_position_;
1421 for (
int iteration = 0;; iteration++) {
1432 info = iterator.Next()) {
1433 finder.NewCandidate(info);
1435 shared = finder.Result();
1436 if (shared ==
nullptr)
break;
1438 if (shared->is_compiled()) {
1444 if (iteration > 1) {
1445 AllowHeapAllocation allow_before_return;
1446 CreateBreakInfo(shared_handle);
1448 return shared_handle;
1452 HandleScope scope(isolate_);
1454 DCHECK(shared->allows_lazy_compilation());
1455 if (!Compiler::Compile(handle(shared, isolate_), Compiler::CLEAR_EXCEPTION))
1458 return isolate_->factory()->undefined_value();
1463 bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) {
1465 if (shared->HasBreakInfo())
return true;
1466 if (!shared->IsSubjectToDebugging() && !CanBreakAtEntry(shared)) {
1469 if (!shared->is_compiled() &&
1470 !Compiler::Compile(shared, Compiler::CLEAR_EXCEPTION)) {
1473 CreateBreakInfo(shared);
1477 void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) {
1478 HandleScope scope(isolate_);
1479 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1483 DCHECK(!debug_info->HasBreakInfo());
1485 Factory* factory = isolate_->factory();
1486 Handle<FixedArray> break_points(
1487 factory->NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction));
1489 int flags = debug_info->flags();
1490 flags |= DebugInfo::kHasBreakInfo;
1491 if (CanBreakAtEntry(shared)) flags |= DebugInfo::kCanBreakAtEntry;
1492 debug_info->set_flags(flags);
1493 debug_info->set_break_points(*break_points);
1496 Handle<DebugInfo> Debug::GetOrCreateDebugInfo(
1497 Handle<SharedFunctionInfo> shared) {
1498 if (shared->HasDebugInfo())
return handle(shared->GetDebugInfo(), isolate_);
1501 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1502 DebugInfoListNode* node =
new DebugInfoListNode(isolate_, *debug_info);
1503 node->set_next(debug_info_list_);
1504 debug_info_list_ = node;
1509 void Debug::InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
1510 Handle<CoverageInfo> coverage_info) {
1511 DCHECK(!coverage_info.is_null());
1513 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1515 DCHECK(!debug_info->HasCoverageInfo());
1517 debug_info->set_flags(debug_info->flags() | DebugInfo::kHasCoverageInfo);
1518 debug_info->set_coverage_info(*coverage_info);
1521 void Debug::RemoveAllCoverageInfos() {
1523 [=](Handle<DebugInfo> info) { info->ClearCoverageInfo(isolate_); });
1526 void Debug::ClearAllDebuggerHints() {
1528 [=](Handle<DebugInfo> info) { info->set_debugger_hints(0); });
1531 void Debug::FindDebugInfo(Handle<DebugInfo> debug_info,
1532 DebugInfoListNode** prev, DebugInfoListNode** curr) {
1533 HandleScope scope(isolate_);
1535 *curr = debug_info_list_;
1536 while (*curr !=
nullptr) {
1537 if ((*curr)->debug_info().is_identical_to(debug_info))
return;
1539 *curr = (*curr)->next();
1545 void Debug::ClearAllDebugInfos(
const DebugInfoClearFunction& clear_function) {
1546 DebugInfoListNode* prev =
nullptr;
1547 DebugInfoListNode* current = debug_info_list_;
1548 while (current !=
nullptr) {
1549 DebugInfoListNode* next = current->next();
1550 Handle<DebugInfo> debug_info = current->debug_info();
1551 clear_function(debug_info);
1552 if (debug_info->IsEmpty()) {
1553 FreeDebugInfoListNode(prev, current);
1562 void Debug::RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info) {
1563 debug_info->ClearBreakInfo(isolate_);
1564 if (debug_info->IsEmpty()) {
1565 DebugInfoListNode* prev;
1566 DebugInfoListNode* node;
1567 FindDebugInfo(debug_info, &prev, &node);
1568 FreeDebugInfoListNode(prev, node);
1572 void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev,
1573 DebugInfoListNode* node) {
1574 DCHECK(node->debug_info()->IsEmpty());
1577 if (prev ==
nullptr) {
1578 debug_info_list_ = node->next();
1580 prev->set_next(node->next());
1585 Handle<DebugInfo> debug_info(node->debug_info());
1586 debug_info->shared()->set_script_or_debug_info(debug_info->script());
1591 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1592 HandleScope scope(isolate_);
1595 Handle<SharedFunctionInfo> shared(frame->function()->shared(), isolate_);
1598 if (!shared->HasBreakInfo())
return false;
1600 DCHECK(!frame->is_optimized());
1601 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
1602 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1603 return location.IsReturn();
1606 void Debug::ScheduleFrameRestart(StackFrame* frame) {
1609 DCHECK(frame->is_java_script());
1611 if (frame->fp() <= thread_local_.restart_fp_)
return;
1614 thread_local_.restart_fp_ = frame->fp();
1617 StackTraceFrameIterator it(isolate_);
1618 thread_local_.break_frame_id_ = StackFrame::NO_ID;
1619 for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1620 if (it.frame()->fp() > thread_local_.restart_fp_) {
1621 thread_local_.break_frame_id_ = it.frame()->id();
1627 Handle<FixedArray> Debug::GetLoadedScripts() {
1628 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1629 GarbageCollectionReason::kDebugger);
1630 Factory* factory = isolate_->factory();
1631 if (!factory->script_list()->IsWeakArrayList()) {
1632 return factory->empty_fixed_array();
1634 Handle<WeakArrayList> array =
1635 Handle<WeakArrayList>::cast(factory->script_list());
1636 Handle<FixedArray> results = factory->NewFixedArray(array->length());
1639 Script::Iterator iterator(isolate_);
1641 while ((script = iterator.Next()) !=
nullptr) {
1642 if (script->HasValidSource()) results->set(length++, script);
1645 return FixedArray::ShrinkOrEmpty(isolate_, results, length);
1648 void Debug::OnThrow(Handle<Object> exception) {
1649 if (in_debug_scope() || ignore_events())
return;
1652 HandleScope scope(isolate_);
1653 Handle<Object> scheduled_exception;
1654 if (isolate_->has_scheduled_exception()) {
1655 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1656 isolate_->clear_scheduled_exception();
1658 Handle<Object> maybe_promise = isolate_->GetPromiseOnStackOnThrow();
1659 OnException(exception, maybe_promise,
1660 maybe_promise->IsJSPromise() ? v8::debug::kPromiseRejection
1661 : v8::debug::kException);
1662 if (!scheduled_exception.is_null()) {
1663 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1665 PrepareStepOnThrow();
1668 void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {
1669 if (in_debug_scope() || ignore_events())
return;
1670 HandleScope scope(isolate_);
1672 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1673 if (!promise->IsJSObject() ||
1674 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
1675 ->IsUndefined(isolate_)) {
1676 OnException(value, promise, v8::debug::kPromiseRejection);
1680 bool Debug::IsExceptionBlackboxed(
bool uncaught) {
1683 StackTraceFrameIterator it(isolate_);
1684 while (!it.done() && it.is_wasm()) it.Advance();
1685 bool is_top_frame_blackboxed =
1686 !it.done() ? IsFrameBlackboxed(it.javascript_frame()) :
true;
1687 if (!uncaught || !is_top_frame_blackboxed)
return is_top_frame_blackboxed;
1688 return AllFramesOnStackAreBlackboxed();
1691 bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
1692 HandleScope scope(isolate_);
1693 std::vector<Handle<SharedFunctionInfo>> infos;
1694 frame->GetFunctions(&infos);
1695 for (
const auto& info : infos) {
1696 if (!IsBlackboxed(info))
return false;
1701 void Debug::OnException(Handle<Object> exception, Handle<Object> promise,
1702 v8::debug::ExceptionType exception_type) {
1704 if (!AllowJavascriptExecution::IsAllowed(isolate_))
return;
1706 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1709 if (catch_type == Isolate::CAUGHT_BY_DESUGARING)
return;
1711 bool uncaught = catch_type == Isolate::NOT_CAUGHT;
1712 if (promise->IsJSObject()) {
1713 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1715 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1716 JSObject::SetProperty(isolate_, jspromise, key, key, LanguageMode::kStrict)
1719 uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
1722 if (!debug_delegate_)
return;
1727 if (!(break_on_uncaught_exception_ || break_on_exception_))
return;
1730 if (!break_on_exception_)
return;
1734 JavaScriptFrameIterator it(isolate_);
1736 if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) ||
1737 IsExceptionBlackboxed(uncaught))) {
1740 if (it.done())
return;
1743 DebugScope debug_scope(
this);
1744 HandleScope scope(isolate_);
1745 DisableBreak no_recursive_break(
this);
1747 Handle<Context> native_context(isolate_->native_context());
1748 debug_delegate_->ExceptionThrown(
1749 v8::Utils::ToLocal(native_context), v8::Utils::ToLocal(exception),
1750 v8::Utils::ToLocal(promise), uncaught, exception_type);
1753 void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
1754 DCHECK(!break_points_hit.is_null());
1756 AssertDebugContext();
1758 if (ignore_events())
return;
1761 PrintBreakLocation();
1764 if (!debug_delegate_)
return;
1765 DCHECK(in_debug_scope());
1766 HandleScope scope(isolate_);
1767 DisableBreak no_recursive_break(
this);
1769 std::vector<int> inspector_break_points_hit;
1770 int inspector_break_points_count = 0;
1772 for (
int i = 0;
i < break_points_hit->length(); ++
i) {
1773 BreakPoint* break_point = BreakPoint::cast(break_points_hit->get(
i));
1774 inspector_break_points_hit.push_back(break_point->id());
1775 ++inspector_break_points_count;
1778 Handle<Context> native_context(isolate_->native_context());
1779 debug_delegate_->BreakProgramRequested(v8::Utils::ToLocal(native_context),
1780 inspector_break_points_hit);
1784 debug::Location GetDebugLocation(Handle<Script> script,
int source_position) {
1785 Script::PositionInfo info;
1786 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
1793 return debug::Location(std::max(info.line, 0), std::max(info.column, 0));
1797 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
1798 if (!debug_delegate_)
return !shared->IsSubjectToDebugging();
1799 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1800 if (!debug_info->computed_debug_is_blackboxed()) {
1801 bool is_blackboxed =
1802 !shared->IsSubjectToDebugging() || !shared->script()->IsScript();
1803 if (!is_blackboxed) {
1804 SuppressDebug while_processing(
this);
1805 HandleScope handle_scope(isolate_);
1806 PostponeInterruptsScope no_interrupts(isolate_);
1807 DisableBreak no_recursive_break(
this);
1808 DCHECK(shared->script()->IsScript());
1809 Handle<Script> script(Script::cast(shared->script()), isolate_);
1810 DCHECK(script->IsUserJavaScript());
1811 debug::Location start = GetDebugLocation(script, shared->StartPosition());
1812 debug::Location end = GetDebugLocation(script, shared->EndPosition());
1813 is_blackboxed = debug_delegate_->IsFunctionBlackboxed(
1814 ToApiHandle<debug::Script>(script), start, end);
1816 debug_info->set_debug_is_blackboxed(is_blackboxed);
1817 debug_info->set_computed_debug_is_blackboxed(
true);
1819 return debug_info->debug_is_blackboxed();
1822 bool Debug::AllFramesOnStackAreBlackboxed() {
1823 HandleScope scope(isolate_);
1824 for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1825 if (!it.is_javascript())
continue;
1826 if (!IsFrameBlackboxed(it.javascript_frame()))
return false;
1831 bool Debug::CanBreakAtEntry(Handle<SharedFunctionInfo> shared) {
1833 if (shared->native() || shared->IsApiFunction()) {
1835 DCHECK(!shared->IsSubjectToDebugging());
1841 bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
1842 bool preview, debug::LiveEditResult* result) {
1843 DebugScope debug_scope(
this);
1844 running_live_edit_ =
true;
1845 LiveEdit::PatchScript(isolate_, script, source, preview, result);
1846 running_live_edit_ =
false;
1847 return result->status == debug::LiveEditResult::OK;
1850 void Debug::OnCompileError(Handle<Script> script) {
1851 ProcessCompileEvent(
true, script);
1854 void Debug::OnAfterCompile(Handle<Script> script) {
1855 ProcessCompileEvent(
false, script);
1858 void Debug::ProcessCompileEvent(
bool has_compile_error, Handle<Script> script) {
1861 if (running_live_edit_)
return;
1864 script->set_context_data(isolate_->native_context()->debug_context_id());
1865 if (ignore_events())
return;
1866 if (!script->IsUserJavaScript() && script->type() != i::Script::TYPE_WASM) {
1869 if (!debug_delegate_)
return;
1870 SuppressDebug while_processing(
this);
1871 DebugScope debug_scope(
this);
1872 HandleScope scope(isolate_);
1873 DisableBreak no_recursive_break(
this);
1874 AllowJavascriptExecution allow_script(isolate_);
1875 debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1876 running_live_edit_, has_compile_error);
1879 int Debug::CurrentFrameCount() {
1880 StackTraceFrameIterator it(isolate_);
1881 if (break_frame_id() != StackFrame::NO_ID) {
1883 DCHECK(in_debug_scope());
1884 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
1887 while (!it.done()) {
1888 if (it.frame()->is_optimized()) {
1889 std::vector<SharedFunctionInfo*> infos;
1890 OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
1891 counter += infos.size();
1900 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) {
1901 debug_delegate_ = delegate;
1905 void Debug::UpdateState() {
1906 bool is_active = debug_delegate_ !=
nullptr;
1907 if (is_active == is_active_)
return;
1911 isolate_->compilation_cache()->Disable();
1913 feature_tracker()->Track(DebugFeatureTracker::kActive);
1915 isolate_->compilation_cache()->Enable();
1918 is_active_ = is_active;
1919 isolate_->PromiseHookStateUpdated();
1922 void Debug::UpdateHookOnFunctionCall() {
1923 STATIC_ASSERT(LastStepAction == StepIn);
1924 hook_on_function_call_ =
1925 thread_local_.last_step_action_ == StepIn ||
1926 isolate_->debug_execution_mode() == DebugInfo::kSideEffects ||
1927 thread_local_.break_on_next_function_call_;
1930 void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
1932 LiveEdit::InitializeThreadLocal(
this);
1934 if (isolate_->bootstrapper()->IsActive())
return;
1936 if (break_disabled())
return;
1938 if (!is_active())
return;
1940 StackLimitCheck check(isolate_);
1941 if (check.HasOverflowed())
return;
1943 { JavaScriptFrameIterator it(isolate_);
1945 Object* fun = it.frame()->function();
1946 if (fun && fun->IsJSFunction()) {
1947 HandleScope scope(isolate_);
1948 Handle<JSFunction>
function(JSFunction::cast(fun), isolate_);
1950 Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
1951 bool ignore_break = ignore_break_mode == kIgnoreIfTopFrameBlackboxed
1952 ? IsBlackboxed(shared)
1953 : AllFramesOnStackAreBlackboxed();
1954 if (ignore_break)
return;
1956 if (IsMutedAtCurrentLocation(it.frame()))
return;
1963 HandleScope scope(isolate_);
1964 DebugScope debug_scope(
this);
1966 OnDebugBreak(isolate_->factory()->empty_fixed_array());
1970 void Debug::PrintBreakLocation() {
1971 if (!FLAG_print_break_location)
return;
1972 HandleScope scope(isolate_);
1973 StackTraceFrameIterator iterator(isolate_);
1974 if (iterator.done())
return;
1975 StandardFrame* frame = iterator.frame();
1976 FrameSummary summary = FrameSummary::GetTop(frame);
1977 int source_position = summary.SourcePosition();
1978 Handle<Object> script_obj = summary.script();
1979 PrintF(
"[debug] break in function '");
1980 summary.FunctionName()->PrintOn(stdout);
1982 if (script_obj->IsScript()) {
1983 Handle<Script> script = Handle<Script>::cast(script_obj);
1984 Handle<String> source(String::cast(script->source()), isolate_);
1985 Script::InitLineEnds(script);
1987 Script::GetLineNumber(script, source_position) - script->line_offset();
1988 int column = Script::GetColumnNumber(script, source_position) -
1989 (line == 0 ? script->column_offset() : 0);
1990 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()),
1992 int line_start = line == 0 ? 0 : Smi::ToInt(line_ends->get(line - 1)) + 1;
1993 int line_end = Smi::ToInt(line_ends->get(line));
1994 DisallowHeapAllocation no_gc;
1995 String::FlatContent content = source->GetFlatContent();
1996 if (content.IsOneByte()) {
1997 PrintF(
"[debug] %.*s\n", line_end - line_start,
1998 content.ToOneByteVector().start() + line_start);
2000 for (
int i = 0;
i < column;
i++) PrintF(
" ");
2003 PrintF(
"[debug] at line %d column %d\n", line, column);
2009 DebugScope::DebugScope(Debug* debug)
2011 prev_(reinterpret_cast<DebugScope*>(
2012 base::Relaxed_Load(&debug->thread_local_.current_debug_scope_))),
2013 no_interrupts_(debug_->isolate_) {
2015 base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
2016 reinterpret_cast<base::AtomicWord>(
this));
2019 break_frame_id_ = debug_->break_frame_id();
2023 StackTraceFrameIterator it(isolate());
2024 bool has_frames = !it.done();
2025 debug_->thread_local_.break_frame_id_ =
2026 has_frames ? it.frame()->id() : StackFrame::NO_ID;
2028 debug_->UpdateState();
2032 DebugScope::~DebugScope() {
2034 base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
2035 reinterpret_cast<base::AtomicWord>(prev_));
2038 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2040 debug_->UpdateState();
2043 ReturnValueScope::ReturnValueScope(Debug* debug) : debug_(debug) {
2044 return_value_ = debug_->return_value_handle();
2047 ReturnValueScope::~ReturnValueScope() {
2048 debug_->set_return_value(*return_value_);
2051 void Debug::UpdateDebugInfosForExecutionMode() {
2054 DebugInfoListNode* current = debug_info_list_;
2055 while (current !=
nullptr) {
2056 Handle<DebugInfo> debug_info = current->debug_info();
2057 if (debug_info->HasInstrumentedBytecodeArray() &&
2058 debug_info->DebugExecutionMode() != isolate_->debug_execution_mode()) {
2059 DCHECK(debug_info->shared()->HasBytecodeArray());
2060 if (isolate_->debug_execution_mode() == DebugInfo::kBreakpoints) {
2061 ClearSideEffectChecks(debug_info);
2062 ApplyBreakPoints(debug_info);
2064 ClearBreakPoints(debug_info);
2065 ApplySideEffectChecks(debug_info);
2068 current = current->next();
2072 void Debug::StartSideEffectCheckMode() {
2073 DCHECK(isolate_->debug_execution_mode() != DebugInfo::kSideEffects);
2074 isolate_->set_debug_execution_mode(DebugInfo::kSideEffects);
2075 UpdateHookOnFunctionCall();
2076 side_effect_check_failed_ =
false;
2078 DCHECK(!temporary_objects_);
2079 temporary_objects_.reset(
new TemporaryObjectsTracker());
2080 isolate_->heap()->AddHeapObjectAllocationTracker(temporary_objects_.get());
2081 Handle<FixedArray> array(isolate_->native_context()->regexp_last_match_info(),
2083 regexp_match_info_ =
2084 Handle<RegExpMatchInfo>::cast(isolate_->factory()->CopyFixedArray(array));
2087 UpdateDebugInfosForExecutionMode();
2090 void Debug::StopSideEffectCheckMode() {
2091 DCHECK(isolate_->debug_execution_mode() == DebugInfo::kSideEffects);
2092 if (side_effect_check_failed_) {
2093 DCHECK(isolate_->has_pending_exception());
2094 DCHECK_EQ(ReadOnlyRoots(isolate_).termination_exception(),
2095 isolate_->pending_exception());
2097 isolate_->CancelTerminateExecution();
2098 isolate_->Throw(*isolate_->factory()->NewEvalError(
2099 MessageTemplate::kNoSideEffectDebugEvaluate));
2101 isolate_->set_debug_execution_mode(DebugInfo::kBreakpoints);
2102 UpdateHookOnFunctionCall();
2103 side_effect_check_failed_ =
false;
2105 DCHECK(temporary_objects_);
2106 isolate_->heap()->RemoveHeapObjectAllocationTracker(temporary_objects_.get());
2107 temporary_objects_.reset();
2108 isolate_->native_context()->set_regexp_last_match_info(*regexp_match_info_);
2109 regexp_match_info_ = Handle<RegExpMatchInfo>::null();
2112 UpdateDebugInfosForExecutionMode();
2115 void Debug::ApplySideEffectChecks(Handle<DebugInfo> debug_info) {
2116 DCHECK(debug_info->HasInstrumentedBytecodeArray());
2117 Handle<BytecodeArray> debug_bytecode(debug_info->DebugBytecodeArray(),
2119 DebugEvaluate::ApplySideEffectChecks(debug_bytecode);
2120 debug_info->SetDebugExecutionMode(DebugInfo::kSideEffects);
2123 void Debug::ClearSideEffectChecks(Handle<DebugInfo> debug_info) {
2124 DCHECK(debug_info->HasInstrumentedBytecodeArray());
2125 Handle<BytecodeArray> debug_bytecode(debug_info->DebugBytecodeArray(),
2127 Handle<BytecodeArray> original(debug_info->OriginalBytecodeArray(), isolate_);
2128 for (interpreter::BytecodeArrayIterator it(debug_bytecode); !it.done();
2132 debug_bytecode->set(it.current_offset(),
2133 original->get(it.current_offset()));
2137 bool Debug::PerformSideEffectCheck(Handle<JSFunction>
function,
2138 Handle<Object> receiver) {
2139 DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2140 DisallowJavascriptExecution no_js(isolate_);
2141 if (!function->is_compiled() &&
2142 !Compiler::Compile(
function, Compiler::KEEP_EXCEPTION)) {
2145 Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
2146 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
2147 DebugInfo::SideEffectState side_effect_state =
2148 debug_info->GetSideEffectState(isolate_);
2149 switch (side_effect_state) {
2150 case DebugInfo::kHasSideEffects:
2151 if (FLAG_trace_side_effect_free_debug_evaluate) {
2152 PrintF(
"[debug-evaluate] Function %s failed side effect check.\n",
2153 function->shared()->DebugName()->ToCString().get());
2155 side_effect_check_failed_ =
true;
2157 isolate_->TerminateExecution();
2159 case DebugInfo::kRequiresRuntimeChecks: {
2160 if (!shared->HasBytecodeArray()) {
2161 return PerformSideEffectCheckForObject(receiver);
2165 DCHECK(shared->is_compiled());
2166 PrepareFunctionForDebugExecution(shared);
2167 ApplySideEffectChecks(debug_info);
2170 case DebugInfo::kHasNoSideEffect:
2172 case DebugInfo::kNotComputed:
2180 Handle<Object> Debug::return_value_handle() {
2181 return handle(thread_local_.return_value_, isolate_);
2184 bool Debug::PerformSideEffectCheckForCallback(
2185 Handle<Object> callback_info, Handle<Object> receiver,
2186 Debug::AccessorKind accessor_kind) {
2187 DCHECK_EQ(!receiver.is_null(), callback_info->IsAccessorInfo());
2188 DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2189 if (!callback_info.is_null() && callback_info->IsCallHandlerInfo() &&
2190 i::CallHandlerInfo::cast(*callback_info)->NextCallHasNoSideEffect()) {
2194 if (!callback_info.is_null()) {
2195 if (callback_info->IsAccessorInfo()) {
2197 AccessorInfo* info = AccessorInfo::cast(*callback_info);
2198 DCHECK_NE(kNotAccessor, accessor_kind);
2199 switch (accessor_kind == kSetter ? info->setter_side_effect_type()
2200 : info->getter_side_effect_type()) {
2201 case SideEffectType::kHasNoSideEffect:
2205 DCHECK_NE(kSetter, accessor_kind);
2207 case SideEffectType::kHasSideEffectToReceiver:
2208 DCHECK(!receiver.is_null());
2209 if (PerformSideEffectCheckForObject(receiver))
return true;
2210 isolate_->OptionalRescheduleException(
false);
2212 case SideEffectType::kHasSideEffect:
2215 if (FLAG_trace_side_effect_free_debug_evaluate) {
2216 PrintF(
"[debug-evaluate] API Callback '");
2217 info->name()->ShortPrint();
2218 PrintF(
"' may cause side effect.\n");
2220 }
else if (callback_info->IsInterceptorInfo()) {
2221 InterceptorInfo* info = InterceptorInfo::cast(*callback_info);
2222 if (info->has_no_side_effect())
return true;
2223 if (FLAG_trace_side_effect_free_debug_evaluate) {
2224 PrintF(
"[debug-evaluate] API Interceptor may cause side effect.\n");
2226 }
else if (callback_info->IsCallHandlerInfo()) {
2227 CallHandlerInfo* info = CallHandlerInfo::cast(*callback_info);
2228 if (info->IsSideEffectFreeCallHandlerInfo())
return true;
2229 if (FLAG_trace_side_effect_free_debug_evaluate) {
2230 PrintF(
"[debug-evaluate] API CallHandlerInfo may cause side effect.\n");
2234 side_effect_check_failed_ =
true;
2236 isolate_->TerminateExecution();
2237 isolate_->OptionalRescheduleException(
false);
2241 bool Debug::PerformSideEffectCheckAtBytecode(InterpretedFrame* frame) {
2242 using interpreter::Bytecode;
2244 DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2245 SharedFunctionInfo* shared = frame->function()->shared();
2246 BytecodeArray bytecode_array = shared->GetBytecodeArray();
2247 int offset = frame->GetBytecodeOffset();
2248 interpreter::BytecodeArrayAccessor bytecode_accessor(
2249 handle(bytecode_array, isolate_), offset);
2251 Bytecode bytecode = bytecode_accessor.current_bytecode();
2252 interpreter::Register reg;
2254 case Bytecode::kStaCurrentContextSlot:
2255 reg = interpreter::Register::current_context();
2258 reg = bytecode_accessor.GetRegisterOperand(0);
2261 Handle<Object>
object =
2262 handle(frame->ReadInterpreterRegister(reg.index()), isolate_);
2263 return PerformSideEffectCheckForObject(
object);
2266 bool Debug::PerformSideEffectCheckForObject(Handle<Object>
object) {
2267 DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2270 if (object->IsNumber())
return true;
2271 if (object->IsName())
return true;
2273 if (temporary_objects_->HasObject(Handle<HeapObject>::cast(
object))) {
2277 if (FLAG_trace_side_effect_free_debug_evaluate) {
2278 PrintF(
"[debug-evaluate] failed runtime side effect check.\n");
2280 side_effect_check_failed_ =
true;
2282 isolate_->TerminateExecution();