41#if !defined(DART_PRECOMPILED_RUNTIME)
48 trace_debugger_stacktrace,
50 "Trace debugger stacktrace collection");
52DEFINE_FLAG(
bool, verbose_debug,
false,
"Verbose debugger messages");
65 intptr_t requested_line_number,
66 intptr_t requested_column_number)
67 : debugger_(debugger),
72 token_pos_(token_pos),
73 end_token_pos_(end_token_pos),
76 requested_line_number_(requested_line_number),
77 requested_column_number_(requested_column_number),
81 for (intptr_t i = 0; i <
scripts.length(); ++i) {
89 intptr_t requested_line_number,
90 intptr_t requested_column_number)
91 : debugger_(debugger),
100 requested_line_number_(requested_line_number),
101 requested_column_number_(requested_column_number),
103 ASSERT(requested_line_number_ >= 0);
108 while (bpt !=
nullptr) {
117 while (bpt !=
nullptr) {
126void BreakpointLocation::SetResolved(
const Function& func,
136 ASSERT(func.is_debuggable());
146 *
pos = TokenPosition::kNoSource;
157 if (line_number_ >= 0) {
162 if (line_number_ < 0) {
170 ASSERT((new_bpt_location ==
nullptr) || bpt_location_->
IsLatent());
171 bpt_location_ = new_bpt_location;
178void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
179 for (intptr_t i = 0; i < scripts_.
length(); ++i) {
180 visitor->VisitPointer(
reinterpret_cast<ObjectPtr*
>(&scripts_.
data()[i]));
182 visitor->VisitPointer(
reinterpret_cast<ObjectPtr*
>(&url_));
184 Breakpoint* bpt = conditions_;
185 while (bpt !=
nullptr) {
186 bpt->VisitObjectPointers(visitor);
212 if (breakpoint_locations_.length() == 0) {
213 return "unlinked breakpoint";
221 intptr_t line_number = breakpoint_location->
line_number();
223 f.Printf(
"breakpoint at %s:%" Pd, source_url.
ToCString(), line_number);
231 const Array& deopt_frame,
232 intptr_t deopt_frame_offset)
236 code_(
Code::ZoneHandle(code.ptr())),
238 closure_(
Closure::null_closure()),
239 deopt_frame_(
Array::ZoneHandle(deopt_frame.ptr())),
240 deopt_frame_offset_(deopt_frame_offset),
251 code_(
Code::ZoneHandle(code.ptr())),
253 closure_(
Closure::ZoneHandle(closure.ptr())),
254 deopt_frame_(
Array::empty_array()),
255 deopt_frame_offset_(0),
256 kind_(kAsyncAwaiter) {}
259 : code_(
Code::ZoneHandle()),
260 function_(
Function::null_function()),
261 closure_(
Closure::null_closure()),
262 deopt_frame_(
Array::empty_array()),
263 deopt_frame_offset_(0),
268bool Debugger::NeedsIsolateEvents() {
274bool Debugger::NeedsDebugEvents() {
298 if (ignore_breakpoints_ ||
IsPaused()) {
303 ServiceEvent
event(isolate_, kind);
305 if (trace->Length() > 0) {
306 event.set_top_frame(trace->FrameAt(0));
311 HandleSteppingRequest();
312 ClearCachedStackTraces();
315 NoSafepointScope no_safepoint;
323 if (NeedsDebugEvents()) {
326 ServiceEvent
event(isolate_, kind);
327 event.set_breakpoint(bpt);
334 set_breakpoints(bpt);
336 dbg->group_debugger()->SyncBreakpointLocation(
this);
352 while (bpt !=
nullptr) {
353 if ((bpt->
closure() == closure.ptr()) &&
359 if (bpt ==
nullptr) {
360 bpt =
new Breakpoint(dbg->nextId(),
this, single_shot, closure);
384 func_start.
IsWithin(token_pos, end_token_pos)) {
388 return script_url.
Equals(url);
394 switch (func.
kind()) {
395 case UntaggedFunction::kImplicitGetter:
396 case UntaggedFunction::kImplicitSetter:
397 case UntaggedFunction::kImplicitStaticGetter:
398 case UntaggedFunction::kFieldInitializer:
399 case UntaggedFunction::kMethodExtractor:
400 case UntaggedFunction::kNoSuchMethodDispatcher:
401 case UntaggedFunction::kInvokeFieldDispatcher:
402 case UntaggedFunction::kIrregexpFunction:
403 case UntaggedFunction::kRecordFieldGetter:
418 while (cbpt !=
nullptr) {
430 if (thread->IsInStoppedMutatorsScope()) {
442 while (cbpt !=
nullptr) {
443 if (code.ptr() == cbpt->code_) {
452 PrintBreakpointsListToJSONArray(breakpoint_locations_, jsarr);
453 PrintBreakpointsListToJSONArray(latent_locations_, jsarr);
458 while (sbpt !=
nullptr) {
460 while (bpt !=
nullptr) {
486 if (
fp() == other_fp) {
510void ActivationFrame::GetPcDescriptors() {
520 if (!token_pos_initialized_) {
521 token_pos_initialized_ =
true;
522 token_pos_ = TokenPosition::kNoSource;
538intptr_t ActivationFrame::TryIndex() {
539 if (!token_pos_initialized_) {
545intptr_t ActivationFrame::DeoptId() {
546 if (!token_pos_initialized_) {
555 if ((line_number_ < 0) && token_pos.
IsReal()) {
557 script.GetTokenLocation(token_pos, &line_number_, &column_number_);
565 if ((column_number_ < 0) && token_pos.
IsReal()) {
567 script.GetTokenLocation(token_pos, &line_number_, &column_number_);
569 return column_number_;
572void ActivationFrame::GetVarDescriptors() {
573 if (var_descriptors_.
IsNull()) {
575 if (unoptimized_code.
IsNull()) {
577 var_descriptors_ = Object::empty_var_descriptors().
ptr();
581 Zone* zone = thread->zone();
584 if (!
error.IsNull()) {
600void ActivationFrame::PrintDescriptorsError(
const char*
message) {
615 StackFrame*
frame = frames.NextFrame();
616 while (
frame !=
nullptr) {
618 frame = frames.NextFrame();
627 if (context_level_ < 0 && !ctx.
IsNull()) {
632 PrintDescriptorsError(
"Missing deopt id");
634 intptr_t var_desc_len = var_descriptors_.
Length();
638 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
640 var_descriptors_.
GetInfo(cur_idx, &var_info);
641 const int8_t
kind = var_info.
kind();
644 context_level_ = var_info.
index();
650 PrintDescriptorsError(
"Missing context level in var descriptors");
652 ASSERT(context_level_ >= 0);
654 return context_level_;
661 intptr_t try_index = TryIndex();
663 ASSERT(!handlers.IsNull());
664 if ((try_index < 0) && !handlers.has_async_handler()) {
669 intptr_t num_handlers_checked = 0;
672 num_handlers_checked++;
673 ASSERT(num_handlers_checked <= handlers.num_entries());
676 if (!handlers.IsGenerated(try_index)) {
677 handled_types = handlers.GetHandledTypes(try_index);
678 const intptr_t num_types = handled_types.
Length();
679 for (intptr_t k = 0; k < num_types; k++) {
680 type ^= handled_types.
At(k);
684 if (
type.IsDynamicType()) {
688 Object::null_type_arguments())) {
693 try_index = handlers.OuterTryIndex(try_index);
701 if (!ctx_.
IsNull())
return ctx_;
703 intptr_t var_desc_len = var_descriptors_.
Length();
705 for (intptr_t i = 0; i < var_desc_len; i++) {
707 var_descriptors_.
GetInfo(i, &var_info);
708 const int8_t
kind = var_info.
kind();
710 if (FLAG_trace_debugger_stacktrace) {
715 obj = GetStackVar(variable_index);
716 if (obj.IsClosure()) {
720 ctx_ = Closure::Cast(obj).GetContext();
721 }
else if (obj.IsContext()) {
722 ctx_ = Context::Cast(obj).
ptr();
735 if (FLAG_trace_debugger_stacktrace) {
739 for (intptr_t frame_index = 0; frame_index <
Length(); frame_index++) {
741 const bool can_handle =
frame->HandlesException(exc_obj);
742 if (FLAG_trace_debugger_stacktrace) {
744 can_handle ?
"+" :
"-",
frame->ToCString());
753void ActivationFrame::GetDescIndices() {
754 if (vars_initialized_) {
759 TokenPosition activation_token_pos =
TokenPos();
760 if (!activation_token_pos.IsDebugPause() || kind_ !=
kRegular) {
763 vars_initialized_ =
true;
767 GrowableArray<String*> var_names(8);
768 intptr_t var_desc_len = var_descriptors_.
Length();
769 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
771 UntaggedLocalVarDescriptors::VarInfo var_info;
772 var_descriptors_.
GetInfo(cur_idx, &var_info);
773 const int8_t
kind = var_info.kind();
778 if (!activation_token_pos.IsWithin(var_info.begin_pos, var_info.end_pos)) {
795 intptr_t indices_len = desc_indices_.
length();
796 bool name_match_found =
false;
797 for (intptr_t i = 0; i < indices_len; i++) {
798 if (var_name.Equals(*var_names[i])) {
801 name_match_found =
true;
802 UntaggedLocalVarDescriptors::VarInfo i_var_info;
803 var_descriptors_.
GetInfo(desc_indices_[i], &i_var_info);
804 if (i_var_info.begin_pos < var_info.begin_pos) {
809 desc_indices_[i] = cur_idx;
818 if (!name_match_found) {
821 desc_indices_.
Add(cur_idx);
822 var_names.Add(&var_name);
825 vars_initialized_ =
true;
830 return desc_indices_.
length();
834 return *
reinterpret_cast<ObjectPtr*
>(addr);
840 ASSERT(0 <= index && index < num_parameters);
847 if (
function().MakesCopyOfParameters()) {
849 if (
function().IsSuspendableFunction()) {
855 intptr_t reverse_index = num_parameters - index;
863 ASSERT(param.IsInstance());
864 ASSERT(Instance::Cast(param).IsClosure());
865 return Closure::Cast(param).ptr();
875 if (suspend_state.IsSuspendState()) {
876 return SuspendState::Cast(suspend_state).function_data();
878 return suspend_state.
ptr();
882 const intptr_t slot_index =
884 if (deopt_frame_.
IsNull()) {
887 return deopt_frame_.
At(
LocalVarIndex(deopt_frame_offset_, slot_index));
892 if (deopt_frame_.
IsNull()) {
899 for (
int i = 0; i < deopt_frame_.
Length(); i++) {
900 obj = deopt_frame_.
At(i);
901 if (obj.
ptr() == Object::optimized_out().ptr()) {
908void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot,
909 intptr_t frame_ctx_level,
910 intptr_t var_ctx_level) {
912 "-------------------------\n"
913 "Encountered context mismatch\n"
916 "\tframe_ctx_level: %" Pd
918 "\tvar_ctx_level: %" Pd "\n\n",
919 ctx_slot, frame_ctx_level, var_ctx_level);
922 "-------------------------\n"
923 "Current frame:\n%s\n",
927 "-------------------------\n"
928 "Context contents:\n");
933 "-------------------------\n"
934 "Debugger stack trace...\n\n");
936 intptr_t num_frames = stack->
Length();
937 for (intptr_t i = 0; i < num_frames; i++) {
943 "-------------------------\n"
944 "All frames...\n\n");
948 StackFrame*
frame = iterator.NextFrame();
950 while ((
frame !=
nullptr)) {
952 frame = iterator.NextFrame();
964 intptr_t desc_index = desc_indices_[i];
970 var_descriptors_.
GetInfo(desc_index, &var_info);
971 ASSERT(declaration_token_pos !=
nullptr);
973 ASSERT(visible_start_token_pos !=
nullptr);
974 *visible_start_token_pos = var_info.
begin_pos;
975 ASSERT(visible_end_token_pos !=
nullptr);
976 *visible_end_token_pos = var_info.
end_pos;
978 const int8_t
kind = var_info.
kind();
981 *
value = GetStackVar(variable_index);
988ObjectPtr ActivationFrame::GetContextVar(intptr_t var_ctx_level,
993 return GetRelativeContextVar(var_ctx_level, ctx_slot, frame_ctx_level);
996ObjectPtr ActivationFrame::GetRelativeContextVar(intptr_t var_ctx_level,
998 intptr_t frame_ctx_level) {
1004 return Object::optimized_out().ptr();
1007 intptr_t level_diff = frame_ctx_level - var_ctx_level;
1008 if (level_diff == 0) {
1009 if ((ctx_slot < 0) || (ctx_slot >= ctx.num_variables())) {
1010 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1012 ASSERT((ctx_slot >= 0) && (ctx_slot < ctx.num_variables()));
1013 return ctx.At(ctx_slot);
1014 }
else if (level_diff > 0) {
1016 while (level_diff > 0 && !var_ctx.IsNull()) {
1018 var_ctx = var_ctx.parent();
1020 if (var_ctx.IsNull() || (ctx_slot < 0) ||
1021 (ctx_slot >= var_ctx.num_variables())) {
1022 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1024 ASSERT(!var_ctx.IsNull());
1025 ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
1026 return var_ctx.At(ctx_slot);
1028 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1035 intptr_t num_variables = desc_indices_.
length();
1039 for (intptr_t i = 0; i < num_variables; i++) {
1042 list.
SetAt(2 * i, var_name);
1050 intptr_t num_variables = desc_indices_.
length();
1053 for (intptr_t i = 0; i < num_variables; i++) {
1060 return Object::optimized_out().ptr();
1064 return (var_name.
Length() >= 1) && (var_name.
CharAt(0) ==
':');
1068 return (var_name.
Length() >= 1) && (var_name.
CharAt(0) ==
'_');
1073 const Array& type_definitions,
1074 const Array& arguments,
1077 auto zone = thread->zone();
1083 const auto& outermost =
1089 if (!klass.IsTopLevel() && !outermost.is_static()) {
1092 receiver.ptr() == Object::optimized_out().ptr());
1095 kernel_buffer, type_definitions,
1096 arguments, type_arguments);
1106 bool type_arguments_available =
false;
1111 intptr_t num_variables = desc_indices_.
length();
1112 for (intptr_t i = 0; i < num_variables; i++) {
1115 if (
name.Equals(Symbols::FunctionTypeArgumentsVar())) {
1116 type_arguments_available =
true;
1117 type_arguments ^=
value.ptr();
1120 value.ptr() != Object::optimized_out().ptr()) {
1124 bool conflict =
false;
1125 for (intptr_t j = 0; j < param_names.
Length(); j++) {
1126 existing_name ^= param_names.
At(j);
1127 if (
name.Equals(existing_name)) {
1143 type_arguments_available) {
1145 type_params_names.
Grow(num_vars);
1147 type_params_bounds.
Grow(num_vars);
1149 type_params_defaults.
Grow(num_vars);
1150 type_params_defaults.
SetLength(num_vars);
1155 intptr_t mapping_offset = num_vars;
1158 if (type_params.
IsNull())
continue;
1161 ASSERT(mapping_offset >= size);
1162 mapping_offset -= size;
1163 for (intptr_t j = 0; j < size; ++j) {
1165 bound = type_params.
BoundAt(j);
1172 type_params_names.
SetAt(mapping_offset + j,
name);
1173 type_params_bounds.
SetAt(mapping_offset + j, bound);
1174 type_params_defaults.
SetAt(mapping_offset + j, defaultType);
1177 if (!type_arguments.
IsNull()) {
1178 if (type_arguments.
Length() == 0) {
1179 for (intptr_t i = 0; i < num_vars; ++i) {
1180 type_arguments.
SetTypeAt(i, Object::dynamic_type());
1187 return type_arguments.
ptr();
1193 KindToCString(kind_));
1200 "[ Frame pc(0x%" Px " code offset:0x%" Px ") fp(0x%" Px ") sp(0x%" Px
1207 "\tcontext level = %" Pd " ]\n",
1208 pc(),
pc() -
code().PayloadStart(),
fp(),
sp(), func_name,
1212 "[ Frame code function = %s\n"
1216 "\tcontext = %s]\n",
1223 PrintToJSONObjectRegular(jsobj);
1225 PrintToJSONObjectAsyncAwaiter(jsobj);
1227 PrintToJSONObjectAsyncSuspensionMarker(jsobj);
1233void ActivationFrame::PrintToJSONObjectRegular(
JSONObject* jsobj) {
1244 for (intptr_t v = 0; v < num_vars; v++) {
1247 TokenPosition declaration_token_pos = TokenPosition::kNoSource;
1248 TokenPosition visible_start_token_pos = TokenPosition::kNoSource;
1249 TokenPosition visible_end_token_pos = TokenPosition::kNoSource;
1250 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
1251 &visible_end_token_pos, &var_value);
1254 jsvar.AddProperty(
"type",
"BoundVariable");
1256 jsvar.AddProperty(
"name", scrubbed_var_name);
1257 jsvar.AddProperty(
"value", var_value);
1259 jsvar.AddProperty(
"declarationTokenPos", declaration_token_pos);
1261 jsvar.AddProperty(
"scopeStartTokenPos", visible_start_token_pos);
1263 jsvar.AddProperty(
"scopeEndTokenPos", visible_end_token_pos);
1269void ActivationFrame::PrintToJSONObjectAsyncAwaiter(JSONObject* jsobj) {
1270 jsobj->AddProperty(
"type",
"Frame");
1271 jsobj->AddProperty(
"kind", KindToCString(kind_));
1274 jsobj->AddLocation(script,
pos);
1275 jsobj->AddProperty(
"function",
function());
1276 jsobj->AddProperty(
"code",
code());
1279void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
1280 JSONObject* jsobj) {
1281 jsobj->AddProperty(
"type",
"Frame");
1282 jsobj->AddProperty(
"kind", KindToCString(kind_));
1283 jsobj->AddProperty(
"marker",
"AsynchronousSuspension");
1287 return FLAG_show_invisible_frames ||
function.is_visible();
1290void DebuggerStackTrace::AddActivation(ActivationFrame*
frame) {
1296void DebuggerStackTrace::AddAsyncSuspension() {
1301 if (trace_.is_empty() ||
1307void DebuggerStackTrace::AddAsyncAwaiterFrame(
uword pc,
1309 const Closure& closure) {
1310 trace_.Add(
new ActivationFrame(pc, code, closure));
1314 UntaggedPcDescriptors::kUnoptStaticCall |
1315 UntaggedPcDescriptors::kRuntimeCall;
1321 : code_(code.ptr()),
1325 breakpoint_kind_(kind),
1326 saved_value_(
Code::null()) {
1330 AddBreakpointLocation(breakpoint_location);
1342 breakpoint_kind_ = UntaggedPcDescriptors::kOther;
1347 if (enabled_count_ == 0) {
1354 if (enabled_count_ == 1) {
1362 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
1363 if (breakpoint_locations_[i] == breakpoint_location) {
1372 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
1373 if (breakpoint_locations_[i] == breakpoint_location) {
1374 breakpoint_locations_.EraseAt(i);
1383 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
1384 if (breakpoint_locations_[i]->debugger() == debugger) {
1385 return breakpoint_locations_[i];
1392 : isolate_group_(isolate_group),
1394 code_breakpoints_(nullptr),
1396 single_stepping_set_lock_(new
RwLock()),
1397 needs_breakpoint_cleanup_(
false) {}
1400 while (code_breakpoints_ !=
nullptr) {
1402 code_breakpoints_ = code_breakpoints_->next();
1409 : isolate_(isolate),
1411 latent_locations_(nullptr),
1412 breakpoint_locations_(nullptr),
1413 resume_action_(kContinue),
1414 resume_frame_index_(-1),
1415 post_deopt_frame_index_(-1),
1416 ignore_breakpoints_(
false),
1417 pause_event_(nullptr),
1418 stack_trace_(nullptr),
1419 async_awaiter_stack_trace_(nullptr),
1421 last_stepping_fp_(0),
1423 skip_next_step_(
false),
1428 ASSERT(latent_locations_ ==
nullptr);
1429 ASSERT(breakpoint_locations_ ==
nullptr);
1430 ASSERT(stack_trace_ ==
nullptr);
1431 ASSERT(async_awaiter_stack_trace_ ==
nullptr);
1442 group_debugger()->breakpoint_locations_lock());
1443 while (breakpoint_locations_ !=
nullptr) {
1447 breakpoint_locations_ = breakpoint_locations_->next();
1450 while (latent_locations_ !=
nullptr) {
1454 latent_locations_ = latent_locations_->next();
1458 if (NeedsIsolateEvents()) {
1467bool Debugger::SetupStepOverAsyncSuspension(
const char**
error) {
1471 if (
error !=
nullptr) {
1472 *
error =
"Isolate must be paused at an async suspension point";
1478 const auto& function_data =
1487 intptr_t frame_index,
1488 const char**
error) {
1489 if (
error !=
nullptr) {
1492 resume_frame_index_ = -1;
1498 set_resume_action(
action);
1505 resume_frame_index_ = frame_index;
1508 return SetupStepOverAsyncSuspension(
error);
1519void Debugger::DeoptimizeWorld() {
1520#if defined(DART_PRECOMPILED_RUNTIME)
1523 if (FLAG_trace_deoptimization) {
1534 auto isolate_group = thread->isolate_group();
1535 auto zone = thread->zone();
1536 CallSiteResetter resetter(zone);
1542 const intptr_t num_classes = class_table.NumCids();
1543 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
1544 SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
1545 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
1546 const intptr_t
cid =
1548 if (class_table.HasValidClassAt(
cid)) {
1549 cls = class_table.At(
cid);
1552 functions = cls.functions();
1553 if (!functions.IsNull()) {
1554 intptr_t num_functions = functions.Length();
1555 for (intptr_t
pos = 0;
pos < num_functions;
pos++) {
1562 function.SwitchToUnoptimizedCode();
1565 if (!
code.IsNull()) {
1566 resetter.ResetSwitchableCalls(code);
1570 if (
function.HasImplicitClosureFunction()) {
1574 function.SwitchToUnoptimizedCode();
1577 if (!
code.IsNull()) {
1578 resetter.ResetSwitchableCalls(code);
1590 if (function.HasOptimizedCode()) {
1591 function.SwitchToUnoptimizedCode();
1593 code =
function.unoptimized_code();
1594 if (!
code.IsNull()) {
1595 resetter.ResetSwitchableCalls(code);
1603void Debugger::RunWithStoppedDeoptimizedWorld(std::function<
void()> fun) {
1604#if !defined(DART_PRECOMPILED_RUNTIME)
1608 group_debugger()->isolate_group()->RunWithStoppedMutators([&]() {
1615void Debugger::NotifySingleStepping(
bool value) {
1619 RunWithStoppedDeoptimizedWorld([&] {
1620 isolate_->set_single_step(value);
1623 group_debugger()->RegisterSingleSteppingDebugger(Thread::Current(),
this);
1626 isolate_->set_single_step(value);
1627 group_debugger()->UnregisterSingleSteppingDebugger(Thread::Current(),
this);
1634 const Array& deopt_frame,
1635 intptr_t deopt_frame_offset) {
1636 ASSERT(code.ContainsInstructionAt(pc));
1638 pc,
frame->fp(),
frame->sp(), code, deopt_frame, deopt_frame_offset);
1639 if (FLAG_trace_debugger_stacktrace) {
1641 OS::PrintErr(
"\tUsing saved context: %s\n", ctx.
ToCString());
1642 OS::PrintErr(
"\tLine number: %" Pd "\n", activation->
LineNumber());
1647#if !defined(DART_PRECOMPILED_RUNTIME)
1651 ASSERT(code.is_optimized() && !code.is_force_optimized());
1656 nullptr,
true,
false );
1661 const Array& dest_frame =
1665 delete deopt_context;
1667 return dest_frame.
ptr();
1672 Thread* thread = Thread::Current();
1675 Code& code = Code::Handle(zone);
1679 StackFrameIterator::kNoCrossThreadIteration);
1683 if (FLAG_trace_debugger_stacktrace) {
1684 OS::PrintErr(
"CollectStackTrace: visiting frame:\n\t%s\n",
1685 frame->ToCString());
1687 if (
frame->IsDartFrame()) {
1688 code =
frame->LookupDartCode();
1689 stack_trace->AppendCodeFrames(
frame, code);
1698#if !defined(DART_PRECOMPILED_RUNTIME)
1699 if (code.is_optimized()) {
1700 if (code.is_force_optimized()) {
1701 if (FLAG_trace_debugger_stacktrace) {
1705 "CollectStackTrace: skipping force-optimized function: %s\n",
1706 function.ToFullyQualifiedCString());
1712 for (InlinedFunctionsIterator it(code,
frame->pc()); !it.Done();
1714 inlined_code_ = it.code();
1715 if (FLAG_trace_debugger_stacktrace) {
1716 const Function&
function = Function::Handle(zone_, it.function());
1718 OS::PrintErr(
"CollectStackTrace: visiting inlined function: %s\n",
1719 function.ToFullyQualifiedCString());
1721 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1723 deopt_frame_, deopt_frame_offset));
1733 Thread* thread = Thread::Current();
1738 constexpr intptr_t kDefaultStackAllocation = 8;
1741 bool has_async =
false;
1742 bool has_async_catch_error =
false;
1743 StackTraceUtils::CollectFrames(
1746 if (
frame.frame !=
nullptr) {
1747 stack_trace->AppendCodeFrames(frame.frame, frame.code);
1751 if (frame.code.ptr() == StubCode::AsynchronousGapMarker().ptr()) {
1752 stack_trace->AddAsyncSuspension();
1762 const uword absolute_pc =
frame.code.PayloadStart() +
frame.pc_offset;
1763 stack_trace->AddAsyncAwaiterFrame(absolute_pc,
frame.code,
1767 &has_async_catch_error);
1774 stack_trace->set_has_async_catch_error(has_async_catch_error);
1782 StackFrameIterator::kNoCrossThreadIteration);
1787 if (!
frame->IsDartFrame()) {
1790 Code& code = Code::Handle(
frame->LookupDartCode());
1792 frame->pc(),
frame->fp(),
frame->sp(), code, Object::null_array(), 0);
1798 return (stack_trace_ !=
nullptr) ? stack_trace_
1799 : DebuggerStackTrace::Collect();
1803 return (async_awaiter_stack_trace_ !=
nullptr)
1804 ? async_awaiter_stack_trace_
1805 : DebuggerStackTrace::CollectAsyncAwaiters();
1811 Object& code_object = Object::Handle();
1812 Code& code = Code::Handle();
1816 const Array& deopt_frame = Array::Handle();
1817 const intptr_t deopt_frame_offset = -1;
1819 for (intptr_t i = 0; i < ex_trace.
Length(); i++) {
1826 if (!code_object.
IsNull()) {
1827 code ^= code_object.
ptr();
1828 ASSERT(code.IsFunctionCode());
1833 if (code.is_optimized() && ex_trace.expand_inlined()) {
1842 ASSERT(code.PayloadStart() <= pc);
1843 ASSERT(pc < (code.PayloadStart() + code.Size()));
1846 pc,
fp, sp, code, deopt_frame, deopt_frame_offset);
1847 stack_trace->AddActivation(activation);
1851 pc,
fp, sp, code, deopt_frame, deopt_frame_offset);
1852 stack_trace->AddActivation(activation);
1864 exc_pause_info_ = pause_info;
1868 return exc_pause_info_;
1873 if (exc_pause_info_ == kNoPauseOnExceptions) {
1876 if (exc_pause_info_ == kPauseOnAllExceptions) {
1879 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
1882 if (stack_trace->
Length() == 0) {
1886 ActivationFrame* top_frame = stack_trace->
FrameAt(0);
1887 if (!top_frame->TokenPos().IsReal() && top_frame->TryIndex() != -1) {
1890 ActivationFrame* handler_frame = stack_trace->
GetHandlerFrame(exception);
1891 if (handler_frame ==
nullptr) {
1900 auto& handler_function = Function::Handle(handler_frame->function().ptr());
1905 if (!handler_function.IsNull() &&
1906 Library::FindPragma(Thread::Current(),
false,
1908 Symbols::vm_notify_debugger_on_exception())) {
1915 if (FLAG_stress_async_stacks) {
1916 DebuggerStackTrace::CollectAsyncAwaiters();
1922 if (ignore_breakpoints_ || IsPaused() ||
1927 DebuggerStackTrace::CollectAsyncAwaiters();
1929 if (async_awaiter_stack_trace !=
nullptr) {
1930 if (!ShouldPauseOnException(async_awaiter_stack_trace, exc)) {
1934 if (!ShouldPauseOnException(stack_trace, exc)) {
1939 event.set_exception(&exc);
1940 if (stack_trace->
Length() > 0) {
1941 event.set_top_frame(stack_trace->
FrameAt(0));
1943 CacheStackTraces(stack_trace, async_awaiter_stack_trace);
1945 HandleSteppingRequest();
1946 ClearCachedStackTraces();
1960 intptr_t requested_column,
1963 intptr_t* best_column,
1964 intptr_t* best_line) {
1966 (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
1967 (requested_column > -1 && exact_token_pos != TokenPosition::kNoSource));
1969 intptr_t token_start_column = -1;
1970 intptr_t token_line = -1;
1971 if (requested_column >= 0) {
1974 script.GetTokenLocation(
pos, &token_line, &token_start_column);
1975 script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
1978 TokenPosition::Deserialize(next_closest_token_position.
Pos() - 1),
1981 if ((token_end_pos.
IsReal() && exact_token_pos.
IsReal() &&
1982 (token_end_pos < exact_token_pos)) ||
1983 (token_start_column > *best_column)) {
1994 if (
pos < *best_fit_pos) {
1995 *best_fit_pos =
pos;
1996 *best_line = token_line;
1997 *best_column = token_start_column;
2065 intptr_t requested_column,
2069 (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
2070 (requested_column > -1 && exact_token_pos != TokenPosition::kNoSource));
2072 requested_token_pos =
2073 TokenPosition::Max(requested_token_pos, func.
token_pos());
2074 last_token_pos = TokenPosition::Min(last_token_pos, func.
end_token_pos());
2076 Zone* zone = Thread::Current()->zone();
2078 Code& code = Code::Handle(zone);
2083 desc = code.pc_descriptors();
2088 intptr_t best_column = INT_MAX;
2089 intptr_t best_line = INT_MAX;
2094 if (
pos.IsSynthetic() &&
pos == requested_token_pos) {
2099 if (!
pos.IsWithin(requested_token_pos, last_token_pos)) {
2103 TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
2104 if (requested_column >= 0) {
2109 if (!
next.IsReal())
continue;
2110 if ((
pos <
next) && (
next < next_closest_token_position)) {
2111 next_closest_token_position =
next;
2116 requested_token_pos, last_token_pos, requested_column,
2117 exact_token_pos, &best_fit_pos, &best_column,
2124 if (best_fit_pos != TokenPosition::kMaxSource) {
2126 const Script& script = Script::Handle(zone, func.
script());
2130 if (best_line < 0) {
2131 script.GetTokenLocation(begin_pos, &best_line);
2135 script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
2136 end_of_line_pos = TokenPosition::Max(end_of_line_pos, begin_pos);
2142 if (requested_column >= 0) {
2143 if (
pos != best_fit_pos) {
2147 }
else if (!
pos.IsWithin(begin_pos, end_of_line_pos)) {
2153 if (iter.
PcOffset() < lowest_pc_offset) {
2154 lowest_pc_offset = iter.
PcOffset();
2158 return best_fit_pos;
2167 -1 , TokenPosition::kNoSource);
2169 return TokenPosition::kNoSource;
2172bool BreakpointLocation::EnsureIsResolved(
const Function& target_function,
2181 requested_column_number(), exact_token_pos);
2183 if (FLAG_verbose_debug) {
2184 OS::PrintErr(
"Failed resolving breakpoint for function '%s'\n",
2191 SetResolved(target_function, resolved_pos);
2193 while (breakpoint !=
nullptr) {
2194 if (FLAG_verbose_debug) {
2195 OS::PrintErr(
"Resolved breakpoint %" Pd
2196 " to pos %s, function '%s' (requested range %s-%s, "
2197 "requested col %" Pd ")\n",
2198 breakpoint->
id(), token_pos().ToCString(),
2201 requested_column_number());
2203 debugger()->SendBreakpointEvent(ServiceEvent::kBreakpointResolved,
2205 breakpoint = breakpoint->
next();
2211void GroupDebugger::MakeCodeBreakpointAtUnsafe(
const Function& func,
2213 DEBUG_ASSERT(Thread::Current()->IsInStoppedMutatorsScope() ||
2214 code_breakpoints_lock()->IsCurrentThreadWriter());
2222 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
2229 if (iter.
TokenPos() == loc->token_pos_) {
2230 if (iter.
PcOffset() < lowest_pc_offset) {
2231 lowest_pc_offset = iter.
PcOffset();
2232 lowest_kind = iter.
Kind();
2240 uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
2242 if (code_bpt ==
nullptr) {
2244 code_bpt =
new CodeBreakpoint(code, loc, lowest_pc, lowest_kind);
2245 if (FLAG_verbose_debug) {
2246 OS::PrintErr(
"Setting code breakpoint at pos %s pc %#" Px " offset %#" Px
2249 lowest_pc - code.PayloadStart());
2251 RegisterCodeBreakpoint(code_bpt);
2253 if (FLAG_verbose_debug) {
2255 "Adding location to existing code breakpoint at pos %s pc %#" Px
2256 " offset %#" Px "\n",
2258 lowest_pc - code.PayloadStart());
2261 code_bpt->AddBreakpointLocation(loc);
2269void GroupDebugger::MakeCodeBreakpointAt(
const Function& func,
2271 auto thread = Thread::Current();
2272 if (thread->IsInStoppedMutatorsScope()) {
2273 MakeCodeBreakpointAtUnsafe(func, loc);
2276 MakeCodeBreakpointAtUnsafe(func, loc);
2280void Debugger::FindCompiledFunctions(
2285 auto thread = Thread::Current();
2286 auto zone = thread->zone();
2287 Script& script = Script::Handle(zone);
2288 for (intptr_t i = 0; i <
scripts.length(); ++i) {
2290 ClosureFunctionsCache::ForAllClosureFunctions(
2293 if ((
function.token_pos() == start_pos) &&
2294 (
function.end_token_pos() == end_pos) &&
2295 (
function.script() == script.ptr())) {
2304 Class& cls = Class::Handle(zone);
2305 Function&
function = Function::Handle(zone);
2306 Array& functions = Array::Handle(zone);
2308 const ClassTable& class_table = *isolate_->group()->class_table();
2309 const intptr_t num_classes = class_table.NumCids();
2310 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
2311 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
2312 const intptr_t
cid =
2314 : ClassTable::CidFromTopLevelIndex(i - num_classes);
2315 if (class_table.HasValidClassAt(cid)) {
2316 cls = class_table.At(cid);
2321 if (!cls.is_finalized()) {
2327 functions = cls.current_functions();
2328 if (!functions.IsNull()) {
2329 const intptr_t num_functions = functions.Length();
2330 for (intptr_t
pos = 0;
pos < num_functions;
pos++) {
2333 bool function_added =
false;
2335 function.token_pos() == start_pos &&
2336 function.end_token_pos() == end_pos &&
2339 function_added =
true;
2341 if (function_added &&
function.HasImplicitClosureFunction()) {
2355 if (best_fit->
IsNull()) {
2356 *best_fit = func.
ptr();
2361 *best_fit = func.
ptr();
2369bool Debugger::FindBestFit(
const Script& script,
2370 TokenPosition token_pos,
2371 TokenPosition last_token_pos,
2372 Function* best_fit) {
2373 auto thread = Thread::Current();
2374 auto isolate_group = thread->isolate_group();
2375 Zone* zone = thread->zone();
2376 Class& cls = Class::Handle(zone);
2383 const GrowableObjectArray& libs = GrowableObjectArray::Handle(
2384 zone, isolate_group->object_store()->libraries());
2385 Library& lib = Library::Handle(zone);
2386 for (
int i = 0; i < libs.Length(); i++) {
2389 const Array&
scripts = Array::Handle(zone, lib.LoadedScripts());
2390 bool lib_has_script =
false;
2391 for (intptr_t j = 0; j <
scripts.Length(); j++) {
2392 if (
scripts.At(j) == script.ptr()) {
2393 lib_has_script =
true;
2397 if (!lib_has_script) {
2401 if (!lib.IsDebuggable()) {
2402 if (FLAG_verbose_debug) {
2403 OS::PrintErr(
"Library '%s' has been marked as non-debuggable\n",
2409 const String& script_url = String::Handle(zone,
script.url());
2410 ClosureFunctionsCache::ForAllClosureFunctions([&](
const Function& fun) {
2418 if (!best_fit->IsNull()) {
2425 Array& functions = Array::Handle(zone);
2426 Function&
function = Function::Handle(zone);
2427 Array& fields = Array::Handle(zone);
2428 Field& field = Field::Handle(zone);
2429 Error&
error = Error::Handle(zone);
2431 const ClassTable& class_table = *isolate_->group()->class_table();
2432 const intptr_t num_classes = class_table.NumCids();
2433 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
2434 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
2435 const intptr_t
cid =
2437 : ClassTable::CidFromTopLevelIndex(i - num_classes);
2438 if (!class_table.HasValidClassAt(cid)) {
2441 cls = class_table.At(cid);
2444 if (cls.library() != lib.ptr()) {
2448 error = cls.EnsureIsFinalized(Thread::Current());
2449 if (!
error.IsNull()) {
2456 functions = cls.current_functions();
2457 if (!functions.IsNull()) {
2458 const intptr_t num_functions = functions.Length();
2459 for (intptr_t
pos = 0;
pos < num_functions;
pos++) {
2483 fields = cls.fields();
2484 if (!fields.IsNull()) {
2485 const intptr_t num_fields = fields.Length();
2486 for (intptr_t
pos = 0;
pos < num_fields;
pos++) {
2487 TokenPosition
start = TokenPosition::kNoSource;
2488 TokenPosition
end = TokenPosition::kNoSource;
2489 field ^= fields.At(
pos);
2491 if (field.Script() !=
script.ptr()) {
2496 if (!field.has_nontrivial_initializer()) {
2499 start = field.token_pos();
2500 end = field.end_token_pos();
2501 if (token_pos.IsWithin(
start,
end) ||
2502 start.IsWithin(token_pos, last_token_pos)) {
2516BreakpointLocation* Debugger::SetCodeBreakpoints(
2517 const GrowableHandlePtrArray<const Script>&
scripts,
2518 TokenPosition token_pos,
2519 TokenPosition last_token_pos,
2520 intptr_t requested_line,
2521 intptr_t requested_column,
2522 TokenPosition exact_token_pos,
2523 const GrowableObjectArray& functions) {
2525 (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
2526 (requested_column > -1 && exact_token_pos != TokenPosition::kNoSource));
2528 Function&
function = Function::Handle();
2531 function, token_pos, last_token_pos, requested_column, exact_token_pos);
2532 if (!breakpoint_pos.IsReal()) {
2535 const String& script_url = String::Handle(
scripts.At(0).url());
2536 BreakpointLocation* loc =
2537 GetResolvedBreakpointLocation(script_url, breakpoint_pos);
2538 if (loc ==
nullptr) {
2540 loc = GetBreakpointLocation(script_url, token_pos, requested_line,
2543 if (loc ==
nullptr) {
2544 loc =
new BreakpointLocation(
this,
scripts, breakpoint_pos, breakpoint_pos,
2545 requested_line, requested_column);
2546 RegisterBreakpointLocation(loc);
2550 if (loc->IsResolved()) {
2553 loc->SetResolved(
function, breakpoint_pos);
2556 Function& func = Function::Handle();
2557 const intptr_t num_functions = functions.Length();
2558 for (intptr_t i = 0; i < num_functions; i++) {
2559 func ^= functions.At(i);
2561 group_debugger()->MakeCodeBreakpointAt(func, loc);
2563 if (FLAG_verbose_debug) {
2564 intptr_t line_number = -1;
2565 intptr_t column_number = -1;
2566 scripts.At(0).GetTokenLocation(breakpoint_pos, &line_number,
2568 OS::PrintErr(
"Resolved code breakpoint for function '%s' at line %" Pd
2570 func.ToFullyQualifiedCString(), line_number, column_number);
2575#if !defined(DART_PRECOMPILED_RUNTIME)
2577 TokenPosition start_of_line,
2578 intptr_t column_number);
2581BreakpointLocation* Debugger::SetBreakpoint(
const Script& script,
2582 TokenPosition token_pos,
2583 TokenPosition last_token_pos,
2584 intptr_t requested_line,
2585 intptr_t requested_column,
2587 GrowableHandlePtrArray<const Script>
scripts(Thread::Current()->zone(), 1);
2593BreakpointLocation* Debugger::SetBreakpoint(
2594 const GrowableHandlePtrArray<const Script>&
scripts,
2595 TokenPosition token_pos,
2596 TokenPosition last_token_pos,
2597 intptr_t requested_line,
2598 intptr_t requested_column,
2600 Function& func = Function::Handle();
2603 if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
2609 if (!func.token_pos().IsReal()) {
2614 if (!func.IsNull()) {
2620 GrowableObjectArray& code_functions =
2621 GrowableObjectArray::Handle(GrowableObjectArray::New());
2622 FindCompiledFunctions(
scripts, func.token_pos(), func.end_token_pos(),
2625 if (code_functions.Length() > 0) {
2630 TokenPosition exact_token_pos = TokenPosition::kNoSource;
2631#if !defined(DART_PRECOMPILED_RUNTIME)
2632 if (token_pos != last_token_pos && requested_column >= 0) {
2637 BreakpointLocation* loc =
nullptr;
2641 RunWithStoppedDeoptimizedWorld([&] {
2642 loc = SetCodeBreakpoints(
scripts, token_pos, last_token_pos,
2643 requested_line, requested_column,
2644 exact_token_pos, code_functions);
2646 if (loc !=
nullptr) {
2654 if (FLAG_verbose_debug) {
2655 intptr_t line_number = -1;
2656 intptr_t column_number = -1;
2657 script.GetTokenLocation(token_pos, &line_number, &column_number);
2658 if (func.IsNull()) {
2660 "Registering pending breakpoint for "
2661 "an uncompiled function literal at line %" Pd " col %" Pd "\n",
2662 line_number, column_number);
2665 "Registering pending breakpoint for "
2666 "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
2667 func.ToFullyQualifiedCString(), line_number, column_number);
2670 const String& script_url = String::Handle(
script.url());
2671 BreakpointLocation* loc = GetBreakpointLocation(
2672 script_url, token_pos, requested_line, requested_column);
2673 if (loc ==
nullptr) {
2674 loc =
new BreakpointLocation(
this,
scripts, token_pos, last_token_pos,
2675 requested_line, requested_column);
2676 RegisterBreakpointLocation(loc);
2687 while (cbpt !=
nullptr) {
2695 cbpt = cbpt->next();
2702 if (!target_function.is_debuggable()) {
2705 const Script& script = Script::Handle(target_function.
script());
2708 -1 , target_function);
2709 if (bpt_location ==
nullptr) {
2722 if (!closure.IsClosure()) {
2725 const Function& func = Function::Handle(Closure::Cast(closure).
function());
2730 return bpt_location->
AddBreakpoint(
this, Closure::Cast(closure), single_shot);
2734 if (!closure.IsClosure()) {
2739 while (loc !=
nullptr) {
2741 while (bpt !=
nullptr) {
2742 if (closure.ptr() == bpt->
closure()) {
2753void Debugger::SetBreakpointAtResumption(
const Object& function_data) {
2755 ASSERT(function_data.IsInstance());
2756 breakpoints_at_resumption_.Add(function_data.
ptr());
2757 isolate_->set_has_resumption_breakpoints(
true);
2760void Debugger::ResumptionBreakpoint() {
2761 ASSERT(!breakpoints_at_resumption_.is_empty());
2762 ASSERT(isolate_->has_resumption_breakpoints());
2766 const auto& function_data =
2769 for (intptr_t i = 0, n = breakpoints_at_resumption_.length(); i < n; ++i) {
2770 if (breakpoints_at_resumption_[i] == function_data.ptr()) {
2771 breakpoints_at_resumption_.RemoveAt(i);
2772 if (breakpoints_at_resumption_.is_empty()) {
2773 isolate_->set_has_resumption_breakpoints(
false);
2775 if (FLAG_verbose_debug) {
2777 "ResumptionBreakpoint - hit a breakpoint, continue single "
2780 EnterSingleStepMode();
2787 intptr_t line_number) {
2791 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
2794 BreakpointLocationAtLineCol(script_url, line_number, -1 );
2795 if (loc !=
nullptr) {
2802 intptr_t line_number,
2803 intptr_t column_number) {
2807 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
2810 BreakpointLocationAtLineCol(script_url, line_number, column_number);
2811 if (loc !=
nullptr) {
2818 const String& script_url,
2819 intptr_t line_number,
2820 intptr_t column_number) {
2821 Zone* zone = Thread::Current()->zone();
2822 Library& lib = Library::Handle(zone);
2825 isolate_->group()->object_store()->libraries());
2826 bool is_package = script_url.
StartsWith(Symbols::PackageScheme());
2827 bool is_dart_colon = script_url.
StartsWith(Symbols::DartScheme());
2828 Script& script_for_lib = Script::Handle(zone);
2829 for (intptr_t i = 0; i < libs.Length(); i++) {
2835 bool useResolvedUri = !is_package && !is_dart_colon;
2836 script_for_lib = lib.
LookupScript(script_url, useResolvedUri);
2837 if (!script_for_lib.
IsNull()) {
2845 GetLatentBreakpoint(script_url, line_number, column_number);
2846 if (FLAG_verbose_debug) {
2848 "Set latent breakpoint in url '%s' at "
2849 "line %" Pd " col %" Pd "\n",
2850 script_url.
ToCString(), line_number, column_number);
2857 scripts.At(0).TokenRangeAtLine(line_number, &first_token_idx,
2859 if (!first_token_idx.
IsReal()) {
2861 if (FLAG_verbose_debug) {
2862 OS::PrintErr(
"Script '%s' does not contain line number %" Pd "\n",
2866 }
else if (!last_token_idx.
IsReal()) {
2868 if (FLAG_verbose_debug) {
2869 OS::PrintErr(
"No executable code at line %" Pd " in '%s'\n", line_number,
2876 ASSERT(first_token_idx <= last_token_idx);
2877 while ((loc ==
nullptr) && (first_token_idx <= last_token_idx)) {
2879 column_number, Function::Handle());
2880 first_token_idx = first_token_idx.
Next();
2882 if ((loc ==
nullptr) && FLAG_verbose_debug) {
2883 OS::PrintErr(
"No executable code at line %" Pd " in '%s'\n", line_number,
2896 const Script& outer_origin = Script::Handle(zone,
function.script());
2898 Function& best_fit = Function::Handle(zone);
2899 ClosureFunctionsCache::ForAllClosureFunctions([&](
const Function& closure) {
2904 if (closure_end.
IsReal() && (
function.end_token_pos() > closure_end) &&
2906 (closure_start > func_start)) &&
2907 token_pos.
IsWithin(closure_start, closure_end) &&
2908 (closure.script() == outer_origin.
ptr())) {
2909 UpdateBestFit(&best_fit, closure);
2913 return best_fit.
ptr();
2916bool GroupDebugger::EnsureLocationIsInFunction(
Zone* zone,
2919 const String& url = String::Handle(zone, location->
url());
2926#if !defined(DART_PRECOMPILED_RUNTIME)
2932 const Script& script = Script::Handle(location->
script());
2939 if (!inner_function.
IsNull()) {
2940 if (FLAG_verbose_debug) {
2942 "Pending breakpoint remains unresolved in "
2943 "inner function '%s'\n",
2959 auto thread = Thread::Current();
2960 auto zone = thread->zone();
2970 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
2972 if (EnsureLocationIsInFunction(zone, resolved_function, location)) {
2982#if !defined(DART_PRECOMPILED_RUNTIME)
2991 if (FLAG_verbose_debug) {
2993 while (bpt !=
nullptr) {
2994 OS::PrintErr(
"Setting breakpoint %" Pd " for %s '%s'\n", bpt->
id(),
2995 function.IsClosureFunction() ?
"closure" :
"function",
2996 function.ToFullyQualifiedCString());
3000 MakeCodeBreakpointAt(
function, location);
3007 while (cbpt !=
nullptr) {
3008 cbpt->VisitObjectPointers(visitor);
3009 cbpt = cbpt->next();
3015 ASSERT(visitor !=
nullptr);
3017 while (loc !=
nullptr) {
3018 loc->VisitObjectPointers(visitor);
3021 loc = latent_locations_;
3022 while (loc !=
nullptr) {
3023 loc->VisitObjectPointers(visitor);
3026 for (intptr_t i = 0, n = breakpoints_at_resumption_.length(); i < n; ++i) {
3033 ASSERT(!ignore_breakpoints_);
3036 pause_event_ =
event;
3037 pause_event_->UpdateTimestamp();
3043 Thread* thread = Thread::Current();
3048 Service::HandleEvent(
event);
3052 isolate_->PauseEventHandler();
3056 const Error&
error = Error::Handle(Thread::Current()->sticky_error());
3058 error.IsUnhandledException());
3061 if (!
error.IsUnwindError()) {
3062 ServiceEvent resume_event(
event->isolate(), ServiceEvent::kResume);
3063 resume_event.set_top_frame(
event->top_frame());
3064 Service::HandleEvent(&resume_event);
3068 group_debugger()->Pause();
3069 pause_event_ =
nullptr;
3072void GroupDebugger::Pause() {
3074 if (needs_breakpoint_cleanup_) {
3075 RemoveUnlinkedCodeBreakpoints();
3079void Debugger::EnterSingleStepMode() {
3080 ResetSteppingFramePointer();
3081 NotifySingleStepping(
true);
3084void Debugger::ResetSteppingFramePointer() {
3088void Debugger::SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
3089 if (stack_trace->Length() > 0) {
3090 stepping_fp_ = stack_trace->FrameAt(0)->fp();
3096void Debugger::HandleSteppingRequest(
bool skip_next_step ) {
3097 ResetSteppingFramePointer();
3098 if (resume_action_ == kStepInto) {
3104 NotifySingleStepping(
true);
3105 skip_next_step_ = skip_next_step;
3106 if (FLAG_verbose_debug) {
3107 OS::PrintErr(
"HandleSteppingRequest - kStepInto\n");
3109 }
else if (resume_action_ == kStepOver) {
3110 NotifySingleStepping(
true);
3111 skip_next_step_ = skip_next_step;
3112 SetSyncSteppingFramePointer(stack_trace_);
3113 if (FLAG_verbose_debug) {
3114 OS::PrintErr(
"HandleSteppingRequest - kStepOver stepping_fp=%" Px "\n",
3117 }
else if (resume_action_ == kStepOut) {
3119 if (async_awaiter_stack_trace_ !=
nullptr &&
3120 async_awaiter_stack_trace_->Length() > 2 &&
3121 async_awaiter_stack_trace_->FrameAt(1)->kind() ==
3122 ActivationFrame::kAsyncSuspensionMarker) {
3123 auto awaiter_frame = async_awaiter_stack_trace_->FrameAt(2);
3124 AsyncStepInto(awaiter_frame->closure());
3125 if (FLAG_verbose_debug) {
3126 OS::PrintErr(
"HandleSteppingRequest - continue to async awaiter %s\n",
3127 Function::Handle(awaiter_frame->closure().function())
3128 .ToFullyQualifiedCString());
3134 NotifySingleStepping(
true);
3136 for (intptr_t i = 1; i < stack_trace_->Length(); i++) {
3137 ActivationFrame*
frame = stack_trace_->FrameAt(i);
3138 if (
frame->IsDebuggable()) {
3139 stepping_fp_ =
frame->fp();
3143 if (FLAG_verbose_debug) {
3144 OS::PrintErr(
"HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
3146 }
else if (resume_action_ == kStepRewind) {
3147 if (FLAG_trace_rewind) {
3148 OS::PrintErr(
"Rewinding to frame %" Pd "\n", resume_frame_index_);
3150 "-------------------------\n"
3151 "All frames...\n\n");
3152 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
3154 StackFrameIterator::kNoCrossThreadIteration);
3155 StackFrame*
frame = iterator.NextFrame();
3157 while ((
frame !=
nullptr)) {
3158 OS::PrintErr(
"#%04" Pd " %s\n", num++,
frame->ToCString());
3159 frame = iterator.NextFrame();
3162 RewindToFrame(resume_frame_index_);
3167void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
3168 DebuggerStackTrace* async_awaiter_stack_trace) {
3169 ASSERT(stack_trace_ ==
nullptr);
3170 stack_trace_ = stack_trace;
3171 ASSERT(async_awaiter_stack_trace_ ==
nullptr);
3172 async_awaiter_stack_trace_ = async_awaiter_stack_trace;
3175void Debugger::ClearCachedStackTraces() {
3176 stack_trace_ =
nullptr;
3177 async_awaiter_stack_trace_ =
nullptr;
3181 intptr_t frame_index) {
3182 for (intptr_t i = frame_index + 1; i < stack->
Length(); i++) {
3184 if (
frame->IsRewindable()) {
3195 intptr_t num_frames = stack->
Length();
3196 if (frame_index < 1 || frame_index >= num_frames) {
3197 if (
error !=
nullptr) {
3198 *
error = Thread::Current()->zone()->PrintToString(
3199 "Frame must be in bounds [1..%" Pd
3202 num_frames - 1, frame_index);
3207 if (!
frame->IsRewindable()) {
3209 if (next_index > 0) {
3210 *
error = Thread::Current()->zone()->PrintToString(
3211 "Cannot rewind to frame %" Pd
3212 " due to conflicting compiler "
3214 "Run the vm with --no-prune-dead-locals to disallow these "
3216 "Next valid rewind frame is %" Pd ".",
3217 frame_index, next_index);
3219 *
error = Thread::Current()->zone()->PrintToString(
3220 "Cannot rewind to frame %" Pd
3221 " due to conflicting compiler "
3223 "Run the vm with --no-prune-dead-locals to disallow these "
3235 ASSERT(!code.is_optimized());
3236 ASSERT(code.ContainsInstructionAt(return_address));
3238 uword pc_offset = return_address - code.PayloadStart();
3240 PcDescriptors::Handle(code.pc_descriptors());
3242 UntaggedPcDescriptors::kRewind |
3243 UntaggedPcDescriptors::kIcCall |
3244 UntaggedPcDescriptors::kUnoptStaticCall);
3245 intptr_t rewind_deopt_id = -1;
3246 uword rewind_pc = 0;
3248 if (iter.
Kind() == UntaggedPcDescriptors::kRewind) {
3250 rewind_pc = code.PayloadStart() + iter.
PcOffset();
3251 rewind_deopt_id = iter.
DeoptId();
3253 if ((pc_offset == iter.
PcOffset()) && (iter.
DeoptId() == rewind_deopt_id)) {
3260void Debugger::RewindToFrame(intptr_t frame_index) {
3261 Thread* thread = Thread::Current();
3262 Zone* zone = thread->zone();
3263 Code& code = Code::Handle(zone);
3264 Function&
function = Function::Handle(zone);
3267 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
3269 StackFrameIterator::kNoCrossThreadIteration);
3270 intptr_t current_frame = 0;
3271 for (StackFrame*
frame = iterator.NextFrame();
frame !=
nullptr;
3272 frame = iterator.NextFrame()) {
3274 if (
frame->IsDartFrame()) {
3275 code =
frame->LookupDartCode();
3277 if (!IsFunctionVisible(
function)) {
3280 if (
code.is_optimized()) {
3281 intptr_t sub_index = 0;
3282 for (InlinedFunctionsIterator it(code,
frame->pc()); !it.Done();
3284 if (current_frame == frame_index) {
3285 RewindToOptimizedFrame(
frame, code, sub_index);
3292 if (current_frame == frame_index) {
3294 RewindToUnoptimizedFrame(
frame, code);
3304void Debugger::RewindToUnoptimizedFrame(StackFrame*
frame,
const Code& code) {
3307 ClearCachedStackTraces();
3308 set_resume_action(kContinue);
3309 resume_frame_index_ = -1;
3310 EnterSingleStepMode();
3313 if (FLAG_trace_rewind && rewind_pc == 0) {
3314 OS::PrintErr(
"Unable to find rewind pc for pc(%" Px ")\n",
frame->pc());
3317 if (FLAG_trace_rewind) {
3319 "===============================\n"
3320 "Rewinding to unoptimized frame:\n"
3321 " rewind_pc(0x%" Px " offset:0x%" Px ") sp(0x%" Px ") fp(0x%" Px
3323 "===============================\n",
3324 rewind_pc, rewind_pc -
code.PayloadStart(),
frame->sp(),
frame->fp());
3326 Exceptions::JumpToFrame(Thread::Current(), rewind_pc,
frame->sp(),
3327 frame->fp(),
true );
3331void Debugger::RewindToOptimizedFrame(StackFrame*
frame,
3332 const Code& optimized_code,
3333 intptr_t sub_index) {
3334 post_deopt_frame_index_ = sub_index;
3338 ClearCachedStackTraces();
3339 set_resume_action(kContinue);
3340 resume_frame_index_ = -1;
3341 EnterSingleStepMode();
3343 if (FLAG_trace_rewind) {
3345 "===============================\n"
3346 "Deoptimizing frame for rewind:\n"
3347 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
3349 "===============================\n",
3352 Thread* thread = Thread::Current();
3353 thread->set_resume_pc(
frame->pc());
3354 uword deopt_stub_pc = StubCode::DeoptForRewind().EntryPoint();
3355 Exceptions::JumpToFrame(thread, deopt_stub_pc,
frame->sp(),
frame->fp(),
3360void Debugger::RewindPostDeopt() {
3361 intptr_t rewind_frame = post_deopt_frame_index_;
3362 post_deopt_frame_index_ = -1;
3363 if (FLAG_trace_rewind) {
3364 OS::PrintErr(
"Post deopt, jumping to frame %" Pd "\n", rewind_frame);
3366 "-------------------------\n"
3367 "All frames...\n\n");
3370 StackFrameIterator::kNoCrossThreadIteration);
3373 while ((
frame !=
nullptr)) {
3374 OS::PrintErr(
"#%04" Pd " %s\n", num++,
frame->ToCString());
3379 Thread* thread = Thread::Current();
3381 Code& code = Code::Handle(zone);
3385 StackFrameIterator::kNoCrossThreadIteration);
3386 intptr_t current_frame = 0;
3390 if (
frame->IsDartFrame()) {
3391 code =
frame->LookupDartCode();
3392 ASSERT(!code.is_optimized());
3393 if (current_frame == rewind_frame) {
3394 RewindToUnoptimizedFrame(
frame, code);
3404 if (!func.is_debuggable()) {
3407 const Class& cls = Class::Handle(func.
Owner());
3412void GroupDebugger::RegisterSingleSteppingDebugger(
Thread* thread,
3414 WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
3415 single_stepping_set_.Insert(debugger);
3418void GroupDebugger::UnregisterSingleSteppingDebugger(
Thread* thread,
3420 WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
3421 single_stepping_set_.Remove(debugger);
3424bool GroupDebugger::HasBreakpointUnsafe(
Thread* thread,
3427 breakpoint_locations_lock()->IsCurrentThreadReader());
3429 String& url = String::Handle(thread->
zone());
3430 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
3432 url = location->
url();
3442 bool hasBreakpoint =
false;
3445 hasBreakpoint = HasBreakpointUnsafe(thread,
function);
3448 hasBreakpoint = HasBreakpointUnsafe(thread,
function);
3450 if (hasBreakpoint) {
3458 if (HasCodeBreakpointInFunction(
function)) {
3468 if (!single_stepping_set_.IsEmpty()) {
3472 return HasBreakpoint(thread,
function);
3475void Debugger::set_resume_action(ResumeAction resume_action) {
3476 auto thread = Thread::Current();
3477 if (resume_action == kContinue) {
3478 group_debugger()->UnregisterSingleSteppingDebugger(thread,
this);
3480 group_debugger()->RegisterSingleSteppingDebugger(thread,
this);
3482 resume_action_ = resume_action;
3485void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
3486 set_resume_action(kContinue);
3487 ResetSteppingFramePointer();
3488 NotifySingleStepping(
false);
3490 if ((bpt !=
nullptr) && bpt->is_single_shot()) {
3491 RemoveBreakpoint(bpt->id());
3495 ServiceEvent
event(isolate_, ServiceEvent::kPauseBreakpoint);
3496 event.set_top_frame(top_frame);
3497 event.set_breakpoint(bpt);
3503 Zone* zone = Thread::Current()->zone();
3508 const auto& pc_descriptors =
3510 if (pc_descriptors.IsNull()) {
3516 if (it.
TokenPos() == looking_for &&
3517 it.
YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
3524ErrorPtr Debugger::PauseStepping() {
3525 ASSERT(isolate_->single_step());
3528 return Error::null();
3530 if (skip_next_step_) {
3531 skip_next_step_ =
false;
3532 return Error::null();
3543 if (stepping_fp_ != 0) {
3547 if (relation == ActivationFrame::kCallee) {
3550 return Error::null();
3551 }
else if (relation == ActivationFrame::kCaller) {
3555 ResetSteppingFramePointer();
3559 if (!
frame->IsDebuggable()) {
3560 return Error::null();
3562 if (!
frame->TokenPos().IsDebugPause()) {
3563 return Error::null();
3566 if (
frame->fp() == last_stepping_fp_ &&
3567 frame->TokenPos() == last_stepping_pos_) {
3570 return Error::null();
3575 if ((
frame->function().IsAsyncFunction() ||
3576 frame->function().IsAsyncGenerator()) &&
3577 frame->GetSuspendStateVar() == Object::null()) {
3578 return Error::null();
3582 last_stepping_fp_ =
frame->fp();
3583 last_stepping_pos_ =
frame->TokenPos();
3588 ASSERT(!group_debugger()->HasActiveBreakpoint(
frame->pc()));
3590 if (FLAG_verbose_debug) {
3591 OS::PrintErr(
">>> single step break at %s:%" Pd ":%" Pd
3592 " (func %s token %s address %#" Px " offset %#" Px ")\n",
3593 String::Handle(
frame->SourceUrl()).ToCString(),
3595 String::Handle(
frame->QualifiedFunctionName()).ToCString(),
3600 CacheStackTraces(DebuggerStackTrace::Collect(),
3601 DebuggerStackTrace::CollectAsyncAwaiters());
3602 SignalPausedEvent(
frame,
nullptr);
3603 HandleSteppingRequest();
3604 ClearCachedStackTraces();
3607 return Thread::Current()->StealStickyError();
3610ErrorPtr Debugger::PauseBreakpoint() {
3614 if (ignore_breakpoints_ || IsPaused()) {
3615 return Error::null();
3620 ASSERT(top_frame !=
nullptr);
3621 if (!Library::Handle(top_frame->
Library()).IsDebuggable()) {
3622 return Error::null();
3626 const char* cbpt_tostring =
nullptr;
3629 group_debugger()->code_breakpoints_lock());
3631 bpt_location = group_debugger()->GetBreakpointLocationFor(
3632 this, top_frame->
pc(), &cbpt);
3633 if (bpt_location ==
nullptr) {
3635 return Error::null();
3638 if (FLAG_verbose_debug) {
3643 Breakpoint* bpt_hit = bpt_location->FindHitBreakpoint(top_frame);
3644 if (bpt_hit ==
nullptr) {
3645 return Error::null();
3648 if (FLAG_verbose_debug) {
3649 OS::PrintErr(
">>> hit %" Pd
3651 " (func %s token %s address %#" Px " offset %#" Px ")\n",
3652 bpt_hit->
id(), cbpt_tostring,
3658 CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());
3659 SignalPausedEvent(top_frame, bpt_hit);
3662 HandleSteppingRequest(
true);
3663 ClearCachedStackTraces();
3666 return Thread::Current()->StealStickyError();
3676 while (bpt !=
nullptr) {
3684 bpt = breakpoints();
3685 while (bpt !=
nullptr) {
3686 if (bpt->
closure() != Instance::null() &&
3694 bpt = breakpoints();
3695 while (bpt !=
nullptr) {
3705void Debugger::PauseDeveloper(
const String& msg) {
3709 if (ignore_breakpoints_ || IsPaused()) {
3715 CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());
3721 SetResumeAction(kStepOut);
3722 HandleSteppingRequest();
3723 ClearCachedStackTraces();
3726void Debugger::NotifyIsolateCreated() {
3727 if (NeedsIsolateEvents()) {
3733#if !defined(DART_PRECOMPILED_RUNTIME)
3738 intptr_t column_number) {
3741 if (script.GetTokenLocation(start_of_line, &line, &col)) {
3742 return TokenPosition::Deserialize(start_of_line.
Pos() +
3743 (column_number - col));
3745 return TokenPosition::kNoSource;
3749void Debugger::NotifyDoneLoading() {
3750 if (latent_locations_ ==
nullptr) {
3754 auto thread = Thread::Current();
3755 auto isolate_group = thread->isolate_group();
3756 auto zone = thread->zone();
3757 Library& lib = Library::Handle(zone);
3758 Script& script = Script::Handle(zone);
3759 String& url = String::Handle(zone);
3763 GrowableObjectArray::Handle(isolate_group->object_store()->libraries());
3766 while (loc !=
nullptr) {
3768 bool found_match =
false;
3769 bool is_package = url.
StartsWith(Symbols::PackageScheme());
3770 for (intptr_t i = 0; i < libs.Length(); i++) {
3773 if (!script.IsNull()) {
3783 if (prev_loc ==
nullptr) {
3784 latent_locations_ = loc;
3786 prev_loc->set_next(loc);
3792 ASSERT(line_number >= 0);
3795 scripts.At(0).TokenRangeAtLine(line_number, &first_token_pos,
3800 Breakpoint* bpt = matched_loc->breakpoints();
3801 while (bpt !=
nullptr) {
3802 if (FLAG_verbose_debug) {
3803 OS::PrintErr(
"No code found at line %" Pd
3805 "dropping latent breakpoint %" Pd " in '%s'\n",
3818 GetBreakpointLocation(url, first_token_pos, -1, column_number);
3819 ASSERT(existing_loc ==
nullptr);
3820 if (existing_loc ==
nullptr) {
3824 this,
scripts, first_token_pos, last_token_pos, line_number,
3826 RegisterBreakpointLocation(unresolved_loc);
3829 Breakpoint* bpt = matched_loc->breakpoints();
3830 unresolved_loc->set_breakpoints(bpt);
3831 matched_loc->set_breakpoints(
nullptr);
3832 while (bpt !=
nullptr) {
3834 if (FLAG_verbose_debug) {
3836 "Converted latent breakpoint "
3837 "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
3838 bpt->
id(), url.
ToCString(), line_number, column_number);
3842 group_debugger()->SyncBreakpointLocation(unresolved_loc);
3859 if (FLAG_verbose_debug) {
3861 while (bpt !=
nullptr) {
3863 "No match found for latent breakpoint id "
3864 "%" Pd " with url '%s'\n",
3876bool GroupDebugger::HasActiveBreakpoint(
uword pc) {
3879 return (cbpt !=
nullptr) && (cbpt->
IsEnabled());
3884 while (cbpt !=
nullptr) {
3885 if (cbpt->
pc() == breakpoint_address) {
3888 cbpt = cbpt->next();
3895 uword breakpoint_address,
3897 ASSERT(pcbpt !=
nullptr);
3899 *pcbpt = code_breakpoints_;
3900 while (*pcbpt !=
nullptr) {
3901 if ((*pcbpt)->pc() == breakpoint_address) {
3902 return (*pcbpt)->FindBreakpointForDebugger(debugger);
3904 *pcbpt = (*pcbpt)->next();
3909void GroupDebugger::RegisterCodeBreakpoint(
CodeBreakpoint* cbpt) {
3910 ASSERT(cbpt->next() ==
nullptr);
3911 DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
3912 Thread::Current()->IsInStoppedMutatorsScope());
3913 cbpt->set_next(code_breakpoints_);
3914 code_breakpoints_ = cbpt;
3917CodePtr GroupDebugger::GetPatchedStubAddress(
uword breakpoint_address) {
3920 if (cbpt !=
nullptr) {
3924 return Code::null();
3929 group_debugger()->breakpoint_locations_lock());
3931 if (FLAG_verbose_debug) {
3932 OS::PrintErr(
"Setting breakpoint %" Pd " to state: %s\n", bpt->
id(),
3933 enable ?
"enabled" :
"disabled");
3936 group_debugger()->SyncBreakpointLocation(bpt->
bpt_location());
3944void Debugger::RemoveBreakpoint(intptr_t bp_id) {
3946 group_debugger()->breakpoint_locations_lock());
3947 if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) {
3950 RemoveBreakpointFromTheList(bp_id, &latent_locations_);
3956bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id,
3960 while (curr_loc !=
nullptr) {
3962 Breakpoint* curr_bpt = curr_loc->breakpoints();
3963 while (curr_bpt !=
nullptr) {
3964 if (curr_bpt->
id() == bp_id) {
3965 if (prev_bpt ==
nullptr) {
3966 curr_loc->set_breakpoints(curr_bpt->
next());
3973 SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
3978 if (pause_event_ !=
nullptr && pause_event_->breakpoint() == curr_bpt) {
3979 pause_event_->set_breakpoint(
nullptr);
3986 if (curr_loc->breakpoints() ==
nullptr) {
3987 if (prev_loc ==
nullptr) {
3988 *list = curr_loc->next();
3990 prev_loc->set_next(curr_loc->next());
3997 group_debugger()->UnlinkCodeBreakpoints(curr_loc);
3999 group_debugger()->UnregisterBreakpointLocation(curr_loc);
4000 BreakpointLocation* next_loc = curr_loc->next();
4002 curr_loc = next_loc;
4010 prev_bpt = curr_bpt;
4011 curr_bpt = curr_bpt->
next();
4013 prev_loc = curr_loc;
4014 curr_loc = curr_loc->next();
4021 DEBUG_ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter() ||
4022 Thread::Current()->IsInStoppedMutatorsScope());
4023 breakpoint_locations_.Add(location);
4027 ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter());
4028 for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
4029 if (breakpoint_locations_.At(i) == location) {
4030 breakpoint_locations_.EraseAt(i);
4041 ASSERT(bpt_location !=
nullptr);
4044 while (curr_bpt !=
nullptr) {
4047 needs_breakpoint_cleanup_ =
true;
4049 curr_bpt = curr_bpt->next();
4055void GroupDebugger::RemoveUnlinkedCodeBreakpoints() {
4056 DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
4057 Thread::Current()->IsInStoppedMutatorsScope());
4060 while (curr_bpt !=
nullptr) {
4062 if (prev_bpt ==
nullptr) {
4063 code_breakpoints_ = code_breakpoints_->
next();
4065 prev_bpt->set_next(curr_bpt->next());
4067 CodeBreakpoint* temp_bpt = curr_bpt;
4068 curr_bpt = curr_bpt->next();
4071 prev_bpt = curr_bpt;
4072 curr_bpt = curr_bpt->next();
4075 needs_breakpoint_cleanup_ =
false;
4078BreakpointLocation* Debugger::GetResolvedBreakpointLocation(
4079 const String& script_url,
4080 TokenPosition code_token_pos) {
4081 BreakpointLocation* loc = breakpoint_locations_;
4082 String& loc_url = String::Handle();
4083 while (loc !=
nullptr) {
4084 loc_url = loc->url();
4085 if (script_url.Equals(loc_url) && loc->code_token_pos_ == code_token_pos) {
4093BreakpointLocation* Debugger::GetBreakpointLocation(
4094 const String& script_url,
4095 TokenPosition token_pos,
4096 intptr_t requested_line,
4097 intptr_t requested_column,
4098 TokenPosition code_token_pos) {
4099 BreakpointLocation* loc = breakpoint_locations_;
4100 String& loc_url = String::Handle();
4101 while (loc !=
nullptr) {
4102 loc_url = loc->url();
4103 if (script_url.Equals(loc_url) &&
4104 (!token_pos.IsReal() || (loc->token_pos() == token_pos)) &&
4105 ((requested_line == -1) ||
4106 (loc->requested_line_number_ == requested_line)) &&
4107 ((requested_column == -1) ||
4108 (loc->requested_column_number_ == requested_column)) &&
4109 (!code_token_pos.IsReal() ||
4110 (loc->code_token_pos_ == code_token_pos))) {
4119 Breakpoint* bpt = GetBreakpointByIdInTheList(
id, breakpoint_locations_);
4120 if (bpt !=
nullptr) {
4123 return GetBreakpointByIdInTheList(
id, latent_locations_);
4126Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t
id,
4129 while (loc !=
nullptr) {
4131 while (bpt !=
nullptr) {
4132 if (bpt->
id() ==
id) {
4142void Debugger::AsyncStepInto(
const Closure& awaiter) {
4143 Zone* zone = Thread::Current()->zone();
4145 auto& suspend_state = SuspendState::Handle(zone);
4146 if (StackTraceUtils::GetSuspendState(awaiter, &suspend_state)) {
4147 const auto& function_data =
4148 Object::Handle(zone, suspend_state.function_data());
4149 SetBreakpointAtResumption(function_data);
4151 SetBreakpointAtActivation(awaiter,
true);
4156void Debugger::Continue() {
4157 SetResumeAction(kContinue);
4158 ResetSteppingFramePointer();
4159 NotifySingleStepping(
false);
4166 String& bpt_url = String::Handle();
4167 while (loc !=
nullptr) {
4168 bpt_url = loc->
url();
4176 loc =
new BreakpointLocation(
this, url, line, column);
4177 loc->set_next(latent_locations_);
4178 latent_locations_ = loc;
4182void Debugger::RegisterBreakpointLocationUnsafe(BreakpointLocation* loc) {
4184 group_debugger()->breakpoint_locations_lock()->IsCurrentThreadWriter() ||
4185 Thread::Current()->IsInStoppedMutatorsScope());
4186 ASSERT(loc->next() ==
nullptr);
4187 loc->set_next(breakpoint_locations_);
4188 breakpoint_locations_ = loc;
4189 group_debugger()->RegisterBreakpointLocation(loc);
4192void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
4193 auto thread = Thread::Current();
4194 if (thread->IsInStoppedMutatorsScope()) {
4195 RegisterBreakpointLocationUnsafe(loc);
4197 SafepointWriteRwLocker sl(thread,
4198 group_debugger()->breakpoint_locations_lock());
4199 RegisterBreakpointLocationUnsafe(loc);
static float next(float f)
static float prev(float f)
#define DEBUG_ASSERT(cond)
#define RELEASE_ASSERT(cond)
StringPtr QualifiedFunctionName()
const Context & GetSavedCurrentContext()
Relation CompareTo(uword other_fp) const
void PrintToJSONObject(JSONObject *jsobj)
const Function & function() const
ArrayPtr GetLocalVariables()
ActivationFrame(uword pc, uword fp, uword sp, const Code &code, const Array &deopt_frame, intptr_t deopt_frame_offset)
ObjectPtr GetParameter(intptr_t index)
bool IsDebuggable() const
ObjectPtr GetSuspendableFunctionData()
bool HandlesException(const Instance &exc_obj)
intptr_t NumLocalVariables()
ObjectPtr GetSuspendStateVar()
ObjectPtr EvaluateCompiledExpression(const ExternalTypedData &kernel_data, const Array &arguments, const Array &type_definitions, const TypeArguments &type_arguments)
TypeArgumentsPtr BuildParameters(const GrowableObjectArray ¶m_names, const GrowableObjectArray ¶m_values, const GrowableObjectArray &type_params_names, const GrowableObjectArray &type_params_bounds, const GrowableObjectArray &type_params_defaults)
const Code & code() const
bool IsRewindable() const
void VariableAt(intptr_t i, String *name, TokenPosition *declaration_token_pos, TokenPosition *visible_start_token_pos, TokenPosition *visible_end_token_pos, Object *value)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
ObjectPtr At(intptr_t index) const
void SetAt(intptr_t index, const Object &value) const
TokenPosition token_pos() const
TokenPosition end_token_pos() const
intptr_t requested_column_number() const
Breakpoint * AddSingleShot(Debugger *dbg)
bool EnsureIsResolved(const Function &target_function, TokenPosition exact_token_pos)
Breakpoint * AddRepeated(Debugger *dbg)
BreakpointLocation(Debugger *debugger, const GrowableHandlePtrArray< const Script > &scripts, TokenPosition token_pos, TokenPosition end_token_pos, intptr_t requested_line_number, intptr_t requested_column_number)
Breakpoint * AddBreakpoint(Debugger *dbg, const Closure &closure, bool single_shot)
void GetCodeLocation(Script *script, TokenPosition *token_pos) const
intptr_t requested_line_number() const
ClosurePtr closure() const
BreakpointLocation * bpt_location() const
bool is_single_shot() const
Breakpoint * next() const
void set_bpt_location(BreakpointLocation *new_bpt_location)
void set_next(Breakpoint *n)
void PrintJSON(JSONStream *stream)
static intptr_t CidFromTopLevelIndex(intptr_t index)
LibraryPtr library() const
static void ForAllClosureFunctions(std::function< bool(const Function &)> callback)
FunctionPtr function() const
const char * ToCString() const
CodeBreakpoint(const Code &code, BreakpointLocation *loc, uword pc, UntaggedPcDescriptors::Kind kind)
CodePtr OrigStubAddress() const
bool HasNoBreakpointLocations()
bool HasBreakpointLocation(BreakpointLocation *breakpoint_location)
bool FindAndDeleteBreakpointLocation(BreakpointLocation *breakpoint_location)
PcDescriptorsPtr pc_descriptors() const
bool is_optimized() const
LocalVarDescriptorsPtr GetLocalVarDescriptors() const
void Disassemble(DisassemblyFormatter *formatter=nullptr) const
uword PayloadStart() const
static ErrorPtr EnsureUnoptimizedCode(Thread *thread, const Function &function)
void Dump(int indent=0) const
ActivationFrame * GetHandlerFrame(const Instance &exc_obj) const
static DebuggerStackTrace * Collect()
ActivationFrame * FrameAt(int i) const
bool has_async_catch_error() const
static DebuggerStackTrace * CollectAsyncAwaiters()
Dart_ExceptionPauseInfo GetExceptionPauseInfo() const
Debugger(Isolate *isolate)
bool SetResumeAction(ResumeAction action, intptr_t frame_index=1, const char **error=nullptr)
void PrintBreakpointsToJSONArray(JSONArray *jsarr) const
Isolate * isolate() const
void PrintSettingsToJSONObject(JSONObject *jsobj) const
DebuggerStackTrace * StackTrace()
ErrorPtr PauseInterrupted()
ErrorPtr PausePostRequest()
@ kStepOverAsyncSuspension
void SetBreakpointAtResumption(const Object &function_data)
static bool IsDebuggable(const Function &func)
intptr_t MaterializeDeferredObjects()
ArrayPtr DestFrameAsArray()
static constexpr intptr_t kNone
static DART_NORETURN void PropagateError(const Error &error)
const char * ToFullyQualifiedCString() const
bool IsSuspendableFunction() const
FunctionPtr parent_function() const
intptr_t NumTypeArguments() const
TokenPosition token_pos() const
bool HasOptimizedCode() const
intptr_t NumTypeParameters() const
bool IsAsyncFunction() const
bool IsAsyncGenerator() const
CodePtr unoptimized_code() const
TypeParametersPtr type_parameters() const
intptr_t num_fixed_parameters() const
UntaggedFunction::Kind kind() const
TokenPosition end_token_pos() const
GroupDebugger(IsolateGroup *isolate_group)
bool HasCodeBreakpointInFunction(const Function &func)
void UnregisterBreakpointLocation(BreakpointLocation *location)
bool HasCodeBreakpointInFunctionUnsafe(const Function &func)
bool HasBreakpointInCode(const Code &code)
SafepointRwLock * code_breakpoints_lock()
void UnlinkCodeBreakpoints(BreakpointLocation *bpt_location)
void Add(const Object &value, Heap::Space space=Heap::kNew) const
void SetLength(intptr_t value) const
ObjectPtr At(intptr_t index) const
void SetAt(intptr_t index, const Object &value) const
void Grow(intptr_t new_capacity, Heap::Space space=Heap::kNew) const
bool IsInstanceOf(const AbstractType &other, const TypeArguments &other_instantiator_type_arguments, const TypeArguments &other_function_type_arguments) const
ObjectPtr EvaluateCompiledExpression(const Class &klass, const ExternalTypedData &kernel_buffer, const Array &type_definitions, const Array &arguments, const TypeArguments &type_arguments) const
ClassTable * class_table() const
void set_deopt_context(DeoptContext *value)
static bool IsSystemIsolate(const Isolate *isolate)
static Isolate * Current()
Debugger * debugger() const
IsolateGroup * group() const
void set_has_attempted_stepping(bool value)
void AddValue(bool b) const
void void void AddLocation(const Script &script, TokenPosition token_pos, TokenPosition end_token_pos=TokenPosition::kNoSource) const
void AddProperty(const char *name, bool b) const
void AddUnresolvedLocation(const BreakpointLocation *bpt_loc) const
void AddFixedServiceId(const char *format,...) const PRINTF_ATTRIBUTE(2
ScriptPtr LookupScript(const String &url, bool useResolvedUri=false) const
void EnsureTopLevelClassIsFinalized() const
bool IsDebuggable() const
StringPtr GetName(intptr_t var_index) const
void GetInfo(intptr_t var_index, UntaggedLocalVarDescriptors::VarInfo *info) const
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static DART_NORETURN void Abort()
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
void VisitPointer(ObjectPtr *p)
virtual const char * ToCString() const
intptr_t YieldIndex() const
TokenPosition TokenPos() const
intptr_t TryIndex() const
UntaggedPcDescriptors::Kind Kind() const
static StreamInfo isolate_stream
static void HandleEvent(ServiceEvent *event, bool enter_safepoint=true)
static StreamInfo debug_stream
@ kNoCrossThreadIteration
uword PcOffsetAtFrame(intptr_t frame_index) const
ObjectPtr CodeAtFrame(intptr_t frame_index) const
static const char * ScrubName(const String &name, bool is_extension=false)
bool Equals(const String &str) const
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
uint16_t CharAt(intptr_t index) const
bool StartsWith(const String &other) const
static const char * ToCString(Thread *thread, StringPtr ptr)
static constexpr intptr_t kSuspendStateVarIndex
static const String & This()
static StringPtr New(Thread *thread, const char *cstr)
static Thread * Current()
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Isolate * isolate() const
bool IsInStoppedMutatorsScope() const
bool IsDebugPause() const
const char * ToCString() const
static TokenPosition Deserialize(int32_t value)
bool IsWithin(const TokenPosition &a, const TokenPosition &b) const
void SetTypeAt(intptr_t index, const AbstractType &value) const
StringPtr NameAt(intptr_t index) const
AbstractTypePtr DefaultAt(intptr_t index) const
AbstractTypePtr BoundAt(intptr_t index) const
char * PrintToString(const char *format,...) PRINTF_ATTRIBUTE(2
char * MakeCopyOfString(const char *str)
#define THR_Print(format,...)
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
#define DECLARE_FLAG(type, name)
#define DEFINE_FLAG(type, name, default_value, comment)
Dart_NativeFunction function
#define RELOAD_OPERATION_SCOPE(thread_expr)
static bool IsPrivateVariableName(const String &var_name)
void SetBreakpoint(Dart_NativeArguments args)
static TokenPosition ResolveBreakpointPos(const Function &func, TokenPosition requested_token_pos, TokenPosition last_token_pos, intptr_t requested_column, TokenPosition exact_token_pos)
void DeoptimizeFunctionsOnStack()
static TokenPosition FindExactTokenPosition(const Script &script, TokenPosition start_of_line, intptr_t column_number)
static DART_FORCE_INLINE intptr_t LocalVarIndex(intptr_t fp_offset, intptr_t var_index)
static bool IsSyntheticVariableName(const String &var_name)
static bool IsImplicitFunction(const Function &func)
DART_EXPORT bool IsNull(Dart_Handle object)
const char *const class_name
static DART_FORCE_INLINE uword ParamAddress(uword fp, intptr_t reverse_index)
constexpr uword kUwordMax
static ArrayPtr DeoptimizeToArray(Thread *thread, StackFrame *frame, const Code &code)
static ActivationFrame * TopDartFrame()
static bool FunctionOverlaps(const Function &func, const String &script_url, TokenPosition token_pos, TokenPosition end_token_pos)
static bool CanRewindFrame(intptr_t frame_index, const char **error)
static bool IsAtAsyncJump(ActivationFrame *top_frame)
FrameLayout runtime_frame_layout
static DART_FORCE_INLINE ObjectPtr GetVariableValue(uword addr)
static uword LookupRewindPc(const Code &code, uword return_address)
static DART_FORCE_INLINE uword LocalVarAddress(uword fp, intptr_t index)
static void RefineBreakpointPos(const Script &script, TokenPosition pos, TokenPosition next_closest_token_position, TokenPosition requested_token_pos, TokenPosition last_token_pos, intptr_t requested_column, TokenPosition exact_token_pos, TokenPosition *best_fit_pos, intptr_t *best_column, intptr_t *best_line)
static DART_FORCE_INLINE bool IsCalleeFrameOf(uword fp, uword other_fp)
static void InvokeEventHandler(ServiceEvent *event)
const uint8_t kSafepointKind
static const char * QualifiedFunctionName(const Function &func)
static FunctionPtr FindInnermostClosure(Zone *zone, const Function &function, TokenPosition token_pos)
static constexpr intptr_t kInvalidTryIndex
static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace *stack, intptr_t frame_index)
static void UpdateBestFit(Function *best_fit, const Function &func)
@ kPauseOnUnhandledExceptions
static bool IsFunctionVisible(const Function &function)
static ActivationFrame * CollectDartFrame(uword pc, StackFrame *frame, const Code &code, const Array &deopt_frame, intptr_t deopt_frame_offset)
intptr_t FrameSlotForVariableIndex(intptr_t index) const
TokenPosition declaration_pos
#define TIMELINE_DURATION(thread, stream, name)