1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/debugger.h"
6
7#include "include/dart_api.h"
8
9#include "vm/code_descriptors.h"
10#include "vm/code_patcher.h"
11#include "vm/compiler/api/deopt_id.h"
12#include "vm/compiler/assembler/disassembler.h"
13#include "vm/compiler/assembler/disassembler_kbc.h"
14#include "vm/compiler/jit/compiler.h"
15#include "vm/dart_entry.h"
16#include "vm/flags.h"
17#include "vm/globals.h"
18#include "vm/interpreter.h"
19#include "vm/isolate_reload.h"
20#include "vm/json_stream.h"
21#include "vm/kernel.h"
22#include "vm/longjump.h"
23#include "vm/message_handler.h"
24#include "vm/object.h"
25#include "vm/object_store.h"
26#include "vm/os.h"
27#include "vm/parser.h"
28#include "vm/port.h"
29#include "vm/runtime_entry.h"
30#include "vm/service.h"
31#include "vm/service_event.h"
32#include "vm/service_isolate.h"
33#include "vm/stack_frame.h"
34#include "vm/stack_trace.h"
35#include "vm/stub_code.h"
36#include "vm/symbols.h"
37#include "vm/thread_interrupter.h"
38#include "vm/timeline.h"
39#include "vm/token_position.h"
40#include "vm/visitor.h"
41
42#if !defined(DART_PRECOMPILED_RUNTIME)
43#include "vm/compiler/frontend/bytecode_reader.h"
44#include "vm/deopt_instructions.h"
45#endif // !defined(DART_PRECOMPILED_RUNTIME)
46
47namespace dart {
48
49DEFINE_FLAG(bool,
50 trace_debugger_stacktrace,
51 false,
52 "Trace debugger stacktrace collection");
53DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind");
54DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
55
56DECLARE_FLAG(bool, enable_interpreter);
57DECLARE_FLAG(bool, trace_deoptimization);
58DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
59
60#ifndef PRODUCT
61
62// Create an unresolved breakpoint in given token range and script.
63BreakpointLocation::BreakpointLocation(const Script& script,
64 TokenPosition token_pos,
65 TokenPosition end_token_pos,
66 intptr_t requested_line_number,
67 intptr_t requested_column_number)
68 : script_(script.raw()),
69 url_(script.url()),
70 token_pos_(token_pos),
71 end_token_pos_(end_token_pos),
72 next_(NULL),
73 conditions_(NULL),
74 requested_line_number_(requested_line_number),
75 requested_column_number_(requested_column_number),
76 function_(Function::null()),
77 bytecode_token_pos_(TokenPosition::kNoSource),
78 code_token_pos_(TokenPosition::kNoSource) {
79 ASSERT(!script.IsNull());
80 ASSERT(token_pos_.IsReal());
81}
82
83// Create a latent breakpoint at given url and line number.
84BreakpointLocation::BreakpointLocation(const String& url,
85 intptr_t requested_line_number,
86 intptr_t requested_column_number)
87 : script_(Script::null()),
88 url_(url.raw()),
89 token_pos_(TokenPosition::kNoSource),
90 end_token_pos_(TokenPosition::kNoSource),
91 next_(NULL),
92 conditions_(NULL),
93 requested_line_number_(requested_line_number),
94 requested_column_number_(requested_column_number),
95 function_(Function::null()),
96 bytecode_token_pos_(TokenPosition::kNoSource),
97 code_token_pos_(TokenPosition::kNoSource) {
98 ASSERT(requested_line_number_ >= 0);
99}
100
101BreakpointLocation::~BreakpointLocation() {
102 Breakpoint* bpt = breakpoints();
103 while (bpt != NULL) {
104 Breakpoint* temp = bpt;
105 bpt = bpt->next();
106 delete temp;
107 }
108}
109
110bool BreakpointLocation::AnyEnabled() const {
111 return breakpoints() != NULL;
112}
113
114void BreakpointLocation::SetResolved(bool in_bytecode,
115 const Function& func,
116 TokenPosition token_pos) {
117 ASSERT(!IsLatent());
118 ASSERT(func.script() == script_);
119 ASSERT((func.token_pos() <= token_pos) &&
120 (token_pos <= func.end_token_pos()));
121 ASSERT(func.is_debuggable());
122 function_ = func.raw();
123 token_pos_ = token_pos;
124 end_token_pos_ = token_pos;
125 if (in_bytecode) {
126 bytecode_token_pos_ = token_pos;
127 } else {
128 code_token_pos_ = token_pos;
129 }
130}
131
132// Returned resolved pos is either in code or in bytecode.
133void BreakpointLocation::GetCodeLocation(Script* script,
134 TokenPosition* pos) const {
135 if (IsLatent()) {
136 *script = Script::null();
137 *pos = TokenPosition::kNoSource;
138 } else {
139 *script = this->script();
140 *pos = token_pos_;
141 }
142}
143
144void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
145 // Only latent breakpoints can be moved.
146 ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
147 bpt_location_ = new_bpt_location;
148}
149
150void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
151 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&closure_));
152}
153
154void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
155 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&script_));
156 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&url_));
157 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&function_));
158
159 Breakpoint* bpt = conditions_;
160 while (bpt != NULL) {
161 bpt->VisitObjectPointers(visitor);
162 bpt = bpt->next();
163 }
164}
165
166void Breakpoint::PrintJSON(JSONStream* stream) {
167 JSONObject jsobj(stream);
168 jsobj.AddProperty("type", "Breakpoint");
169
170 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
171 jsobj.AddProperty("breakpointNumber", id());
172 if (is_synthetic_async()) {
173 jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async());
174 }
175 jsobj.AddProperty("resolved", bpt_location_->IsResolved());
176 if (bpt_location_->IsResolved()) {
177 jsobj.AddLocation(bpt_location_);
178 } else {
179 jsobj.AddUnresolvedLocation(bpt_location_);
180 }
181}
182
183void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
184 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&code_));
185 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&bytecode_));
186 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_value_));
187}
188
189ActivationFrame::ActivationFrame(uword pc,
190 uword fp,
191 uword sp,
192 const Code& code,
193 const Array& deopt_frame,
194 intptr_t deopt_frame_offset,
195 ActivationFrame::Kind kind)
196 : pc_(pc),
197 fp_(fp),
198 sp_(sp),
199 ctx_(Context::ZoneHandle()),
200 code_(Code::ZoneHandle(code.raw())),
201 bytecode_(Bytecode::ZoneHandle()),
202 function_(Function::ZoneHandle(code.function())),
203 live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
204 token_pos_initialized_(false),
205 token_pos_(TokenPosition::kNoSource),
206 try_index_(-1),
207 deopt_id_(DeoptId::kNone),
208 line_number_(-1),
209 column_number_(-1),
210 context_level_(-1),
211 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
212 deopt_frame_offset_(deopt_frame_offset),
213 kind_(kind),
214 vars_initialized_(false),
215 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
216 desc_indices_(8),
217 pc_desc_(PcDescriptors::ZoneHandle()) {
218 ASSERT(!function_.IsNull());
219}
220
221#if !defined(DART_PRECOMPILED_RUNTIME)
222ActivationFrame::ActivationFrame(uword pc,
223 uword fp,
224 uword sp,
225 const Bytecode& bytecode,
226 ActivationFrame::Kind kind)
227 : pc_(pc),
228 fp_(fp),
229 sp_(sp),
230 ctx_(Context::ZoneHandle()),
231 code_(Code::ZoneHandle()),
232 bytecode_(Bytecode::ZoneHandle(bytecode.raw())),
233 function_(Function::ZoneHandle(bytecode.function())),
234 live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
235 token_pos_initialized_(false),
236 token_pos_(TokenPosition::kNoSource),
237 try_index_(-1),
238 deopt_id_(DeoptId::kNone),
239 line_number_(-1),
240 column_number_(-1),
241 context_level_(-1),
242 deopt_frame_(Array::ZoneHandle()),
243 deopt_frame_offset_(0),
244 kind_(kind),
245 vars_initialized_(false),
246 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
247 desc_indices_(8),
248 pc_desc_(PcDescriptors::ZoneHandle()) {
249 // The frame of a bytecode stub has a null function. It may be encountered
250 // when single stepping.
251}
252#endif // !defined(DART_PRECOMPILED_RUNTIME)
253
254ActivationFrame::ActivationFrame(Kind kind)
255 : pc_(0),
256 fp_(0),
257 sp_(0),
258 ctx_(Context::ZoneHandle()),
259 code_(Code::ZoneHandle()),
260 bytecode_(Bytecode::ZoneHandle()),
261 function_(Function::ZoneHandle()),
262 live_frame_(kind == kRegular),
263 token_pos_initialized_(false),
264 token_pos_(TokenPosition::kNoSource),
265 try_index_(-1),
266 deopt_id_(DeoptId::kNone),
267 line_number_(-1),
268 column_number_(-1),
269 context_level_(-1),
270 deopt_frame_(Array::ZoneHandle()),
271 deopt_frame_offset_(0),
272 kind_(kind),
273 vars_initialized_(false),
274 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
275 desc_indices_(8),
276 pc_desc_(PcDescriptors::ZoneHandle()) {}
277
278ActivationFrame::ActivationFrame(const Closure& async_activation)
279 : pc_(0),
280 fp_(0),
281 sp_(0),
282 ctx_(Context::ZoneHandle()),
283 code_(Code::ZoneHandle()),
284 bytecode_(Bytecode::ZoneHandle()),
285 function_(Function::ZoneHandle()),
286 live_frame_(false),
287 token_pos_initialized_(false),
288 token_pos_(TokenPosition::kNoSource),
289 try_index_(-1),
290 deopt_id_(DeoptId::kNone),
291 line_number_(-1),
292 column_number_(-1),
293 context_level_(-1),
294 deopt_frame_(Array::ZoneHandle()),
295 deopt_frame_offset_(0),
296 kind_(kAsyncActivation),
297 vars_initialized_(false),
298 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
299 desc_indices_(8),
300 pc_desc_(PcDescriptors::ZoneHandle()) {
301 // Extract the function and the code from the asynchronous activation.
302 function_ = async_activation.function();
303#if !defined(DART_PRECOMPILED_RUNTIME)
304 if (!function_.HasCode() && function_.HasBytecode()) {
305 bytecode_ = function_.bytecode();
306 }
307#endif
308 if (bytecode_.IsNull()) {
309 // Force-optimize functions should not be debuggable.
310 ASSERT(!function_.ForceOptimize());
311 function_.EnsureHasCompiledUnoptimizedCode();
312 code_ = function_.unoptimized_code();
313 }
314 ctx_ = async_activation.context();
315 ASSERT(fp_ == 0);
316 ASSERT(!ctx_.IsNull());
317}
318
319bool Debugger::NeedsIsolateEvents() {
320 return !Isolate::IsVMInternalIsolate(isolate_) &&
321 Service::isolate_stream.enabled();
322}
323
324bool Debugger::NeedsDebugEvents() {
325 ASSERT(!Isolate::IsVMInternalIsolate(isolate_));
326 return FLAG_warn_on_pause_with_no_debugger || Service::debug_stream.enabled();
327}
328
329void Debugger::InvokeEventHandler(ServiceEvent* event) {
330 ASSERT(!event->IsPause()); // For pause events, call Pause instead.
331 Service::HandleEvent(event);
332}
333
334ErrorPtr Debugger::PauseInterrupted() {
335 return PauseRequest(ServiceEvent::kPauseInterrupted);
336}
337
338ErrorPtr Debugger::PausePostRequest() {
339 return PauseRequest(ServiceEvent::kPausePostRequest);
340}
341
342ErrorPtr Debugger::PauseRequest(ServiceEvent::EventKind kind) {
343 if (ignore_breakpoints_ || IsPaused()) {
344 // We don't let the isolate get interrupted if we are already
345 // paused or ignoring breakpoints.
346 return Thread::Current()->StealStickyError();
347 }
348 ServiceEvent event(isolate_, kind);
349 DebuggerStackTrace* trace = CollectStackTrace();
350 if (trace->Length() > 0) {
351 event.set_top_frame(trace->FrameAt(0));
352 }
353 CacheStackTraces(trace, CollectAsyncCausalStackTrace(),
354 CollectAwaiterReturnStackTrace());
355 resume_action_ = kContinue;
356 Pause(&event);
357 HandleSteppingRequest(trace);
358 ClearCachedStackTraces();
359
360 // If any error occurred while in the debug message loop, return it here.
361 NoSafepointScope no_safepoint;
362 ErrorPtr error = Thread::Current()->StealStickyError();
363 ASSERT((error == Error::null()) || error->IsUnwindError());
364 return error;
365}
366
367void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind,
368 Breakpoint* bpt) {
369 if (NeedsDebugEvents()) {
370 // TODO(turnidge): Currently we send single-shot breakpoint events
371 // to the vm service. Do we want to change this?
372 ServiceEvent event(isolate_, kind);
373 event.set_breakpoint(bpt);
374 InvokeEventHandler(&event);
375 }
376}
377
378void BreakpointLocation::AddBreakpoint(Breakpoint* bpt, Debugger* dbg) {
379 bpt->set_next(breakpoints());
380 set_breakpoints(bpt);
381
382 dbg->SyncBreakpointLocation(this);
383 dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
384}
385
386Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) {
387 Breakpoint* bpt = breakpoints();
388 while (bpt != NULL) {
389 if (bpt->IsRepeated()) break;
390 bpt = bpt->next();
391 }
392 if (bpt == NULL) {
393 bpt = new Breakpoint(dbg->nextId(), this);
394 bpt->SetIsRepeated();
395 AddBreakpoint(bpt, dbg);
396 }
397 return bpt;
398}
399
400Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) {
401 Breakpoint* bpt = breakpoints();
402 while (bpt != NULL) {
403 if (bpt->IsSingleShot()) break;
404 bpt = bpt->next();
405 }
406 if (bpt == NULL) {
407 bpt = new Breakpoint(dbg->nextId(), this);
408 bpt->SetIsSingleShot();
409 AddBreakpoint(bpt, dbg);
410 }
411 return bpt;
412}
413
414Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
415 const Instance& closure,
416 bool for_over_await) {
417 Breakpoint* bpt = NULL;
418 // Do not reuse existing breakpoints for stepping over await clauses.
419 // A second async step-over command will set a new breakpoint before
420 // the existing one gets deleted when first async step-over resumes.
421 if (!for_over_await) {
422 bpt = breakpoints();
423 while (bpt != NULL) {
424 if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break;
425 bpt = bpt->next();
426 }
427 }
428 if (bpt == NULL) {
429 bpt = new Breakpoint(dbg->nextId(), this);
430 bpt->SetIsPerClosure(closure);
431 bpt->set_is_synthetic_async(for_over_await);
432 AddBreakpoint(bpt, dbg);
433 }
434 return bpt;
435}
436
437const char* Debugger::QualifiedFunctionName(const Function& func) {
438 const String& func_name = String::Handle(func.name());
439 Class& func_class = Class::Handle(func.Owner());
440 String& class_name = String::Handle(func_class.Name());
441
442 return OS::SCreate(Thread::Current()->zone(), "%s%s%s",
443 func_class.IsTopLevel() ? "" : class_name.ToCString(),
444 func_class.IsTopLevel() ? "" : ".", func_name.ToCString());
445}
446
447// Returns true if the function |func| overlaps the token range
448// [|token_pos|, |end_token_pos|] in |script|.
449static bool FunctionOverlaps(const Function& func,
450 const Script& script,
451 TokenPosition token_pos,
452 TokenPosition end_token_pos) {
453 TokenPosition func_start = func.token_pos();
454 if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
455 ((token_pos <= func_start) && (func_start <= end_token_pos))) {
456 // Check script equality second because it allocates
457 // handles as a side effect.
458 return func.script() == script.raw();
459 }
460 return false;
461}
462
463static bool IsImplicitFunction(const Function& func) {
464 switch (func.kind()) {
465 case FunctionLayout::kImplicitGetter:
466 case FunctionLayout::kImplicitSetter:
467 case FunctionLayout::kImplicitStaticGetter:
468 case FunctionLayout::kFieldInitializer:
469 case FunctionLayout::kMethodExtractor:
470 case FunctionLayout::kNoSuchMethodDispatcher:
471 case FunctionLayout::kInvokeFieldDispatcher:
472 case FunctionLayout::kIrregexpFunction:
473 return true;
474 default:
475 if (func.token_pos() == func.end_token_pos()) {
476 // |func| could be an implicit constructor for example.
477 return true;
478 }
479 }
480 return false;
481}
482
483bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
484 if (!func.HasCode() && !func.HasBytecode()) {
485 // If the function is not compiled yet, just check whether there
486 // is a user-defined breakpoint that falls into the token
487 // range of the function. This may be a false positive: the breakpoint
488 // might be inside a local closure.
489 Script& script = Script::Handle(zone);
490 BreakpointLocation* sbpt = breakpoint_locations_;
491 while (sbpt != NULL) {
492 script = sbpt->script();
493 if (FunctionOverlaps(func, script, sbpt->token_pos(),
494 sbpt->end_token_pos())) {
495 return true;
496 }
497 sbpt = sbpt->next_;
498 }
499 return false;
500 }
501 CodeBreakpoint* cbpt = code_breakpoints_;
502 while (cbpt != NULL) {
503 if (func.raw() == cbpt->function()) {
504 return true;
505 }
506 cbpt = cbpt->next_;
507 }
508 return false;
509}
510
511bool Debugger::HasBreakpoint(const Code& code) {
512 CodeBreakpoint* cbpt = code_breakpoints_;
513 while (cbpt != NULL) {
514 if (code.raw() == cbpt->code_) {
515 return true;
516 }
517 cbpt = cbpt->next_;
518 }
519 return false;
520}
521
522void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
523 PrintBreakpointsListToJSONArray(breakpoint_locations_, jsarr);
524 PrintBreakpointsListToJSONArray(latent_locations_, jsarr);
525}
526
527void Debugger::PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
528 JSONArray* jsarr) const {
529 while (sbpt != NULL) {
530 Breakpoint* bpt = sbpt->breakpoints();
531 while (bpt != NULL) {
532 jsarr->AddValue(bpt);
533 bpt = bpt->next();
534 }
535 sbpt = sbpt->next_;
536 }
537}
538
539void Debugger::PrintSettingsToJSONObject(JSONObject* jsobj) const {
540 // This won't cut it when we support filtering by class, etc.
541 switch (GetExceptionPauseInfo()) {
542 case kNoPauseOnExceptions:
543 jsobj->AddProperty("_exceptions", "none");
544 break;
545 case kPauseOnAllExceptions:
546 jsobj->AddProperty("_exceptions", "all");
547 break;
548 case kPauseOnUnhandledExceptions:
549 jsobj->AddProperty("_exceptions", "unhandled");
550 break;
551 default:
552 UNREACHABLE();
553 }
554}
555
556// If the current top Dart frame is interpreted, returns the fp of the caller
557// in compiled code that invoked the interpreter, or 0 if not found.
558// If the current top Dart frame is compiled, returns the fp of the caller in
559// interpreted bytecode that invoked compiled code, or ULONG_MAX if not found.
560// Returning compiled code fp 0 (or bytecode fp ULONG_MAX) as fp value insures
561// that the fp will compare as a callee of any valid frame pointer of the same
562// mode (compiled code or bytecode).
563static uword CrossCallerFp() {
564 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
565 Thread::Current(),
566 StackFrameIterator::kNoCrossThreadIteration);
567 StackFrame* frame;
568 do {
569 frame = iterator.NextFrame();
570 RELEASE_ASSERT(frame != nullptr);
571 } while (!frame->IsDartFrame());
572 const bool top_is_interpreted = frame->is_interpreted();
573 do {
574 frame = iterator.NextFrame();
575 if (frame == nullptr) {
576 return top_is_interpreted ? 0 : ULONG_MAX;
577 }
578 if (!frame->IsDartFrame()) {
579 continue;
580 }
581 } while (top_is_interpreted == frame->is_interpreted());
582 return frame->fp();
583}
584
585ActivationFrame::Relation ActivationFrame::CompareTo(
586 uword other_fp,
587 bool other_is_interpreted) const {
588 if (fp() == other_fp) {
589 ASSERT(IsInterpreted() == other_is_interpreted);
590 return kSelf;
591 }
592 if (IsInterpreted()) {
593 if (!other_is_interpreted) {
594 // Instead of fp(), use the fp of the compiled frame that called into the
595 // interpreter (CrossCallerFp).
596 // Note that if CrossCallerFp == other_fp, it must compare as a caller.
597 return IsCalleeFrameOf(other_fp, CrossCallerFp()) ? kCallee : kCaller;
598 }
599 return IsBytecodeCalleeFrameOf(other_fp, fp()) ? kCallee : kCaller;
600 }
601 if (other_is_interpreted) {
602 // Instead of fp(), use the fp of the interpreted frame that called into
603 // compiled code (CrossCallerFp).
604 // Note that if CrossCallerFp == other_fp, it must compare as a caller.
605 return IsBytecodeCalleeFrameOf(other_fp, CrossCallerFp()) ? kCallee
606 : kCaller;
607 }
608 return IsCalleeFrameOf(other_fp, fp()) ? kCallee : kCaller;
609}
610
611StringPtr ActivationFrame::QualifiedFunctionName() {
612 return String::New(Debugger::QualifiedFunctionName(function()));
613}
614
615StringPtr ActivationFrame::SourceUrl() {
616 const Script& script = Script::Handle(SourceScript());
617 return script.url();
618}
619
620ScriptPtr ActivationFrame::SourceScript() {
621 return function().script();
622}
623
624LibraryPtr ActivationFrame::Library() {
625 const Class& cls = Class::Handle(function().origin());
626 return cls.library();
627}
628
629void ActivationFrame::GetPcDescriptors() {
630 ASSERT(!IsInterpreted()); // We need to set try_index_ simultaneously.
631 if (pc_desc_.IsNull()) {
632 pc_desc_ = code().pc_descriptors();
633 ASSERT(!pc_desc_.IsNull());
634 }
635}
636
637// If not token_pos_initialized_, compute token_pos_, try_index_ and,
638// if not IsInterpreted(), also compute deopt_id_.
639TokenPosition ActivationFrame::TokenPos() {
640 if (!token_pos_initialized_) {
641 token_pos_initialized_ = true;
642 if (IsInterpreted()) {
643 token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
644 try_index_ = bytecode().GetTryIndexAtPc(pc_);
645 return token_pos_;
646 }
647 token_pos_ = TokenPosition::kNoSource;
648 GetPcDescriptors();
649 PcDescriptors::Iterator iter(pc_desc_, PcDescriptorsLayout::kAnyKind);
650 const uword pc_offset = pc_ - code().PayloadStart();
651 while (iter.MoveNext()) {
652 if (iter.PcOffset() == pc_offset) {
653 try_index_ = iter.TryIndex();
654 token_pos_ = iter.TokenPos();
655 deopt_id_ = iter.DeoptId();
656 break;
657 }
658 }
659 }
660 return token_pos_;
661}
662
663intptr_t ActivationFrame::TryIndex() {
664 if (!token_pos_initialized_) {
665 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_.
666 }
667 return try_index_;
668}
669
670intptr_t ActivationFrame::DeoptId() {
671 ASSERT(!IsInterpreted());
672 if (!token_pos_initialized_) {
673 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_.
674 }
675 return deopt_id_;
676}
677
678intptr_t ActivationFrame::LineNumber() {
679 // Compute line number lazily since it causes scanning of the script.
680 if ((line_number_ < 0) && TokenPos().IsSourcePosition()) {
681 const TokenPosition token_pos = TokenPos().SourcePosition();
682 const Script& script = Script::Handle(SourceScript());
683 script.GetTokenLocation(token_pos, &line_number_, NULL);
684 }
685 return line_number_;
686}
687
688intptr_t ActivationFrame::ColumnNumber() {
689 // Compute column number lazily since it causes scanning of the script.
690 if ((column_number_ < 0) && TokenPos().IsSourcePosition()) {
691 const TokenPosition token_pos = TokenPos().SourcePosition();
692 const Script& script = Script::Handle(SourceScript());
693 if (script.HasSource()) {
694 script.GetTokenLocation(token_pos, &line_number_, &column_number_);
695 } else {
696 column_number_ = -1;
697 }
698 }
699 return column_number_;
700}
701
702void ActivationFrame::GetVarDescriptors() {
703 if (var_descriptors_.IsNull()) {
704 if (IsInterpreted()) {
705 var_descriptors_ = bytecode().GetLocalVarDescriptors();
706 ASSERT(!var_descriptors_.IsNull());
707 return;
708 }
709 Code& unoptimized_code = Code::Handle(function().unoptimized_code());
710 if (unoptimized_code.IsNull()) {
711 Thread* thread = Thread::Current();
712 Zone* zone = thread->zone();
713 const Error& error = Error::Handle(
714 zone, Compiler::EnsureUnoptimizedCode(thread, function()));
715 if (!error.IsNull()) {
716 Exceptions::PropagateError(error);
717 }
718 unoptimized_code = function().unoptimized_code();
719 }
720 ASSERT(!unoptimized_code.IsNull());
721 var_descriptors_ = unoptimized_code.GetLocalVarDescriptors();
722 ASSERT(!var_descriptors_.IsNull());
723 }
724}
725
726bool ActivationFrame::IsDebuggable() const {
727 // When stepping in bytecode stub, function is null.
728 return !function().IsNull() && Debugger::IsDebuggable(function());
729}
730
731void ActivationFrame::PrintDescriptorsError(const char* message) {
732 OS::PrintErr("Bad descriptors: %s\n", message);
733 OS::PrintErr("function %s\n", function().ToQualifiedCString());
734 OS::PrintErr("pc_ %" Px "\n", pc_);
735 OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
736 OS::PrintErr("context_level_ %" Px "\n", context_level_);
737 OS::PrintErr("token_pos_ %s\n", token_pos_.ToCString());
738 if (function().is_declared_in_bytecode()) {
739#if !defined(DART_PRECOMPILED_RUNTIME)
740 KernelBytecodeDisassembler::Disassemble(function());
741#else
742 UNREACHABLE();
743#endif // !defined(DART_PRECOMPILED_RUNTIME)
744 }
745 if (!IsInterpreted()) {
746 DisassembleToStdout formatter;
747 code().Disassemble(&formatter);
748 PcDescriptors::Handle(code().pc_descriptors()).Print();
749 }
750 StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
751 Thread::Current(),
752 StackFrameIterator::kNoCrossThreadIteration);
753 StackFrame* frame = frames.NextFrame();
754 while (frame != NULL) {
755 OS::PrintErr("%s\n", frame->ToCString());
756 frame = frames.NextFrame();
757 }
758 OS::Abort();
759}
760
761// Calculate the context level at the current pc of the frame.
762intptr_t ActivationFrame::ContextLevel() {
763 ASSERT(live_frame_);
764 const Context& ctx = GetSavedCurrentContext();
765 if (context_level_ < 0 && !ctx.IsNull()) {
766 if (IsInterpreted()) {
767#if !defined(DART_PRECOMPILED_RUNTIME)
768 Thread* thread = Thread::Current();
769 Zone* zone = thread->zone();
770 const auto& bytecode = Bytecode::Handle(zone, function_.bytecode());
771 if (!bytecode.HasLocalVariablesInfo()) {
772 PrintDescriptorsError("Missing local variables info");
773 }
774 intptr_t pc_offset = pc_ - bytecode.PayloadStart();
775 // Look for innermost scope, i.e. with the highest context level.
776 // Since scopes are ordered by StartPC(), the last scope which includes
777 // pc_offset will be the innermost one.
778 kernel::BytecodeLocalVariablesIterator local_vars(zone, bytecode);
779 while (local_vars.MoveNext()) {
780 if (local_vars.Kind() ==
781 kernel::BytecodeLocalVariablesIterator::kScope) {
782 if (local_vars.StartPC() > pc_offset) {
783 break;
784 }
785 if (pc_offset <= local_vars.EndPC()) {
786 ASSERT(context_level_ <= local_vars.ContextLevel());
787 context_level_ = local_vars.ContextLevel();
788 }
789 }
790 }
791 if (context_level_ < 0) {
792 PrintDescriptorsError("Missing context level in local variables info");
793 }
794#else
795 UNREACHABLE();
796#endif // !defined(DART_PRECOMPILED_RUNTIME)
797 } else {
798 ASSERT(!code_.is_optimized());
799 GetVarDescriptors();
800 intptr_t deopt_id = DeoptId();
801 if (deopt_id == DeoptId::kNone) {
802 PrintDescriptorsError("Missing deopt id");
803 }
804 intptr_t var_desc_len = var_descriptors_.Length();
805 bool found = false;
806 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
807 LocalVarDescriptorsLayout::VarInfo var_info;
808 var_descriptors_.GetInfo(cur_idx, &var_info);
809 const int8_t kind = var_info.kind();
810 if ((kind == LocalVarDescriptorsLayout::kContextLevel) &&
811 (deopt_id >= var_info.begin_pos.value()) &&
812 (deopt_id <= var_info.end_pos.value())) {
813 context_level_ = var_info.index();
814 found = true;
815 break;
816 }
817 }
818 if (!found) {
819 PrintDescriptorsError("Missing context level in var descriptors");
820 }
821 ASSERT(context_level_ >= 0);
822 }
823 }
824 return context_level_;
825}
826
827ObjectPtr ActivationFrame::GetAsyncContextVariable(const String& name) {
828 if (!function_.IsAsyncClosure() && !function_.IsAsyncGenClosure()) {
829 return Object::null();
830 }
831 GetVarDescriptors();
832 intptr_t var_ctxt_level = -1;
833 intptr_t ctxt_slot = -1;
834 intptr_t var_desc_len = var_descriptors_.Length();
835 for (intptr_t i = 0; i < var_desc_len; i++) {
836 LocalVarDescriptorsLayout::VarInfo var_info;
837 var_descriptors_.GetInfo(i, &var_info);
838 if (var_descriptors_.GetName(i) == name.raw()) {
839 const int8_t kind = var_info.kind();
840 if (!live_frame_) {
841 ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
842 }
843 const auto variable_index = VariableIndex(var_info.index());
844 if (kind == LocalVarDescriptorsLayout::kStackVar) {
845 return GetStackVar(variable_index);
846 } else {
847 ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
848 // Variable descriptors constructed from bytecode have all variables of
849 // enclosing functions, even shadowed by the current function.
850 // Pick the variable with the highest context level.
851 if (var_info.scope_id > var_ctxt_level) {
852 var_ctxt_level = var_info.scope_id;
853 ctxt_slot = variable_index.value();
854 }
855 }
856 }
857 }
858 if (var_ctxt_level >= 0) {
859 if (!live_frame_) {
860 ASSERT(!ctx_.IsNull());
861 // Compiled code uses relative context levels, i.e. the frame context
862 // level is always 0 on entry.
863 // Bytecode uses absolute context levels, i.e. the frame context level
864 // on entry must be calculated.
865 const intptr_t frame_ctx_level =
866 function().is_declared_in_bytecode() ? ctx_.GetLevel() : 0;
867 return GetRelativeContextVar(var_ctxt_level, ctxt_slot, frame_ctx_level);
868 }
869 return GetContextVar(var_ctxt_level, ctxt_slot);
870 }
871 return Object::null();
872}
873
874ObjectPtr ActivationFrame::GetAsyncCompleter() {
875 return GetAsyncContextVariable(Symbols::AsyncCompleter());
876}
877
878ObjectPtr ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) {
879 DEBUG_ASSERT(Thread::Current()->TopErrorHandlerIsExitFrame());
880
881 Object& future = Object::Handle();
882 const Class& completer_cls = Class::Handle(completer.clazz());
883 ASSERT(!completer_cls.IsNull());
884 const Function& future_getter = Function::Handle(
885 completer_cls.LookupGetterFunction(Symbols::CompleterFuture()));
886 ASSERT(!future_getter.IsNull());
887 const Array& args = Array::Handle(Array::New(1));
888 args.SetAt(0, Instance::Cast(completer));
889 future = DartEntry::InvokeFunction(future_getter, args);
890 if (future.IsError()) {
891 Exceptions::PropagateError(Error::Cast(future));
892 }
893 if (future.IsNull()) {
894 // The completer object may not be fully initialized yet.
895 return Object::null();
896 }
897 const Class& future_cls = Class::Handle(future.clazz());
898 ASSERT(!future_cls.IsNull());
899 const Field& awaiter_field = Field::Handle(
900 future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
901 ASSERT(!awaiter_field.IsNull());
902 return Instance::Cast(future).GetField(awaiter_field);
903}
904
905ObjectPtr ActivationFrame::GetAsyncStreamControllerStream() {
906 return GetAsyncContextVariable(Symbols::ControllerStream());
907}
908
909ObjectPtr ActivationFrame::GetAsyncStreamControllerStreamAwaiter(
910 const Object& stream) {
911 const Class& stream_cls = Class::Handle(stream.clazz());
912 ASSERT(!stream_cls.IsNull());
913 const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass());
914 const Field& awaiter_field = Field::Handle(
915 stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
916 ASSERT(!awaiter_field.IsNull());
917 return Instance::Cast(stream).GetField(awaiter_field);
918}
919
920ObjectPtr ActivationFrame::GetAsyncAwaiter() {
921 const Object& async_stream_controller_stream =
922 Object::Handle(GetAsyncStreamControllerStream());
923 if (!async_stream_controller_stream.IsNull()) {
924 return GetAsyncStreamControllerStreamAwaiter(
925 async_stream_controller_stream);
926 }
927 const Object& completer = Object::Handle(GetAsyncCompleter());
928 if (!completer.IsNull()) {
929 return GetAsyncCompleterAwaiter(completer);
930 }
931 return Object::null();
932}
933
934ObjectPtr ActivationFrame::GetCausalStack() {
935 return GetAsyncContextVariable(Symbols::AsyncStackTraceVar());
936}
937
938bool ActivationFrame::HandlesException(const Instance& exc_obj) {
939 if ((kind_ == kAsyncSuspensionMarker) || (kind_ == kAsyncCausal)) {
940 // These frames are historical.
941 return false;
942 }
943 intptr_t try_index = TryIndex();
944 if (try_index < 0) {
945 return false;
946 }
947 ExceptionHandlers& handlers = ExceptionHandlers::Handle();
948 Array& handled_types = Array::Handle();
949 AbstractType& type = Type::Handle();
950 const bool is_async =
951 function().IsAsyncClosure() || function().IsAsyncGenClosure();
952 if (IsInterpreted()) {
953 handlers = bytecode().exception_handlers();
954 } else {
955 handlers = code().exception_handlers();
956 }
957 ASSERT(!handlers.IsNull());
958 intptr_t num_handlers_checked = 0;
959 while (try_index != kInvalidTryIndex) {
960 // Detect circles in the exception handler data.
961 num_handlers_checked++;
962 ASSERT(num_handlers_checked <= handlers.num_entries());
963 // Only consider user written handlers for async methods.
964 if (!is_async || !handlers.IsGenerated(try_index)) {
965 handled_types = handlers.GetHandledTypes(try_index);
966 const intptr_t num_types = handled_types.Length();
967 for (intptr_t k = 0; k < num_types; k++) {
968 type ^= handled_types.At(k);
969 ASSERT(!type.IsNull());
970 // Uninstantiated types are not added to ExceptionHandlers data.
971 ASSERT(type.IsInstantiated());
972 if (type.IsDynamicType()) {
973 return true;
974 }
975 if (exc_obj.IsInstanceOf(type, Object::null_type_arguments(),
976 Object::null_type_arguments())) {
977 return true;
978 }
979 }
980 }
981 try_index = handlers.OuterTryIndex(try_index);
982 }
983 return false;
984}
985
986intptr_t ActivationFrame::GetAwaitJumpVariable() {
987 GetVarDescriptors();
988 intptr_t var_ctxt_level = -1;
989 intptr_t ctxt_slot = -1;
990 intptr_t var_desc_len = var_descriptors_.Length();
991 intptr_t await_jump_var = -1;
992 for (intptr_t i = 0; i < var_desc_len; i++) {
993 LocalVarDescriptorsLayout::VarInfo var_info;
994 var_descriptors_.GetInfo(i, &var_info);
995 const int8_t kind = var_info.kind();
996 if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().raw()) {
997 ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
998 ASSERT(!ctx_.IsNull());
999 // Variable descriptors constructed from bytecode have all variables of
1000 // enclosing functions, even shadowed by the current function.
1001 // Pick the :await_jump_var variable with the highest context level.
1002 if (var_info.scope_id > var_ctxt_level) {
1003 var_ctxt_level = var_info.scope_id;
1004 ctxt_slot = var_info.index();
1005 }
1006 }
1007 }
1008 if (var_ctxt_level >= 0) {
1009 Object& await_jump_index = Object::Handle(ctx_.At(ctxt_slot));
1010 ASSERT(await_jump_index.IsSmi());
1011 await_jump_var = Smi::Cast(await_jump_index).Value();
1012 }
1013 return await_jump_var;
1014}
1015
1016void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
1017 // Attempt to determine the token pos and try index from the async closure.
1018 Thread* thread = Thread::Current();
1019 Zone* zone = thread->zone();
1020
1021 ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure());
1022 // This should only be called on frames that aren't active on the stack.
1023 ASSERT(fp() == 0);
1024
1025 if (function_.is_declared_in_bytecode()) {
1026#if !defined(DART_PRECOMPILED_RUNTIME)
1027 const auto& bytecode = Bytecode::Handle(zone, function_.bytecode());
1028 if (!bytecode.HasSourcePositions()) {
1029 return;
1030 }
1031 const intptr_t await_jump_var = GetAwaitJumpVariable();
1032 if (await_jump_var < 0) {
1033 return;
1034 }
1035 // Yield points are counted from 1 (0 is reserved for normal entry).
1036 intptr_t yield_point_index = 1;
1037 kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
1038 while (iter.MoveNext()) {
1039 if (iter.IsYieldPoint()) {
1040 if (yield_point_index == await_jump_var) {
1041 token_pos_ = iter.TokenPos();
1042 token_pos_initialized_ = true;
1043 const uword return_address =
1044 KernelBytecode::Next(bytecode.PayloadStart() + iter.PcOffset());
1045 try_index_ = bytecode.GetTryIndexAtPc(return_address);
1046 return;
1047 }
1048 ++yield_point_index;
1049 }
1050 }
1051 return;
1052#else
1053 UNREACHABLE();
1054#endif // !defined(DART_PRECOMPILED_RUNTIME)
1055 }
1056
1057 ASSERT(!IsInterpreted());
1058 const intptr_t await_jump_var = GetAwaitJumpVariable();
1059 if (await_jump_var < 0) {
1060 return;
1061 }
1062
1063 const auto& pc_descriptors =
1064 PcDescriptors::Handle(zone, code().pc_descriptors());
1065 ASSERT(!pc_descriptors.IsNull());
1066 PcDescriptors::Iterator it(pc_descriptors, PcDescriptorsLayout::kOther);
1067 while (it.MoveNext()) {
1068 if (it.YieldIndex() == await_jump_var) {
1069 try_index_ = it.TryIndex();
1070 token_pos_ = it.TokenPos();
1071 token_pos_initialized_ = true;
1072 return;
1073 }
1074 }
1075}
1076
1077bool ActivationFrame::IsAsyncMachinery() const {
1078 if (function_.IsNull()) {
1079 ASSERT(IsInterpreted()); // This frame is a bytecode stub frame.
1080 return false;
1081 }
1082 Isolate* isolate = Isolate::Current();
1083 if (function_.raw() == isolate->object_store()->complete_on_async_return()) {
1084 // We are completing an async function's completer.
1085 return true;
1086 }
1087 if (function_.Owner() ==
1088 isolate->object_store()->async_star_stream_controller()) {
1089 // We are inside the async* stream controller code.
1090 return true;
1091 }
1092 return false;
1093}
1094
1095// Get the saved current context of this activation.
1096const Context& ActivationFrame::GetSavedCurrentContext() {
1097 if (!ctx_.IsNull()) return ctx_;
1098 GetVarDescriptors();
1099 intptr_t var_desc_len = var_descriptors_.Length();
1100 Object& obj = Object::Handle();
1101 for (intptr_t i = 0; i < var_desc_len; i++) {
1102 LocalVarDescriptorsLayout::VarInfo var_info;
1103 var_descriptors_.GetInfo(i, &var_info);
1104 const int8_t kind = var_info.kind();
1105 if (kind == LocalVarDescriptorsLayout::kSavedCurrentContext) {
1106 if (FLAG_trace_debugger_stacktrace) {
1107 OS::PrintErr("\tFound saved current ctx at index %d\n",
1108 var_info.index());
1109 }
1110 const auto variable_index = VariableIndex(var_info.index());
1111 obj = GetStackVar(variable_index);
1112 if (obj.IsClosure()) {
1113 ASSERT(function().name() == Symbols::Call().raw());
1114 ASSERT(function().IsInvokeFieldDispatcher());
1115 // Closure.call frames.
1116 ctx_ = Closure::Cast(obj).context();
1117 } else if (obj.IsContext()) {
1118 ctx_ = Context::Cast(obj).raw();
1119 } else {
1120 ASSERT(obj.IsNull() || obj.raw() == Symbols::OptimizedOut().raw());
1121 ctx_ = Context::null();
1122 }
1123 return ctx_;
1124 }
1125 }
1126 return ctx_;
1127}
1128
1129ObjectPtr ActivationFrame::GetAsyncOperation() {
1130 if (function().name() == Symbols::AsyncOperation().raw()) {
1131 return GetParameter(0);
1132 }
1133 return Object::null();
1134}
1135
1136ActivationFrame* DebuggerStackTrace::GetHandlerFrame(
1137 const Instance& exc_obj) const {
1138 for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) {
1139 ActivationFrame* frame = FrameAt(frame_index);
1140 if (FLAG_trace_debugger_stacktrace) {
1141 OS::PrintErr("GetHandlerFrame: #%04" Pd " %s", frame_index,
1142 frame->ToCString());
1143 }
1144 if (frame->HandlesException(exc_obj)) {
1145 return frame;
1146 }
1147 }
1148 return NULL;
1149}
1150
1151void ActivationFrame::GetDescIndices() {
1152 if (vars_initialized_) {
1153 return;
1154 }
1155 GetVarDescriptors();
1156
1157 TokenPosition activation_token_pos = TokenPos();
1158 if (!activation_token_pos.IsDebugPause() || !live_frame_) {
1159 // We don't have a token position for this frame, so can't determine
1160 // which variables are visible.
1161 vars_initialized_ = true;
1162 return;
1163 }
1164
1165 GrowableArray<String*> var_names(8);
1166 intptr_t var_desc_len = var_descriptors_.Length();
1167 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
1168 ASSERT(var_names.length() == desc_indices_.length());
1169 LocalVarDescriptorsLayout::VarInfo var_info;
1170 var_descriptors_.GetInfo(cur_idx, &var_info);
1171 const int8_t kind = var_info.kind();
1172 if ((kind != LocalVarDescriptorsLayout::kStackVar) &&
1173 (kind != LocalVarDescriptorsLayout::kContextVar)) {
1174 continue;
1175 }
1176 if ((var_info.begin_pos <= activation_token_pos) &&
1177 (activation_token_pos <= var_info.end_pos)) {
1178 if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
1179 (ContextLevel() < var_info.scope_id)) {
1180 // The variable is textually in scope but the context level
1181 // at the activation frame's PC is lower than the context
1182 // level of the variable. The context containing the variable
1183 // has already been removed from the chain. This can happen when we
1184 // break at a return statement, since the contexts get discarded
1185 // before the debugger gets called.
1186 continue;
1187 }
1188 // The current variable is textually in scope. Now check whether
1189 // there is another local variable with the same name that shadows
1190 // or is shadowed by this variable.
1191 String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
1192 intptr_t indices_len = desc_indices_.length();
1193 bool name_match_found = false;
1194 for (intptr_t i = 0; i < indices_len; i++) {
1195 if (var_name.Equals(*var_names[i])) {
1196 // Found two local variables with the same name. Now determine
1197 // which one is shadowed.
1198 name_match_found = true;
1199 LocalVarDescriptorsLayout::VarInfo i_var_info;
1200 var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
1201 if (i_var_info.begin_pos < var_info.begin_pos) {
1202 // The variable we found earlier is in an outer scope
1203 // and is shadowed by the current variable. Replace the
1204 // descriptor index of the previously found variable
1205 // with the descriptor index of the current variable.
1206 desc_indices_[i] = cur_idx;
1207 } else {
1208 // The variable we found earlier is in an inner scope
1209 // and shadows the current variable. Skip the current
1210 // variable. (Nothing to do.)
1211 }
1212 break; // Stop looking for name matches.
1213 }
1214 }
1215 if (!name_match_found) {
1216 // No duplicate name found. Add the current descriptor index to the
1217 // list of visible variables.
1218 desc_indices_.Add(cur_idx);
1219 var_names.Add(&var_name);
1220 }
1221 }
1222 }
1223 vars_initialized_ = true;
1224}
1225
1226intptr_t ActivationFrame::NumLocalVariables() {
1227 GetDescIndices();
1228 return desc_indices_.length();
1229}
1230
1231DART_FORCE_INLINE static ObjectPtr GetVariableValue(uword addr) {
1232 return *reinterpret_cast<ObjectPtr*>(addr);
1233}
1234
1235// Caution: GetParameter only works for fixed parameters.
1236ObjectPtr ActivationFrame::GetParameter(intptr_t index) {
1237 intptr_t num_parameters = function().num_fixed_parameters();
1238 ASSERT(0 <= index && index < num_parameters);
1239
1240 if (IsInterpreted()) {
1241 if (function().NumOptionalParameters() > 0) {
1242 // Note that we do not access optional but only fixed parameters, hence
1243 // we do not need to replicate the logic of IndexFor() in bytecode reader.
1244 return GetVariableValue(fp() + index * kWordSize);
1245 } else {
1246 return GetVariableValue(
1247 fp() - (kKBCParamEndSlotFromFp + num_parameters - index) * kWordSize);
1248 }
1249 }
1250
1251 if (function().NumOptionalParameters() > 0) {
1252 // If the function has optional parameters, the first positional parameter
1253 // can be in a number of places in the caller's frame depending on how many
1254 // were actually supplied at the call site, but they are copied to a fixed
1255 // place in the callee's frame.
1256
1257 return GetVariableValue(LocalVarAddress(
1258 fp(), runtime_frame_layout.FrameSlotForVariableIndex(-index)));
1259 } else {
1260 intptr_t reverse_index = num_parameters - index;
1261 return GetVariableValue(ParamAddress(fp(), reverse_index));
1262 }
1263}
1264
1265ObjectPtr ActivationFrame::GetClosure() {
1266 ASSERT(function().IsClosureFunction());
1267 return GetParameter(0);
1268}
1269
1270ObjectPtr ActivationFrame::GetStackVar(VariableIndex variable_index) {
1271 if (IsInterpreted()) {
1272 intptr_t slot_index = -variable_index.value();
1273 if (slot_index < 0) {
1274 slot_index -= kKBCParamEndSlotFromFp; // Accessing a parameter.
1275 }
1276 return GetVariableValue(fp() + slot_index * kWordSize);
1277 }
1278 const intptr_t slot_index =
1279 runtime_frame_layout.FrameSlotForVariableIndex(variable_index.value());
1280 if (deopt_frame_.IsNull()) {
1281 return GetVariableValue(LocalVarAddress(fp(), slot_index));
1282 } else {
1283 return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index));
1284 }
1285}
1286
1287bool ActivationFrame::IsRewindable() const {
1288 if (deopt_frame_.IsNull()) {
1289 return true;
1290 }
1291 // TODO(turnidge): This is conservative. It looks at all values in
1292 // the deopt_frame_ even though some of them may correspond to other
1293 // inlined frames.
1294 Object& obj = Object::Handle();
1295 for (int i = 0; i < deopt_frame_.Length(); i++) {
1296 obj = deopt_frame_.At(i);
1297 if (obj.raw() == Symbols::OptimizedOut().raw()) {
1298 return false;
1299 }
1300 }
1301 return true;
1302}
1303
1304void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot,
1305 intptr_t frame_ctx_level,
1306 intptr_t var_ctx_level) {
1307 OS::PrintErr(
1308 "-------------------------\n"
1309 "Encountered context mismatch\n"
1310 "\tctx_slot: %" Pd
1311 "\n"
1312 "\tframe_ctx_level: %" Pd
1313 "\n"
1314 "\tvar_ctx_level: %" Pd "\n\n",
1315 ctx_slot, frame_ctx_level, var_ctx_level);
1316
1317 OS::PrintErr(
1318 "-------------------------\n"
1319 "Current frame:\n%s\n",
1320 this->ToCString());
1321
1322 OS::PrintErr(
1323 "-------------------------\n"
1324 "Context contents:\n");
1325 const Context& ctx = GetSavedCurrentContext();
1326 ctx.Dump(8);
1327
1328 OS::PrintErr(
1329 "-------------------------\n"
1330 "Debugger stack trace...\n\n");
1331 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
1332 intptr_t num_frames = stack->Length();
1333 for (intptr_t i = 0; i < num_frames; i++) {
1334 ActivationFrame* frame = stack->FrameAt(i);
1335 OS::PrintErr("#%04" Pd " %s", i, frame->ToCString());
1336 }
1337
1338 OS::PrintErr(
1339 "-------------------------\n"
1340 "All frames...\n\n");
1341 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
1342 Thread::Current(),
1343 StackFrameIterator::kNoCrossThreadIteration);
1344 StackFrame* frame = iterator.NextFrame();
1345 intptr_t num = 0;
1346 while ((frame != NULL)) {
1347 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
1348 frame = iterator.NextFrame();
1349 }
1350}
1351
1352void ActivationFrame::VariableAt(intptr_t i,
1353 String* name,
1354 TokenPosition* declaration_token_pos,
1355 TokenPosition* visible_start_token_pos,
1356 TokenPosition* visible_end_token_pos,
1357 Object* value) {
1358 GetDescIndices();
1359 ASSERT(i < desc_indices_.length());
1360 intptr_t desc_index = desc_indices_[i];
1361 ASSERT(name != NULL);
1362
1363 *name = var_descriptors_.GetName(desc_index);
1364
1365 LocalVarDescriptorsLayout::VarInfo var_info;
1366 var_descriptors_.GetInfo(desc_index, &var_info);
1367 ASSERT(declaration_token_pos != NULL);
1368 *declaration_token_pos = var_info.declaration_pos;
1369 ASSERT(visible_start_token_pos != NULL);
1370 *visible_start_token_pos = var_info.begin_pos;
1371 ASSERT(visible_end_token_pos != NULL);
1372 *visible_end_token_pos = var_info.end_pos;
1373 ASSERT(value != NULL);
1374 const int8_t kind = var_info.kind();
1375 const auto variable_index = VariableIndex(var_info.index());
1376 if (kind == LocalVarDescriptorsLayout::kStackVar) {
1377 *value = GetStackVar(variable_index);
1378 } else {
1379 ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
1380 *value = GetContextVar(var_info.scope_id, variable_index.value());
1381 }
1382}
1383
1384ObjectPtr ActivationFrame::GetContextVar(intptr_t var_ctx_level,
1385 intptr_t ctx_slot) {
1386 // The context level at the PC/token index of this activation frame.
1387 intptr_t frame_ctx_level = ContextLevel();
1388
1389 return GetRelativeContextVar(var_ctx_level, ctx_slot, frame_ctx_level);
1390}
1391
1392ObjectPtr ActivationFrame::GetRelativeContextVar(intptr_t var_ctx_level,
1393 intptr_t ctx_slot,
1394 intptr_t frame_ctx_level) {
1395 const Context& ctx = GetSavedCurrentContext();
1396
1397 // It's possible that ctx was optimized out as no locals were captured by the
1398 // context. See issue #38182.
1399 if (ctx.IsNull()) {
1400 return Symbols::OptimizedOut().raw();
1401 }
1402
1403 intptr_t level_diff = frame_ctx_level - var_ctx_level;
1404 if (level_diff == 0) {
1405 if ((ctx_slot < 0) || (ctx_slot >= ctx.num_variables())) {
1406 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1407 }
1408 ASSERT((ctx_slot >= 0) && (ctx_slot < ctx.num_variables()));
1409 return ctx.At(ctx_slot);
1410 } else if (level_diff > 0) {
1411 Context& var_ctx = Context::Handle(ctx.raw());
1412 while (level_diff > 0 && !var_ctx.IsNull()) {
1413 level_diff--;
1414 var_ctx = var_ctx.parent();
1415 }
1416 if (var_ctx.IsNull() || (ctx_slot < 0) ||
1417 (ctx_slot >= var_ctx.num_variables())) {
1418 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1419 }
1420 ASSERT(!var_ctx.IsNull());
1421 ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
1422 return var_ctx.At(ctx_slot);
1423 } else {
1424 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
1425 return Object::null();
1426 }
1427}
1428
1429ArrayPtr ActivationFrame::GetLocalVariables() {
1430 GetDescIndices();
1431 intptr_t num_variables = desc_indices_.length();
1432 String& var_name = String::Handle();
1433 Object& value = Instance::Handle();
1434 const Array& list = Array::Handle(Array::New(2 * num_variables));
1435 for (intptr_t i = 0; i < num_variables; i++) {
1436 TokenPosition ignore;
1437 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
1438 list.SetAt(2 * i, var_name);
1439 list.SetAt((2 * i) + 1, value);
1440 }
1441 return list.raw();
1442}
1443
1444ObjectPtr ActivationFrame::GetReceiver() {
1445 GetDescIndices();
1446 intptr_t num_variables = desc_indices_.length();
1447 String& var_name = String::Handle();
1448 Instance& value = Instance::Handle();
1449 for (intptr_t i = 0; i < num_variables; i++) {
1450 TokenPosition ignore;
1451 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
1452 if (var_name.Equals(Symbols::This())) {
1453 return value.raw();
1454 }
1455 }
1456 return Symbols::OptimizedOut().raw();
1457}
1458
1459static bool IsSyntheticVariableName(const String& var_name) {
1460 return (var_name.Length() >= 1) && (var_name.CharAt(0) == ':');
1461}
1462
1463static bool IsPrivateVariableName(const String& var_name) {
1464 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_');
1465}
1466
1467ObjectPtr ActivationFrame::EvaluateCompiledExpression(
1468 const ExternalTypedData& kernel_buffer,
1469 const Array& type_definitions,
1470 const Array& arguments,
1471 const TypeArguments& type_arguments) {
1472 if (function().is_static()) {
1473 const Class& cls = Class::Handle(function().Owner());
1474 return cls.EvaluateCompiledExpression(kernel_buffer, type_definitions,
1475 arguments, type_arguments);
1476 } else {
1477 const Object& receiver = Object::Handle(GetReceiver());
1478 const Class& method_cls = Class::Handle(function().origin());
1479 ASSERT(receiver.IsInstance() || receiver.IsNull());
1480 if (!(receiver.IsInstance() || receiver.IsNull())) {
1481 return Object::null();
1482 }
1483 const Instance& inst = Instance::Cast(receiver);
1484 return inst.EvaluateCompiledExpression(
1485 method_cls, kernel_buffer, type_definitions, arguments, type_arguments);
1486 }
1487}
1488
1489TypeArgumentsPtr ActivationFrame::BuildParameters(
1490 const GrowableObjectArray& param_names,
1491 const GrowableObjectArray& param_values,
1492 const GrowableObjectArray& type_params_names) {
1493 GetDescIndices();
1494 bool type_arguments_available = false;
1495 String& name = String::Handle();
1496 String& existing_name = String::Handle();
1497 Object& value = Instance::Handle();
1498 TypeArguments& type_arguments = TypeArguments::Handle();
1499 intptr_t num_variables = desc_indices_.length();
1500 for (intptr_t i = 0; i < num_variables; i++) {
1501 TokenPosition ignore;
1502 VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
1503 if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
1504 type_arguments_available = true;
1505 type_arguments ^= value.raw();
1506 } else if (!name.Equals(Symbols::This()) &&
1507 !IsSyntheticVariableName(name)) {
1508 if (IsPrivateVariableName(name)) {
1509 name = Symbols::New(Thread::Current(), String::ScrubName(name));
1510 }
1511 bool conflict = false;
1512 for (intptr_t j = 0; j < param_names.Length(); j++) {
1513 existing_name ^= param_names.At(j);
1514 if (name.Equals(existing_name)) {
1515 conflict = true;
1516 break;
1517 }
1518 }
1519 // If local has the same name as a binding in the incoming scope, prefer
1520 // the one from the incoming scope, since it is logically a child scope
1521 // of the activation's current scope.
1522 if (!conflict) {
1523 param_names.Add(name);
1524 param_values.Add(value);
1525 }
1526 }
1527 }
1528
1529 if ((function().IsGeneric() || function().HasGenericParent()) &&
1530 type_arguments_available) {
1531 intptr_t num_vars =
1532 function().NumTypeParameters() + function().NumParentTypeParameters();
1533 type_params_names.Grow(num_vars);
1534 type_params_names.SetLength(num_vars);
1535 TypeArguments& type_params = TypeArguments::Handle();
1536 TypeParameter& type_param = TypeParameter::Handle();
1537 Function& current = Function::Handle(function().raw());
1538 intptr_t mapping_offset = num_vars;
1539 for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
1540 current = current.parent_function()) {
1541 type_params = current.type_parameters();
1542 intptr_t size = current.NumTypeParameters();
1543 ASSERT(mapping_offset >= size);
1544 mapping_offset -= size;
1545 for (intptr_t j = 0; j < size; ++j) {
1546 type_param = TypeParameter::RawCast(type_params.TypeAt(j));
1547 name = type_param.name();
1548 // Write the names in backwards in terms of chain of functions.
1549 // But keep the order of names within the same function. so they
1550 // match up with the order of the types in 'type_arguments'.
1551 // Index:0 1 2 3 ...
1552 // |Names in Grandparent| |Names in Parent| ..|Names in Child|
1553 type_params_names.SetAt(mapping_offset + j, name);
1554 }
1555 }
1556 if (!type_arguments.IsNull()) {
1557 if (type_arguments.Length() == 0) {
1558 for (intptr_t i = 0; i < num_vars; ++i) {
1559 type_arguments.SetTypeAt(i, Object::dynamic_type());
1560 }
1561 }
1562 ASSERT(type_arguments.Length() == num_vars);
1563 }
1564 }
1565
1566 return type_arguments.raw();
1567}
1568
1569const char* ActivationFrame::ToCString() {
1570 if (function().IsNull()) {
1571 return Thread::Current()->zone()->PrintToString("[ Frame kind: %s]\n",
1572 KindToCString(kind_));
1573 }
1574 const String& url = String::Handle(SourceUrl());
1575 intptr_t line = LineNumber();
1576 const char* func_name = function().ToFullyQualifiedCString();
1577 if (live_frame_) {
1578 return Thread::Current()->zone()->PrintToString(
1579 "[ Frame pc(0x%" Px " %s offset:0x%" Px ") fp(0x%" Px ") sp(0x%" Px
1580 ")\n"
1581 "\tfunction = %s\n"
1582 "\turl = %s\n"
1583 "\tline = %" Pd
1584 "\n"
1585 "\tcontext = %s\n"
1586 "\tcontext level = %" Pd " ]\n",
1587 pc(), IsInterpreted() ? "bytecode" : "code",
1588 pc() - (IsInterpreted() ? bytecode().PayloadStart()
1589 : code().PayloadStart()),
1590 fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(),
1591 ContextLevel());
1592 } else {
1593 return Thread::Current()->zone()->PrintToString(
1594 "[ Frame %s function = %s\n"
1595 "\turl = %s\n"
1596 "\tline = %" Pd
1597 "\n"
1598 "\tcontext = %s]\n",
1599 IsInterpreted() ? "bytecode" : "code", func_name, url.ToCString(), line,
1600 ctx_.ToCString());
1601 }
1602}
1603
1604void ActivationFrame::PrintToJSONObject(JSONObject* jsobj) {
1605 if (kind_ == kRegular || kind_ == kAsyncActivation) {
1606 PrintToJSONObjectRegular(jsobj);
1607 } else if (kind_ == kAsyncCausal) {
1608 PrintToJSONObjectAsyncCausal(jsobj);
1609 } else if (kind_ == kAsyncSuspensionMarker) {
1610 PrintToJSONObjectAsyncSuspensionMarker(jsobj);
1611 } else {
1612 UNIMPLEMENTED();
1613 }
1614}
1615
1616void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj) {
1617 const Script& script = Script::Handle(SourceScript());
1618 jsobj->AddProperty("type", "Frame");
1619 jsobj->AddProperty("kind", KindToCString(kind_));
1620 const TokenPosition pos = TokenPos().SourcePosition();
1621 jsobj->AddLocation(script, pos);
1622 jsobj->AddProperty("function", function());
1623 if (IsInterpreted()) {
1624 jsobj->AddProperty("code", bytecode());
1625 } else {
1626 jsobj->AddProperty("code", code());
1627 }
1628 {
1629 JSONArray jsvars(jsobj, "vars");
1630 const int num_vars = NumLocalVariables();
1631 for (intptr_t v = 0; v < num_vars; v++) {
1632 String& var_name = String::Handle();
1633 Instance& var_value = Instance::Handle();
1634 TokenPosition declaration_token_pos;
1635 TokenPosition visible_start_token_pos;
1636 TokenPosition visible_end_token_pos;
1637 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
1638 &visible_end_token_pos, &var_value);
1639 if (!IsSyntheticVariableName(var_name)) {
1640 JSONObject jsvar(&jsvars);
1641 jsvar.AddProperty("type", "BoundVariable");
1642 const char* scrubbed_var_name = String::ScrubName(var_name);
1643 jsvar.AddProperty("name", scrubbed_var_name);
1644 jsvar.AddProperty("value", var_value);
1645 // Where was the variable declared?
1646 jsvar.AddProperty("declarationTokenPos", declaration_token_pos);
1647 // When the variable becomes visible to the scope.
1648 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos);
1649 // When the variable stops being visible to the scope.
1650 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos);
1651 }
1652 }
1653 }
1654}
1655
1656void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj) {
1657 jsobj->AddProperty("type", "Frame");
1658 jsobj->AddProperty("kind", KindToCString(kind_));
1659 const Script& script = Script::Handle(SourceScript());
1660 const TokenPosition pos = TokenPos().SourcePosition();
1661 jsobj->AddLocation(script, pos);
1662 jsobj->AddProperty("function", function());
1663 if (IsInterpreted()) {
1664 jsobj->AddProperty("code", bytecode());
1665 } else {
1666 jsobj->AddProperty("code", code());
1667 }
1668}
1669
1670void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
1671 JSONObject* jsobj) {
1672 jsobj->AddProperty("type", "Frame");
1673 jsobj->AddProperty("kind", KindToCString(kind_));
1674 jsobj->AddProperty("marker", "AsynchronousSuspension");
1675}
1676
1677static bool IsFunctionVisible(const Function& function) {
1678 return FLAG_show_invisible_frames || function.is_visible();
1679}
1680
1681void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
1682 if (IsFunctionVisible(frame->function())) {
1683 trace_.Add(frame);
1684 }
1685}
1686
1687void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) {
1688 ASSERT(marker == ActivationFrame::kAsyncSuspensionMarker);
1689 trace_.Add(new ActivationFrame(marker));
1690}
1691
1692void DebuggerStackTrace::AddAsyncCausalFrame(uword pc, const Code& code) {
1693 trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0,
1694 ActivationFrame::kAsyncCausal));
1695}
1696
1697#if !defined(DART_PRECOMPILED_RUNTIME)
1698void DebuggerStackTrace::AddAsyncCausalFrame(uword pc,
1699 const Bytecode& bytecode) {
1700 trace_.Add(
1701 new ActivationFrame(pc, 0, 0, bytecode, ActivationFrame::kAsyncCausal));
1702}
1703#endif // !defined(DART_PRECOMPILED_RUNTIME)
1704
1705const uint8_t kSafepointKind = PcDescriptorsLayout::kIcCall |
1706 PcDescriptorsLayout::kUnoptStaticCall |
1707 PcDescriptorsLayout::kRuntimeCall;
1708
1709CodeBreakpoint::CodeBreakpoint(const Code& code,
1710 TokenPosition token_pos,
1711 uword pc,
1712 PcDescriptorsLayout::Kind kind)
1713 : code_(code.raw()),
1714 bytecode_(Bytecode::null()),
1715 token_pos_(token_pos),
1716 pc_(pc),
1717 line_number_(-1),
1718 is_enabled_(false),
1719 bpt_location_(NULL),
1720 next_(NULL),
1721 breakpoint_kind_(kind),
1722 saved_value_(Code::null()) {
1723 ASSERT(!code.IsNull());
1724 ASSERT(token_pos_.IsReal());
1725 ASSERT(pc_ != 0);
1726 ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
1727}
1728
1729CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
1730 TokenPosition token_pos,
1731 uword pc)
1732 : code_(Code::null()),
1733 bytecode_(bytecode.raw()),
1734 token_pos_(token_pos),
1735 pc_(pc),
1736 line_number_(-1),
1737 is_enabled_(false),
1738 bpt_location_(NULL),
1739 next_(NULL),
1740 breakpoint_kind_(PcDescriptorsLayout::kAnyKind),
1741 saved_value_(Code::null()) {
1742 ASSERT(!bytecode.IsNull());
1743 ASSERT(FLAG_enable_interpreter);
1744 ASSERT(token_pos_.IsReal());
1745 ASSERT(pc_ != 0);
1746}
1747
1748CodeBreakpoint::~CodeBreakpoint() {
1749 // Make sure we don't leave patched code behind.
1750 ASSERT(!IsEnabled());
1751// Poison the data so we catch use after free errors.
1752#ifdef DEBUG
1753 code_ = Code::null();
1754 bytecode_ = Bytecode::null();
1755 pc_ = 0ul;
1756 bpt_location_ = NULL;
1757 next_ = NULL;
1758 breakpoint_kind_ = PcDescriptorsLayout::kOther;
1759#endif
1760}
1761
1762FunctionPtr CodeBreakpoint::function() const {
1763 if (IsInterpreted()) {
1764 ASSERT(Bytecode::Handle(bytecode_).function() != Function::null());
1765 return Bytecode::Handle(bytecode_).function();
1766 } else {
1767 return Code::Handle(code_).function();
1768 }
1769}
1770
1771ScriptPtr CodeBreakpoint::SourceCode() {
1772 const Function& func = Function::Handle(this->function());
1773 return func.script();
1774}
1775
1776StringPtr CodeBreakpoint::SourceUrl() {
1777 const Script& script = Script::Handle(SourceCode());
1778 return script.url();
1779}
1780
1781intptr_t CodeBreakpoint::LineNumber() {
1782 // Compute line number lazily since it causes scanning of the script.
1783 if (line_number_ < 0) {
1784 const Script& script = Script::Handle(SourceCode());
1785 script.GetTokenLocation(token_pos_, &line_number_, NULL);
1786 }
1787 return line_number_;
1788}
1789
1790void CodeBreakpoint::Enable() {
1791 if (!is_enabled_) {
1792 if (IsInterpreted()) {
1793#if !defined(DART_PRECOMPILED_RUNTIME)
1794 SetBytecodeBreakpoint();
1795#else
1796 UNREACHABLE();
1797#endif // !defined(DART_PRECOMPILED_RUNTIME)
1798 } else {
1799 PatchCode();
1800 }
1801 }
1802 ASSERT(is_enabled_);
1803}
1804
1805void CodeBreakpoint::Disable() {
1806 if (is_enabled_) {
1807 if (IsInterpreted()) {
1808#if !defined(DART_PRECOMPILED_RUNTIME)
1809 UnsetBytecodeBreakpoint();
1810#else
1811 UNREACHABLE();
1812#endif // !defined(DART_PRECOMPILED_RUNTIME)
1813 } else {
1814 RestoreCode();
1815 }
1816 }
1817 ASSERT(!is_enabled_);
1818}
1819
1820Debugger::Debugger(Isolate* isolate)
1821 : isolate_(isolate),
1822 next_id_(1),
1823 latent_locations_(NULL),
1824 breakpoint_locations_(NULL),
1825 code_breakpoints_(NULL),
1826 resume_action_(kContinue),
1827 resume_frame_index_(-1),
1828 post_deopt_frame_index_(-1),
1829 ignore_breakpoints_(false),
1830 pause_event_(NULL),
1831 stack_trace_(NULL),
1832 async_causal_stack_trace_(NULL),
1833 awaiter_stack_trace_(NULL),
1834 stepping_fp_(0),
1835 interpreted_stepping_(false),
1836 last_stepping_fp_(0),
1837 last_stepping_pos_(TokenPosition::kNoSource),
1838 async_stepping_fp_(0),
1839 interpreted_async_stepping_(false),
1840 top_frame_awaiter_(Object::null()),
1841 skip_next_step_(false),
1842 needs_breakpoint_cleanup_(false),
1843 synthetic_async_breakpoint_(NULL),
1844 exc_pause_info_(kNoPauseOnExceptions) {}
1845
1846Debugger::~Debugger() {
1847 ASSERT(!IsPaused());
1848 ASSERT(latent_locations_ == NULL);
1849 ASSERT(breakpoint_locations_ == NULL);
1850 ASSERT(code_breakpoints_ == NULL);
1851 ASSERT(stack_trace_ == NULL);
1852 ASSERT(async_causal_stack_trace_ == NULL);
1853 ASSERT(synthetic_async_breakpoint_ == NULL);
1854}
1855
1856void Debugger::Shutdown() {
1857 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need
1858 // them. Then, assert here that isolate_ is not one of those isolates.
1859 if (Isolate::IsVMInternalIsolate(isolate_)) {
1860 return;
1861 }
1862 while (breakpoint_locations_ != NULL) {
1863 BreakpointLocation* loc = breakpoint_locations_;
1864 breakpoint_locations_ = breakpoint_locations_->next();
1865 delete loc;
1866 }
1867 while (latent_locations_ != NULL) {
1868 BreakpointLocation* loc = latent_locations_;
1869 latent_locations_ = latent_locations_->next();
1870 delete loc;
1871 }
1872 while (code_breakpoints_ != NULL) {
1873 CodeBreakpoint* cbpt = code_breakpoints_;
1874 code_breakpoints_ = code_breakpoints_->next();
1875 cbpt->Disable();
1876 delete cbpt;
1877 }
1878 if (NeedsIsolateEvents()) {
1879 ServiceEvent event(isolate_, ServiceEvent::kIsolateExit);
1880 InvokeEventHandler(&event);
1881 }
1882}
1883
1884void Debugger::OnIsolateRunnable() {}
1885
1886bool Debugger::SetupStepOverAsyncSuspension(const char** error) {
1887 ActivationFrame* top_frame = TopDartFrame();
1888 if (!IsAtAsyncJump(top_frame)) {
1889 // Not at an async operation.
1890 if (error != nullptr) {
1891 *error = "Isolate must be paused at an async suspension point";
1892 }
1893 return false;
1894 }
1895 Object& closure = Object::Handle(top_frame->GetAsyncOperation());
1896 ASSERT(!closure.IsNull());
1897 ASSERT(closure.IsInstance());
1898 ASSERT(Instance::Cast(closure).IsClosure());
1899 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
1900 if (bpt == NULL) {
1901 // Unable to set the breakpoint.
1902 if (error != nullptr) {
1903 *error = "Unable to set breakpoint at async suspension point";
1904 }
1905 return false;
1906 }
1907 return true;
1908}
1909
1910bool Debugger::SetResumeAction(ResumeAction action,
1911 intptr_t frame_index,
1912 const char** error) {
1913 if (error != nullptr) {
1914 *error = NULL;
1915 }
1916 resume_frame_index_ = -1;
1917 switch (action) {
1918 case kStepInto:
1919 case kStepOver:
1920 case kStepOut:
1921 case kContinue:
1922 resume_action_ = action;
1923 return true;
1924 case kStepRewind:
1925 if (!CanRewindFrame(frame_index, error)) {
1926 return false;
1927 }
1928 resume_action_ = kStepRewind;
1929 resume_frame_index_ = frame_index;
1930 return true;
1931 case kStepOverAsyncSuspension:
1932 return SetupStepOverAsyncSuspension(error);
1933 default:
1934 UNREACHABLE();
1935 return false;
1936 }
1937}
1938
1939// Deoptimize all functions in the isolate.
1940// TODO(hausner): Actually we only need to deoptimize those functions
1941// that inline the function that contains the newly created breakpoint.
1942// We currently don't have this info so we deoptimize all functions.
1943void Debugger::DeoptimizeWorld() {
1944#if defined(DART_PRECOMPILED_RUNTIME)
1945 UNREACHABLE();
1946#else
1947 BackgroundCompiler::Stop(isolate_);
1948 if (FLAG_trace_deoptimization) {
1949 THR_Print("Deopt for debugger\n");
1950 }
1951 isolate_->set_has_attempted_stepping(true);
1952
1953 DeoptimizeFunctionsOnStack();
1954
1955 // Iterate over all classes, deoptimize functions.
1956 // TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
1957 const ClassTable& class_table = *isolate_->class_table();
1958 Zone* zone = Thread::Current()->zone();
1959 CallSiteResetter resetter(zone);
1960 Class& cls = Class::Handle(zone);
1961 Array& functions = Array::Handle(zone);
1962 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
1963 Function& function = Function::Handle(zone);
1964 Code& code = Code::Handle(zone);
1965
1966 const intptr_t num_classes = class_table.NumCids();
1967 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
1968 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
1969 const classid_t cid =
1970 i < num_classes ? i : ClassTable::CidFromTopLevelIndex(i - num_classes);
1971 if (class_table.HasValidClassAt(cid)) {
1972 cls = class_table.At(cid);
1973
1974 // Disable optimized functions.
1975 functions = cls.functions();
1976 if (!functions.IsNull()) {
1977 intptr_t num_functions = functions.Length();
1978 for (intptr_t pos = 0; pos < num_functions; pos++) {
1979 function ^= functions.At(pos);
1980 ASSERT(!function.IsNull());
1981 // Force-optimized functions don't have unoptimized code and can't
1982 // deoptimize. Their optimized codes are still valid.
1983 if (function.ForceOptimize()) {
1984 ASSERT(!function.HasImplicitClosureFunction());
1985 continue;
1986 }
1987 if (function.HasOptimizedCode()) {
1988 function.SwitchToUnoptimizedCode();
1989 }
1990 code = function.unoptimized_code();
1991 if (!code.IsNull()) {
1992 resetter.ResetSwitchableCalls(code);
1993 }
1994 // Also disable any optimized implicit closure functions.
1995 if (function.HasImplicitClosureFunction()) {
1996 function = function.ImplicitClosureFunction();
1997 if (function.HasOptimizedCode()) {
1998 function.SwitchToUnoptimizedCode();
1999 }
2000 code = function.unoptimized_code();
2001 if (!code.IsNull()) {
2002 resetter.ResetSwitchableCalls(code);
2003 }
2004 }
2005 }
2006 }
2007 }
2008 }
2009
2010 // Disable optimized closure functions.
2011 closures = isolate_->object_store()->closure_functions();
2012 const intptr_t num_closures = closures.Length();
2013 for (intptr_t pos = 0; pos < num_closures; pos++) {
2014 function ^= closures.At(pos);
2015 ASSERT(!function.IsNull());
2016 if (function.HasOptimizedCode()) {
2017 function.SwitchToUnoptimizedCode();
2018 }
2019 code = function.unoptimized_code();
2020 if (!code.IsNull()) {
2021 resetter.ResetSwitchableCalls(code);
2022 }
2023 }
2024#endif // defined(DART_PRECOMPILED_RUNTIME)
2025}
2026
2027void Debugger::NotifySingleStepping(bool value) const {
2028 isolate_->set_single_step(value);
2029#if !defined(DART_PRECOMPILED_RUNTIME)
2030 // Do not call Interpreter::Current(), which may allocate an interpreter.
2031 Interpreter* interpreter = Thread::Current()->interpreter();
2032 if (interpreter != nullptr) {
2033 // Do not reset is_debugging to false if bytecode debug breaks are enabled.
2034 interpreter->set_is_debugging(value || HasEnabledBytecodeBreakpoints());
2035 }
2036#endif // !defined(DART_PRECOMPILED_RUNTIME)
2037}
2038
2039ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
2040 uword pc,
2041 StackFrame* frame,
2042 const Code& code,
2043 const Array& deopt_frame,
2044 intptr_t deopt_frame_offset,
2045 ActivationFrame::Kind kind) {
2046 ASSERT(code.ContainsInstructionAt(pc));
2047 ActivationFrame* activation =
2048 new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame,
2049 deopt_frame_offset, kind);
2050 if (FLAG_trace_debugger_stacktrace) {
2051 const Context& ctx = activation->GetSavedCurrentContext();
2052 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
2053 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
2054 }
2055 return activation;
2056}
2057
2058#if !defined(DART_PRECOMPILED_RUNTIME)
2059ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
2060 uword pc,
2061 StackFrame* frame,
2062 const Bytecode& bytecode,
2063 ActivationFrame::Kind kind) {
2064 ASSERT(bytecode.ContainsInstructionAt(pc));
2065 ActivationFrame* activation =
2066 new ActivationFrame(pc, frame->fp(), frame->sp(), bytecode, kind);
2067 if (FLAG_trace_debugger_stacktrace) {
2068 const Context& ctx = activation->GetSavedCurrentContext();
2069 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
2070 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
2071 }
2072 return activation;
2073}
2074
2075ArrayPtr Debugger::DeoptimizeToArray(Thread* thread,
2076 StackFrame* frame,
2077 const Code& code) {
2078 ASSERT(code.is_optimized() && !code.is_force_optimized());
2079 Isolate* isolate = thread->isolate();
2080 // Create the DeoptContext for this deoptimization.
2081 DeoptContext* deopt_context =
2082 new DeoptContext(frame, code, DeoptContext::kDestIsAllocated, NULL, NULL,
2083 true, false /* deoptimizing_code */);
2084 isolate->set_deopt_context(deopt_context);
2085
2086 deopt_context->FillDestFrame();
2087 deopt_context->MaterializeDeferredObjects();
2088 const Array& dest_frame =
2089 Array::Handle(thread->zone(), deopt_context->DestFrameAsArray());
2090
2091 isolate->set_deopt_context(NULL);
2092 delete deopt_context;
2093
2094 return dest_frame.raw();
2095}
2096#endif // !defined(DART_PRECOMPILED_RUNTIME)
2097
2098DebuggerStackTrace* Debugger::CollectStackTrace() {
2099 Thread* thread = Thread::Current();
2100 Zone* zone = thread->zone();
2101 Isolate* isolate = thread->isolate();
2102 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
2103 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
2104 Thread::Current(),
2105 StackFrameIterator::kNoCrossThreadIteration);
2106 Code& code = Code::Handle(zone);
2107#if !defined(DART_PRECOMPILED_RUNTIME)
2108 Bytecode& bytecode = Bytecode::Handle(zone);
2109#endif // !defined(DART_PRECOMPILED_RUNTIME)
2110 Code& inlined_code = Code::Handle(zone);
2111 Array& deopt_frame = Array::Handle(zone);
2112
2113 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2114 frame = iterator.NextFrame()) {
2115 ASSERT(frame->IsValid());
2116 if (FLAG_trace_debugger_stacktrace) {
2117 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
2118 frame->ToCString());
2119 }
2120 if (frame->IsDartFrame()) {
2121 if (frame->is_interpreted()) {
2122#if !defined(DART_PRECOMPILED_RUNTIME)
2123 bytecode = frame->LookupDartBytecode();
2124 if (bytecode.function() == Function::null()) {
2125 continue; // Skip bytecode stub frame.
2126 }
2127 stack_trace->AddActivation(
2128 CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2129#else
2130 UNREACHABLE();
2131#endif // !defined(DART_PRECOMPILED_RUNTIME)
2132 } else {
2133 code = frame->LookupDartCode();
2134 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
2135 &inlined_code, &deopt_frame);
2136 }
2137 }
2138 }
2139 return stack_trace;
2140}
2141
2142void Debugger::AppendCodeFrames(Thread* thread,
2143 Isolate* isolate,
2144 Zone* zone,
2145 DebuggerStackTrace* stack_trace,
2146 StackFrame* frame,
2147 Code* code,
2148 Code* inlined_code,
2149 Array* deopt_frame) {
2150#if !defined(DART_PRECOMPILED_RUNTIME)
2151 if (code->is_optimized()) {
2152 if (code->is_force_optimized()) {
2153 if (FLAG_trace_debugger_stacktrace) {
2154 const Function& function = Function::Handle(zone, code->function());
2155 ASSERT(!function.IsNull());
2156 OS::PrintErr(
2157 "CollectStackTrace: skipping force-optimized function: %s\n",
2158 function.ToFullyQualifiedCString());
2159 }
2160 return; // Skip frame of force-optimized (and non-debuggable) function.
2161 }
2162 // TODO(rmacnak): Use CodeSourceMap
2163 *deopt_frame = DeoptimizeToArray(thread, frame, *code);
2164 for (InlinedFunctionsIterator it(*code, frame->pc()); !it.Done();
2165 it.Advance()) {
2166 *inlined_code = it.code();
2167 if (FLAG_trace_debugger_stacktrace) {
2168 const Function& function = Function::Handle(zone, it.function());
2169 ASSERT(!function.IsNull());
2170 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
2171 function.ToFullyQualifiedCString());
2172 }
2173 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
2174 stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame,
2175 *inlined_code, *deopt_frame,
2176 deopt_frame_offset));
2177 }
2178 return;
2179 }
2180#endif // !defined(DART_PRECOMPILED_RUNTIME)
2181 stack_trace->AddActivation(CollectDartFrame(isolate, frame->pc(), frame,
2182 *code, Object::null_array(), 0));
2183}
2184
2185DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() {
2186 if (FLAG_lazy_async_stacks) {
2187 return CollectAsyncLazyStackTrace();
2188 }
2189 if (!FLAG_causal_async_stacks) {
2190 return NULL;
2191 }
2192 Thread* thread = Thread::Current();
2193 Zone* zone = thread->zone();
2194 Isolate* isolate = thread->isolate();
2195 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
2196
2197 Object& code_obj = Object::Handle(zone);
2198 Code& code = Code::Handle(zone);
2199#if !defined(DART_PRECOMPILED_RUNTIME)
2200 Bytecode& bytecode = Bytecode::Handle(zone);
2201#endif // !defined(DART_PRECOMPILED_RUNTIME)
2202 Smi& offset = Smi::Handle();
2203 Code& inlined_code = Code::Handle(zone);
2204 Array& deopt_frame = Array::Handle(zone);
2205
2206 Function& async_function = Function::Handle(zone);
2207 class StackTrace& async_stack_trace = StackTrace::Handle(zone);
2208 Array& async_code_array = Array::Handle(zone);
2209 Array& async_pc_offset_array = Array::Handle(zone);
2210 StackTraceUtils::ExtractAsyncStackTraceInfo(
2211 thread, &async_function, &async_stack_trace, &async_code_array,
2212 &async_pc_offset_array);
2213
2214 if (async_function.IsNull()) {
2215 return NULL;
2216 }
2217
2218 bool sync_async_end = false;
2219 intptr_t synchronous_stack_trace_length =
2220 StackTraceUtils::CountFrames(thread, 0, async_function, &sync_async_end);
2221
2222 // Append the top frames from the synchronous stack trace, up until the active
2223 // asynchronous function. We truncate the remainder of the synchronous
2224 // stack trace because it contains activations that are part of the
2225 // asynchronous dispatch mechanisms.
2226 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
2227 Thread::Current(),
2228 StackFrameIterator::kNoCrossThreadIteration);
2229 StackFrame* frame = iterator.NextFrame();
2230 while (synchronous_stack_trace_length > 0) {
2231 ASSERT(frame != NULL);
2232 if (frame->IsDartFrame()) {
2233 if (frame->is_interpreted()) {
2234#if !defined(DART_PRECOMPILED_RUNTIME)
2235 bytecode = frame->LookupDartBytecode();
2236 if (bytecode.function() == Function::null()) {
2237 continue; // Skip bytecode stub frame.
2238 }
2239 stack_trace->AddActivation(
2240 CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2241#else
2242 UNREACHABLE();
2243#endif // !defined(DART_PRECOMPILED_RUNTIME)
2244 } else {
2245 code = frame->LookupDartCode();
2246 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
2247 &inlined_code, &deopt_frame);
2248 }
2249 synchronous_stack_trace_length--;
2250 }
2251 frame = iterator.NextFrame();
2252 }
2253
2254 // Now we append the asynchronous causal stack trace. These are not active
2255 // frames but a historical record of how this asynchronous function was
2256 // activated.
2257
2258 intptr_t frame_skip =
2259 sync_async_end ? StackTrace::kSyncAsyncCroppedFrames : 0;
2260 while (!async_stack_trace.IsNull()) {
2261 for (intptr_t i = frame_skip; i < async_stack_trace.Length(); i++) {
2262 code_obj = async_stack_trace.CodeAtFrame(i);
2263 if (code_obj.IsNull()) {
2264 break;
2265 }
2266 if (code_obj.raw() == StubCode::AsynchronousGapMarker().raw()) {
2267 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
2268 // The frame immediately below the asynchronous gap marker is the
2269 // identical to the frame above the marker. Skip the frame to enhance
2270 // the readability of the trace.
2271 i++;
2272 } else {
2273 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
2274#if !defined(DART_PRECOMPILED_RUNTIME)
2275 if (code_obj.IsBytecode()) {
2276 bytecode ^= code_obj.raw();
2277 uword pc = bytecode.PayloadStart() + offset.Value();
2278 stack_trace->AddAsyncCausalFrame(pc, bytecode);
2279 continue;
2280 }
2281#endif // !defined(DART_PRECOMPILED_RUNTIME)
2282 code ^= code_obj.raw();
2283 uword pc = code.PayloadStart() + offset.Value();
2284 if (code.is_optimized()) {
2285 for (InlinedFunctionsIterator it(code, pc); !it.Done();
2286 it.Advance()) {
2287 inlined_code = it.code();
2288 stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
2289 }
2290 } else {
2291 stack_trace->AddAsyncCausalFrame(pc, code);
2292 }
2293 }
2294 }
2295 // Follow the link.
2296 frame_skip = async_stack_trace.skip_sync_start_in_parent_stack()
2297 ? StackTrace::kSyncAsyncCroppedFrames
2298 : 0;
2299 async_stack_trace = async_stack_trace.async_link();
2300 }
2301
2302 return stack_trace;
2303}
2304
2305DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() {
2306 Thread* thread = Thread::Current();
2307 Zone* zone = thread->zone();
2308 Isolate* isolate = thread->isolate();
2309
2310 Code& code = Code::Handle(zone);
2311 Code& inlined_code = Code::Handle(zone);
2312 Smi& offset = Smi::Handle();
2313 Array& deopt_frame = Array::Handle(zone);
2314#if !defined(DART_PRECOMPILED_RUNTIME)
2315 Bytecode& bytecode = Bytecode::Handle(zone);
2316#endif // !defined(DART_PRECOMPILED_RUNTIME)
2317
2318 constexpr intptr_t kDefaultStackAllocation = 8;
2319 auto stack_trace = new DebuggerStackTrace(kDefaultStackAllocation);
2320
2321 std::function<void(StackFrame*)> on_sync_frame = [&](StackFrame* frame) {
2322 if (frame->is_interpreted()) {
2323#if !defined(DART_PRECOMPILED_RUNTIME)
2324 bytecode = frame->LookupDartBytecode();
2325 stack_trace->AddActivation(
2326 CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2327#else
2328 UNREACHABLE();
2329#endif // !defined(DART_PRECOMPILED_RUNTIME)
2330 } else {
2331 code = frame->LookupDartCode();
2332 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
2333 &inlined_code, &deopt_frame);
2334 }
2335 };
2336
2337 const auto& code_array = GrowableObjectArray::ZoneHandle(
2338 zone, GrowableObjectArray::New(kDefaultStackAllocation));
2339 const auto& pc_offset_array = GrowableObjectArray::ZoneHandle(
2340 zone, GrowableObjectArray::New(kDefaultStackAllocation));
2341 bool has_async = false;
2342 StackTraceUtils::CollectFramesLazy(thread, code_array, pc_offset_array,
2343 /*skip_frames=*/0, &on_sync_frame,
2344 &has_async);
2345
2346 if (!has_async) {
2347 return nullptr;
2348 }
2349
2350 const intptr_t length = code_array.Length();
2351 for (intptr_t i = stack_trace->Length(); i < length; ++i) {
2352 code ^= code_array.At(i);
2353 offset ^= pc_offset_array.At(i);
2354 if (code.raw() == StubCode::AsynchronousGapMarker().raw()) {
2355 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
2356 } else {
2357 const uword absolute_pc = code.PayloadStart() + offset.Value();
2358 stack_trace->AddAsyncCausalFrame(absolute_pc, code);
2359 }
2360 }
2361
2362 return stack_trace;
2363}
2364
2365DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
2366#if defined(DART_PRECOMPILED_RUNTIME)
2367 // Causal async stacks are not supported in the AOT runtime.
2368 ASSERT(!FLAG_async_debugger);
2369 return NULL;
2370#else
2371 if (!FLAG_async_debugger) {
2372 return NULL;
2373 }
2374
2375 Thread* thread = Thread::Current();
2376 Zone* zone = thread->zone();
2377 Isolate* isolate = thread->isolate();
2378 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
2379
2380 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
2381 Thread::Current(),
2382 StackFrameIterator::kNoCrossThreadIteration);
2383
2384 Object& code_object = Object::Handle(zone);
2385 Code& code = Code::Handle(zone);
2386 Bytecode& bytecode = Bytecode::Handle(zone);
2387 Smi& offset = Smi::Handle(zone);
2388 Function& function = Function::Handle(zone);
2389 Code& inlined_code = Code::Handle(zone);
2390 Closure& async_activation = Closure::Handle(zone);
2391 Object& next_async_activation = Object::Handle(zone);
2392 Array& deopt_frame = Array::Handle(zone);
2393 class StackTrace& async_stack_trace = StackTrace::Handle(zone);
2394 bool stack_has_async_function = false;
2395
2396 // Number of frames we are trying to skip that form "sync async" entry.
2397 int skip_sync_async_frames_count = -1;
2398 String& function_name = String::Handle(zone);
2399 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2400 frame = iterator.NextFrame()) {
2401 ASSERT(frame->IsValid());
2402 if (FLAG_trace_debugger_stacktrace) {
2403 OS::PrintErr("CollectAwaiterReturnStackTrace: visiting frame:\n\t%s\n",
2404 frame->ToCString());
2405 }
2406 if (frame->IsDartFrame()) {
2407 if (frame->is_interpreted()) {
2408 bytecode = frame->LookupDartBytecode();
2409 function = bytecode.function();
2410 if (function.IsNull()) {
2411 continue; // Skip bytecode stub frame.
2412 }
2413
2414 if (skip_sync_async_frames_count > 0) {
2415 function_name = function.QualifiedScrubbedName();
2416 if (!StackTraceUtils::CheckAndSkipAsync(&skip_sync_async_frames_count,
2417 function_name)) {
2418 // Unexpected function in synchronous call of async function.
2419 break;
2420 }
2421 }
2422
2423 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2424 ActivationFrame* activation =
2425 CollectDartFrame(isolate, frame->pc(), frame, bytecode,
2426 ActivationFrame::kAsyncActivation);
2427 ASSERT(activation != NULL);
2428 stack_trace->AddActivation(activation);
2429 stack_has_async_function = true;
2430 // Grab the awaiter.
2431 async_activation ^= activation->GetAsyncAwaiter();
2432 async_stack_trace ^= activation->GetCausalStack();
2433 // Interpreted bytecode does not invoke _ClosureCall().
2434 // Skip _AsyncAwaitCompleterStart() only.
2435 skip_sync_async_frames_count = 1;
2436 } else {
2437 stack_trace->AddActivation(
2438 CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2439 }
2440 } else {
2441 code = frame->LookupDartCode();
2442 if (code.is_optimized()) {
2443 if (code.is_force_optimized()) {
2444 if (FLAG_trace_debugger_stacktrace) {
2445 function = code.function();
2446 ASSERT(!function.IsNull());
2447 OS::PrintErr(
2448 "CollectAwaiterReturnStackTrace: "
2449 "skipping force-optimized function: %s\n",
2450 function.ToFullyQualifiedCString());
2451 }
2452 // Skip frame of force-optimized (and non-debuggable) function.
2453 continue;
2454 }
2455 deopt_frame = DeoptimizeToArray(thread, frame, code);
2456 bool found_async_awaiter = false;
2457 bool abort_attempt_to_navigate_through_sync_async = false;
2458 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
2459 it.Advance()) {
2460 inlined_code = it.code();
2461 function = it.function();
2462
2463 if (skip_sync_async_frames_count > 0) {
2464 function_name ^= function.QualifiedScrubbedName();
2465 if (!StackTraceUtils::CheckAndSkipAsync(
2466 &skip_sync_async_frames_count, function_name)) {
2467 // Unexpected function in sync async call
2468 skip_sync_async_frames_count = -1;
2469 abort_attempt_to_navigate_through_sync_async = true;
2470 break;
2471 }
2472 }
2473
2474 if (FLAG_trace_debugger_stacktrace) {
2475 ASSERT(!function.IsNull());
2476 OS::PrintErr(
2477 "CollectAwaiterReturnStackTrace: "
2478 "visiting inlined function: %s\n ",
2479 function.ToFullyQualifiedCString());
2480 }
2481 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
2482 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2483 ActivationFrame* activation = CollectDartFrame(
2484 isolate, it.pc(), frame, inlined_code, deopt_frame,
2485 deopt_frame_offset, ActivationFrame::kAsyncActivation);
2486 ASSERT(activation != NULL);
2487 stack_trace->AddActivation(activation);
2488 stack_has_async_function = true;
2489 // Grab the awaiter.
2490 async_activation ^= activation->GetAsyncAwaiter();
2491 found_async_awaiter = true;
2492 // async function might have been called synchronously, in which
2493 // case we need to keep going down the stack.
2494 // To determine how we are called we peek few more frames further
2495 // expecting to see Closure_call followed by
2496 // AsyncAwaitCompleter_start.
2497 // If we are able to see those functions we continue going down
2498 // thestack, if we are not, we break out of the loop as we are
2499 // not interested in exploring rest of the stack - there is only
2500 // dart-internal code left.
2501 skip_sync_async_frames_count = 2;
2502 } else {
2503 stack_trace->AddActivation(
2504 CollectDartFrame(isolate, it.pc(), frame, inlined_code,
2505 deopt_frame, deopt_frame_offset));
2506 }
2507 }
2508 // Break out of outer loop.
2509 if (found_async_awaiter ||
2510 abort_attempt_to_navigate_through_sync_async) {
2511 break;
2512 }
2513 } else {
2514 function = code.function();
2515
2516 if (skip_sync_async_frames_count > 0) {
2517 function_name ^= function.QualifiedScrubbedName();
2518 if (!StackTraceUtils::CheckAndSkipAsync(
2519 &skip_sync_async_frames_count, function_name)) {
2520 // Unexpected function in synchronous call of async function.
2521 break;
2522 }
2523 }
2524
2525 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2526 ActivationFrame* activation = CollectDartFrame(
2527 isolate, frame->pc(), frame, code, Object::null_array(), 0,
2528 ActivationFrame::kAsyncActivation);
2529 ASSERT(activation != NULL);
2530 stack_trace->AddActivation(activation);
2531 stack_has_async_function = true;
2532 // Grab the awaiter.
2533 async_activation ^= activation->GetAsyncAwaiter();
2534 async_stack_trace ^= activation->GetCausalStack();
2535 // see comment regarding skipping frames of async functions called
2536 // synchronously above.
2537 skip_sync_async_frames_count = 2;
2538 } else {
2539 stack_trace->AddActivation(CollectDartFrame(
2540 isolate, frame->pc(), frame, code, Object::null_array(), 0));
2541 }
2542 }
2543 }
2544 }
2545 }
2546
2547 // If the stack doesn't have any async functions on it, return NULL.
2548 if (!stack_has_async_function) {
2549 return NULL;
2550 }
2551
2552 // Append the awaiter return call stack.
2553 while (!async_activation.IsNull()) {
2554 ActivationFrame* activation = new (zone) ActivationFrame(async_activation);
2555 activation->ExtractTokenPositionFromAsyncClosure();
2556 stack_trace->AddActivation(activation);
2557 if (FLAG_trace_debugger_stacktrace) {
2558 OS::PrintErr(
2559 "CollectAwaiterReturnStackTrace: visiting awaiter return "
2560 "closures:\n\t%s\n",
2561 activation->function().ToFullyQualifiedCString());
2562 }
2563 next_async_activation = activation->GetAsyncAwaiter();
2564 if (next_async_activation.IsNull()) {
2565 // No more awaiters. Extract the causal stack trace (if it exists).
2566 async_stack_trace ^= activation->GetCausalStack();
2567 break;
2568 }
2569 async_activation = Closure::RawCast(next_async_activation.raw());
2570 }
2571
2572 // Now we append the asynchronous causal stack trace. These are not active
2573 // frames but a historical record of how this asynchronous function was
2574 // activated.
2575 while (!async_stack_trace.IsNull()) {
2576 for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
2577 if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
2578 // Incomplete OutOfMemory/StackOverflow trace OR array padding.
2579 break;
2580 }
2581 if (async_stack_trace.CodeAtFrame(i) ==
2582 StubCode::AsynchronousGapMarker().raw()) {
2583 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
2584 // The frame immediately below the asynchronous gap marker is the
2585 // identical to the frame above the marker. Skip the frame to enhance
2586 // the readability of the trace.
2587 i++;
2588 } else {
2589 code_object = async_stack_trace.CodeAtFrame(i);
2590 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
2591 if (code_object.IsBytecode()) {
2592 bytecode ^= code_object.raw();
2593 if (FLAG_trace_debugger_stacktrace) {
2594 OS::PrintErr("CollectAwaiterReturnStackTrace: visiting frame %" Pd
2595 " in async causal stack trace:\n\t%s\n",
2596 i,
2597 Function::Handle(bytecode.function())
2598 .ToFullyQualifiedCString());
2599 }
2600 uword pc = bytecode.PayloadStart() + offset.Value();
2601 stack_trace->AddAsyncCausalFrame(pc, bytecode);
2602 } else {
2603 code ^= code_object.raw();
2604 if (FLAG_trace_debugger_stacktrace) {
2605 OS::PrintErr(
2606 "CollectAwaiterReturnStackTrace: visiting frame %" Pd
2607 " in async causal stack trace:\n\t%s\n",
2608 i, Function::Handle(code.function()).ToFullyQualifiedCString());
2609 }
2610 uword pc = code.PayloadStart() + offset.Value();
2611 if (code.is_optimized()) {
2612 for (InlinedFunctionsIterator it(code, pc); !it.Done();
2613 it.Advance()) {
2614 inlined_code = it.code();
2615 stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
2616 }
2617 } else {
2618 stack_trace->AddAsyncCausalFrame(pc, code);
2619 }
2620 }
2621 }
2622 }
2623 // Follow the link.
2624 async_stack_trace = async_stack_trace.async_link();
2625 }
2626
2627 return stack_trace;
2628#endif // defined(DART_PRECOMPILED_RUNTIME)
2629}
2630
2631ActivationFrame* Debugger::TopDartFrame() const {
2632 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
2633 Thread::Current(),
2634 StackFrameIterator::kNoCrossThreadIteration);
2635 StackFrame* frame;
2636 while (true) {
2637 frame = iterator.NextFrame();
2638 RELEASE_ASSERT(frame != nullptr);
2639 if (!frame->IsDartFrame()) {
2640 continue;
2641 }
2642#if !defined(DART_PRECOMPILED_RUNTIME)
2643 if (frame->is_interpreted()) {
2644 Bytecode& bytecode = Bytecode::Handle(frame->LookupDartBytecode());
2645 // Note that we do not skip bytecode stub frame (with a null function),
2646 // so that we can ignore a single stepping breakpoint in such a frame.
2647 // A bytecode stub contains a VM internal bytecode followed by a
2648 // ReturnTOS bytecode. The single step on the ReturnTOS bytecode
2649 // needs to be skipped.
2650 ActivationFrame* activation =
2651 new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), bytecode);
2652 return activation;
2653 }
2654#endif // !defined(DART_PRECOMPILED_RUNTIME)
2655 Code& code = Code::Handle(frame->LookupDartCode());
2656 ActivationFrame* activation = new ActivationFrame(
2657 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
2658 return activation;
2659 }
2660}
2661
2662DebuggerStackTrace* Debugger::StackTrace() {
2663 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace();
2664}
2665
2666DebuggerStackTrace* Debugger::CurrentStackTrace() {
2667 return CollectStackTrace();
2668}
2669
2670DebuggerStackTrace* Debugger::AsyncCausalStackTrace() {
2671 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_
2672 : CollectAsyncCausalStackTrace();
2673}
2674
2675DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() {
2676 return CollectAsyncCausalStackTrace();
2677}
2678
2679DebuggerStackTrace* Debugger::AwaiterStackTrace() {
2680 return (awaiter_stack_trace_ != NULL) ? awaiter_stack_trace_
2681 : CollectAwaiterReturnStackTrace();
2682}
2683
2684DebuggerStackTrace* Debugger::CurrentAwaiterStackTrace() {
2685 return CollectAwaiterReturnStackTrace();
2686}
2687
2688DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) {
2689 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
2690 Function& function = Function::Handle();
2691 Object& code_object = Object::Handle();
2692 Code& code = Code::Handle();
2693#if !defined(DART_PRECOMPILED_RUNTIME)
2694 Bytecode& bytecode = Bytecode::Handle();
2695#endif // !defined(DART_PRECOMPILED_RUNTIME)
2696
2697 const uword fp = 0;
2698 const uword sp = 0;
2699 const Array& deopt_frame = Array::Handle();
2700 const intptr_t deopt_frame_offset = -1;
2701
2702 for (intptr_t i = 0; i < ex_trace.Length(); i++) {
2703 code_object = ex_trace.CodeAtFrame(i);
2704 // Pre-allocated StackTraces may include empty slots, either (a) to indicate
2705 // where frames were omitted in the case a stack has more frames than the
2706 // pre-allocated trace (such as a stack overflow) or (b) because a stack has
2707 // fewer frames that the pre-allocated trace (such as memory exhaustion with
2708 // a shallow stack).
2709 if (!code_object.IsNull()) {
2710 if (code_object.IsBytecode()) {
2711#if !defined(DART_PRECOMPILED_RUNTIME)
2712 bytecode ^= code_object.raw();
2713 function = bytecode.function();
2714 // Skip bytecode stub frames and frames with invisible function.
2715 if (!function.IsNull() && function.is_visible()) {
2716 ASSERT(function.raw() == bytecode.function());
2717 uword pc =
2718 bytecode.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
2719 ActivationFrame* activation =
2720 new ActivationFrame(pc, fp, sp, bytecode);
2721 stack_trace->AddActivation(activation);
2722 }
2723#else
2724 UNREACHABLE();
2725#endif // !defined(DART_PRECOMPILED_RUNTIME)
2726 } else {
2727 code ^= code_object.raw();
2728 ASSERT(code.IsFunctionCode());
2729 function = code.function();
2730 if (function.is_visible()) {
2731 ASSERT(function.raw() == code.function());
2732 uword pc =
2733 code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
2734 if (code.is_optimized() && ex_trace.expand_inlined()) {
2735 // Traverse inlined frames.
2736 for (InlinedFunctionsIterator it(code, pc); !it.Done();
2737 it.Advance()) {
2738 function = it.function();
2739 code = it.code();
2740 ASSERT(function.raw() == code.function());
2741 uword pc = it.pc();
2742 ASSERT(pc != 0);
2743 ASSERT(code.PayloadStart() <= pc);
2744 ASSERT(pc < (code.PayloadStart() + code.Size()));
2745
2746 ActivationFrame* activation = new ActivationFrame(
2747 pc, fp, sp, code, deopt_frame, deopt_frame_offset);
2748 stack_trace->AddActivation(activation);
2749 }
2750 } else {
2751 ActivationFrame* activation = new ActivationFrame(
2752 pc, fp, sp, code, deopt_frame, deopt_frame_offset);
2753 stack_trace->AddActivation(activation);
2754 }
2755 }
2756 }
2757 }
2758 }
2759 return stack_trace;
2760}
2761
2762void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) {
2763 ASSERT((pause_info == kNoPauseOnExceptions) ||
2764 (pause_info == kPauseOnUnhandledExceptions) ||
2765 (pause_info == kPauseOnAllExceptions));
2766 exc_pause_info_ = pause_info;
2767}
2768
2769Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const {
2770 return exc_pause_info_;
2771}
2772
2773bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
2774 const Instance& exception) {
2775 if (exc_pause_info_ == kNoPauseOnExceptions) {
2776 return false;
2777 }
2778 if (exc_pause_info_ == kPauseOnAllExceptions) {
2779 return true;
2780 }
2781 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
2782 // Exceptions coming from invalid token positions should be skipped
2783 ActivationFrame* top_frame = stack_trace->FrameAt(0);
2784 if (!top_frame->TokenPos().IsReal() && top_frame->TryIndex() != -1) {
2785 return false;
2786 }
2787 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
2788 if (handler_frame == NULL) {
2789 // Did not find an exception handler that catches this exception.
2790 // Note that this check is not precise, since we can't check
2791 // uninstantiated types, i.e. types containing type parameters.
2792 // Thus, we may report an exception as unhandled when in fact
2793 // it will be caught once we unwind the stack.
2794 return true;
2795 }
2796 return false;
2797}
2798
2799void Debugger::PauseException(const Instance& exc) {
2800 if (FLAG_stress_async_stacks) {
2801 CollectAwaiterReturnStackTrace();
2802 }
2803 // We ignore this exception event when the VM is executing code invoked
2804 // by the debugger to evaluate variables values, when we see a nested
2805 // breakpoint or exception event, or if the debugger is not
2806 // interested in exception events.
2807 if (ignore_breakpoints_ || IsPaused() ||
2808 (exc_pause_info_ == kNoPauseOnExceptions)) {
2809 return;
2810 }
2811 DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace();
2812 DebuggerStackTrace* stack_trace = CollectStackTrace();
2813 if (awaiter_stack_trace != NULL) {
2814 if (!ShouldPauseOnException(awaiter_stack_trace, exc)) {
2815 return;
2816 }
2817 } else {
2818 if (!ShouldPauseOnException(stack_trace, exc)) {
2819 return;
2820 }
2821 }
2822 ServiceEvent event(isolate_, ServiceEvent::kPauseException);
2823 event.set_exception(&exc);
2824 if (stack_trace->Length() > 0) {
2825 event.set_top_frame(stack_trace->FrameAt(0));
2826 }
2827 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
2828 CollectAwaiterReturnStackTrace());
2829 Pause(&event);
2830 HandleSteppingRequest(stack_trace_); // we may get a rewind request
2831 ClearCachedStackTraces();
2832}
2833
2834// Helper to refine the resolved token pos.
2835static void RefineBreakpointPos(const Script& script,
2836 TokenPosition pos,
2837 TokenPosition next_closest_token_position,
2838 TokenPosition requested_token_pos,
2839 TokenPosition last_token_pos,
2840 intptr_t requested_column,
2841 TokenPosition exact_token_pos,
2842 TokenPosition* best_fit_pos,
2843 intptr_t* best_column,
2844 intptr_t* best_line,
2845 TokenPosition* best_token_pos) {
2846 intptr_t token_start_column = -1;
2847 intptr_t token_line = -1;
2848 if (requested_column >= 0) {
2849 TokenPosition ignored;
2850 TokenPosition end_of_line_pos;
2851 script.GetTokenLocation(pos, &token_line, &token_start_column);
2852 script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
2853 TokenPosition token_end_pos =
2854 (end_of_line_pos < next_closest_token_position)
2855 ? end_of_line_pos
2856 : next_closest_token_position;
2857
2858 if ((token_end_pos < exact_token_pos) ||
2859 (token_start_column > *best_column)) {
2860 // Prefer the token with the lowest column number compatible
2861 // with the requested column.
2862 return;
2863 }
2864 }
2865
2866 // Prefer the lowest (first) token pos.
2867 if (pos < *best_fit_pos) {
2868 *best_fit_pos = pos;
2869 *best_line = token_line;
2870 *best_column = token_start_column;
2871 // best_token_pos is only used when column number is specified.
2872 *best_token_pos = TokenPosition(exact_token_pos.value() -
2873 (requested_column - *best_column));
2874 }
2875}
2876
2877// Returns the best fit token position for a breakpoint.
2878//
2879// Takes a range of tokens [requested_token_pos, last_token_pos] and
2880// an optional column (requested_column). The range of tokens usually
2881// represents one line of the program text, but can represent a larger
2882// range on recursive calls.
2883//
2884// The best fit is found in two passes.
2885//
2886// The first pass finds a candidate token which:
2887//
2888// - is a safepoint,
2889// - has the lowest column number compatible with the requested column
2890// if a column has been specified,
2891// and:
2892// - has the lowest token position number which satisfies the above.
2893//
2894// When we consider a column number, we look for the token which
2895// intersects the desired column. For example:
2896//
2897// 1 2 3
2898// 12345678901234567890 0
2899//
2900// var x = function(function(y));
2901// ^
2902//
2903// If we request a breakpoint at column 14, the lowest column number
2904// compatible with that would for column 11 (beginning of the
2905// 'function' token) in the example above.
2906//
2907// Once this candidate token from the first pass is found, we then
2908// have a second pass which considers only those tokens on the same
2909// line as the candidate token.
2910//
2911// The second pass finds a best fit token which:
2912//
2913// - is a safepoint,
2914// - has the same column number as the candidate token (perhaps
2915// more than one token has the same column number),
2916// and:
2917// - has the lowest code address in the generated code.
2918//
2919// We prefer the lowest compiled code address, because this tends to
2920// select the first subexpression on a line. For example in a line
2921// with nested function calls f(g(x)), the call to g() will have a
2922// lower compiled code address than the call to f().
2923//
2924// If no best fit token can be found, the search is expanded,
2925// searching through the rest of the current function by calling this
2926// function recursively.
2927//
2928// TODO(turnidge): Given that we usually call this function with a
2929// token range restricted to a single line, this could be a one-pass
2930// algorithm, which would be simpler. I believe that it only needs
2931// two passes to support the recursive try-the-whole-function case.
2932// Rewrite this later, once there are more tests in place.
2933TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
2934 const Function& func,
2935 TokenPosition requested_token_pos,
2936 TokenPosition last_token_pos,
2937 intptr_t requested_column,
2938 TokenPosition exact_token_pos) {
2939 ASSERT(!func.HasOptimizedCode());
2940
2941 if (requested_token_pos < func.token_pos()) {
2942 requested_token_pos = func.token_pos();
2943 }
2944 if (last_token_pos > func.end_token_pos()) {
2945 last_token_pos = func.end_token_pos();
2946 }
2947
2948 Zone* zone = Thread::Current()->zone();
2949 Script& script = Script::Handle(zone, func.script());
2950 Code& code = Code::Handle(zone);
2951#if !defined(DART_PRECOMPILED_RUNTIME)
2952 Bytecode& bytecode = Bytecode::Handle(zone);
2953#endif // !defined(DART_PRECOMPILED_RUNTIME)
2954 PcDescriptors& desc = PcDescriptors::Handle(zone);
2955 if (in_bytecode) {
2956#if !defined(DART_PRECOMPILED_RUNTIME)
2957 ASSERT(func.HasBytecode());
2958 bytecode = func.bytecode();
2959 ASSERT(!bytecode.IsNull());
2960#else
2961 UNREACHABLE();
2962#endif // !defined(DART_PRECOMPILED_RUNTIME)
2963 } else {
2964 ASSERT(func.HasCode());
2965 code = func.unoptimized_code();
2966 ASSERT(!code.IsNull());
2967 desc = code.pc_descriptors();
2968 }
2969
2970 // First pass: find the safe point which is closest to the beginning
2971 // of the given token range.
2972 TokenPosition best_fit_pos = TokenPosition::kMaxSource;
2973 intptr_t best_column = INT_MAX;
2974 intptr_t best_line = INT_MAX;
2975 // best_token_pos and exact_token_pos are only used
2976 // if column number is provided.
2977 TokenPosition best_token_pos = TokenPosition::kNoSource;
2978
2979 if (in_bytecode) {
2980#if !defined(DART_PRECOMPILED_RUNTIME)
2981 kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
2982 uword pc_offset = kUwordMax;
2983 TokenPosition pos = TokenPosition::kNoSource;
2984 // Ignore all possible breakpoint positions until the first DebugCheck
2985 // opcode of the function.
2986 const uword debug_check_pc = bytecode.GetFirstDebugCheckOpcodePc();
2987 if (debug_check_pc != 0) {
2988 const uword debug_check_pc_offset =
2989 debug_check_pc - bytecode.PayloadStart();
2990 while (iter.MoveNext()) {
2991 if (pc_offset != kUwordMax) {
2992 // Check that there is at least one 'debug checked' opcode in the last
2993 // source position range.
2994 uword pc = bytecode.GetDebugCheckedOpcodeReturnAddress(
2995 pc_offset, iter.PcOffset());
2996 pc_offset = kUwordMax;
2997 if (pc != 0) {
2998 TokenPosition next_closest_token_position =
2999 TokenPosition::kMaxSource;
3000 if (requested_column >= 0) {
3001 kernel::BytecodeSourcePositionsIterator iter2(zone, bytecode);
3002 TokenPosition next_closest_token_position =
3003 TokenPosition::kMaxSource;
3004 while (iter2.MoveNext()) {
3005 const TokenPosition next = iter2.TokenPos();
3006 if (next.IsReal() && next < next_closest_token_position &&
3007 next > pos) {
3008 next_closest_token_position = next;
3009 }
3010 }
3011 }
3012 RefineBreakpointPos(
3013 script, pos, next_closest_token_position, requested_token_pos,
3014 last_token_pos, requested_column, exact_token_pos,
3015 &best_fit_pos, &best_column, &best_line, &best_token_pos);
3016 }
3017 }
3018 pos = iter.TokenPos();
3019 if ((!pos.IsReal()) || (pos < requested_token_pos) ||
3020 (pos > last_token_pos)) {
3021 // Token is not in the target range.
3022 continue;
3023 }
3024 pc_offset = iter.PcOffset();
3025 if (pc_offset < debug_check_pc_offset) {
3026 // No breakpoints in prologue.
3027 pc_offset = debug_check_pc_offset;
3028 }
3029 }
3030 if (pc_offset != kUwordMax) {
3031 uword pc = bytecode.GetDebugCheckedOpcodeReturnAddress(pc_offset,
3032 bytecode.Size());
3033 if (pc != 0) {
3034 RefineBreakpointPos(script, pos, TokenPosition::kMaxSource,
3035 requested_token_pos, last_token_pos,
3036 requested_column, exact_token_pos, &best_fit_pos,
3037 &best_column, &best_line, &best_token_pos);
3038 }
3039 }
3040 }
3041#else
3042 UNREACHABLE();
3043#endif // !defined(DART_PRECOMPILED_RUNTIME)
3044 } else {
3045 PcDescriptors::Iterator iter(desc, kSafepointKind);
3046 while (iter.MoveNext()) {
3047 const TokenPosition pos = iter.TokenPos();
3048 if ((!pos.IsReal()) || (pos < requested_token_pos) ||
3049 (pos > last_token_pos)) {
3050 // Token is not in the target range.
3051 continue;
3052 }
3053 TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
3054 if (requested_column >= 0) {
3055 // Find next closest safepoint
3056 PcDescriptors::Iterator iter2(desc, kSafepointKind);
3057 while (iter2.MoveNext()) {
3058 const TokenPosition next = iter2.TokenPos();
3059 if (next < next_closest_token_position && next > pos) {
3060 next_closest_token_position = next;
3061 }
3062 }
3063 }
3064 RefineBreakpointPos(script, pos, next_closest_token_position,
3065 requested_token_pos, last_token_pos, requested_column,
3066 exact_token_pos, &best_fit_pos, &best_column,
3067 &best_line, &best_token_pos);
3068 }
3069 }
3070
3071 // Second pass (if we found a safe point in the first pass). Find
3072 // the token on the line which is at the best fit column (if column
3073 // was specified) and has the lowest code address.
3074 if (best_fit_pos != TokenPosition::kMaxSource) {
3075 const Script& script = Script::Handle(zone, func.script());
3076 const TokenPosition begin_pos = best_fit_pos;
3077
3078 TokenPosition end_of_line_pos;
3079 if (best_line == -1) {
3080 script.GetTokenLocation(begin_pos, &best_line, NULL);
3081 }
3082 ASSERT(best_line > 0);
3083 TokenPosition ignored;
3084 script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
3085 if (end_of_line_pos < begin_pos) {
3086 end_of_line_pos = begin_pos;
3087 }
3088
3089 uword lowest_pc_offset = kUwordMax;
3090 if (in_bytecode) {
3091#if !defined(DART_PRECOMPILED_RUNTIME)
3092 kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
3093 while (iter.MoveNext()) {
3094 const TokenPosition pos = iter.TokenPos();
3095 if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
3096 // Token is not on same line as best fit.
3097 continue;
3098 }
3099
3100 if (requested_column >= 0) {
3101 if (pos != best_token_pos) {
3102 continue;
3103 }
3104 }
3105
3106 // Prefer the lowest pc offset.
3107 if (iter.PcOffset() < lowest_pc_offset) {
3108 lowest_pc_offset = iter.PcOffset();
3109 best_fit_pos = pos;
3110 }
3111 }
3112#else
3113 UNREACHABLE();
3114#endif // !defined(DART_PRECOMPILED_RUNTIME)
3115 } else {
3116 PcDescriptors::Iterator iter(desc, kSafepointKind);
3117 while (iter.MoveNext()) {
3118 const TokenPosition pos = iter.TokenPos();
3119 if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
3120 // Token is not on same line as best fit.
3121 continue;
3122 }
3123
3124 if (requested_column >= 0) {
3125 if (pos != best_token_pos) {
3126 continue;
3127 }
3128 }
3129
3130 // Prefer the lowest pc offset.
3131 if (iter.PcOffset() < lowest_pc_offset) {
3132 lowest_pc_offset = iter.PcOffset();
3133 best_fit_pos = pos;
3134 }
3135 }
3136 }
3137 return best_fit_pos;
3138 }
3139
3140 // We didn't find a safe point in the given token range. Try and
3141 // find a safe point in the remaining source code of the function.
3142 // Since we have moved to the next line of the function, we no
3143 // longer are requesting a specific column number.
3144 if (last_token_pos < func.end_token_pos()) {
3145 return ResolveBreakpointPos(in_bytecode, func, last_token_pos,
3146 func.end_token_pos(), -1 /* no column */,
3147 TokenPosition::kNoSource);
3148 }
3149 return TokenPosition::kNoSource;
3150}
3151
3152void Debugger::MakeCodeBreakpointAt(const Function& func,
3153 BreakpointLocation* loc) {
3154 ASSERT(loc->token_pos_.IsReal());
3155 ASSERT((loc != NULL) && loc->IsResolved());
3156 ASSERT(!func.HasOptimizedCode());
3157 ASSERT(func.HasCode() || func.HasBytecode());
3158#if !defined(DART_PRECOMPILED_RUNTIME)
3159 if (func.HasBytecode() && FLAG_enable_interpreter) {
3160 Bytecode& bytecode = Bytecode::Handle(func.bytecode());
3161 ASSERT(!bytecode.IsNull());
3162 uword pc = 0;
3163 if (bytecode.HasSourcePositions()) {
3164 kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
3165 bytecode);
3166 // Ignore all possible breakpoint positions until the first DebugCheck
3167 // opcode of the function.
3168 const uword debug_check_pc = bytecode.GetFirstDebugCheckOpcodePc();
3169 if (debug_check_pc != 0) {
3170 const uword debug_check_pc_offset =
3171 debug_check_pc - bytecode.PayloadStart();
3172 uword pc_offset = kUwordMax;
3173 while (iter.MoveNext()) {
3174 if (pc_offset != kUwordMax) {
3175 pc = bytecode.GetDebugCheckedOpcodeReturnAddress(pc_offset,
3176 iter.PcOffset());
3177 pc_offset = kUwordMax;
3178 if (pc != 0) {
3179 // TODO(regis): We may want to find all PCs for a token position,
3180 // e.g. in the case of duplicated bytecode in finally clauses.
3181 break;
3182 }
3183 // This range does not contain a 'debug checked' opcode or the
3184 // first DebugCheck opcode of the function is not reached yet.
3185 }
3186 if (iter.TokenPos() == loc->token_pos_) {
3187 pc_offset = iter.PcOffset();
3188 if (pc_offset < debug_check_pc_offset) {
3189 // No breakpoints in prologue.
3190 pc_offset = debug_check_pc_offset;
3191 }
3192 }
3193 }
3194 if (pc_offset != kUwordMax) {
3195 pc = bytecode.GetDebugCheckedOpcodeReturnAddress(pc_offset,
3196 bytecode.Size());
3197 }
3198 }
3199 }
3200 if (pc != 0) {
3201 CodeBreakpoint* code_bpt = GetCodeBreakpoint(pc);
3202 if (code_bpt == NULL) {
3203 // No code breakpoint for this code exists; create one.
3204 code_bpt = new CodeBreakpoint(bytecode, loc->token_pos_, pc);
3205 if (FLAG_verbose_debug) {
3206 OS::PrintErr("Setting bytecode breakpoint at pos %s pc %#" Px
3207 " offset %#" Px "\n",
3208 loc->token_pos_.ToCString(), pc,
3209 pc - bytecode.PayloadStart());
3210 }
3211 RegisterCodeBreakpoint(code_bpt);
3212 }
3213 code_bpt->set_bpt_location(loc);
3214 if (loc->AnyEnabled()) {
3215 code_bpt->Enable();
3216 }
3217 }
3218 }
3219#endif // !defined(DART_PRECOMPILED_RUNTIME)
3220 if (func.HasCode()) {
3221 Code& code = Code::Handle(func.unoptimized_code());
3222 ASSERT(!code.IsNull());
3223 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
3224 uword lowest_pc_offset = kUwordMax;
3225 PcDescriptorsLayout::Kind lowest_kind = PcDescriptorsLayout::kAnyKind;
3226 // Find the safe point with the lowest compiled code address
3227 // that maps to the token position of the source breakpoint.
3228 PcDescriptors::Iterator iter(desc, kSafepointKind);
3229 while (iter.MoveNext()) {
3230 if (iter.TokenPos() == loc->token_pos_) {
3231 if (iter.PcOffset() < lowest_pc_offset) {
3232 lowest_pc_offset = iter.PcOffset();
3233 lowest_kind = iter.Kind();
3234 }
3235 }
3236 }
3237 if (lowest_pc_offset != kUwordMax) {
3238 uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
3239 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
3240 if (code_bpt == NULL) {
3241 // No code breakpoint for this code exists; create one.
3242 code_bpt =
3243 new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
3244 if (FLAG_verbose_debug) {
3245 OS::PrintErr("Setting code breakpoint at pos %s pc %#" Px
3246 " offset %#" Px "\n",
3247 loc->token_pos_.ToCString(), lowest_pc,
3248 lowest_pc - code.PayloadStart());
3249 }
3250 RegisterCodeBreakpoint(code_bpt);
3251 }
3252 code_bpt->set_bpt_location(loc);
3253 if (loc->AnyEnabled()) {
3254 code_bpt->Enable();
3255 }
3256 }
3257 }
3258}
3259
3260void Debugger::FindCompiledFunctions(
3261 const Script& script,
3262 TokenPosition start_pos,
3263 TokenPosition end_pos,
3264 GrowableObjectArray* bytecode_function_list,
3265 GrowableObjectArray* code_function_list) {
3266 Zone* zone = Thread::Current()->zone();
3267 Class& cls = Class::Handle(zone);
3268 Array& functions = Array::Handle(zone);
3269 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
3270 Function& function = Function::Handle(zone);
3271
3272 closures = isolate_->object_store()->closure_functions();
3273 const intptr_t num_closures = closures.Length();
3274 for (intptr_t pos = 0; pos < num_closures; pos++) {
3275 function ^= closures.At(pos);
3276 ASSERT(!function.IsNull());
3277 if ((function.token_pos() == start_pos) &&
3278 (function.end_token_pos() == end_pos) &&
3279 (function.script() == script.raw())) {
3280 if (function.is_debuggable()) {
3281 if (FLAG_enable_interpreter && function.HasBytecode()) {
3282 bytecode_function_list->Add(function);
3283 }
3284 if (function.HasCode()) {
3285 code_function_list->Add(function);
3286 }
3287 }
3288 if (function.HasImplicitClosureFunction()) {
3289 function = function.ImplicitClosureFunction();
3290 if (function.is_debuggable()) {
3291 if (FLAG_enable_interpreter && function.HasBytecode()) {
3292 bytecode_function_list->Add(function);
3293 }
3294 if (function.HasCode()) {
3295 code_function_list->Add(function);
3296 }
3297 }
3298 }
3299 }
3300 }
3301
3302 const ClassTable& class_table = *isolate_->class_table();
3303 const intptr_t num_classes = class_table.NumCids();
3304 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
3305 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
3306 const classid_t cid =
3307 i < num_classes ? i : ClassTable::CidFromTopLevelIndex(i - num_classes);
3308 if (class_table.HasValidClassAt(cid)) {
3309 cls = class_table.At(cid);
3310 // If the class is not finalized, e.g. if it hasn't been parsed
3311 // yet entirely, we can ignore it. If it contains a function with
3312 // an unresolved breakpoint, we will detect it if and when the
3313 // function gets compiled.
3314 if (!cls.is_finalized()) {
3315 continue;
3316 }
3317 // Note: we need to check the functions of this class even if
3318 // the class is defined in a different 'script'. There could
3319 // be mixin functions from the given script in this class.
3320 functions = cls.functions();
3321 if (!functions.IsNull()) {
3322 const intptr_t num_functions = functions.Length();
3323 for (intptr_t pos = 0; pos < num_functions; pos++) {
3324 function ^= functions.At(pos);
3325 ASSERT(!function.IsNull());
3326 bool function_added = false;
3327 if (function.is_debuggable() &&
3328 (function.HasCode() ||
3329 (FLAG_enable_interpreter && function.HasBytecode())) &&
3330 function.token_pos() == start_pos &&
3331 function.end_token_pos() == end_pos &&
3332 function.script() == script.raw()) {
3333 if (FLAG_enable_interpreter && function.HasBytecode()) {
3334 bytecode_function_list->Add(function);
3335 }
3336 if (function.HasCode()) {
3337 code_function_list->Add(function);
3338 }
3339 function_added = true;
3340 }
3341 if (function_added && function.HasImplicitClosureFunction()) {
3342 function = function.ImplicitClosureFunction();
3343 if (function.is_debuggable()) {
3344 if (FLAG_enable_interpreter && function.HasBytecode()) {
3345 bytecode_function_list->Add(function);
3346 }
3347 if (function.HasCode()) {
3348 code_function_list->Add(function);
3349 }
3350 }
3351 }
3352 }
3353 }
3354 }
3355 }
3356}
3357
3358static void SelectBestFit(Function* best_fit, Function* func) {
3359 if (best_fit->IsNull()) {
3360 *best_fit = func->raw();
3361 } else {
3362 if ((func->token_pos() > best_fit->token_pos()) &&
3363 ((func->end_token_pos() <= best_fit->end_token_pos()))) {
3364 *best_fit = func->raw();
3365 }
3366 }
3367}
3368
3369// Returns true if a best fit is found. A best fit can either be a function
3370// or a field. If it is a function, then the best fit function is returned
3371// in |best_fit|. If a best fit is a field, it means that a latent
3372// breakpoint can be set in the range |token_pos| to |last_token_pos|.
3373bool Debugger::FindBestFit(const Script& script,
3374 TokenPosition token_pos,
3375 TokenPosition last_token_pos,
3376 Function* best_fit) {
3377 Thread* thread = Thread::Current();
3378 Zone* zone = thread->zone();
3379 Class& cls = Class::Handle(zone);
3380
3381 // A single script can belong to several libraries because of mixins.
3382 // Go through all libraries and for each that contains the script, try to find
3383 // a fit there.
3384 // Return the first fit found, but if a library doesn't contain a fit,
3385 // process the next one.
3386 const GrowableObjectArray& libs = GrowableObjectArray::Handle(
3387 zone, thread->isolate()->object_store()->libraries());
3388 Library& lib = Library::Handle(zone);
3389 for (int i = 0; i < libs.Length(); i++) {
3390 lib ^= libs.At(i);
3391 ASSERT(!lib.IsNull());
3392 const Array& scripts = Array::Handle(zone, lib.LoadedScripts());
3393 bool lib_has_script = false;
3394 for (intptr_t j = 0; j < scripts.Length(); j++) {
3395 if (scripts.At(j) == script.raw()) {
3396 lib_has_script = true;
3397 break;
3398 }
3399 }
3400 if (!lib_has_script) {
3401 continue;
3402 }
3403
3404 if (!lib.IsDebuggable()) {
3405 if (FLAG_verbose_debug) {
3406 OS::PrintErr("Library '%s' has been marked as non-debuggable\n",
3407 lib.ToCString());
3408 }
3409 continue;
3410 }
3411 const GrowableObjectArray& closures = GrowableObjectArray::Handle(
3412 zone, isolate_->object_store()->closure_functions());
3413 Array& functions = Array::Handle(zone);
3414 Function& function = Function::Handle(zone);
3415 Array& fields = Array::Handle(zone);
3416 Field& field = Field::Handle(zone);
3417 Error& error = Error::Handle(zone);
3418
3419 const intptr_t num_closures = closures.Length();
3420 for (intptr_t i = 0; i < num_closures; i++) {
3421 function ^= closures.At(i);
3422 if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
3423 // Select the inner most closure.
3424 SelectBestFit(best_fit, &function);
3425 }
3426 }
3427 if (!best_fit->IsNull()) {
3428 // The inner most closure found will be the best fit. Going
3429 // over class functions below will not help in any further
3430 // narrowing.
3431 return true;
3432 }
3433
3434 const ClassTable& class_table = *isolate_->class_table();
3435 const intptr_t num_classes = class_table.NumCids();
3436 const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
3437 for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
3438 const classid_t cid =
3439 i < num_classes ? i
3440 : ClassTable::CidFromTopLevelIndex(i - num_classes);
3441 if (!class_table.HasValidClassAt(cid)) {
3442 continue;
3443 }
3444 cls = class_table.At(cid);
3445 // This class is relevant to us only if it belongs to the
3446 // library to which |script| belongs.
3447 if (cls.library() != lib.raw()) {
3448 continue;
3449 }
3450 // Parse class definition if not done yet.
3451 error = cls.EnsureIsFinalized(Thread::Current());
3452 if (!error.IsNull()) {
3453 // Ignore functions in this class.
3454 // TODO(hausner): Should we propagate this error? How?
3455 // EnsureIsFinalized only returns an error object if there
3456 // is no longjump base on the stack.
3457 continue;
3458 }
3459 functions = cls.functions();
3460 if (!functions.IsNull()) {
3461 const intptr_t num_functions = functions.Length();
3462 for (intptr_t pos = 0; pos < num_functions; pos++) {
3463 function ^= functions.At(pos);
3464 ASSERT(!function.IsNull());
3465 if (IsImplicitFunction(function)) {
3466 // Implicit functions do not have a user specifiable source
3467 // location.
3468 continue;
3469 }
3470 if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
3471 // Closures and inner functions within a class method are not
3472 // present in the functions of a class. Hence, we can return
3473 // right away as looking through other functions of a class
3474 // will not narrow down to any inner function/closure.
3475 *best_fit = function.raw();
3476 return true;
3477 }
3478 }
3479 }
3480 // If none of the functions in the class contain token_pos, then we
3481 // check if it falls within a function literal initializer of a field
3482 // that has not been initialized yet. If the field (and hence the
3483 // function literal initializer) has already been initialized, then
3484 // it would have been found above in the object store as a closure.
3485 fields = cls.fields();
3486 if (!fields.IsNull()) {
3487 const intptr_t num_fields = fields.Length();
3488 for (intptr_t pos = 0; pos < num_fields; pos++) {
3489 TokenPosition start;
3490 TokenPosition end;
3491 field ^= fields.At(pos);
3492 ASSERT(!field.IsNull());
3493 if (field.Script() != script.raw()) {
3494 // The field should be defined in the script we want to set
3495 // the breakpoint in.
3496 continue;
3497 }
3498 if (!field.has_nontrivial_initializer()) {
3499 continue;
3500 }
3501 start = field.token_pos();
3502 end = field.end_token_pos();
3503 if ((start <= token_pos && token_pos <= end) ||
3504 (token_pos <= start && start <= last_token_pos)) {
3505 return true;
3506 }
3507 }
3508 }
3509 }
3510 }
3511 return false;
3512}
3513
3514BreakpointLocation* Debugger::SetCodeBreakpoints(
3515 bool in_bytecode,
3516 BreakpointLocation* loc,
3517 const Script& script,
3518 TokenPosition token_pos,
3519 TokenPosition last_token_pos,
3520 intptr_t requested_line,
3521 intptr_t requested_column,
3522 TokenPosition exact_token_pos,
3523 const GrowableObjectArray& functions) {
3524 ASSERT(!in_bytecode || FLAG_enable_interpreter);
3525 Function& function = Function::Handle();
3526 function ^= functions.At(0);
3527 TokenPosition breakpoint_pos =
3528 ResolveBreakpointPos(in_bytecode, function, token_pos, last_token_pos,
3529 requested_column, exact_token_pos);
3530 if (!breakpoint_pos.IsReal()) {
3531 return NULL;
3532 }
3533 if (loc == NULL) {
3534 // Find an existing resolved breakpoint location.
3535 loc = GetBreakpointLocation(
3536 script, TokenPosition::kNoSource,
3537 /* requested_line = */ -1,
3538 /* requested_column = */ -1,
3539 in_bytecode ? breakpoint_pos : TokenPosition::kNoSource,
3540 !in_bytecode ? breakpoint_pos : TokenPosition::kNoSource);
3541 }
3542 if (loc == NULL) {
3543 // Find an existing unresolved breakpoint location.
3544 loc = GetBreakpointLocation(script, token_pos, requested_line,
3545 requested_column);
3546 }
3547 if (loc == NULL) {
3548 loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
3549 requested_line, requested_column);
3550 RegisterBreakpointLocation(loc);
3551 }
3552 // A source breakpoint for this location may already exists, but it may
3553 // not yet be resolved in both bytecode and code.
3554 if (loc->IsResolved(in_bytecode)) {
3555 return loc;
3556 }
3557 loc->SetResolved(in_bytecode, function, breakpoint_pos);
3558
3559 // Create code breakpoints for all compiled functions we found.
3560 Function& func = Function::Handle();
3561 const intptr_t num_functions = functions.Length();
3562 for (intptr_t i = 0; i < num_functions; i++) {
3563 func ^= functions.At(i);
3564 ASSERT((in_bytecode && func.HasBytecode()) ||
3565 (!in_bytecode && func.HasCode()));
3566 MakeCodeBreakpointAt(func, loc);
3567 }
3568 if (FLAG_verbose_debug) {
3569 intptr_t line_number;
3570 intptr_t column_number;
3571 script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
3572 OS::PrintErr("Resolved %s breakpoint for function '%s' at line %" Pd
3573 " col %" Pd "\n",
3574 in_bytecode ? "bytecode" : "code",
3575 func.ToFullyQualifiedCString(), line_number, column_number);
3576 }
3577 return loc;
3578}
3579
3580BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
3581 TokenPosition token_pos,
3582 TokenPosition last_token_pos,
3583 intptr_t requested_line,
3584 intptr_t requested_column,
3585 const Function& function) {
3586 Function& func = Function::Handle();
3587 if (function.IsNull()) {
3588 if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
3589 return NULL;
3590 }
3591 // If func was not set (still Null), the best fit is a field.
3592 } else {
3593 func = function.raw();
3594 if (!func.token_pos().IsReal()) {
3595 return NULL; // Missing source positions in bytecode?
3596 }
3597 }
3598 if (!func.IsNull()) {
3599 // There may be more than one function object for a given function
3600 // in source code. There may be implicit closure functions, and
3601 // there may be copies of mixin functions. Collect all compiled
3602 // functions whose source code range matches exactly the best fit
3603 // function we found.
3604 GrowableObjectArray& bytecode_functions =
3605 GrowableObjectArray::Handle(GrowableObjectArray::New());
3606 GrowableObjectArray& code_functions =
3607 GrowableObjectArray::Handle(GrowableObjectArray::New());
3608 FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
3609 &bytecode_functions, &code_functions);
3610
3611 if (bytecode_functions.Length() > 0 || code_functions.Length() > 0) {
3612 // One or more function object containing this breakpoint location
3613 // have already been compiled. We can resolve the breakpoint now.
3614 // If requested_column is larger than zero, [token_pos, last_token_pos]
3615 // governs one single line of code.
3616 TokenPosition exact_token_pos = TokenPosition(-1);
3617 if (token_pos != last_token_pos && requested_column >= 0) {
3618#if !defined(DART_PRECOMPILED_RUNTIME)
3619 exact_token_pos =
3620 FindExactTokenPosition(script, token_pos, requested_column);
3621#endif // !defined(DART_PRECOMPILED_RUNTIME)
3622 }
3623 DeoptimizeWorld();
3624 // Since source positions may differ in code and bytecode, process
3625 // breakpoints in bytecode and code separately.
3626 BreakpointLocation* loc = NULL;
3627 if (bytecode_functions.Length() > 0) {
3628 loc = SetCodeBreakpoints(true, loc, script, token_pos, last_token_pos,
3629 requested_line, requested_column,
3630 exact_token_pos, bytecode_functions);
3631 }
3632 if (code_functions.Length() > 0) {
3633 loc = SetCodeBreakpoints(false, loc, script, token_pos, last_token_pos,
3634 requested_line, requested_column,
3635 exact_token_pos, code_functions);
3636 }
3637 if (loc != NULL) {
3638 return loc;
3639 }
3640 }
3641 }
3642 // There is either an uncompiled function, or an uncompiled function literal
3643 // initializer of a field at |token_pos|. Hence, Register an unresolved
3644 // breakpoint.
3645 if (FLAG_verbose_debug) {
3646 intptr_t line_number;
3647 intptr_t column_number;
3648 script.GetTokenLocation(token_pos, &line_number, &column_number);
3649 if (func.IsNull()) {
3650 OS::PrintErr(
3651 "Registering pending breakpoint for "
3652 "an uncompiled function literal at line %" Pd " col %" Pd "\n",
3653 line_number, column_number);
3654 } else {
3655 OS::PrintErr(
3656 "Registering pending breakpoint for "
3657 "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
3658 func.ToFullyQualifiedCString(), line_number, column_number);
3659 }
3660 }
3661 BreakpointLocation* loc =
3662 GetBreakpointLocation(script, token_pos, -1, requested_column);
3663 if (loc == NULL) {
3664 loc = new BreakpointLocation(script, token_pos, last_token_pos,
3665 requested_line, requested_column);
3666 RegisterBreakpointLocation(loc);
3667 }
3668 return loc;
3669}
3670
3671// Synchronize the enabled/disabled state of all code breakpoints
3672// associated with the breakpoint location loc.
3673void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) {
3674 bool any_enabled = loc->AnyEnabled();
3675
3676 CodeBreakpoint* cbpt = code_breakpoints_;
3677 while (cbpt != NULL) {
3678 if (loc == cbpt->bpt_location()) {
3679 if (any_enabled) {
3680 cbpt->Enable();
3681 } else {
3682 cbpt->Disable();
3683 }
3684 }
3685 cbpt = cbpt->next();
3686 }
3687}
3688
3689Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
3690 bool single_shot) {
3691 ASSERT(!target_function.IsNull());
3692 // AsyncFunction is marked not debuggable. When target_function is an async
3693 // function, it is actually referring the inner async_op. Allow the
3694 // breakpoint to be set, it will get resolved correctly when inner async_op
3695 // gets compiled.
3696 if (!target_function.is_debuggable() && !target_function.IsAsyncFunction()) {
3697 return NULL;
3698 }
3699 const Script& script = Script::Handle(target_function.script());
3700 BreakpointLocation* bpt_location = SetBreakpoint(
3701 script, target_function.token_pos(), target_function.end_token_pos(), -1,
3702 -1 /* no requested line/col */, target_function);
3703 if (bpt_location == NULL) {
3704 return NULL;
3705 }
3706
3707 if (single_shot) {
3708 return bpt_location->AddSingleShot(this);
3709 } else {
3710 return bpt_location->AddRepeated(this);
3711 }
3712}
3713
3714Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure,
3715 bool for_over_await) {
3716 if (!closure.IsClosure()) {
3717 return NULL;
3718 }
3719 const Function& func = Function::Handle(Closure::Cast(closure).function());
3720 const Script& script = Script::Handle(func.script());
3721 BreakpointLocation* bpt_location =
3722 SetBreakpoint(script, func.token_pos(), func.end_token_pos(), -1,
3723 -1 /* no line/col */, func);
3724 return bpt_location->AddPerClosure(this, closure, for_over_await);
3725}
3726
3727Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) {
3728 if (!closure.IsClosure()) {
3729 return NULL;
3730 }
3731
3732 BreakpointLocation* loc = breakpoint_locations_;
3733 while (loc != NULL) {
3734 Breakpoint* bpt = loc->breakpoints();
3735 while (bpt != NULL) {
3736 if (bpt->IsPerClosure()) {
3737 if (closure.raw() == bpt->closure()) {
3738 return bpt;
3739 }
3740 }
3741 bpt = bpt->next();
3742 }
3743 loc = loc->next();
3744 }
3745
3746 return NULL;
3747}
3748
3749Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
3750 intptr_t line_number) {
3751 // Prevent future tests from calling this function in the wrong
3752 // execution state. If you hit this assert, consider using
3753 // Dart_SetBreakpoint instead.
3754 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
3755
3756 BreakpointLocation* loc =
3757 BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */);
3758 if (loc != NULL) {
3759 return loc->AddRepeated(this);
3760 }
3761 return NULL;
3762}
3763
3764Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url,
3765 intptr_t line_number,
3766 intptr_t column_number) {
3767 // Prevent future tests from calling this function in the wrong
3768 // execution state. If you hit this assert, consider using
3769 // Dart_SetBreakpoint instead.
3770 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);
3771
3772 BreakpointLocation* loc =
3773 BreakpointLocationAtLineCol(script_url, line_number, column_number);
3774 if (loc != NULL) {
3775 return loc->AddRepeated(this);
3776 }
3777 return NULL;
3778}
3779
3780BreakpointLocation* Debugger::BreakpointLocationAtLineCol(
3781 const String& script_url,
3782 intptr_t line_number,
3783 intptr_t column_number) {
3784 Zone* zone = Thread::Current()->zone();
3785 Library& lib = Library::Handle(zone);
3786 Script& script = Script::Handle(zone);
3787 const GrowableObjectArray& libs =
3788 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
3789 bool is_package = script_url.StartsWith(Symbols::PackageScheme());
3790 Script& script_for_lib = Script::Handle(zone);
3791 for (intptr_t i = 0; i < libs.Length(); i++) {
3792 lib ^= libs.At(i);
3793 // Ensure that all top-level members are loaded so their scripts
3794 // are available for look up. When certain script only contains
3795 // top level functions, scripts could still be loaded correctly.
3796 lib.EnsureTopLevelClassIsFinalized();
3797 script_for_lib = lib.LookupScript(script_url, !is_package);
3798 if (!script_for_lib.IsNull()) {
3799 if (script.IsNull()) {
3800 script = script_for_lib.raw();
3801 } else if (script.raw() != script_for_lib.raw()) {
3802 if (FLAG_verbose_debug) {
3803 OS::PrintErr("Multiple scripts match url '%s'\n",
3804 script_url.ToCString());
3805 }
3806 return NULL;
3807 }
3808 }
3809 }
3810 if (script.IsNull()) {
3811 // No script found with given url. Create a latent breakpoint which
3812 // will be set if the url is loaded later.
3813 BreakpointLocation* latent_bpt =
3814 GetLatentBreakpoint(script_url, line_number, column_number);
3815 if (FLAG_verbose_debug) {
3816 OS::PrintErr(
3817 "Set latent breakpoint in url '%s' at "
3818 "line %" Pd " col %" Pd "\n",
3819 script_url.ToCString(), line_number, column_number);
3820 }
3821 return latent_bpt;
3822 }
3823 TokenPosition first_token_idx, last_token_idx;
3824 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
3825 if (!first_token_idx.IsReal()) {
3826 // Script does not contain the given line number.
3827 if (FLAG_verbose_debug) {
3828 OS::PrintErr("Script '%s' does not contain line number %" Pd "\n",
3829 script_url.ToCString(), line_number);
3830 }
3831 return NULL;
3832 } else if (!last_token_idx.IsReal()) {
3833 // Line does not contain any tokens.
3834 if (FLAG_verbose_debug) {
3835 OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
3836 script_url.ToCString());
3837 }
3838 return NULL;
3839 }
3840
3841 BreakpointLocation* loc = NULL;
3842 ASSERT(first_token_idx <= last_token_idx);
3843 while ((loc == NULL) && (first_token_idx <= last_token_idx)) {
3844 loc = SetBreakpoint(script, first_token_idx, last_token_idx, line_number,
3845 column_number, Function::Handle());
3846 first_token_idx.Next();
3847 }
3848 if ((loc == NULL) && FLAG_verbose_debug) {
3849 OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
3850 script_url.ToCString());
3851 }
3852 return loc;
3853}
3854
3855// static
3856void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
3857 ASSERT(visitor != NULL);
3858 BreakpointLocation* loc = breakpoint_locations_;
3859 while (loc != NULL) {
3860 loc->VisitObjectPointers(visitor);
3861 loc = loc->next();
3862 }
3863 loc = latent_locations_;
3864 while (loc != NULL) {
3865 loc->VisitObjectPointers(visitor);
3866 loc = loc->next();
3867 }
3868 CodeBreakpoint* cbpt = code_breakpoints_;
3869 while (cbpt != NULL) {
3870 cbpt->VisitObjectPointers(visitor);
3871 cbpt = cbpt->next();
3872 }
3873 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&top_frame_awaiter_));
3874}
3875
3876void Debugger::Pause(ServiceEvent* event) {
3877 ASSERT(event->IsPause()); // Should call InvokeEventHandler instead.
3878 ASSERT(!ignore_breakpoints_); // We shouldn't get here when ignoring bpts.
3879 ASSERT(!IsPaused()); // No recursive pausing.
3880
3881 pause_event_ = event;
3882 pause_event_->UpdateTimestamp();
3883
3884 // We are about to invoke the debugger's event handler. Disable
3885 // interrupts for this thread while waiting for debug commands over
3886 // the service protocol.
3887 {
3888 Thread* thread = Thread::Current();
3889 DisableThreadInterruptsScope dtis(thread);
3890 TIMELINE_DURATION(thread, Debugger, "Debugger Pause");
3891
3892 // Send the pause event.
3893 Service::HandleEvent(event);
3894
3895 {
3896 TransitionVMToNative transition(thread);
3897 isolate_->PauseEventHandler();
3898 }
3899
3900 // Notify the service that we have resumed.
3901 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3902 ASSERT(error.IsNull() || error.IsUnwindError() ||
3903 error.IsUnhandledException());
3904
3905 // Only send a resume event when the isolate is not unwinding.
3906 if (!error.IsUnwindError()) {
3907 ServiceEvent resume_event(event->isolate(), ServiceEvent::kResume);
3908 resume_event.set_top_frame(event->top_frame());
3909 Service::HandleEvent(&resume_event);
3910 }
3911 }
3912
3913 if (needs_breakpoint_cleanup_) {
3914 RemoveUnlinkedCodeBreakpoints();
3915 }
3916 pause_event_ = NULL;
3917}
3918
3919void Debugger::EnterSingleStepMode() {
3920 ResetSteppingFramePointers();
3921 DeoptimizeWorld();
3922 NotifySingleStepping(true);
3923}
3924
3925void Debugger::ResetSteppingFramePointers() {
3926 stepping_fp_ = 0;
3927 async_stepping_fp_ = 0;
3928}
3929
3930bool Debugger::SteppedForSyntheticAsyncBreakpoint() const {
3931 return synthetic_async_breakpoint_ != NULL;
3932}
3933
3934void Debugger::CleanupSyntheticAsyncBreakpoint() {
3935 if (synthetic_async_breakpoint_ != NULL) {
3936 RemoveBreakpoint(synthetic_async_breakpoint_->id());
3937 synthetic_async_breakpoint_ = NULL;
3938 }
3939}
3940
3941void Debugger::RememberTopFrameAwaiter() {
3942 if (!FLAG_async_debugger) {
3943 return;
3944 }
3945 if (stack_trace_->Length() > 0) {
3946 top_frame_awaiter_ = stack_trace_->FrameAt(0)->GetAsyncAwaiter();
3947 } else {
3948 top_frame_awaiter_ = Object::null();
3949 }
3950}
3951
3952void Debugger::SetAsyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
3953 if (!FLAG_async_debugger) {
3954 return;
3955 }
3956 if ((stack_trace->Length()) > 0 &&
3957 (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
3958 stack_trace->FrameAt(0)->function().IsAsyncGenClosure())) {
3959 async_stepping_fp_ = stack_trace->FrameAt(0)->fp();
3960 interpreted_async_stepping_ = stack_trace->FrameAt(0)->IsInterpreted();
3961 } else {
3962 async_stepping_fp_ = 0;
3963 }
3964}
3965
3966void Debugger::SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
3967 if (stack_trace->Length() > 0) {
3968 stepping_fp_ = stack_trace->FrameAt(0)->fp();
3969 interpreted_stepping_ = stack_trace->FrameAt(0)->IsInterpreted();
3970 } else {
3971 stepping_fp_ = 0;
3972 }
3973}
3974
3975void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace,
3976 bool skip_next_step) {
3977 ResetSteppingFramePointers();
3978 RememberTopFrameAwaiter();
3979 if (resume_action_ == kStepInto) {
3980 // When single stepping, we need to deoptimize because we might be
3981 // stepping into optimized code. This happens in particular if
3982 // the isolate has been interrupted, but can happen in other cases
3983 // as well. We need to deoptimize the world in case we are about
3984 // to call an optimized function.
3985 DeoptimizeWorld();
3986 NotifySingleStepping(true);
3987 skip_next_step_ = skip_next_step;
3988 SetAsyncSteppingFramePointer(stack_trace);
3989 if (FLAG_verbose_debug) {
3990 OS::PrintErr("HandleSteppingRequest- kStepInto\n");
3991 }
3992 } else if (resume_action_ == kStepOver) {
3993 DeoptimizeWorld();
3994 NotifySingleStepping(true);
3995 skip_next_step_ = skip_next_step;
3996 SetSyncSteppingFramePointer(stack_trace);
3997 SetAsyncSteppingFramePointer(stack_trace);
3998 if (FLAG_verbose_debug) {
3999 OS::PrintErr("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
4000 }
4001 } else if (resume_action_ == kStepOut) {
4002 if (FLAG_async_debugger) {
4003 if (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
4004 stack_trace->FrameAt(0)->function().IsAsyncGenClosure()) {
4005 // Request to step out of an async/async* closure.
4006 const Object& async_op =
4007 Object::Handle(stack_trace->FrameAt(0)->GetAsyncAwaiter());
4008 if (!async_op.IsNull()) {
4009 // Step out to the awaiter.
4010 ASSERT(async_op.IsClosure());
4011 AsyncStepInto(Closure::Cast(async_op));
4012 if (FLAG_verbose_debug) {
4013 OS::PrintErr("HandleSteppingRequest- kContinue to async_op %s\n",
4014 Function::Handle(Closure::Cast(async_op).function())
4015 .ToFullyQualifiedCString());
4016 }
4017 return;
4018 }
4019 }
4020 }
4021 // Fall through to synchronous stepping.
4022 DeoptimizeWorld();
4023 NotifySingleStepping(true);
4024 // Find topmost caller that is debuggable.
4025 for (intptr_t i = 1; i < stack_trace->Length(); i++) {
4026 ActivationFrame* frame = stack_trace->FrameAt(i);
4027 if (frame->IsDebuggable()) {
4028 stepping_fp_ = frame->fp();
4029 interpreted_stepping_ = frame->IsInterpreted();
4030 break;
4031 }
4032 }
4033 if (FLAG_verbose_debug) {
4034 OS::PrintErr("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
4035 }
4036 } else if (resume_action_ == kStepRewind) {
4037 if (FLAG_trace_rewind) {
4038 OS::PrintErr("Rewinding to frame %" Pd "\n", resume_frame_index_);
4039 OS::PrintErr(
4040 "-------------------------\n"
4041 "All frames...\n\n");
4042 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
4043 Thread::Current(),
4044 StackFrameIterator::kNoCrossThreadIteration);
4045 StackFrame* frame = iterator.NextFrame();
4046 intptr_t num = 0;
4047 while ((frame != NULL)) {
4048 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
4049 frame = iterator.NextFrame();
4050 }
4051 }
4052 RewindToFrame(resume_frame_index_);
4053 UNREACHABLE();
4054 }
4055}
4056
4057void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
4058 DebuggerStackTrace* async_causal_stack_trace,
4059 DebuggerStackTrace* awaiter_stack_trace) {
4060 ASSERT(stack_trace_ == NULL);
4061 stack_trace_ = stack_trace;
4062 ASSERT(async_causal_stack_trace_ == NULL);
4063 async_causal_stack_trace_ = async_causal_stack_trace;
4064 ASSERT(awaiter_stack_trace_ == NULL);
4065 awaiter_stack_trace_ = awaiter_stack_trace;
4066}
4067
4068void Debugger::ClearCachedStackTraces() {
4069 stack_trace_ = NULL;
4070 async_causal_stack_trace_ = NULL;
4071 awaiter_stack_trace_ = NULL;
4072}
4073
4074static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack,
4075 intptr_t frame_index) {
4076 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) {
4077 ActivationFrame* frame = stack->FrameAt(i);
4078 if (frame->IsRewindable()) {
4079 return i;
4080 }
4081 }
4082 return -1;
4083}
4084
4085// Can the top frame be rewound?
4086bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const {
4087 // check rewind pc is found
4088 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
4089 intptr_t num_frames = stack->Length();
4090 if (frame_index < 1 || frame_index >= num_frames) {
4091 if (error != nullptr) {
4092 *error = Thread::Current()->zone()->PrintToString(
4093 "Frame must be in bounds [1..%" Pd
4094 "]: "
4095 "saw %" Pd "",
4096 num_frames - 1, frame_index);
4097 }
4098 return false;
4099 }
4100 ActivationFrame* frame = stack->FrameAt(frame_index);
4101 if (!frame->IsRewindable()) {
4102 intptr_t next_index = FindNextRewindFrameIndex(stack, frame_index);
4103 if (next_index > 0) {
4104 *error = Thread::Current()->zone()->PrintToString(
4105 "Cannot rewind to frame %" Pd
4106 " due to conflicting compiler "
4107 "optimizations. "
4108 "Run the vm with --no-prune-dead-locals to disallow these "
4109 "optimizations. "
4110 "Next valid rewind frame is %" Pd ".",
4111 frame_index, next_index);
4112 } else {
4113 *error = Thread::Current()->zone()->PrintToString(
4114 "Cannot rewind to frame %" Pd
4115 " due to conflicting compiler "
4116 "optimizations. "
4117 "Run the vm with --no-prune-dead-locals to disallow these "
4118 "optimizations.",
4119 frame_index);
4120 }
4121 return false;
4122 }
4123 return true;
4124}
4125
4126// Given a return address, find the "rewind" pc, which is the pc
4127// before the corresponding call.
4128static uword LookupRewindPc(const Code& code, uword return_address) {
4129 ASSERT(!code.is_optimized());
4130 ASSERT(code.ContainsInstructionAt(return_address));
4131
4132 uword pc_offset = return_address - code.PayloadStart();
4133 const PcDescriptors& descriptors =
4134 PcDescriptors::Handle(code.pc_descriptors());
4135 PcDescriptors::Iterator iter(
4136 descriptors, PcDescriptorsLayout::kRewind | PcDescriptorsLayout::kIcCall |
4137 PcDescriptorsLayout::kUnoptStaticCall);
4138 intptr_t rewind_deopt_id = -1;
4139 uword rewind_pc = 0;
4140 while (iter.MoveNext()) {
4141 if (iter.Kind() == PcDescriptorsLayout::kRewind) {
4142 // Remember the last rewind so we don't need to iterator twice.
4143 rewind_pc = code.PayloadStart() + iter.PcOffset();
4144 rewind_deopt_id = iter.DeoptId();
4145 }
4146 if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) {
4147 return rewind_pc;
4148 }
4149 }
4150 return 0;
4151}
4152
4153// Given a return address, find the "rewind" pc, which is the pc
4154// before the corresponding call.
4155static uword LookupRewindPc(const Bytecode& bytecode, uword return_address) {
4156#if defined(DART_PRECOMPILED_RUNTIME)
4157 UNREACHABLE();
4158#else
4159 ASSERT(bytecode.ContainsInstructionAt(return_address));
4160 uword pc = bytecode.PayloadStart();
4161 const uword end_pc = pc + bytecode.Size();
4162 while (pc < end_pc) {
4163 uword next_pc = KernelBytecode::Next(pc);
4164 if (next_pc == return_address) {
4165 return pc;
4166 }
4167 pc = next_pc;
4168 }
4169 return 0;
4170#endif
4171}
4172
4173void Debugger::RewindToFrame(intptr_t frame_index) {
4174 Thread* thread = Thread::Current();
4175 Zone* zone = thread->zone();
4176 Code& code = Code::Handle(zone);
4177#if !defined(DART_PRECOMPILED_RUNTIME)
4178 Bytecode& bytecode = Bytecode::Handle(zone);
4179#endif // !defined(DART_PRECOMPILED_RUNTIME)
4180 Function& function = Function::Handle(zone);
4181
4182 // Find the requested frame.
4183 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
4184 Thread::Current(),
4185 StackFrameIterator::kNoCrossThreadIteration);
4186 intptr_t current_frame = 0;
4187 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
4188 frame = iterator.NextFrame()) {
4189 ASSERT(frame->IsValid());
4190 if (frame->IsDartFrame()) {
4191 if (frame->is_interpreted()) {
4192#if !defined(DART_PRECOMPILED_RUNTIME)
4193 bytecode = frame->LookupDartBytecode();
4194 function = bytecode.function();
4195 if (function.IsNull() || !IsFunctionVisible(function)) {
4196 continue; // Skip bytecode stub frame or invisible frame.
4197 }
4198 if (current_frame == frame_index) {
4199 // We are rewinding to an interpreted frame.
4200 RewindToInterpretedFrame(frame, bytecode);
4201 UNREACHABLE();
4202 }
4203 current_frame++;
4204#else
4205 UNREACHABLE();
4206#endif // !defined(DART_PRECOMPILED_RUNTIME)
4207 } else {
4208 code = frame->LookupDartCode();
4209 function = code.function();
4210 if (!IsFunctionVisible(function)) {
4211 continue;
4212 }
4213 if (code.is_optimized()) {
4214 intptr_t sub_index = 0;
4215 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
4216 it.Advance()) {
4217 if (current_frame == frame_index) {
4218 RewindToOptimizedFrame(frame, code, sub_index);
4219 UNREACHABLE();
4220 }
4221 current_frame++;
4222 sub_index++;
4223 }
4224 } else {
4225 if (current_frame == frame_index) {
4226 // We are rewinding to an unoptimized frame.
4227 RewindToUnoptimizedFrame(frame, code);
4228 UNREACHABLE();
4229 }
4230 current_frame++;
4231 }
4232 }
4233 }
4234 }
4235 UNIMPLEMENTED();
4236}
4237
4238void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) {
4239 // We will be jumping out of the debugger rather than exiting this
4240 // function, so prepare the debugger state.
4241 ClearCachedStackTraces();
4242 resume_action_ = kContinue;
4243 resume_frame_index_ = -1;
4244 EnterSingleStepMode();
4245
4246 uword rewind_pc = LookupRewindPc(code, frame->pc());
4247 if (FLAG_trace_rewind && rewind_pc == 0) {
4248 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc());
4249 }
4250 ASSERT(rewind_pc != 0);
4251 if (FLAG_trace_rewind) {
4252 OS::PrintErr(
4253 "===============================\n"
4254 "Rewinding to unoptimized frame:\n"
4255 " rewind_pc(0x%" Px " offset:0x%" Px ") sp(0x%" Px ") fp(0x%" Px
4256 ")\n"
4257 "===============================\n",
4258 rewind_pc, rewind_pc - code.PayloadStart(), frame->sp(), frame->fp());
4259 }
4260 Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(),
4261 frame->fp(), true /* clear lazy deopt at target */);
4262 UNREACHABLE();
4263}
4264
4265void Debugger::RewindToOptimizedFrame(StackFrame* frame,
4266 const Code& optimized_code,
4267 intptr_t sub_index) {
4268 post_deopt_frame_index_ = sub_index;
4269
4270 // We will be jumping out of the debugger rather than exiting this
4271 // function, so prepare the debugger state.
4272 ClearCachedStackTraces();
4273 resume_action_ = kContinue;
4274 resume_frame_index_ = -1;
4275 EnterSingleStepMode();
4276
4277 if (FLAG_trace_rewind) {
4278 OS::PrintErr(
4279 "===============================\n"
4280 "Deoptimizing frame for rewind:\n"
4281 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
4282 ")\n"
4283 "===============================\n",
4284 frame->pc(), frame->sp(), frame->fp());
4285 }
4286 Thread* thread = Thread::Current();
4287 thread->set_resume_pc(frame->pc());
4288 uword deopt_stub_pc = StubCode::DeoptForRewind().EntryPoint();
4289 Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(),
4290 true /* clear lazy deopt at target */);
4291 UNREACHABLE();
4292}
4293
4294void Debugger::RewindToInterpretedFrame(StackFrame* frame,
4295 const Bytecode& bytecode) {
4296 // We will be jumping out of the debugger rather than exiting this
4297 // function, so prepare the debugger state.
4298 ClearCachedStackTraces();
4299 resume_action_ = kContinue;
4300 resume_frame_index_ = -1;
4301 EnterSingleStepMode();
4302
4303 uword rewind_pc = LookupRewindPc(bytecode, frame->pc());
4304 if (FLAG_trace_rewind && rewind_pc == 0) {
4305 OS::PrintErr("Unable to find rewind pc for bytecode pc(%" Px ")\n",
4306 frame->pc());
4307 }
4308 ASSERT(rewind_pc != 0);
4309 if (FLAG_trace_rewind) {
4310 OS::PrintErr(
4311 "===============================\n"
4312 "Rewinding to interpreted frame:\n"
4313 " rewind_pc(0x%" Px " offset:0x%" Px ") sp(0x%" Px ") fp(0x%" Px
4314 ")\n"
4315 "===============================\n",
4316 rewind_pc, rewind_pc - bytecode.PayloadStart(), frame->sp(),
4317 frame->fp());
4318 }
4319 Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(),
4320 frame->fp(), true /* clear lazy deopt at target */);
4321 UNREACHABLE();
4322}
4323
4324void Debugger::RewindPostDeopt() {
4325 intptr_t rewind_frame = post_deopt_frame_index_;
4326 post_deopt_frame_index_ = -1;
4327 if (FLAG_trace_rewind) {
4328 OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame);
4329 OS::PrintErr(
4330 "-------------------------\n"
4331 "All frames...\n\n");
4332 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
4333 Thread::Current(),
4334 StackFrameIterator::kNoCrossThreadIteration);
4335 StackFrame* frame = iterator.NextFrame();
4336 intptr_t num = 0;
4337 while ((frame != NULL)) {
4338 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
4339 frame = iterator.NextFrame();
4340 }
4341 }
4342
4343 Thread* thread = Thread::Current();
4344 Zone* zone = thread->zone();
4345 Code& code = Code::Handle(zone);
4346
4347 StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
4348 Thread::Current(),
4349 StackFrameIterator::kNoCrossThreadIteration);
4350 intptr_t current_frame = 0;
4351 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
4352 frame = iterator.NextFrame()) {
4353 ASSERT(frame->IsValid());
4354 if (frame->IsDartFrame()) {
4355 code = frame->LookupDartCode();
4356 ASSERT(!code.is_optimized());
4357 if (current_frame == rewind_frame) {
4358 RewindToUnoptimizedFrame(frame, code);
4359 UNREACHABLE();
4360 }
4361 current_frame++;
4362 }
4363 }
4364}
4365
4366// static
4367bool Debugger::IsDebuggable(const Function& func) {
4368 if (!func.is_debuggable()) {
4369 return false;
4370 }
4371 const Class& cls = Class::Handle(func.Owner());
4372 const Library& lib = Library::Handle(cls.library());
4373 return lib.IsDebuggable();
4374}
4375
4376bool Debugger::IsDebugging(Thread* thread, const Function& func) {
4377 Debugger* debugger = thread->isolate()->debugger();
4378 return debugger->IsStepping() ||
4379 debugger->HasBreakpoint(func, thread->zone());
4380}
4381
4382void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
4383 resume_action_ = kContinue;
4384 ResetSteppingFramePointers();
4385 NotifySingleStepping(false);
4386 ASSERT(!IsPaused());
4387 if ((bpt != NULL) && bpt->IsSingleShot()) {
4388 RemoveBreakpoint(bpt->id());
4389 bpt = NULL;
4390 }
4391
4392 ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint);
4393 event.set_top_frame(top_frame);
4394 event.set_breakpoint(bpt);
4395 event.set_at_async_jump(IsAtAsyncJump(top_frame));
4396 Pause(&event);
4397}
4398
4399bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) {
4400 Zone* zone = Thread::Current()->zone();
4401 Object& closure_or_null =
4402 Object::Handle(zone, top_frame->GetAsyncOperation());
4403 if (!closure_or_null.IsNull()) {
4404 ASSERT(top_frame->function().IsAsyncClosure() ||
4405 top_frame->function().IsAsyncGenClosure());
4406 ASSERT(closure_or_null.IsInstance());
4407 ASSERT(Instance::Cast(closure_or_null).IsClosure());
4408 if (top_frame->function().is_declared_in_bytecode()) {
4409#if !defined(DART_PRECOMPILED_RUNTIME)
4410 const auto& bytecode =
4411 Bytecode::Handle(zone, top_frame->function().bytecode());
4412 const TokenPosition token_pos = top_frame->TokenPos();
4413 kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
4414 while (iter.MoveNext()) {
4415 if (iter.IsYieldPoint() && (iter.TokenPos() == token_pos)) {
4416 return true;
4417 }
4418 }
4419 return false;
4420#else
4421 UNREACHABLE();
4422#endif // !defined(DART_PRECOMPILED_RUNTIME)
4423 }
4424 ASSERT(!top_frame->IsInterpreted());
4425 const auto& pc_descriptors =
4426 PcDescriptors::Handle(zone, top_frame->code().pc_descriptors());
4427 if (pc_descriptors.IsNull()) {
4428 return false;
4429 }
4430 const TokenPosition looking_for = top_frame->TokenPos();
4431 PcDescriptors::Iterator it(pc_descriptors, PcDescriptorsLayout::kOther);
4432 while (it.MoveNext()) {
4433 if (it.TokenPos() == looking_for &&
4434 it.YieldIndex() != PcDescriptorsLayout::kInvalidYieldIndex) {
4435 return true;
4436 }
4437 }
4438 }
4439 return false;
4440}
4441
4442ErrorPtr Debugger::PauseStepping() {
4443 ASSERT(isolate_->single_step());
4444 // Don't pause recursively.
4445 if (IsPaused()) {
4446 return Error::null();
4447 }
4448 if (skip_next_step_) {
4449 skip_next_step_ = false;
4450 return Error::null();
4451 }
4452
4453 // Check whether we are in a Dart function that the user is
4454 // interested in. If we saved the frame pointer of a stack frame
4455 // the user is interested in, we ignore the single step if we are
4456 // in a callee of that frame. Note that we assume that the stack
4457 // grows towards lower addresses.
4458 ActivationFrame* frame = TopDartFrame();
4459 ASSERT(frame != NULL);
4460
4461 if (FLAG_async_debugger) {
4462 if ((async_stepping_fp_ != 0) && (top_frame_awaiter_ != Object::null())) {
4463 // Check if the user has single stepped out of an async function with
4464 // an awaiter. The first check handles the case of calling into the
4465 // async machinery as we finish the async function. The second check
4466 // handles the case of returning from an async function.
4467 const ActivationFrame::Relation relation =
4468 frame->CompareTo(async_stepping_fp_, interpreted_async_stepping_);
4469 const bool exited_async_function =
4470 (relation == ActivationFrame::kCallee && frame->IsAsyncMachinery()) ||
4471 relation == ActivationFrame::kCaller;
4472 if (exited_async_function) {
4473 // Step to the top frame awaiter.
4474 const Object& async_op = Object::Handle(top_frame_awaiter_);
4475 top_frame_awaiter_ = Object::null();
4476 AsyncStepInto(Closure::Cast(async_op));
4477 return Error::null();
4478 }
4479 }
4480 }
4481
4482 if (stepping_fp_ != 0) {
4483 // There is an "interesting frame" set. Only pause at appropriate
4484 // locations in this frame.
4485 const ActivationFrame::Relation relation =
4486 frame->CompareTo(stepping_fp_, interpreted_stepping_);
4487 if (relation == ActivationFrame::kCallee) {
4488 // We are in a callee of the frame we're interested in.
4489 // Ignore this stepping break.
4490 return Error::null();
4491 } else if (relation == ActivationFrame::kCaller) {
4492 // We returned from the "interesting frame", there can be no more
4493 // stepping breaks for it. Pause at the next appropriate location
4494 // and let the user set the "interesting" frame again.
4495 ResetSteppingFramePointers();
4496 }
4497 }
4498
4499 if (!frame->IsDebuggable()) {
4500 return Error::null();
4501 }
4502 if (!frame->TokenPos().IsDebugPause()) {
4503 return Error::null();
4504 }
4505
4506 if (frame->fp() == last_stepping_fp_ &&
4507 frame->TokenPos() == last_stepping_pos_) {
4508 // Do not stop multiple times for the same token position.
4509 // Several 'debug checked' opcodes may be issued in the same token range.
4510 return Error::null();
4511 }
4512
4513 // In bytecode, do not stop before encountering the DebugCheck opcode.
4514 // Skip this check if we previously stopped in this frame.
4515 // If no DebugCheck was emitted, do not stop (InPrologue returns true).
4516 if (frame->IsInterpreted() && frame->fp() != last_stepping_fp_) {
4517 uword debug_check_pc = frame->bytecode().GetFirstDebugCheckOpcodePc();
4518 // Frame pc is return address, debug_check_pc is exact, so use '<=' in test.
4519 if (debug_check_pc == 0 || frame->pc() <= debug_check_pc) {
4520 return Error::null();
4521 }
4522 }
4523
4524 // We are stopping in this frame at the token pos.
4525 last_stepping_fp_ = frame->fp();
4526 last_stepping_pos_ = frame->TokenPos();
4527
4528 // If there is an active breakpoint at this pc, then we should have
4529 // already bailed out of this function in the skip_next_step_ test
4530 // above.
4531 ASSERT(!HasActiveBreakpoint(frame->pc()));
4532
4533 if (FLAG_verbose_debug) {
4534 OS::PrintErr(
4535 ">>> single step break at %s:%" Pd ":%" Pd
4536 " (func %s token %s address %#" Px " offset %#" Px ")\n",
4537 String::Handle(frame->SourceUrl()).ToCString(), frame->LineNumber(),
4538 frame->ColumnNumber(),
4539 String::Handle(frame->QualifiedFunctionName()).ToCString(),
4540 frame->TokenPos().ToCString(), frame->pc(),
4541 frame->pc() - (frame->IsInterpreted() ? frame->bytecode().PayloadStart()
4542 : frame->code().PayloadStart()));
4543 }
4544
4545 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(),
4546 CollectAwaiterReturnStackTrace());
4547 if (SteppedForSyntheticAsyncBreakpoint()) {
4548 CleanupSyntheticAsyncBreakpoint();
4549 }
4550 SignalPausedEvent(frame, NULL);
4551 HandleSteppingRequest(stack_trace_);
4552 ClearCachedStackTraces();
4553
4554 // If any error occurred while in the debug message loop, return it here.
4555 return Thread::Current()->StealStickyError();
4556}
4557
4558ErrorPtr Debugger::PauseBreakpoint() {
4559 // We ignore this breakpoint when the VM is executing code invoked
4560 // by the debugger to evaluate variables values, or when we see a nested
4561 // breakpoint or exception event.
4562 if (ignore_breakpoints_ || IsPaused()) {
4563 return Error::null();
4564 }
4565 DebuggerStackTrace* stack_trace = CollectStackTrace();
4566 ASSERT(stack_trace->Length() > 0);
4567 ActivationFrame* top_frame = stack_trace->FrameAt(0);
4568 ASSERT(top_frame != NULL);
4569 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
4570 ASSERT(cbpt != NULL);
4571
4572 if (!Library::Handle(top_frame->Library()).IsDebuggable()) {
4573 return Error::null();
4574 }
4575
4576 Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame);
4577 if (bpt_hit == NULL) {
4578 return Error::null();
4579 }
4580
4581 if (bpt_hit->is_synthetic_async()) {
4582 DebuggerStackTrace* stack_trace = CollectStackTrace();
4583 ASSERT(stack_trace->Length() > 0);
4584 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
4585 CollectAwaiterReturnStackTrace());
4586
4587 // Hit a synthetic async breakpoint.
4588 if (FLAG_verbose_debug) {
4589 OS::PrintErr(
4590 ">>> hit synthetic breakpoint at %s:%" Pd
4591 " (func %s token %s address %#" Px " offset %#" Px ")\n",
4592 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(),
4593 String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
4594 cbpt->token_pos().ToCString(), top_frame->pc(),
4595 top_frame->pc() - (top_frame->IsInterpreted()
4596 ? top_frame->bytecode().PayloadStart()
4597 : top_frame->code().PayloadStart()));
4598 }
4599
4600 ASSERT(synthetic_async_breakpoint_ == NULL);
4601 synthetic_async_breakpoint_ = bpt_hit;
4602 bpt_hit = NULL;
4603
4604 // We are at the entry of an async function.
4605 // We issue a step over to resume at the point after the await statement.
4606 SetResumeAction(kStepOver);
4607 // When we single step from a user breakpoint, our next stepping
4608 // point will be at the exact same pc. Skip it.
4609 HandleSteppingRequest(stack_trace_, true /* skip next step */);
4610 ClearCachedStackTraces();
4611 return Error::null();
4612 }
4613
4614 if (FLAG_verbose_debug) {
4615 OS::PrintErr(">>> hit breakpoint %" Pd " at %s:%" Pd
4616 " (func %s token %s address %#" Px " offset %#" Px ")\n",
4617 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(),
4618 cbpt->LineNumber(),
4619 String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
4620 cbpt->token_pos().ToCString(), top_frame->pc(),
4621 top_frame->pc() - (top_frame->IsInterpreted()
4622 ? top_frame->bytecode().PayloadStart()
4623 : top_frame->code().PayloadStart()));
4624 }
4625
4626 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
4627 CollectAwaiterReturnStackTrace());
4628 SignalPausedEvent(top_frame, bpt_hit);
4629 // When we single step from a user breakpoint, our next stepping
4630 // point will be at the exact same pc. Skip it.
4631 HandleSteppingRequest(stack_trace_, true /* skip next step */);
4632 ClearCachedStackTraces();
4633
4634 // If any error occurred while in the debug message loop, return it here.
4635 return Thread::Current()->StealStickyError();
4636}
4637
4638Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location,
4639 ActivationFrame* top_frame) {
4640 if (location == NULL) {
4641 return NULL;
4642 }
4643 // There may be more than one applicable breakpoint at this location, but we
4644 // will report only one as reached. If there is a single-shot breakpoint, we
4645 // favor it; then a closure-specific breakpoint ; then an general breakpoint.
4646
4647 // First check for a single-shot breakpoint.
4648 Breakpoint* bpt = location->breakpoints();
4649 while (bpt != NULL) {
4650 if (bpt->IsSingleShot()) {
4651 return bpt;
4652 }
4653 bpt = bpt->next();
4654 }
4655
4656 // Now check for a closure-specific breakpoint.
4657 bpt = location->breakpoints();
4658 while (bpt != NULL) {
4659 if (bpt->IsPerClosure()) {
4660 Object& closure = Object::Handle(top_frame->GetClosure());
4661 ASSERT(closure.IsInstance());
4662 ASSERT(Instance::Cast(closure).IsClosure());
4663 if (closure.raw() == bpt->closure()) {
4664 return bpt;
4665 }
4666 }
4667 bpt = bpt->next();
4668 }
4669
4670 // Finally, check for a general breakpoint.
4671 bpt = location->breakpoints();
4672 while (bpt != NULL) {
4673 if (bpt->IsRepeated()) {
4674 return bpt;
4675 }
4676 bpt = bpt->next();
4677 }
4678
4679 return NULL;
4680}
4681
4682void Debugger::PauseDeveloper(const String& msg) {
4683 // We ignore this breakpoint when the VM is executing code invoked
4684 // by the debugger to evaluate variables values, or when we see a nested
4685 // breakpoint or exception event.
4686 if (ignore_breakpoints_ || IsPaused()) {
4687 return;
4688 }
4689
4690 DebuggerStackTrace* stack_trace = CollectStackTrace();
4691 ASSERT(stack_trace->Length() > 0);
4692 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
4693 CollectAwaiterReturnStackTrace());
4694 // TODO(johnmccutchan): Send |msg| to Observatory.
4695
4696 // We are in the native call to Developer_debugger. the developer
4697 // gets a better experience by not seeing this call. To accomplish
4698 // this, we continue execution until the call exits (step out).
4699 SetResumeAction(kStepOut);
4700 HandleSteppingRequest(stack_trace_);
4701 ClearCachedStackTraces();
4702}
4703
4704void Debugger::NotifyIsolateCreated() {
4705 if (NeedsIsolateEvents()) {
4706 ServiceEvent event(isolate_, ServiceEvent::kIsolateStart);
4707 InvokeEventHandler(&event);
4708 }
4709}
4710
4711// Return innermost closure contained in 'function' that contains
4712// the given token position.
4713FunctionPtr Debugger::FindInnermostClosure(const Function& function,
4714 TokenPosition token_pos) {
4715 Zone* zone = Thread::Current()->zone();
4716 const Script& outer_origin = Script::Handle(zone, function.script());
4717 const GrowableObjectArray& closures = GrowableObjectArray::Handle(
4718 zone, Isolate::Current()->object_store()->closure_functions());
4719 const intptr_t num_closures = closures.Length();
4720 Function& closure = Function::Handle(zone);
4721 Function& best_fit = Function::Handle(zone);
4722 for (intptr_t i = 0; i < num_closures; i++) {
4723 closure ^= closures.At(i);
4724 if ((function.token_pos() < closure.token_pos()) &&
4725 (closure.end_token_pos() < function.end_token_pos()) &&
4726 (closure.token_pos() <= token_pos) &&
4727 (token_pos <= closure.end_token_pos()) &&
4728 (closure.script() == outer_origin.raw())) {
4729 SelectBestFit(&best_fit, &closure);
4730 }
4731 }
4732 return best_fit.raw();
4733}
4734
4735#if !defined(DART_PRECOMPILED_RUNTIME)
4736// On single line of code with given column number,
4737// Calculate exact tokenPosition
4738TokenPosition Debugger::FindExactTokenPosition(const Script& script,
4739 TokenPosition start_of_line,
4740 intptr_t column_number) {
4741 intptr_t line = -1;
4742 intptr_t col = -1;
4743 Zone* zone = Thread::Current()->zone();
4744 kernel::KernelLineStartsReader line_starts_reader(
4745 TypedData::Handle(zone, script.line_starts()), zone);
4746 line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
4747 return TokenPosition(start_of_line.value() + (column_number - col));
4748}
4749#endif // !defined(DART_PRECOMPILED_RUNTIME)
4750
4751void Debugger::HandleCodeChange(bool bytecode_loaded, const Function& func) {
4752 if (breakpoint_locations_ == NULL) {
4753 // Return with minimal overhead if there are no breakpoints.
4754 return;
4755 }
4756 if (bytecode_loaded && !FLAG_enable_interpreter) {
4757 // We do not set breakpoints in bytecode if the interpreter is not used.
4758 return;
4759 }
4760 if (!func.is_debuggable()) {
4761 // Nothing to do if the function is not debuggable. If there is
4762 // a pending breakpoint in an inner function (that is debuggable),
4763 // we'll resolve the breakpoint when the inner function is compiled.
4764 return;
4765 }
4766 // Iterate over all source breakpoints to check whether breakpoints
4767 // need to be set in the newly compiled function.
4768 Zone* zone = Thread::Current()->zone();
4769 Script& script = Script::Handle(zone);
4770 for (BreakpointLocation* loc = breakpoint_locations_; loc != NULL;
4771 loc = loc->next()) {
4772 script = loc->script();
4773 if (FunctionOverlaps(func, script, loc->token_pos(),
4774 loc->end_token_pos())) {
4775 TokenPosition token_pos = loc->token_pos();
4776 TokenPosition end_token_pos = loc->end_token_pos();
4777 if (token_pos != end_token_pos && loc->requested_column_number() >= 0) {
4778#if !defined(DART_PRECOMPILED_RUNTIME)
4779 // Narrow down the token position range to a single value
4780 // if requested column number is provided so that inner
4781 // Closure won't be missed.
4782 token_pos = FindExactTokenPosition(script, token_pos,
4783 loc->requested_column_number());
4784#endif // !defined(DART_PRECOMPILED_RUNTIME)
4785 }
4786 const Function& inner_function =
4787 Function::Handle(zone, FindInnermostClosure(func, token_pos));
4788 if (!inner_function.IsNull()) {
4789 if (bytecode_loaded) {
4790 // func's bytecode was just loaded.
4791 // If func is a closure and has an inner closure, the inner closure
4792 // may not have been loaded yet.
4793 if (inner_function.HasBytecode()) {
4794 ASSERT(loc->IsResolved(bytecode_loaded));
4795 } else {
4796 if (FLAG_verbose_debug) {
4797 OS::PrintErr(
4798 "Pending breakpoint remains unresolved in "
4799 "inner bytecode function '%s'\n",
4800 inner_function.ToFullyQualifiedCString());
4801 }
4802 }
4803 continue;
4804 } else {
4805 // func was just compiled.
4806 // The local function of a function we just compiled cannot
4807 // be compiled already.
4808 ASSERT(!inner_function.HasCode());
4809 if (FLAG_verbose_debug) {
4810 OS::PrintErr(
4811 "Pending breakpoint remains unresolved in "
4812 "inner function '%s'\n",
4813 inner_function.ToFullyQualifiedCString());
4814 }
4815 continue;
4816 }
4817
4818 // TODO(hausner): What should we do if function is optimized?
4819 // Can we deoptimize the function?
4820 ASSERT(!func.HasOptimizedCode());
4821 }
4822
4823 // There is no local function within func that contains the
4824 // breakpoint token position. Resolve the breakpoint if necessary
4825 // and set the code breakpoints.
4826 const bool resolved_in_bytecode =
4827 !bytecode_loaded && loc->IsResolved(/* in_bytecode = */ true);
4828 if (!loc->IsResolved(bytecode_loaded)) {
4829 // Resolve source breakpoint in the newly compiled function.
4830 TokenPosition bp_pos = ResolveBreakpointPos(
4831 bytecode_loaded, func, loc->token_pos(), loc->end_token_pos(),
4832 loc->requested_column_number(), token_pos);
4833 if (!bp_pos.IsDebugPause()) {
4834 if (FLAG_verbose_debug) {
4835 OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
4836 func.ToFullyQualifiedCString());
4837 }
4838 continue;
4839 }
4840 TokenPosition requested_pos = loc->token_pos();
4841 TokenPosition requested_end_pos = loc->end_token_pos();
4842 loc->SetResolved(bytecode_loaded, func, bp_pos);
4843 Breakpoint* bpt = loc->breakpoints();
4844 while (bpt != NULL) {
4845 if (FLAG_verbose_debug) {
4846 OS::PrintErr(
4847 "Resolved breakpoint %" Pd
4848 " to pos %s, function '%s' (requested range %s-%s, "
4849 "requested col %" Pd ")\n",
4850 bpt->id(), loc->token_pos().ToCString(),
4851 func.ToFullyQualifiedCString(), requested_pos.ToCString(),
4852 requested_end_pos.ToCString(), loc->requested_column_number());
4853 }
4854 // Do not signal resolution in code if already signaled resolution
4855 // in bytecode.
4856 if (!resolved_in_bytecode) {
4857 SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
4858 }
4859 bpt = bpt->next();
4860 }
4861 }
4862 ASSERT(loc->IsResolved(bytecode_loaded));
4863 if (FLAG_verbose_debug) {
4864 Breakpoint* bpt = loc->breakpoints();
4865 while (bpt != NULL) {
4866 OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
4867 func.IsClosureFunction() ? "closure" : "function",
4868 func.ToFullyQualifiedCString());
4869 bpt = bpt->next();
4870 }
4871 }
4872 MakeCodeBreakpointAt(func, loc);
4873 }
4874 }
4875}
4876
4877void Debugger::NotifyDoneLoading() {
4878 if (latent_locations_ == NULL) {
4879 // Common, fast path.
4880 return;
4881 }
4882 Zone* zone = Thread::Current()->zone();
4883 Library& lib = Library::Handle(zone);
4884 Script& script = Script::Handle(zone);
4885 String& url = String::Handle(zone);
4886 BreakpointLocation* loc = latent_locations_;
4887 BreakpointLocation* prev_loc = NULL;
4888 const GrowableObjectArray& libs =
4889 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
4890 while (loc != NULL) {
4891 url = loc->url();
4892 bool found_match = false;
4893 bool is_package = url.StartsWith(Symbols::PackageScheme());
4894 for (intptr_t i = 0; i < libs.Length(); i++) {
4895 lib ^= libs.At(i);
4896 script = lib.LookupScript(url, !is_package);
4897 if (!script.IsNull()) {
4898 // Found a script with matching url for this latent breakpoint.
4899 // Unlink the latent breakpoint from the list.
4900 found_match = true;
4901 BreakpointLocation* matched_loc = loc;
4902 loc = loc->next();
4903 if (prev_loc == NULL) {
4904 latent_locations_ = loc;
4905 } else {
4906 prev_loc->set_next(loc);
4907 }
4908 // Now find the token range at the requested line and make a
4909 // new unresolved source breakpoint.
4910 intptr_t line_number = matched_loc->requested_line_number();
4911 intptr_t column_number = matched_loc->requested_column_number();
4912 ASSERT(line_number >= 0);
4913 TokenPosition first_token_pos, last_token_pos;
4914 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
4915 if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) {
4916 // Script does not contain the given line number or there are no
4917 // tokens on the line. Drop the breakpoint silently.
4918 Breakpoint* bpt = matched_loc->breakpoints();
4919 while (bpt != NULL) {
4920 if (FLAG_verbose_debug) {
4921 OS::PrintErr("No code found at line %" Pd
4922 ": "
4923 "dropping latent breakpoint %" Pd " in '%s'\n",
4924 line_number, bpt->id(), url.ToCString());
4925 }
4926 Breakpoint* prev = bpt;
4927 bpt = bpt->next();
4928 delete prev;
4929 }
4930 delete matched_loc;
4931 } else {
4932 // We don't expect to already have a breakpoint for this location.
4933 // If there is one, assert in debug build but silently drop
4934 // the latent breakpoint in release build.
4935 BreakpointLocation* existing_loc =
4936 GetBreakpointLocation(script, first_token_pos, -1, column_number);
4937 ASSERT(existing_loc == NULL);
4938 if (existing_loc == NULL) {
4939 // Create and register a new source breakpoint for the
4940 // latent breakpoint.
4941 BreakpointLocation* unresolved_loc =
4942 new BreakpointLocation(script, first_token_pos, last_token_pos,
4943 line_number, column_number);
4944 RegisterBreakpointLocation(unresolved_loc);
4945
4946 // Move breakpoints over.
4947 Breakpoint* bpt = matched_loc->breakpoints();
4948 unresolved_loc->set_breakpoints(bpt);
4949 matched_loc->set_breakpoints(NULL);
4950 while (bpt != NULL) {
4951 bpt->set_bpt_location(unresolved_loc);
4952 if (FLAG_verbose_debug) {
4953 OS::PrintErr(
4954 "Converted latent breakpoint "
4955 "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
4956 bpt->id(), url.ToCString(), line_number, column_number);
4957 }
4958 bpt = bpt->next();
4959 }
4960 SyncBreakpointLocation(unresolved_loc);
4961 }
4962 delete matched_loc;
4963 // Break out of the iteration over loaded libraries. If the
4964 // same url has been loaded into more than one library, we
4965 // only set a breakpoint in the first one.
4966 // TODO(hausner): There is one possible pitfall here.
4967 // If the user sets a latent breakpoint using a partial url that
4968 // ends up matching more than one script, the breakpoint might
4969 // get set in the wrong script.
4970 // It would be better if we could warn the user if multiple
4971 // scripts are matching.
4972 break;
4973 }
4974 }
4975 }
4976 if (!found_match) {
4977 // No matching url found in any of the libraries.
4978 if (FLAG_verbose_debug) {
4979 Breakpoint* bpt = loc->breakpoints();
4980 while (bpt != NULL) {
4981 OS::PrintErr(
4982 "No match found for latent breakpoint id "
4983 "%" Pd " with url '%s'\n",
4984 bpt->id(), url.ToCString());
4985 bpt = bpt->next();
4986 }
4987 }
4988 loc = loc->next();
4989 }
4990 }
4991}
4992
4993// TODO(hausner): Could potentially make this faster by checking
4994// whether the call target at pc is a debugger stub.
4995bool Debugger::HasActiveBreakpoint(uword pc) {
4996 CodeBreakpoint* cbpt = GetCodeBreakpoint(pc);
4997 return (cbpt != NULL) && (cbpt->IsEnabled());
4998}
4999
5000CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
5001 CodeBreakpoint* cbpt = code_breakpoints_;
5002 while (cbpt != NULL) {
5003 if (cbpt->pc() == breakpoint_address) {
5004 return cbpt;
5005 }
5006 cbpt = cbpt->next();
5007 }
5008 return NULL;
5009}
5010
5011CodePtr Debugger::GetPatchedStubAddress(uword breakpoint_address) {
5012 CodeBreakpoint* cbpt = GetCodeBreakpoint(breakpoint_address);
5013 if (cbpt != NULL) {
5014 return cbpt->OrigStubAddress();
5015 }
5016 UNREACHABLE();
5017 return Code::null();
5018}
5019
5020// Remove and delete the source breakpoint bpt and its associated
5021// code breakpoints.
5022void Debugger::RemoveBreakpoint(intptr_t bp_id) {
5023 if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) {
5024 return;
5025 }
5026 RemoveBreakpointFromTheList(bp_id, &latent_locations_);
5027}
5028
5029// Remove and delete the source breakpoint bpt and its associated
5030// code breakpoints. Returns true, if breakpoint was found and removed,
5031// returns false, if breakpoint was not found.
5032bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id,
5033 BreakpointLocation** list) {
5034 BreakpointLocation* prev_loc = NULL;
5035 BreakpointLocation* curr_loc = *list;
5036 while (curr_loc != NULL) {
5037 Breakpoint* prev_bpt = NULL;
5038 Breakpoint* curr_bpt = curr_loc->breakpoints();
5039 while (curr_bpt != NULL) {
5040 if (curr_bpt->id() == bp_id) {
5041 if (prev_bpt == NULL) {
5042 curr_loc->set_breakpoints(curr_bpt->next());
5043 } else {
5044 prev_bpt->set_next(curr_bpt->next());
5045 }
5046
5047 // Send event to client before the breakpoint's fields are
5048 // poisoned and deleted.
5049 SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
5050
5051 curr_bpt->set_next(NULL);
5052 curr_bpt->set_bpt_location(NULL);
5053 // Remove possible references to the breakpoint.
5054 if (pause_event_ != NULL && pause_event_->breakpoint() == curr_bpt) {
5055 pause_event_->set_breakpoint(NULL);
5056 }
5057 if (synthetic_async_breakpoint_ == curr_bpt) {
5058 synthetic_async_breakpoint_ = NULL;
5059 }
5060 delete curr_bpt;
5061 curr_bpt = NULL;
5062
5063 // Delete the breakpoint location object if there are no more
5064 // breakpoints at that location.
5065 if (curr_loc->breakpoints() == NULL) {
5066 if (prev_loc == NULL) {
5067 *list = curr_loc->next();
5068 } else {
5069 prev_loc->set_next(curr_loc->next());
5070 }
5071
5072 if (!curr_loc->IsLatent()) {
5073 // Remove references from code breakpoints to this breakpoint
5074 // location and disable them.
5075 // Latent breakpoint locations won't have code breakpoints.
5076 UnlinkCodeBreakpoints(curr_loc);
5077 }
5078 BreakpointLocation* next_loc = curr_loc->next();
5079 delete curr_loc;
5080 curr_loc = next_loc;
5081 }
5082
5083 // The code breakpoints will be deleted when the VM resumes
5084 // after the pause event.
5085 return true;
5086 }
5087
5088 prev_bpt = curr_bpt;
5089 curr_bpt = curr_bpt->next();
5090 }
5091 prev_loc = curr_loc;
5092 curr_loc = curr_loc->next();
5093 }
5094 // breakpoint with bp_id does not exist, nothing to do.
5095 return false;
5096}
5097
5098// Unlink code breakpoints from the given breakpoint location.
5099// They will later be deleted when control returns from the pause event
5100// callback. Also, disable the breakpoint so it no longer fires if it
5101// should be hit before it gets deleted.
5102void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) {
5103 ASSERT(bpt_location != NULL);
5104 CodeBreakpoint* curr_bpt = code_breakpoints_;
5105 while (curr_bpt != NULL) {
5106 if (curr_bpt->bpt_location() == bpt_location) {
5107 curr_bpt->Disable();
5108 curr_bpt->set_bpt_location(NULL);
5109 needs_breakpoint_cleanup_ = true;
5110 }
5111 curr_bpt = curr_bpt->next();
5112 }
5113}
5114
5115// Remove and delete unlinked code breakpoints, i.e. breakpoints that
5116// are not associated with a breakpoint location.
5117void Debugger::RemoveUnlinkedCodeBreakpoints() {
5118 CodeBreakpoint* prev_bpt = NULL;
5119 CodeBreakpoint* curr_bpt = code_breakpoints_;
5120 while (curr_bpt != NULL) {
5121 if (curr_bpt->bpt_location() == NULL) {
5122 if (prev_bpt == NULL) {
5123 code_breakpoints_ = code_breakpoints_->next();
5124 } else {
5125 prev_bpt->set_next(curr_bpt->next());
5126 }
5127 CodeBreakpoint* temp_bpt = curr_bpt;
5128 curr_bpt = curr_bpt->next();
5129 temp_bpt->Disable();
5130 delete temp_bpt;
5131 } else {
5132 prev_bpt = curr_bpt;
5133 curr_bpt = curr_bpt->next();
5134 }
5135 }
5136 needs_breakpoint_cleanup_ = false;
5137}
5138
5139BreakpointLocation* Debugger::GetBreakpointLocation(
5140 const Script& script,
5141 TokenPosition token_pos,
5142 intptr_t requested_line,
5143 intptr_t requested_column,
5144 TokenPosition bytecode_token_pos,
5145 TokenPosition code_token_pos) {
5146 BreakpointLocation* loc = breakpoint_locations_;
5147 while (loc != NULL) {
5148 if (loc->script_ == script.raw() &&
5149 (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
5150 ((requested_line == -1) ||
5151 (loc->requested_line_number_ == requested_line)) &&
5152 ((requested_column == -1) ||
5153 (loc->requested_column_number_ == requested_column)) &&
5154 (!bytecode_token_pos.IsReal() ||
5155 (loc->bytecode_token_pos_ == bytecode_token_pos)) &&
5156 (!code_token_pos.IsReal() ||
5157 (loc->code_token_pos_ == code_token_pos))) {
5158 return loc;
5159 }
5160 loc = loc->next();
5161 }
5162 return NULL;
5163}
5164
5165Breakpoint* Debugger::GetBreakpointById(intptr_t id) {
5166 Breakpoint* bpt = GetBreakpointByIdInTheList(id, breakpoint_locations_);
5167 if (bpt != NULL) {
5168 return bpt;
5169 }
5170 return GetBreakpointByIdInTheList(id, latent_locations_);
5171}
5172
5173Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t id,
5174 BreakpointLocation* list) {
5175 BreakpointLocation* loc = list;
5176 while (loc != NULL) {
5177 Breakpoint* bpt = loc->breakpoints();
5178 while (bpt != NULL) {
5179 if (bpt->id() == id) {
5180 return bpt;
5181 }
5182 bpt = bpt->next();
5183 }
5184 loc = loc->next();
5185 }
5186 return NULL;
5187}
5188
5189void Debugger::MaybeAsyncStepInto(const Closure& async_op) {
5190 if (FLAG_async_debugger && IsSingleStepping()) {
5191 // We are single stepping, set a breakpoint on the closure activation
5192 // and resume execution so we can hit the breakpoint.
5193 AsyncStepInto(async_op);
5194 }
5195}
5196
5197void Debugger::AsyncStepInto(const Closure& async_op) {
5198 SetBreakpointAtActivation(async_op, true);
5199 Continue();
5200}
5201
5202void Debugger::Continue() {
5203 SetResumeAction(kContinue);
5204 ResetSteppingFramePointers();
5205 NotifySingleStepping(false);
5206}
5207
5208BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
5209 intptr_t line,
5210 intptr_t column) {
5211 BreakpointLocation* loc = latent_locations_;
5212 String& bpt_url = String::Handle();
5213 while (loc != NULL) {
5214 bpt_url = loc->url();
5215 if (bpt_url.Equals(url) && (loc->requested_line_number() == line) &&
5216 (loc->requested_column_number() == column)) {
5217 return loc;
5218 }
5219 loc = loc->next();
5220 }
5221 // No breakpoint for this location requested. Allocate new one.
5222 loc = new BreakpointLocation(url, line, column);
5223 loc->set_next(latent_locations_);
5224 latent_locations_ = loc;
5225 return loc;
5226}
5227
5228void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
5229 ASSERT(loc->next() == NULL);
5230 loc->set_next(breakpoint_locations_);
5231 breakpoint_locations_ = loc;
5232}
5233
5234void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* cbpt) {
5235 ASSERT(cbpt->next() == NULL);
5236 cbpt->set_next(code_breakpoints_);
5237 code_breakpoints_ = cbpt;
5238}
5239
5240#endif // !PRODUCT
5241
5242} // namespace dart
5243