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())),
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) {
359 if (bpt ==
nullptr) {
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();
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;
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_));
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,
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();
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) {
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)
1656 nullptr,
true,
false );
1661 const Array& dest_frame =
1665 delete deopt_context;
1667 return dest_frame.
ptr();
1672 Thread* thread = Thread::Current();
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()) {
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();
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()) {
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();
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()) {
1833 if (
code.is_optimized() && ex_trace.expand_inlined()) {
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_;
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());
2076 Zone* zone = Thread::Current()->zone();
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) {
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());
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) {
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();
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) &&
2304 Class& cls = Class::Handle(zone);
2305 Array& functions = Array::Handle(zone);
2306 Function&
function = Function::Handle(zone);
2307 Array& fields = Array::Handle(zone);
2308 Field& field = Field::Handle(zone);
2310 const ClassTable& class_table = *isolate_->group()->class_table();
2311 const intptr_t num_classes = class_table.NumCids();
2312 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
2313 for (intptr_t
i = 1;
i < num_classes + num_tlc_classes;
i++) {
2314 const intptr_t
cid =
2316 : ClassTable::CidFromTopLevelIndex(
i - num_classes);
2317 if (class_table.HasValidClassAt(
cid)) {
2318 cls = class_table.At(
cid);
2323 if (!cls.is_finalized()) {
2329 functions = cls.current_functions();
2330 if (!functions.IsNull()) {
2331 const intptr_t num_functions = functions.Length();
2332 for (intptr_t
pos = 0;
pos < num_functions;
pos++) {
2335 bool function_added =
false;
2337 function.token_pos() == start_pos &&
2338 function.end_token_pos() == end_pos &&
2341 function_added =
true;
2343 if (function_added &&
function.HasImplicitClosureFunction()) {
2351 fields = cls.fields();
2352 if (!fields.IsNull()) {
2353 const intptr_t num_fields = fields.Length();
2354 for (intptr_t
pos = 0;
pos < num_fields;
pos++) {
2355 field ^= fields.At(
pos);
2357 if (field.Script() !=
script.ptr()) {
2360 if (!field.has_nontrivial_initializer()) {
2363 function = field.EnsureInitializerFunction();
2366 function.token_pos() == start_pos &&
2367 function.end_token_pos() == end_pos &&
2379 if (best_fit->
IsNull()) {
2380 *best_fit = func.
ptr();
2385 *best_fit = func.
ptr();
2393bool Debugger::FindBestFit(
const Script&
script,
2394 TokenPosition token_pos,
2395 TokenPosition last_token_pos,
2396 Function* best_fit) {
2397 auto thread = Thread::Current();
2398 auto isolate_group = thread->isolate_group();
2399 Zone* zone = thread->zone();
2400 Class& cls = Class::Handle(zone);
2407 const GrowableObjectArray&
libs = GrowableObjectArray::Handle(
2408 zone, isolate_group->object_store()->libraries());
2409 Library& lib = Library::Handle(zone);
2410 for (
int i = 0;
i <
libs.Length();
i++) {
2413 const Array&
scripts = Array::Handle(zone, lib.LoadedScripts());
2414 bool lib_has_script =
false;
2415 for (intptr_t j = 0; j <
scripts.Length(); j++) {
2417 lib_has_script =
true;
2421 if (!lib_has_script) {
2425 if (!lib.IsDebuggable()) {
2426 if (FLAG_verbose_debug) {
2427 OS::PrintErr(
"Library '%s' has been marked as non-debuggable\n",
2433 const String& script_url = String::Handle(zone,
script.url());
2434 ClosureFunctionsCache::ForAllClosureFunctions([&](
const Function& fun) {
2435 if (fun.script() ==
script.ptr() &&
2443 if (!best_fit->IsNull()) {
2450 Array& functions = Array::Handle(zone);
2451 Function&
function = Function::Handle(zone);
2452 Array& fields = Array::Handle(zone);
2453 Field& field = Field::Handle(zone);
2454 Error&
error = Error::Handle(zone);
2456 const ClassTable& class_table = *isolate_->group()->class_table();
2457 const intptr_t num_classes = class_table.NumCids();
2458 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
2459 for (intptr_t
i = 1;
i < num_classes + num_tlc_classes;
i++) {
2460 const intptr_t
cid =
2462 : ClassTable::CidFromTopLevelIndex(
i - num_classes);
2463 if (!class_table.HasValidClassAt(
cid)) {
2466 cls = class_table.At(
cid);
2469 if (cls.library() != lib.ptr()) {
2473 error = cls.EnsureIsFinalized(Thread::Current());
2474 if (!
error.IsNull()) {
2481 functions = cls.current_functions();
2482 if (!functions.IsNull()) {
2483 const intptr_t num_functions = functions.Length();
2484 for (intptr_t
pos = 0;
pos < num_functions;
pos++) {
2505 fields = cls.fields();
2506 if (!fields.IsNull()) {
2507 const intptr_t num_fields = fields.Length();
2508 for (intptr_t
pos = 0;
pos < num_fields;
pos++) {
2509 TokenPosition
start = TokenPosition::kNoSource;
2510 TokenPosition
end = TokenPosition::kNoSource;
2511 field ^= fields.At(
pos);
2513 if (field.Script() !=
script.ptr()) {
2518 if (!field.has_nontrivial_initializer()) {
2521 start = field.token_pos();
2522 end = field.end_token_pos();
2523 if (token_pos.IsWithin(
start,
end) ||
2524 start.IsWithin(token_pos, last_token_pos)) {
2525 *best_fit = field.InitializerFunction();
2539BreakpointLocation* Debugger::SetCodeBreakpoints(
2540 const GrowableHandlePtrArray<const Script>&
scripts,
2541 TokenPosition token_pos,
2542 TokenPosition last_token_pos,
2543 intptr_t requested_line,
2544 intptr_t requested_column,
2545 TokenPosition exact_token_pos,
2546 const GrowableObjectArray& functions) {
2548 (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
2549 (requested_column > -1 && exact_token_pos != TokenPosition::kNoSource));
2551 Function&
function = Function::Handle();
2554 function, token_pos, last_token_pos, requested_column, exact_token_pos);
2555 if (!breakpoint_pos.IsReal()) {
2558 const String& script_url = String::Handle(
scripts.At(0).url());
2559 BreakpointLocation* loc =
2560 GetResolvedBreakpointLocation(script_url, breakpoint_pos);
2561 if (loc ==
nullptr) {
2563 loc = GetBreakpointLocation(script_url, token_pos, requested_line,
2566 if (loc ==
nullptr) {
2567 loc =
new BreakpointLocation(
this,
scripts, breakpoint_pos, breakpoint_pos,
2568 requested_line, requested_column);
2569 RegisterBreakpointLocation(loc);
2573 if (loc->IsResolved()) {
2576 loc->SetResolved(
function, breakpoint_pos);
2579 Function& func = Function::Handle();
2580 const intptr_t num_functions = functions.Length();
2581 for (intptr_t
i = 0;
i < num_functions;
i++) {
2582 func ^= functions.At(
i);
2584 group_debugger()->MakeCodeBreakpointAt(func, loc);
2586 if (FLAG_verbose_debug) {
2587 intptr_t line_number = -1;
2588 intptr_t column_number = -1;
2589 scripts.At(0).GetTokenLocation(breakpoint_pos, &line_number,
2591 OS::PrintErr(
"Resolved code breakpoint for function '%s' at line %" Pd
2593 func.ToFullyQualifiedCString(), line_number, column_number);
2598#if !defined(DART_PRECOMPILED_RUNTIME)
2600 TokenPosition start_of_line,
2601 intptr_t column_number);
2605 TokenPosition token_pos,
2606 TokenPosition last_token_pos,
2607 intptr_t requested_line,
2608 intptr_t requested_column,
2610 GrowableHandlePtrArray<const Script>
scripts(Thread::Current()->zone(), 1);
2617 const GrowableHandlePtrArray<const Script>&
scripts,
2618 TokenPosition token_pos,
2619 TokenPosition last_token_pos,
2620 intptr_t requested_line,
2621 intptr_t requested_column,
2623 Function& func = Function::Handle();
2626 if (!FindBestFit(
script, token_pos, last_token_pos, &func)) {
2632 if (!func.token_pos().IsReal()) {
2637 if (!func.IsNull()) {
2643 GrowableObjectArray& code_functions =
2644 GrowableObjectArray::Handle(GrowableObjectArray::New());
2645 FindCompiledFunctions(
scripts, func.token_pos(), func.end_token_pos(),
2648 if (code_functions.Length() > 0) {
2653 TokenPosition exact_token_pos = TokenPosition::kNoSource;
2654#if !defined(DART_PRECOMPILED_RUNTIME)
2655 if (token_pos != last_token_pos && requested_column >= 0) {
2660 BreakpointLocation* loc =
nullptr;
2664 RunWithStoppedDeoptimizedWorld([&] {
2665 loc = SetCodeBreakpoints(
scripts, token_pos, last_token_pos,
2666 requested_line, requested_column,
2667 exact_token_pos, code_functions);
2669 if (loc !=
nullptr) {
2677 if (FLAG_verbose_debug) {
2678 intptr_t line_number = -1;
2679 intptr_t column_number = -1;
2680 script.GetTokenLocation(token_pos, &line_number, &column_number);
2681 if (func.IsNull()) {
2683 "Registering pending breakpoint for "
2684 "an uncompiled function literal at line %" Pd " col %" Pd "\n",
2685 line_number, column_number);
2688 "Registering pending breakpoint for "
2689 "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
2690 func.ToFullyQualifiedCString(), line_number, column_number);
2693 const String& script_url = String::Handle(
script.url());
2694 BreakpointLocation* loc = GetBreakpointLocation(
2695 script_url, token_pos, requested_line, requested_column);
2696 if (loc ==
nullptr) {
2697 loc =
new BreakpointLocation(
this,
scripts, token_pos, last_token_pos,
2698 requested_line, requested_column);
2699 RegisterBreakpointLocation(loc);
2710 while (cbpt !=
nullptr) {
2718 cbpt = cbpt->next();
2725 if (!target_function.is_debuggable()) {
2731 -1 , target_function);
2732 if (bpt_location ==
nullptr) {
2762 while (loc !=
nullptr) {
2764 while (bpt !=
nullptr) {
2776void Debugger::SetBreakpointAtResumption(
const Object& function_data) {
2778 ASSERT(function_data.IsInstance());
2779 breakpoints_at_resumption_.Add(function_data.
ptr());
2780 isolate_->set_has_resumption_breakpoints(
true);
2783void Debugger::ResumptionBreakpoint() {
2784 ASSERT(!breakpoints_at_resumption_.is_empty());
2785 ASSERT(isolate_->has_resumption_breakpoints());
2789 const auto& function_data =
2792 for (intptr_t
i = 0, n = breakpoints_at_resumption_.length();
i < n; ++
i) {
2793 if (breakpoints_at_resumption_[
i] == function_data.ptr()) {
2794 breakpoints_at_resumption_.RemoveAt(
i);
2795 if (breakpoints_at_resumption_.is_empty()) {
2796 isolate_->set_has_resumption_breakpoints(
false);
2798 if (FLAG_verbose_debug) {
2800 "ResumptionBreakpoint - hit a breakpoint, continue single "
2803 EnterSingleStepMode();
2810 intptr_t line_number) {
2814 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
2817 BreakpointLocationAtLineCol(script_url, line_number, -1 );
2818 if (loc !=
nullptr) {
2825 intptr_t line_number,
2826 intptr_t column_number) {
2830 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
2833 BreakpointLocationAtLineCol(script_url, line_number, column_number);
2834 if (loc !=
nullptr) {
2841 const String& script_url,
2842 intptr_t line_number,
2843 intptr_t column_number) {
2844 Zone* zone = Thread::Current()->zone();
2845 Library& lib = Library::Handle(zone);
2848 isolate_->group()->object_store()->libraries());
2849 bool is_package = script_url.
StartsWith(Symbols::PackageScheme());
2850 bool is_dart_colon = script_url.
StartsWith(Symbols::DartScheme());
2851 Script& script_for_lib = Script::Handle(zone);
2852 for (intptr_t
i = 0;
i <
libs.Length();
i++) {
2858 bool useResolvedUri = !is_package && !is_dart_colon;
2859 script_for_lib = lib.
LookupScript(script_url, useResolvedUri);
2860 if (!script_for_lib.
IsNull()) {
2868 GetLatentBreakpoint(script_url, line_number, column_number);
2869 if (FLAG_verbose_debug) {
2871 "Set latent breakpoint in url '%s' at "
2872 "line %" Pd " col %" Pd "\n",
2873 script_url.
ToCString(), line_number, column_number);
2880 scripts.At(0).TokenRangeAtLine(line_number, &first_token_idx,
2882 if (!first_token_idx.
IsReal()) {
2884 if (FLAG_verbose_debug) {
2885 OS::PrintErr(
"Script '%s' does not contain line number %" Pd "\n",
2889 }
else if (!last_token_idx.
IsReal()) {
2891 if (FLAG_verbose_debug) {
2892 OS::PrintErr(
"No executable code at line %" Pd " in '%s'\n", line_number,
2899 ASSERT(first_token_idx <= last_token_idx);
2900 while ((loc ==
nullptr) && (first_token_idx <= last_token_idx)) {
2902 column_number, Function::Handle());
2903 first_token_idx = first_token_idx.
Next();
2905 if ((loc ==
nullptr) && FLAG_verbose_debug) {
2906 OS::PrintErr(
"No executable code at line %" Pd " in '%s'\n", line_number,
2919 const Script& outer_origin = Script::Handle(zone,
function.script());
2921 Function& best_fit = Function::Handle(zone);
2922 ClosureFunctionsCache::ForAllClosureFunctions([&](
const Function&
closure) {
2927 if (closure_end.
IsReal() && (
function.end_token_pos() > closure_end) &&
2929 (closure_start > func_start)) &&
2930 token_pos.
IsWithin(closure_start, closure_end) &&
2932 UpdateBestFit(&best_fit, closure);
2936 return best_fit.
ptr();
2939bool GroupDebugger::EnsureLocationIsInFunction(
Zone* zone,
2942 const String& url = String::Handle(zone, location->
url());
2949#if !defined(DART_PRECOMPILED_RUNTIME)
2962 if (!inner_function.
IsNull()) {
2963 if (FLAG_verbose_debug) {
2965 "Pending breakpoint remains unresolved in "
2966 "inner function '%s'\n",
2982 auto thread = Thread::Current();
2983 auto zone = thread->zone();
2993 for (intptr_t
i = 0;
i < breakpoint_locations_.length();
i++) {
2995 if (EnsureLocationIsInFunction(zone, resolved_function, location)) {
3005#if !defined(DART_PRECOMPILED_RUNTIME)
3014 if (FLAG_verbose_debug) {
3016 while (bpt !=
nullptr) {
3017 OS::PrintErr(
"Setting breakpoint %" Pd " for %s '%s'\n", bpt->
id(),
3018 function.IsClosureFunction() ?
"closure" :
"function",
3019 function.ToFullyQualifiedCString());
3023 MakeCodeBreakpointAt(
function, location);
3030 while (cbpt !=
nullptr) {
3031 cbpt->VisitObjectPointers(visitor);
3032 cbpt = cbpt->next();
3038 ASSERT(visitor !=
nullptr);
3040 while (loc !=
nullptr) {
3041 loc->VisitObjectPointers(visitor);
3044 loc = latent_locations_;
3045 while (loc !=
nullptr) {
3046 loc->VisitObjectPointers(visitor);
3049 for (intptr_t
i = 0, n = breakpoints_at_resumption_.length();
i < n; ++
i) {
3056 ASSERT(!ignore_breakpoints_);
3059 pause_event_ =
event;
3060 pause_event_->UpdateTimestamp();
3066 Thread* thread = Thread::Current();
3071 Service::HandleEvent(
event);
3075 isolate_->PauseEventHandler();
3079 const Error&
error = Error::Handle(Thread::Current()->sticky_error());
3081 error.IsUnhandledException());
3084 if (!
error.IsUnwindError()) {
3085 ServiceEvent resume_event(
event->isolate(), ServiceEvent::kResume);
3086 resume_event.set_top_frame(
event->top_frame());
3087 Service::HandleEvent(&resume_event);
3091 group_debugger()->Pause();
3092 pause_event_ =
nullptr;
3097 if (needs_breakpoint_cleanup_) {
3098 RemoveUnlinkedCodeBreakpoints();
3102void Debugger::EnterSingleStepMode() {
3103 ResetSteppingFramePointer();
3104 NotifySingleStepping(
true);
3107void Debugger::ResetSteppingFramePointer() {
3111void Debugger::SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
3112 if (stack_trace->Length() > 0) {
3113 stepping_fp_ = stack_trace->FrameAt(0)->fp();
3119void Debugger::HandleSteppingRequest(
bool skip_next_step ) {
3120 ResetSteppingFramePointer();
3121 if (resume_action_ == kStepInto) {
3127 NotifySingleStepping(
true);
3128 skip_next_step_ = skip_next_step;
3129 if (FLAG_verbose_debug) {
3130 OS::PrintErr(
"HandleSteppingRequest - kStepInto\n");
3132 }
else if (resume_action_ == kStepOver) {
3133 NotifySingleStepping(
true);
3134 skip_next_step_ = skip_next_step;
3135 SetSyncSteppingFramePointer(stack_trace_);
3136 if (FLAG_verbose_debug) {
3137 OS::PrintErr(
"HandleSteppingRequest - kStepOver stepping_fp=%" Px "\n",
3140 }
else if (resume_action_ == kStepOut) {
3142 if (async_awaiter_stack_trace_ !=
nullptr &&
3143 async_awaiter_stack_trace_->Length() > 2 &&
3144 async_awaiter_stack_trace_->FrameAt(1)->kind() ==
3145 ActivationFrame::kAsyncSuspensionMarker) {
3146 auto awaiter_frame = async_awaiter_stack_trace_->FrameAt(2);
3147 AsyncStepInto(awaiter_frame->closure());
3148 if (FLAG_verbose_debug) {
3149 OS::PrintErr(
"HandleSteppingRequest - continue to async awaiter %s\n",
3150 Function::Handle(awaiter_frame->closure().function())
3151 .ToFullyQualifiedCString());
3157 NotifySingleStepping(
true);
3159 for (intptr_t
i = 1;
i < stack_trace_->Length();
i++) {
3160 ActivationFrame*
frame = stack_trace_->FrameAt(
i);
3161 if (
frame->IsDebuggable()) {
3162 stepping_fp_ =
frame->fp();
3166 if (FLAG_verbose_debug) {
3167 OS::PrintErr(
"HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
3169 }
else if (resume_action_ == kStepRewind) {
3170 if (FLAG_trace_rewind) {
3171 OS::PrintErr(
"Rewinding to frame %" Pd "\n", resume_frame_index_);
3173 "-------------------------\n"
3174 "All frames...\n\n");
3175 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
3177 StackFrameIterator::kNoCrossThreadIteration);
3178 StackFrame*
frame = iterator.NextFrame();
3180 while ((
frame !=
nullptr)) {
3181 OS::PrintErr(
"#%04" Pd " %s\n", num++,
frame->ToCString());
3182 frame = iterator.NextFrame();
3185 RewindToFrame(resume_frame_index_);
3190void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
3191 DebuggerStackTrace* async_awaiter_stack_trace) {
3192 ASSERT(stack_trace_ ==
nullptr);
3193 stack_trace_ = stack_trace;
3194 ASSERT(async_awaiter_stack_trace_ ==
nullptr);
3195 async_awaiter_stack_trace_ = async_awaiter_stack_trace;
3198void Debugger::ClearCachedStackTraces() {
3199 stack_trace_ =
nullptr;
3200 async_awaiter_stack_trace_ =
nullptr;
3204 intptr_t frame_index) {
3205 for (intptr_t
i = frame_index + 1;
i < stack->
Length();
i++) {
3207 if (
frame->IsRewindable()) {
3218 intptr_t num_frames = stack->
Length();
3219 if (frame_index < 1 || frame_index >= num_frames) {
3220 if (
error !=
nullptr) {
3221 *
error = Thread::Current()->zone()->PrintToString(
3222 "Frame must be in bounds [1..%" Pd
3225 num_frames - 1, frame_index);
3230 if (!
frame->IsRewindable()) {
3232 if (next_index > 0) {
3233 *
error = Thread::Current()->zone()->PrintToString(
3234 "Cannot rewind to frame %" Pd
3235 " due to conflicting compiler "
3237 "Run the vm with --no-prune-dead-locals to disallow these "
3239 "Next valid rewind frame is %" Pd ".",
3240 frame_index, next_index);
3242 *
error = Thread::Current()->zone()->PrintToString(
3243 "Cannot rewind to frame %" Pd
3244 " due to conflicting compiler "
3246 "Run the vm with --no-prune-dead-locals to disallow these "
3259 ASSERT(
code.ContainsInstructionAt(return_address));
3261 uword pc_offset = return_address -
code.PayloadStart();
3263 PcDescriptors::Handle(
code.pc_descriptors());
3265 UntaggedPcDescriptors::kRewind |
3266 UntaggedPcDescriptors::kIcCall |
3267 UntaggedPcDescriptors::kUnoptStaticCall);
3268 intptr_t rewind_deopt_id = -1;
3269 uword rewind_pc = 0;
3271 if (iter.
Kind() == UntaggedPcDescriptors::kRewind) {
3274 rewind_deopt_id = iter.
DeoptId();
3276 if ((pc_offset == iter.
PcOffset()) && (iter.
DeoptId() == rewind_deopt_id)) {
3283void Debugger::RewindToFrame(intptr_t frame_index) {
3284 Thread* thread = Thread::Current();
3285 Zone* zone = thread->zone();
3286 Code&
code = Code::Handle(zone);
3287 Function&
function = Function::Handle(zone);
3290 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
3292 StackFrameIterator::kNoCrossThreadIteration);
3293 intptr_t current_frame = 0;
3294 for (StackFrame*
frame = iterator.NextFrame();
frame !=
nullptr;
3295 frame = iterator.NextFrame()) {
3297 if (
frame->IsDartFrame()) {
3303 if (
code.is_optimized()) {
3304 intptr_t sub_index = 0;
3305 for (InlinedFunctionsIterator it(
code,
frame->pc()); !it.Done();
3307 if (current_frame == frame_index) {
3308 RewindToOptimizedFrame(
frame,
code, sub_index);
3315 if (current_frame == frame_index) {
3327void Debugger::RewindToUnoptimizedFrame(StackFrame*
frame,
const Code&
code) {
3330 ClearCachedStackTraces();
3331 set_resume_action(kContinue);
3332 resume_frame_index_ = -1;
3333 EnterSingleStepMode();
3336 if (FLAG_trace_rewind && rewind_pc == 0) {
3337 OS::PrintErr(
"Unable to find rewind pc for pc(%" Px ")\n",
frame->pc());
3340 if (FLAG_trace_rewind) {
3342 "===============================\n"
3343 "Rewinding to unoptimized frame:\n"
3344 " rewind_pc(0x%" Px " offset:0x%" Px ") sp(0x%" Px ") fp(0x%" Px
3346 "===============================\n",
3347 rewind_pc, rewind_pc -
code.PayloadStart(),
frame->sp(),
frame->fp());
3349 Exceptions::JumpToFrame(Thread::Current(), rewind_pc,
frame->sp(),
3350 frame->fp(),
true );
3354void Debugger::RewindToOptimizedFrame(StackFrame*
frame,
3355 const Code& optimized_code,
3356 intptr_t sub_index) {
3357 post_deopt_frame_index_ = sub_index;
3361 ClearCachedStackTraces();
3362 set_resume_action(kContinue);
3363 resume_frame_index_ = -1;
3364 EnterSingleStepMode();
3366 if (FLAG_trace_rewind) {
3368 "===============================\n"
3369 "Deoptimizing frame for rewind:\n"
3370 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
3372 "===============================\n",
3375 Thread* thread = Thread::Current();
3376 thread->set_resume_pc(
frame->pc());
3377 uword deopt_stub_pc = StubCode::DeoptForRewind().EntryPoint();
3378 Exceptions::JumpToFrame(thread, deopt_stub_pc,
frame->sp(),
frame->fp(),
3383void Debugger::RewindPostDeopt() {
3384 intptr_t rewind_frame = post_deopt_frame_index_;
3385 post_deopt_frame_index_ = -1;
3386 if (FLAG_trace_rewind) {
3387 OS::PrintErr(
"Post deopt, jumping to frame %" Pd "\n", rewind_frame);
3389 "-------------------------\n"
3390 "All frames...\n\n");
3393 StackFrameIterator::kNoCrossThreadIteration);
3396 while ((
frame !=
nullptr)) {
3397 OS::PrintErr(
"#%04" Pd " %s\n", num++,
frame->ToCString());
3402 Thread* thread = Thread::Current();
3408 StackFrameIterator::kNoCrossThreadIteration);
3409 intptr_t current_frame = 0;
3413 if (
frame->IsDartFrame()) {
3416 if (current_frame == rewind_frame) {
3427 if (!func.is_debuggable()) {
3430 const Class& cls = Class::Handle(func.
Owner());
3435void GroupDebugger::RegisterSingleSteppingDebugger(
Thread* thread,
3437 WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
3438 single_stepping_set_.Insert(debugger);
3441void GroupDebugger::UnregisterSingleSteppingDebugger(
Thread* thread,
3443 WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
3444 single_stepping_set_.Remove(debugger);
3447bool GroupDebugger::HasBreakpointUnsafe(
Thread* thread,
3450 breakpoint_locations_lock()->IsCurrentThreadReader());
3452 String& url = String::Handle(thread->
zone());
3453 for (intptr_t
i = 0;
i < breakpoint_locations_.length();
i++) {
3455 url = location->
url();
3465 bool hasBreakpoint =
false;
3468 hasBreakpoint = HasBreakpointUnsafe(thread,
function);
3471 hasBreakpoint = HasBreakpointUnsafe(thread,
function);
3473 if (hasBreakpoint) {
3481 if (HasCodeBreakpointInFunction(
function)) {
3491 if (!single_stepping_set_.IsEmpty()) {
3495 return HasBreakpoint(thread,
function);
3498void Debugger::set_resume_action(ResumeAction resume_action) {
3499 auto thread = Thread::Current();
3500 if (resume_action == kContinue) {
3501 group_debugger()->UnregisterSingleSteppingDebugger(thread,
this);
3503 group_debugger()->RegisterSingleSteppingDebugger(thread,
this);
3505 resume_action_ = resume_action;
3508void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
3509 set_resume_action(kContinue);
3510 ResetSteppingFramePointer();
3511 NotifySingleStepping(
false);
3513 if ((bpt !=
nullptr) && bpt->is_single_shot()) {
3518 ServiceEvent
event(isolate_, ServiceEvent::kPauseBreakpoint);
3519 event.set_top_frame(top_frame);
3520 event.set_breakpoint(bpt);
3526 Zone* zone = Thread::Current()->zone();
3531 const auto& pc_descriptors =
3533 if (pc_descriptors.IsNull()) {
3539 if (it.
TokenPos() == looking_for &&
3540 it.
YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
3547ErrorPtr Debugger::PauseStepping() {
3548 ASSERT(isolate_->single_step());
3551 return Error::null();
3553 if (skip_next_step_) {
3554 skip_next_step_ =
false;
3555 return Error::null();
3566 if (stepping_fp_ != 0) {
3570 if (relation == ActivationFrame::kCallee) {
3573 return Error::null();
3574 }
else if (relation == ActivationFrame::kCaller) {
3578 ResetSteppingFramePointer();
3582 if (!
frame->IsDebuggable()) {
3583 return Error::null();
3585 if (!
frame->TokenPos().IsDebugPause()) {
3586 return Error::null();
3589 if (
frame->fp() == last_stepping_fp_ &&
3590 frame->TokenPos() == last_stepping_pos_) {
3593 return Error::null();
3598 if ((
frame->function().IsAsyncFunction() ||
3599 frame->function().IsAsyncGenerator()) &&
3600 frame->GetSuspendStateVar() == Object::null()) {
3601 return Error::null();
3605 last_stepping_fp_ =
frame->fp();
3606 last_stepping_pos_ =
frame->TokenPos();
3611 ASSERT(!group_debugger()->HasActiveBreakpoint(
frame->pc()));
3613 if (FLAG_verbose_debug) {
3614 OS::PrintErr(
">>> single step break at %s:%" Pd ":%" Pd
3615 " (func %s token %s address %#" Px " offset %#" Px ")\n",
3616 String::Handle(
frame->SourceUrl()).ToCString(),
3618 String::Handle(
frame->QualifiedFunctionName()).ToCString(),
3623 CacheStackTraces(DebuggerStackTrace::Collect(),
3624 DebuggerStackTrace::CollectAsyncAwaiters());
3625 SignalPausedEvent(
frame,
nullptr);
3626 HandleSteppingRequest();
3627 ClearCachedStackTraces();
3630 return Thread::Current()->StealStickyError();
3633ErrorPtr Debugger::PauseBreakpoint() {
3637 if (ignore_breakpoints_ || IsPaused()) {
3638 return Error::null();
3643 ASSERT(top_frame !=
nullptr);
3644 if (!Library::Handle(top_frame->
Library()).IsDebuggable()) {
3645 return Error::null();
3649 const char* cbpt_tostring =
nullptr;
3652 group_debugger()->code_breakpoints_lock());
3654 bpt_location = group_debugger()->GetBreakpointLocationFor(
3655 this, top_frame->
pc(), &cbpt);
3656 if (bpt_location ==
nullptr) {
3658 return Error::null();
3661 if (FLAG_verbose_debug) {
3666 Breakpoint* bpt_hit = bpt_location->FindHitBreakpoint(top_frame);
3667 if (bpt_hit ==
nullptr) {
3668 return Error::null();
3671 if (FLAG_verbose_debug) {
3672 OS::PrintErr(
">>> hit %" Pd
3674 " (func %s token %s address %#" Px " offset %#" Px ")\n",
3675 bpt_hit->
id(), cbpt_tostring,
3681 CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());
3682 SignalPausedEvent(top_frame, bpt_hit);
3685 HandleSteppingRequest(
true);
3686 ClearCachedStackTraces();
3689 return Thread::Current()->StealStickyError();
3699 while (bpt !=
nullptr) {
3707 bpt = breakpoints();
3708 while (bpt !=
nullptr) {
3709 if (bpt->
closure() != Instance::null() &&
3717 bpt = breakpoints();
3718 while (bpt !=
nullptr) {
3728void Debugger::PauseDeveloper(
const String& msg) {
3732 if (ignore_breakpoints_ || IsPaused()) {
3738 CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());
3744 SetResumeAction(kStepOut);
3745 HandleSteppingRequest();
3746 ClearCachedStackTraces();
3749void Debugger::NotifyIsolateCreated() {
3750 if (NeedsIsolateEvents()) {
3756#if !defined(DART_PRECOMPILED_RUNTIME)
3761 intptr_t column_number) {
3764 if (
script.GetTokenLocation(start_of_line, &
line, &col)) {
3765 return TokenPosition::Deserialize(start_of_line.
Pos() +
3766 (column_number - col));
3768 return TokenPosition::kNoSource;
3772void Debugger::NotifyDoneLoading() {
3773 if (latent_locations_ ==
nullptr) {
3777 auto thread = Thread::Current();
3778 auto isolate_group = thread->isolate_group();
3779 auto zone = thread->zone();
3780 Library& lib = Library::Handle(zone);
3782 String& url = String::Handle(zone);
3786 GrowableObjectArray::Handle(isolate_group->object_store()->libraries());
3789 while (loc !=
nullptr) {
3791 bool found_match =
false;
3792 bool is_package = url.
StartsWith(Symbols::PackageScheme());
3793 for (intptr_t
i = 0;
i <
libs.Length();
i++) {
3806 if (prev_loc ==
nullptr) {
3807 latent_locations_ = loc;
3809 prev_loc->set_next(loc);
3815 ASSERT(line_number >= 0);
3818 scripts.At(0).TokenRangeAtLine(line_number, &first_token_pos,
3823 Breakpoint* bpt = matched_loc->breakpoints();
3824 while (bpt !=
nullptr) {
3825 if (FLAG_verbose_debug) {
3826 OS::PrintErr(
"No code found at line %" Pd
3828 "dropping latent breakpoint %" Pd " in '%s'\n",
3841 GetBreakpointLocation(url, first_token_pos, -1, column_number);
3842 ASSERT(existing_loc ==
nullptr);
3843 if (existing_loc ==
nullptr) {
3847 this,
scripts, first_token_pos, last_token_pos, line_number,
3849 RegisterBreakpointLocation(unresolved_loc);
3852 Breakpoint* bpt = matched_loc->breakpoints();
3853 unresolved_loc->set_breakpoints(bpt);
3854 matched_loc->set_breakpoints(
nullptr);
3855 while (bpt !=
nullptr) {
3857 if (FLAG_verbose_debug) {
3859 "Converted latent breakpoint "
3860 "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
3861 bpt->
id(), url.
ToCString(), line_number, column_number);
3865 group_debugger()->SyncBreakpointLocation(unresolved_loc);
3882 if (FLAG_verbose_debug) {
3884 while (bpt !=
nullptr) {
3886 "No match found for latent breakpoint id "
3887 "%" Pd " with url '%s'\n",
3899bool GroupDebugger::HasActiveBreakpoint(
uword pc) {
3902 return (cbpt !=
nullptr) && (cbpt->
IsEnabled());
3907 while (cbpt !=
nullptr) {
3908 if (cbpt->
pc() == breakpoint_address) {
3911 cbpt = cbpt->next();
3918 uword breakpoint_address,
3920 ASSERT(pcbpt !=
nullptr);
3922 *pcbpt = code_breakpoints_;
3923 while (*pcbpt !=
nullptr) {
3924 if ((*pcbpt)->pc() == breakpoint_address) {
3925 return (*pcbpt)->FindBreakpointForDebugger(debugger);
3927 *pcbpt = (*pcbpt)->next();
3932void GroupDebugger::RegisterCodeBreakpoint(
CodeBreakpoint* cbpt) {
3933 ASSERT(cbpt->next() ==
nullptr);
3934 DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
3935 Thread::Current()->IsInStoppedMutatorsScope());
3936 cbpt->set_next(code_breakpoints_);
3937 code_breakpoints_ = cbpt;
3940CodePtr GroupDebugger::GetPatchedStubAddress(
uword breakpoint_address) {
3943 if (cbpt !=
nullptr) {
3947 return Code::null();
3952 group_debugger()->breakpoint_locations_lock());
3954 if (FLAG_verbose_debug) {
3955 OS::PrintErr(
"Setting breakpoint %" Pd " to state: %s\n", bpt->
id(),
3956 enable ?
"enabled" :
"disabled");
3959 group_debugger()->SyncBreakpointLocation(bpt->
bpt_location());
3969 group_debugger()->breakpoint_locations_lock());
3970 if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) {
3973 RemoveBreakpointFromTheList(bp_id, &latent_locations_);
3979bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id,
3983 while (curr_loc !=
nullptr) {
3985 Breakpoint* curr_bpt = curr_loc->breakpoints();
3986 while (curr_bpt !=
nullptr) {
3987 if (curr_bpt->
id() == bp_id) {
3988 if (prev_bpt ==
nullptr) {
3989 curr_loc->set_breakpoints(curr_bpt->
next());
3996 SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
4001 if (pause_event_ !=
nullptr && pause_event_->breakpoint() == curr_bpt) {
4002 pause_event_->set_breakpoint(
nullptr);
4009 if (curr_loc->breakpoints() ==
nullptr) {
4010 if (prev_loc ==
nullptr) {
4011 *list = curr_loc->next();
4013 prev_loc->set_next(curr_loc->next());
4020 group_debugger()->UnlinkCodeBreakpoints(curr_loc);
4022 group_debugger()->UnregisterBreakpointLocation(curr_loc);
4023 BreakpointLocation* next_loc = curr_loc->next();
4025 curr_loc = next_loc;
4033 prev_bpt = curr_bpt;
4034 curr_bpt = curr_bpt->
next();
4036 prev_loc = curr_loc;
4037 curr_loc = curr_loc->next();
4044 DEBUG_ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter() ||
4045 Thread::Current()->IsInStoppedMutatorsScope());
4046 breakpoint_locations_.Add(location);
4050 ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter());
4051 for (intptr_t
i = 0;
i < breakpoint_locations_.length();
i++) {
4052 if (breakpoint_locations_.At(
i) == location) {
4053 breakpoint_locations_.EraseAt(
i);
4064 ASSERT(bpt_location !=
nullptr);
4067 while (curr_bpt !=
nullptr) {
4070 needs_breakpoint_cleanup_ =
true;
4072 curr_bpt = curr_bpt->next();
4078void GroupDebugger::RemoveUnlinkedCodeBreakpoints() {
4079 DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
4080 Thread::Current()->IsInStoppedMutatorsScope());
4083 while (curr_bpt !=
nullptr) {
4085 if (prev_bpt ==
nullptr) {
4086 code_breakpoints_ = code_breakpoints_->
next();
4088 prev_bpt->set_next(curr_bpt->next());
4090 CodeBreakpoint* temp_bpt = curr_bpt;
4091 curr_bpt = curr_bpt->next();
4094 prev_bpt = curr_bpt;
4095 curr_bpt = curr_bpt->next();
4098 needs_breakpoint_cleanup_ =
false;
4101BreakpointLocation* Debugger::GetResolvedBreakpointLocation(
4102 const String& script_url,
4103 TokenPosition code_token_pos) {
4104 BreakpointLocation* loc = breakpoint_locations_;
4105 String& loc_url = String::Handle();
4106 while (loc !=
nullptr) {
4107 loc_url = loc->url();
4108 if (script_url.Equals(loc_url) && loc->code_token_pos_ == code_token_pos) {
4116BreakpointLocation* Debugger::GetBreakpointLocation(
4117 const String& script_url,
4118 TokenPosition token_pos,
4119 intptr_t requested_line,
4120 intptr_t requested_column,
4121 TokenPosition code_token_pos) {
4122 BreakpointLocation* loc = breakpoint_locations_;
4123 String& loc_url = String::Handle();
4124 while (loc !=
nullptr) {
4125 loc_url = loc->url();
4126 if (script_url.Equals(loc_url) &&
4127 (!token_pos.IsReal() || (loc->token_pos() == token_pos)) &&
4128 ((requested_line == -1) ||
4129 (loc->requested_line_number_ == requested_line)) &&
4130 ((requested_column == -1) ||
4131 (loc->requested_column_number_ == requested_column)) &&
4132 (!code_token_pos.IsReal() ||
4133 (loc->code_token_pos_ == code_token_pos))) {
4142 Breakpoint* bpt = GetBreakpointByIdInTheList(
id, breakpoint_locations_);
4143 if (bpt !=
nullptr) {
4146 return GetBreakpointByIdInTheList(
id, latent_locations_);
4149Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t
id,
4152 while (loc !=
nullptr) {
4154 while (bpt !=
nullptr) {
4155 if (bpt->
id() ==
id) {
4165void Debugger::AsyncStepInto(
const Closure& awaiter) {
4166 Zone* zone = Thread::Current()->zone();
4168 auto& suspend_state = SuspendState::Handle(zone);
4169 if (StackTraceUtils::GetSuspendState(awaiter, &suspend_state)) {
4170 const auto& function_data =
4171 Object::Handle(zone, suspend_state.function_data());
4172 SetBreakpointAtResumption(function_data);
4174 SetBreakpointAtActivation(awaiter,
true);
4179void Debugger::Continue() {
4180 SetResumeAction(kContinue);
4181 ResetSteppingFramePointer();
4182 NotifySingleStepping(
false);
4189 String& bpt_url = String::Handle();
4190 while (loc !=
nullptr) {
4191 bpt_url = loc->
url();
4199 loc =
new BreakpointLocation(
this, url,
line, column);
4200 loc->set_next(latent_locations_);
4201 latent_locations_ = loc;
4205void Debugger::RegisterBreakpointLocationUnsafe(BreakpointLocation* loc) {
4207 group_debugger()->breakpoint_locations_lock()->IsCurrentThreadWriter() ||
4208 Thread::Current()->IsInStoppedMutatorsScope());
4209 ASSERT(loc->next() ==
nullptr);
4210 loc->set_next(breakpoint_locations_);
4211 breakpoint_locations_ = loc;
4212 group_debugger()->RegisterBreakpointLocation(loc);
4215void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
4216 auto thread = Thread::Current();
4217 if (thread->IsInStoppedMutatorsScope()) {
4218 RegisterBreakpointLocationUnsafe(loc);
4220 SafepointWriteRwLocker sl(thread,
4221 group_debugger()->breakpoint_locations_lock());
4222 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,...)
const uint8_t uint32_t uint32_t GError ** error
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)
static void SetBreakpointState(Thread *thread, JSONStream *js)
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 constexpr intptr_t kDefaultStackAllocation
static bool IsImplicitFunction(const Function &func)
DART_EXPORT bool IsNull(Dart_Handle object)
const char *const class_name
static void RemoveBreakpoint(Thread *thread, JSONStream *js)
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 void Pause(Thread *thread, JSONStream *js)
static ActivationFrame * TopDartFrame()
static bool FunctionOverlaps(const Function &func, const String &script_url, TokenPosition token_pos, TokenPosition end_token_pos)
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
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)
DECLARE_FLAG(bool, show_invisible_frames)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
std::function< void()> closure
scripts
Printing Glyph Map Stats.
static constexpr Color Min(Color c, float threshold)
intptr_t FrameSlotForVariableIndex(intptr_t index) const
TokenPosition declaration_pos
#define TIMELINE_DURATION(thread, stream, name)