Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Side by Side Diff: runtime/vm/debugger.cc

Issue 2603383004: Sane asynchronous debugging and stack traces (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/flag_list.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "platform/address_sanitizer.h" 9 #include "platform/address_sanitizer.h"
10 10
11 #include "vm/code_generator.h" 11 #include "vm/code_generator.h"
12 #include "vm/code_patcher.h" 12 #include "vm/code_patcher.h"
13 #include "vm/compiler.h" 13 #include "vm/compiler.h"
14 #include "vm/dart_entry.h" 14 #include "vm/dart_entry.h"
15 #include "vm/deopt_instructions.h" 15 #include "vm/deopt_instructions.h"
16 #include "vm/flags.h" 16 #include "vm/flags.h"
17 #include "vm/globals.h" 17 #include "vm/globals.h"
18 #include "vm/longjump.h" 18 #include "vm/longjump.h"
19 #include "vm/json_stream.h" 19 #include "vm/json_stream.h"
20 #include "vm/message_handler.h" 20 #include "vm/message_handler.h"
21 #include "vm/object.h" 21 #include "vm/object.h"
22 #include "vm/object_store.h" 22 #include "vm/object_store.h"
23 #include "vm/os.h" 23 #include "vm/os.h"
24 #include "vm/port.h" 24 #include "vm/port.h"
25 #include "vm/service_event.h" 25 #include "vm/service_event.h"
26 #include "vm/service_isolate.h" 26 #include "vm/service_isolate.h"
27 #include "vm/service.h" 27 #include "vm/service.h"
28 #include "vm/stack_frame.h" 28 #include "vm/stack_frame.h"
29 #include "vm/stack_trace.h"
29 #include "vm/stub_code.h" 30 #include "vm/stub_code.h"
30 #include "vm/symbols.h" 31 #include "vm/symbols.h"
31 #include "vm/thread_interrupter.h" 32 #include "vm/thread_interrupter.h"
32 #include "vm/timeline.h" 33 #include "vm/timeline.h"
33 #include "vm/token_position.h" 34 #include "vm/token_position.h"
34 #include "vm/visitor.h" 35 #include "vm/visitor.h"
35 36
36 37
37 namespace dart { 38 namespace dart {
38 39
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 238
238 239
239 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 240 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
240 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); 241 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
241 #if !defined(TARGET_ARCH_DBC) 242 #if !defined(TARGET_ARCH_DBC)
242 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_)); 243 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
243 #endif 244 #endif
244 } 245 }
245 246
246 247
247 ActivationFrame::ActivationFrame(uword pc,
248 uword fp,
249 uword sp,
250 const Code& code,
251 const Array& deopt_frame,
252 intptr_t deopt_frame_offset)
253 : pc_(pc),
254 fp_(fp),
255 sp_(sp),
256 ctx_(Context::ZoneHandle()),
257 code_(Code::ZoneHandle(code.raw())),
258 function_(Function::ZoneHandle(code.function())),
259 token_pos_initialized_(false),
260 token_pos_(TokenPosition::kNoSource),
261 try_index_(-1),
262 line_number_(-1),
263 column_number_(-1),
264 context_level_(-1),
265 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
266 deopt_frame_offset_(deopt_frame_offset),
267 vars_initialized_(false),
268 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
269 desc_indices_(8),
270 pc_desc_(PcDescriptors::ZoneHandle()) {}
271
272
273 bool Debugger::NeedsIsolateEvents() { 248 bool Debugger::NeedsIsolateEvents() {
274 return ((isolate_ != Dart::vm_isolate()) && 249 return ((isolate_ != Dart::vm_isolate()) &&
275 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && 250 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) &&
276 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); 251 ((event_handler_ != NULL) || Service::isolate_stream.enabled()));
277 } 252 }
278 253
279 254
280 bool Debugger::NeedsDebugEvents() { 255 bool Debugger::NeedsDebugEvents() {
281 ASSERT(isolate_ != Dart::vm_isolate() && 256 ASSERT(isolate_ != Dart::vm_isolate() &&
282 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); 257 !ServiceIsolate::IsServiceIsolateDescendant(isolate_));
(...skipping 28 matching lines...) Expand all
311 if (ignore_breakpoints_ || IsPaused()) { 286 if (ignore_breakpoints_ || IsPaused()) {
312 // We don't let the isolate get interrupted if we are already 287 // We don't let the isolate get interrupted if we are already
313 // paused or ignoring breakpoints. 288 // paused or ignoring breakpoints.
314 return Error::null(); 289 return Error::null();
315 } 290 }
316 ServiceEvent event(isolate_, kind); 291 ServiceEvent event(isolate_, kind);
317 DebuggerStackTrace* trace = CollectStackTrace(); 292 DebuggerStackTrace* trace = CollectStackTrace();
318 if (trace->Length() > 0) { 293 if (trace->Length() > 0) {
319 event.set_top_frame(trace->FrameAt(0)); 294 event.set_top_frame(trace->FrameAt(0));
320 } 295 }
321 ASSERT(stack_trace_ == NULL); 296 CacheStackTraces(trace, CollectAsyncStackTrace(),
322 stack_trace_ = trace; 297 CollectAsyncReturnCallStack());
323 resume_action_ = kContinue; 298 resume_action_ = kContinue;
324 Pause(&event); 299 Pause(&event);
325 HandleSteppingRequest(trace); 300 HandleSteppingRequest(trace);
326 stack_trace_ = NULL; 301 ClearCachedStackTraces();
327 302
328 // If any error occurred while in the debug message loop, return it here. 303 // If any error occurred while in the debug message loop, return it here.
329 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 304 const Error& error = Error::Handle(Thread::Current()->sticky_error());
330 ASSERT(error.IsNull() || error.IsUnwindError()); 305 ASSERT(error.IsNull() || error.IsUnwindError());
331 Thread::Current()->clear_sticky_error(); 306 Thread::Current()->clear_sticky_error();
332 return error.raw(); 307 return error.raw();
333 } 308 }
334 309
335 310
336 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind, 311 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 break; 471 break;
497 case kPauseOnUnhandledExceptions: 472 case kPauseOnUnhandledExceptions:
498 jsobj->AddProperty("_exceptions", "unhandled"); 473 jsobj->AddProperty("_exceptions", "unhandled");
499 break; 474 break;
500 default: 475 default:
501 UNREACHABLE(); 476 UNREACHABLE();
502 } 477 }
503 } 478 }
504 479
505 480
481 ActivationFrame::ActivationFrame(uword pc,
482 uword fp,
483 uword sp,
484 const Code& code,
485 const Array& deopt_frame,
486 intptr_t deopt_frame_offset,
487 ActivationFrame::Kind kind)
488 : pc_(pc),
489 fp_(fp),
490 sp_(sp),
491 ctx_(Context::ZoneHandle()),
492 code_(Code::ZoneHandle(code.raw())),
493 function_(Function::ZoneHandle(code.function())),
494 suspended_frame_(false),
495 token_pos_initialized_(false),
496 token_pos_(TokenPosition::kNoSource),
497 try_index_(-1),
498 line_number_(-1),
499 column_number_(-1),
500 context_level_(-1),
501 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
502 deopt_frame_offset_(deopt_frame_offset),
503 kind_(kind),
504 vars_initialized_(false),
505 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
506 desc_indices_(8),
507 pc_desc_(PcDescriptors::ZoneHandle()) {}
508
509
510 ActivationFrame::ActivationFrame(Kind kind)
511 : pc_(0),
512 fp_(0),
513 sp_(0),
514 ctx_(Context::ZoneHandle()),
515 code_(Code::ZoneHandle()),
516 function_(Function::ZoneHandle()),
517 suspended_frame_(true),
518 token_pos_initialized_(false),
519 token_pos_(TokenPosition::kNoSource),
520 try_index_(-1),
521 line_number_(-1),
522 column_number_(-1),
523 context_level_(-1),
524 deopt_frame_(Array::ZoneHandle()),
525 deopt_frame_offset_(0),
526 kind_(kind),
527 vars_initialized_(false),
528 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
529 desc_indices_(8),
530 pc_desc_(PcDescriptors::ZoneHandle()) {}
531
532
533 ActivationFrame::ActivationFrame(const Closure& async_activation)
534 : pc_(0),
535 fp_(0),
536 sp_(0),
537 ctx_(Context::ZoneHandle()),
538 code_(Code::ZoneHandle()),
539 function_(Function::ZoneHandle()),
540 suspended_frame_(true),
541 token_pos_initialized_(false),
542 token_pos_(TokenPosition::kNoSource),
543 try_index_(-1),
544 line_number_(-1),
545 column_number_(-1),
546 context_level_(-1),
547 deopt_frame_(Array::ZoneHandle()),
548 deopt_frame_offset_(0),
549 kind_(kAsyncLive),
550 vars_initialized_(false),
551 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
552 desc_indices_(8),
553 pc_desc_(PcDescriptors::ZoneHandle()) {
554 // Extract the function and the code from the asynchronous activation.
555 function_ = async_activation.function();
556 code_ = function_.unoptimized_code();
557 ctx_ = async_activation.context();
558 }
559
560
506 RawString* ActivationFrame::QualifiedFunctionName() { 561 RawString* ActivationFrame::QualifiedFunctionName() {
507 return String::New(Debugger::QualifiedFunctionName(function())); 562 return String::New(Debugger::QualifiedFunctionName(function()));
508 } 563 }
509 564
510 565
511 RawString* ActivationFrame::SourceUrl() { 566 RawString* ActivationFrame::SourceUrl() {
512 const Script& script = Script::Handle(SourceScript()); 567 const Script& script = Script::Handle(SourceScript());
513 return script.url(); 568 return script.url();
514 } 569 }
515 570
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 // Calculate the context level at the current token index of the frame. 670 // Calculate the context level at the current token index of the frame.
616 intptr_t ActivationFrame::ContextLevel() { 671 intptr_t ActivationFrame::ContextLevel() {
617 const Context& ctx = GetSavedCurrentContext(); 672 const Context& ctx = GetSavedCurrentContext();
618 if (context_level_ < 0 && !ctx.IsNull()) { 673 if (context_level_ < 0 && !ctx.IsNull()) {
619 ASSERT(!code_.is_optimized()); 674 ASSERT(!code_.is_optimized());
620 context_level_ = 0; 675 context_level_ = 0;
621 // TODO(hausner): What to do if there is no descriptor entry 676 // TODO(hausner): What to do if there is no descriptor entry
622 // for the code position of the frame? For now say we are at context 677 // for the code position of the frame? For now say we are at context
623 // level 0. 678 // level 0.
624 TokenPos(); 679 TokenPos();
625 if (token_pos_ == TokenPosition::kNoSource) { 680 if (token_pos_.IsClassifying() || token_pos_.IsNoSource()) {
626 // No PcDescriptor. 681 // No PcDescriptor.
627 return context_level_; 682 return context_level_;
628 } 683 }
629 ASSERT(!pc_desc_.IsNull()); 684 ASSERT(!pc_desc_.IsNull());
630 TokenPosition innermost_begin_pos = TokenPosition::kMinSource; 685 TokenPosition innermost_begin_pos = TokenPosition::kMinSource;
631 TokenPosition activation_token_pos = TokenPos(); 686 TokenPosition activation_token_pos = TokenPos().FromSynthetic();
632 ASSERT(activation_token_pos.IsReal()); 687 ASSERT(activation_token_pos.IsReal());
633 GetVarDescriptors(); 688 GetVarDescriptors();
634 intptr_t var_desc_len = var_descriptors_.Length(); 689 intptr_t var_desc_len = var_descriptors_.Length();
635 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { 690 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
636 RawLocalVarDescriptors::VarInfo var_info; 691 RawLocalVarDescriptors::VarInfo var_info;
637 var_descriptors_.GetInfo(cur_idx, &var_info); 692 var_descriptors_.GetInfo(cur_idx, &var_info);
638 const int8_t kind = var_info.kind(); 693 const int8_t kind = var_info.kind();
639 if ((kind == RawLocalVarDescriptors::kContextLevel) && 694 if ((kind == RawLocalVarDescriptors::kContextLevel) &&
640 (var_info.begin_pos <= activation_token_pos) && 695 (var_info.begin_pos <= activation_token_pos) &&
641 (activation_token_pos < var_info.end_pos)) { 696 (activation_token_pos < var_info.end_pos)) {
(...skipping 27 matching lines...) Expand all
669 var_info.index()); 724 var_info.index());
670 } 725 }
671 ctx_ ^= GetStackVar(var_info.index()); 726 ctx_ ^= GetStackVar(var_info.index());
672 return ctx_; 727 return ctx_;
673 } 728 }
674 } 729 }
675 return Context::ZoneHandle(Context::null()); 730 return Context::ZoneHandle(Context::null());
676 } 731 }
677 732
678 733
734 RawObject* ActivationFrame::GetAsyncCompleter() {
735 if (!function_.IsAsyncClosure()) {
736 return Object::null();
737 }
738 GetVarDescriptors();
739 intptr_t var_desc_len = var_descriptors_.Length();
740 if (fp() == 0) {
741 // Not actually on the stack. Pull it out of the closure's context.
742 intptr_t var_desc_len = var_descriptors_.Length();
743 for (intptr_t i = 0; i < var_desc_len; i++) {
744 RawLocalVarDescriptors::VarInfo var_info;
745 var_descriptors_.GetInfo(i, &var_info);
746 const int8_t kind = var_info.kind();
747 if (var_descriptors_.GetName(i) == Symbols::AsyncCompleter().raw()) {
748 ASSERT(kind == RawLocalVarDescriptors::kContextVar);
749 ASSERT(!ctx_.IsNull());
750 return ctx_.At(var_info.index());
751 }
752 }
753 } else {
754 // On the stack.
755 for (intptr_t i = 0; i < var_desc_len; i++) {
756 RawLocalVarDescriptors::VarInfo var_info;
757 var_descriptors_.GetInfo(i, &var_info);
758 if (var_descriptors_.GetName(i) == Symbols::AsyncCompleter().raw()) {
759 const int8_t kind = var_info.kind();
760 if (kind == RawLocalVarDescriptors::kStackVar) {
761 return GetStackVar(var_info.index());
762 } else {
763 ASSERT(kind == RawLocalVarDescriptors::kContextVar);
764 return GetContextVar(var_info.scope_id, var_info.index());
765 }
766 }
767 }
768 }
769 return Object::null();
770 }
771
772
773 RawObject* ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) {
774 const Class& sync_completer_cls = Class::Handle(completer.clazz());
775 ASSERT(!sync_completer_cls.IsNull());
776 const Class& completer_cls = Class::Handle(sync_completer_cls.SuperClass());
777 const Field& future_field =
778 Field::Handle(completer_cls.LookupInstanceFieldAllowPrivate(
779 Symbols::CompleterFuture()));
780 ASSERT(!future_field.IsNull());
781 Instance& future = Instance::Handle();
782 future ^= Instance::Cast(completer).GetField(future_field);
783 ASSERT(!future.IsNull());
784 const Class& future_cls = Class::Handle(future.clazz());
785 ASSERT(!future_cls.IsNull());
786 const Field& awaiter_field = Field::Handle(
787 future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
788 ASSERT(!awaiter_field.IsNull());
789 return future.GetField(awaiter_field);
790 }
791
792
793 RawObject* ActivationFrame::GetAsyncStreamControllerStream() {
794 if (!function_.IsAsyncGenClosure()) {
795 return Object::null();
796 }
797 GetVarDescriptors();
798 intptr_t var_desc_len = var_descriptors_.Length();
799 if (fp() == 0) {
800 // Not actually on the stack. Pull it out of the closure's context.
801 intptr_t var_desc_len = var_descriptors_.Length();
802 for (intptr_t i = 0; i < var_desc_len; i++) {
803 RawLocalVarDescriptors::VarInfo var_info;
804 var_descriptors_.GetInfo(i, &var_info);
805 const int8_t kind = var_info.kind();
806 if (var_descriptors_.GetName(i) == Symbols::ControllerStream().raw()) {
807 ASSERT(kind == RawLocalVarDescriptors::kContextVar);
808 ASSERT(!ctx_.IsNull());
809 return ctx_.At(var_info.index());
810 }
811 }
812 } else {
813 // On the stack.
814 for (intptr_t i = 0; i < var_desc_len; i++) {
815 RawLocalVarDescriptors::VarInfo var_info;
816 var_descriptors_.GetInfo(i, &var_info);
817 if (var_descriptors_.GetName(i) == Symbols::ControllerStream().raw()) {
818 const int8_t kind = var_info.kind();
819 if (kind == RawLocalVarDescriptors::kStackVar) {
820 return GetStackVar(var_info.index());
821 } else {
822 ASSERT(kind == RawLocalVarDescriptors::kContextVar);
823 return GetContextVar(var_info.scope_id, var_info.index());
824 }
825 }
826 }
827 }
828 return Object::null();
829 }
830
831
832 RawObject* ActivationFrame::GetAsyncStreamControllerStreamAwaiter(
833 const Object& stream) {
834 const Class& stream_cls = Class::Handle(stream.clazz());
835 ASSERT(!stream_cls.IsNull());
836 const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass());
837 const Field& awaiter_field = Field::Handle(
838 stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
839 ASSERT(!awaiter_field.IsNull());
840 return Instance::Cast(stream).GetField(awaiter_field);
841 }
842
843
844 RawObject* ActivationFrame::GetAsyncAwaiter() {
845 const Object& completer = Object::Handle(GetAsyncCompleter());
846 if (!completer.IsNull()) {
847 return GetAsyncCompleterAwaiter(completer);
848 }
849 const Object& async_stream_controller_stream =
850 Object::Handle(GetAsyncStreamControllerStream());
851 if (!async_stream_controller_stream.IsNull()) {
852 return GetAsyncStreamControllerStreamAwaiter(
853 async_stream_controller_stream);
854 }
855 return Object::null();
856 }
857
858
859 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
860 // Attempt to determine the token position from the async closure.
861 ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure());
862 // This should only be called on frames that aren't active on the stack.
863 ASSERT(fp() == 0);
864 const Array& await_to_token_map =
865 Array::Handle(code_.await_token_positions());
866 if (await_to_token_map.IsNull()) {
867 OS::PrintErr("NO await_token_positions MAPPING\n");
868 // No mapping.
869 return;
870 }
871 GetVarDescriptors();
872 GetPcDescriptors();
873 intptr_t var_desc_len = var_descriptors_.Length();
874 intptr_t await_jump_var = -1;
875 for (intptr_t i = 0; i < var_desc_len; i++) {
876 RawLocalVarDescriptors::VarInfo var_info;
877 var_descriptors_.GetInfo(i, &var_info);
878 const int8_t kind = var_info.kind();
879 if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().raw()) {
880 ASSERT(kind == RawLocalVarDescriptors::kContextVar);
881 ASSERT(!ctx_.IsNull());
882 Object& await_jump_index = Object::Handle(ctx_.At(var_info.index()));
883 ASSERT(await_jump_index.IsSmi());
884 await_jump_var = Smi::Cast(await_jump_index).Value();
885 OS::PrintErr("Extracted await var: %" Pd "\n", await_jump_var);
886 }
887 }
888 if (await_jump_var < 0) {
889 OS::PrintErr("await_jump_var < 0\n");
890 return;
891 }
892 ASSERT(await_jump_var < await_to_token_map.Length());
893 const Object& token_pos =
894 Object::Handle(await_to_token_map.At(await_jump_var));
895 if (token_pos.IsNull()) {
896 OS::PrintErr("token_pos was null\n");
897 return;
898 }
899 ASSERT(token_pos.IsSmi());
900 token_pos_ = TokenPosition(Smi::Cast(token_pos).Value());
901 token_pos_initialized_ = true;
902 OS::PrintErr("async token position: %s\n", token_pos_.ToCString());
903 // Now that we have the token position, we clear a bunch of frame state that
904 // will repopulated based on the token position.
905 // Clear the context.
906 #if 0
907 ctx_ ^= Object::null();
908 context_level_ = -1;
909 // Clear variable descriptors.
910 vars_initialized_ = false;
911 var_descriptors_ ^= Object::null();
912 desc_indices_.Clear();
913 #endif
914 }
915
916
679 RawObject* ActivationFrame::GetAsyncOperation() { 917 RawObject* ActivationFrame::GetAsyncOperation() {
680 GetVarDescriptors(); 918 GetVarDescriptors();
681 intptr_t var_desc_len = var_descriptors_.Length(); 919 intptr_t var_desc_len = var_descriptors_.Length();
682 for (intptr_t i = 0; i < var_desc_len; i++) { 920 for (intptr_t i = 0; i < var_desc_len; i++) {
683 RawLocalVarDescriptors::VarInfo var_info; 921 RawLocalVarDescriptors::VarInfo var_info;
684 var_descriptors_.GetInfo(i, &var_info); 922 var_descriptors_.GetInfo(i, &var_info);
685 if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) { 923 if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) {
686 const int8_t kind = var_info.kind(); 924 const int8_t kind = var_info.kind();
687 if (kind == RawLocalVarDescriptors::kStackVar) { 925 if (kind == RawLocalVarDescriptors::kStackVar) {
688 return GetStackVar(var_info.index()); 926 return GetStackVar(var_info.index());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 } 971 }
734 972
735 973
736 void ActivationFrame::GetDescIndices() { 974 void ActivationFrame::GetDescIndices() {
737 if (vars_initialized_) { 975 if (vars_initialized_) {
738 return; 976 return;
739 } 977 }
740 GetVarDescriptors(); 978 GetVarDescriptors();
741 979
742 TokenPosition activation_token_pos = TokenPos(); 980 TokenPosition activation_token_pos = TokenPos();
743 if (!activation_token_pos.IsDebugPause()) { 981 if (!activation_token_pos.IsDebugPause() || suspended_frame_) {
744 // We don't have a token position for this frame, so can't determine 982 // We don't have a token position for this frame, so can't determine
745 // which variables are visible. 983 // which variables are visible.
746 vars_initialized_ = true; 984 vars_initialized_ = true;
747 return; 985 return;
748 } 986 }
749 987
750 GrowableArray<String*> var_names(8); 988 GrowableArray<String*> var_names(8);
751 intptr_t var_desc_len = var_descriptors_.Length(); 989 intptr_t var_desc_len = var_descriptors_.Length();
752 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { 990 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
753 ASSERT(var_names.length() == desc_indices_.length()); 991 ASSERT(var_names.length() == desc_indices_.length());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 for (int i = 0; i < deopt_frame_.Length(); i++) { 1102 for (int i = 0; i < deopt_frame_.Length(); i++) {
865 obj = deopt_frame_.At(i); 1103 obj = deopt_frame_.At(i);
866 if (obj.raw() == Symbols::OptimizedOut().raw()) { 1104 if (obj.raw() == Symbols::OptimizedOut().raw()) {
867 return false; 1105 return false;
868 } 1106 }
869 } 1107 }
870 return true; 1108 return true;
871 } 1109 }
872 1110
873 1111
1112 bool ActivationFrame::IsCompleteOnAsyncReturn() {
1113 const class Library& async_library = Library::Handle(Library::AsyncLibrary());
1114 ASSERT(!async_library.IsNull());
1115
1116 const Function& complete_on_async_return_function =
1117 Function::Handle(async_library.LookupFunctionAllowPrivate(
1118 Symbols::CompleterCompleteOnAsyncReturn()));
1119 ASSERT(!complete_on_async_return_function.IsNull());
1120 return complete_on_async_return_function.raw() == function_.raw();
1121 }
1122
1123
1124 bool ActivationFrame::IsInAsyncStarStreamController() {
1125 const class Library& async_library = Library::Handle(Library::AsyncLibrary());
1126 ASSERT(!async_library.IsNull());
1127
1128 const Class& async_stream_controller =
1129 Class::Handle(async_library.LookupClassAllowPrivate(
1130 Symbols::_AsyncStarStreamController()));
1131 ASSERT(!async_stream_controller.IsNull());
1132 return function_.Owner() == async_stream_controller.raw();
1133 }
1134
1135
1136 bool ActivationFrame::IsInAsyncMachinery() {
1137 return IsCompleteOnAsyncReturn() || IsInAsyncStarStreamController();
1138 }
1139
1140
874 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot, 1141 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot,
875 intptr_t frame_ctx_level, 1142 intptr_t frame_ctx_level,
876 intptr_t var_ctx_level) { 1143 intptr_t var_ctx_level) {
877 OS::PrintErr( 1144 OS::PrintErr(
878 "-------------------------\n" 1145 "-------------------------\n"
879 "Encountered context mismatch\n" 1146 "Encountered context mismatch\n"
880 "\tctx_slot: %" Pd 1147 "\tctx_slot: %" Pd
881 "\n" 1148 "\n"
882 "\tframe_ctx_level: %" Pd 1149 "\tframe_ctx_level: %" Pd
883 "\n" 1150 "\n"
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 "\tline = %" Pd 1346 "\tline = %" Pd
1080 "\n" 1347 "\n"
1081 "\tcontext = %s\n" 1348 "\tcontext = %s\n"
1082 "\tcontext level = %" Pd " ]\n", 1349 "\tcontext level = %" Pd " ]\n",
1083 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(), 1350 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(),
1084 ContextLevel()); 1351 ContextLevel());
1085 } 1352 }
1086 1353
1087 1354
1088 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { 1355 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) {
1356 if (kind_ == kRegular) {
1357 PrintToJSONObjectRegular(jsobj, full);
1358 } else {
1359 PrintToJSONObjectAsync(jsobj, full);
1360 }
1361 }
1362
1363
1364 void ActivationFrame::PrintToJSONObjectAsync(JSONObject* jsobj, bool full) {
1365 jsobj->AddProperty("type", "AsyncFrame");
1366 jsobj->AddProperty("kind", KindToCString(kind_));
1367 if (kind_ == kAsyncSuspensionMarker) {
1368 jsobj->AddProperty("marker", "AsynchronousSuspension");
1369 } else if (kind_ == kAsyncHistorical) {
1370 PrintToJSONObjectHistoricalFrame(jsobj, full);
1371 } else {
1372 PrintToJSONObjectLiveFrame(jsobj, full);
1373 }
1374 }
1375
1376
1377 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) {
1378 jsobj->AddProperty("type", "Frame");
1379 PrintToJSONObjectLiveFrame(jsobj, full);
1380 }
1381
1382
1383 void ActivationFrame::PrintToJSONObjectHistoricalFrame(JSONObject* jsobj,
1384 bool full) {
1089 const Script& script = Script::Handle(SourceScript()); 1385 const Script& script = Script::Handle(SourceScript());
1090 jsobj->AddProperty("type", "Frame");
1091 TokenPosition pos = TokenPos(); 1386 TokenPosition pos = TokenPos();
1092 if (pos.IsSynthetic()) { 1387 if (pos.IsSynthetic()) {
1093 pos = pos.FromSynthetic(); 1388 pos = pos.FromSynthetic();
1389 }
1390 jsobj->AddLocation(script, pos);
1391 jsobj->AddProperty("function", function(), !full);
1392 jsobj->AddProperty("code", code());
1393 if (full) {
1394 // TODO(cutch): The old "full" script usage no longer fits
1395 // in the world where we pass the script as part of the
1396 // location.
1397 jsobj->AddProperty("script", script, !full);
1398 }
1399 }
1400
1401
1402 void ActivationFrame::PrintToJSONObjectLiveFrame(JSONObject* jsobj, bool full) {
1403 const Script& script = Script::Handle(SourceScript());
1404 TokenPosition pos = TokenPos();
1405 if (pos.IsSynthetic()) {
1406 pos = pos.FromSynthetic();
1094 } 1407 }
1095 jsobj->AddLocation(script, pos); 1408 jsobj->AddLocation(script, pos);
1096 jsobj->AddProperty("function", function(), !full); 1409 jsobj->AddProperty("function", function(), !full);
1097 jsobj->AddProperty("code", code()); 1410 jsobj->AddProperty("code", code());
1098 if (full) { 1411 if (full) {
1099 // TODO(cutch): The old "full" script usage no longer fits 1412 // TODO(cutch): The old "full" script usage no longer fits
1100 // in the world where we pass the script as part of the 1413 // in the world where we pass the script as part of the
1101 // location. 1414 // location.
1102 jsobj->AddProperty("script", script, !full); 1415 jsobj->AddProperty("script", script, !full);
1103 } 1416 }
1104 { 1417 {
1105 JSONArray jsvars(jsobj, "vars"); 1418 JSONArray jsvars(jsobj, "vars");
1106 const int num_vars = NumLocalVariables(); 1419 const int num_vars = NumLocalVariables();
1107 for (intptr_t v = 0; v < num_vars; v++) { 1420 for (intptr_t v = 0; v < num_vars; v++) {
1108 String& var_name = String::Handle(); 1421 String& var_name = String::Handle();
1109 Instance& var_value = Instance::Handle(); 1422 Instance& var_value = Instance::Handle();
1110 TokenPosition declaration_token_pos; 1423 TokenPosition declaration_token_pos;
1111 TokenPosition visible_start_token_pos; 1424 TokenPosition visible_start_token_pos;
1112 TokenPosition visible_end_token_pos; 1425 TokenPosition visible_end_token_pos;
1113 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos, 1426 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
1114 &visible_end_token_pos, &var_value); 1427 &visible_end_token_pos, &var_value);
1115 if (var_name.raw() != Symbols::AsyncOperation().raw()) { 1428 if ((var_name.raw() != Symbols::AsyncOperation().raw()) &&
1429 (var_name.raw() != Symbols::AsyncCompleter().raw())) {
1116 JSONObject jsvar(&jsvars); 1430 JSONObject jsvar(&jsvars);
1117 jsvar.AddProperty("type", "BoundVariable"); 1431 jsvar.AddProperty("type", "BoundVariable");
1118 var_name = String::ScrubName(var_name); 1432 var_name = String::ScrubName(var_name);
1119 jsvar.AddProperty("name", var_name.ToCString()); 1433 jsvar.AddProperty("name", var_name.ToCString());
1120 jsvar.AddProperty("value", var_value, !full); 1434 jsvar.AddProperty("value", var_value, !full);
1121 // Where was the variable declared? 1435 // Where was the variable declared?
1122 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); 1436 jsvar.AddProperty("declarationTokenPos", declaration_token_pos);
1123 // When the variable becomes visible to the scope. 1437 // When the variable becomes visible to the scope.
1124 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); 1438 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos);
1125 // When the variable stops being visible to the scope. 1439 // When the variable stops being visible to the scope.
1126 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos); 1440 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos);
1127 } 1441 }
1128 } 1442 }
1129 } 1443 }
1130 } 1444 }
1131 1445
1446
1132 static bool IsFunctionVisible(const Function& function) { 1447 static bool IsFunctionVisible(const Function& function) {
1133 return FLAG_show_invisible_frames || function.is_visible(); 1448 return FLAG_show_invisible_frames || function.is_visible();
1134 } 1449 }
1135 1450
1136 1451
1137 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { 1452 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
1138 if (IsFunctionVisible(frame->function())) { 1453 if (IsFunctionVisible(frame->function())) {
1139 trace_.Add(frame); 1454 trace_.Add(frame);
1140 } 1455 }
1141 } 1456 }
1142 1457
1143 1458
1459 void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) {
1460 ASSERT((marker >= ActivationFrame::kAsyncSuspensionMarker) &&
1461 (marker <= ActivationFrame::kAsyncSuspensionMarker));
1462 trace_.Add(new ActivationFrame(marker));
1463 }
1464
1465
1466 void DebuggerStackTrace::AddAsyncHistoricalFrame(uword pc, const Code& code) {
1467 trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0,
1468 ActivationFrame::kAsyncHistorical));
1469 }
1470
1471
1144 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | 1472 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
1145 RawPcDescriptors::kUnoptStaticCall | 1473 RawPcDescriptors::kUnoptStaticCall |
1146 RawPcDescriptors::kRuntimeCall; 1474 RawPcDescriptors::kRuntimeCall;
1147 1475
1148 1476
1149 CodeBreakpoint::CodeBreakpoint(const Code& code, 1477 CodeBreakpoint::CodeBreakpoint(const Code& code,
1150 TokenPosition token_pos, 1478 TokenPosition token_pos,
1151 uword pc, 1479 uword pc,
1152 RawPcDescriptors::Kind kind) 1480 RawPcDescriptors::Kind kind)
1153 : code_(code.raw()), 1481 : code_(code.raw()),
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 1550
1223 1551
1224 void CodeBreakpoint::Disable() { 1552 void CodeBreakpoint::Disable() {
1225 if (is_enabled_) { 1553 if (is_enabled_) {
1226 RestoreCode(); 1554 RestoreCode();
1227 } 1555 }
1228 ASSERT(!is_enabled_); 1556 ASSERT(!is_enabled_);
1229 } 1557 }
1230 1558
1231 1559
1560 const char* CodeBreakpoint::ToCString() {
1561 Zone* zone = Thread::Current()->zone();
1562 ASSERT(zone != NULL);
1563 return OS::SCreate(zone, "%s: %" Pd " (token %s)",
1564 String::Handle(SourceUrl()).ToCString(), LineNumber(),
1565 token_pos().ToCString());
1566 }
1567
1568
1232 RemoteObjectCache::RemoteObjectCache(intptr_t initial_size) { 1569 RemoteObjectCache::RemoteObjectCache(intptr_t initial_size) {
1233 objs_ = 1570 objs_ =
1234 &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New(initial_size)); 1571 &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New(initial_size));
1235 } 1572 }
1236 1573
1237 1574
1238 intptr_t RemoteObjectCache::AddObject(const Object& obj) { 1575 intptr_t RemoteObjectCache::AddObject(const Object& obj) {
1239 intptr_t len = objs_->Length(); 1576 intptr_t len = objs_->Length();
1240 for (intptr_t i = 0; i < len; i++) { 1577 for (intptr_t i = 0; i < len; i++) {
1241 if (objs_->At(i) == obj.raw()) { 1578 if (objs_->At(i) == obj.raw()) {
(...skipping 19 matching lines...) Expand all
1261 latent_locations_(NULL), 1598 latent_locations_(NULL),
1262 breakpoint_locations_(NULL), 1599 breakpoint_locations_(NULL),
1263 code_breakpoints_(NULL), 1600 code_breakpoints_(NULL),
1264 resume_action_(kContinue), 1601 resume_action_(kContinue),
1265 resume_frame_index_(-1), 1602 resume_frame_index_(-1),
1266 post_deopt_frame_index_(-1), 1603 post_deopt_frame_index_(-1),
1267 ignore_breakpoints_(false), 1604 ignore_breakpoints_(false),
1268 pause_event_(NULL), 1605 pause_event_(NULL),
1269 obj_cache_(NULL), 1606 obj_cache_(NULL),
1270 stack_trace_(NULL), 1607 stack_trace_(NULL),
1608 async_stack_trace_(NULL),
1609 async_return_call_stack_(NULL),
1271 stepping_fp_(0), 1610 stepping_fp_(0),
1611 top_frame_awaiter_(Object::null()),
1612 async_stepping_fp_(0),
1272 skip_next_step_(false), 1613 skip_next_step_(false),
1273 synthetic_async_breakpoint_(NULL), 1614 synthetic_async_breakpoint_(NULL),
1274 exc_pause_info_(kNoPauseOnExceptions) {} 1615 exc_pause_info_(kNoPauseOnExceptions) {}
1275 1616
1276 1617
1277 Debugger::~Debugger() { 1618 Debugger::~Debugger() {
1278 isolate_id_ = ILLEGAL_ISOLATE_ID; 1619 isolate_id_ = ILLEGAL_ISOLATE_ID;
1279 ASSERT(!IsPaused()); 1620 ASSERT(!IsPaused());
1280 ASSERT(latent_locations_ == NULL); 1621 ASSERT(latent_locations_ == NULL);
1281 ASSERT(breakpoint_locations_ == NULL); 1622 ASSERT(breakpoint_locations_ == NULL);
1282 ASSERT(code_breakpoints_ == NULL); 1623 ASSERT(code_breakpoints_ == NULL);
1283 ASSERT(stack_trace_ == NULL); 1624 ASSERT(stack_trace_ == NULL);
1625 ASSERT(async_stack_trace_ == NULL);
1284 ASSERT(obj_cache_ == NULL); 1626 ASSERT(obj_cache_ == NULL);
1285 ASSERT(synthetic_async_breakpoint_ == NULL); 1627 ASSERT(synthetic_async_breakpoint_ == NULL);
1286 } 1628 }
1287 1629
1288 1630
1289 void Debugger::Shutdown() { 1631 void Debugger::Shutdown() {
1290 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need 1632 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need
1291 // them. Then, assert here that isolate_ is not one of those isolates. 1633 // them. Then, assert here that isolate_ is not one of those isolates.
1292 if ((isolate_ == Dart::vm_isolate()) || 1634 if ((isolate_ == Dart::vm_isolate()) ||
1293 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { 1635 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) {
(...skipping 26 matching lines...) Expand all
1320 const String& fname) { 1662 const String& fname) {
1321 ASSERT(!library.IsNull()); 1663 ASSERT(!library.IsNull());
1322 const Object& object = Object::Handle(library.ResolveName(fname)); 1664 const Object& object = Object::Handle(library.ResolveName(fname));
1323 if (!object.IsNull() && object.IsFunction()) { 1665 if (!object.IsNull() && object.IsFunction()) {
1324 return Function::Cast(object).raw(); 1666 return Function::Cast(object).raw();
1325 } 1667 }
1326 return Function::null(); 1668 return Function::null();
1327 } 1669 }
1328 1670
1329 1671
1672 bool Debugger::SteppedForSyntheticAsyncBreakpoint() const {
1673 return synthetic_async_breakpoint_ != NULL;
1674 }
1675
1676
1677 RawError* Debugger::StepForSyntheticAsyncBreakpoint(Breakpoint* bpt) {
1678 ASSERT(bpt->is_synthetic_async());
1679
1680 TD_Print("ASYNC: Auto step-over\n");
1681 CacheStackTraces(CollectStackTrace(), CollectAsyncStackTrace(),
1682 CollectAsyncReturnCallStack());
1683
1684 ASSERT(synthetic_async_breakpoint_ == NULL);
1685 synthetic_async_breakpoint_ = bpt;
1686 // We are at the entry of an async closure.
1687 // We issue a step over to resume at the point after the await statement.
1688 SetResumeAction(kStepOver);
1689 // When we single step from a breakpoint, our next stepping point will be at
1690 // the exact same pc. Skip it.
1691 HandleSteppingRequest(stack_trace_, true /* skip next step */);
1692 ClearCachedStackTraces();
1693 return Error::null();
1694 }
1695
1696
1697 void Debugger::CleanupSyntheticAsyncBreakpoint() {
1698 if (synthetic_async_breakpoint_ != NULL) {
1699 RemoveBreakpoint(synthetic_async_breakpoint_->id());
1700 synthetic_async_breakpoint_ = NULL;
1701 }
1702 }
1703
1330 bool Debugger::SetupStepOverAsyncSuspension(const char** error) { 1704 bool Debugger::SetupStepOverAsyncSuspension(const char** error) {
1331 ActivationFrame* top_frame = TopDartFrame(); 1705 ActivationFrame* top_frame = TopDartFrame();
1332 if (!IsAtAsyncJump(top_frame)) { 1706 if (!IsAtAsyncJump(top_frame)) {
1333 // Not at an async operation. 1707 // Not at an async operation.
1334 if (error) { 1708 if (error) {
1335 *error = "Isolate must be paused at an async suspension point"; 1709 *error = "Isolate must be paused at an async suspension point";
1336 } 1710 }
1337 return false; 1711 return false;
1338 } 1712 }
1339 Object& closure = Object::Handle(top_frame->GetAsyncOperation()); 1713 Object& closure = Object::Handle(top_frame->GetAsyncOperation());
1340 ASSERT(!closure.IsNull()); 1714 ASSERT(!closure.IsNull());
1341 ASSERT(closure.IsInstance()); 1715 ASSERT(closure.IsInstance());
1342 ASSERT(Instance::Cast(closure).IsClosure()); 1716 ASSERT(Instance::Cast(closure).IsClosure());
1343 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true); 1717 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
1344 if (bpt == NULL) { 1718 if (bpt == NULL) {
1345 // Unable to set the breakpoint. 1719 // Unable to set the breakpoint.
1346 if (error) { 1720 if (error) {
1347 *error = "Unable to set breakpoint at async suspension point"; 1721 *error = "Unable to set breakpoint at async suspension point";
1348 } 1722 }
1349 return false; 1723 return false;
1350 } 1724 }
1351 return true; 1725 return true;
1352 } 1726 }
1353 1727
1354 1728
1729 // Returns the stepping frame pointer when stepping into a caller of
1730 // the async activation generator functions.
1731 uword Debugger::GetAsyncActivationGeneratorSteppingFramePointer() {
1732 StackFrameIterator iterator(false);
1733 // Scan until we hit the top Dart frame.
1734 StackFrame* frame = iterator.NextFrame();
1735 while ((frame != NULL) && !frame->IsDartFrame()) {
1736 frame = iterator.NextFrame();
1737 }
1738 if (frame != NULL) {
1739 frame = iterator.NextFrame();
1740 if ((frame != NULL) && frame->IsDartFrame()) {
1741 // Check to see if we are in a callee of the async function.
1742 const Function& function = Function::Handle(frame->LookupDartFunction());
1743 if (function.IsAsyncFunction() || function.IsAsyncGenerator()) {
1744 // We are, continue until this function has exited.
1745 return frame->fp();
1746 }
1747 }
1748 }
1749 return 0;
1750 }
1751
1752
1355 bool Debugger::SetResumeAction(ResumeAction action, 1753 bool Debugger::SetResumeAction(ResumeAction action,
1356 intptr_t frame_index, 1754 intptr_t frame_index,
1357 const char** error) { 1755 const char** error) {
1358 if (error) { 1756 if (error) {
1359 *error = NULL; 1757 *error = NULL;
1360 } 1758 }
1361 resume_frame_index_ = -1; 1759 resume_frame_index_ = -1;
1362 switch (action) { 1760 switch (action) {
1363 case kStepInto: 1761 case kStepInto:
1364 case kStepOver: 1762 case kStepOver:
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 } 1853 }
1456 } 1854 }
1457 } 1855 }
1458 1856
1459 1857
1460 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, 1858 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
1461 uword pc, 1859 uword pc,
1462 StackFrame* frame, 1860 StackFrame* frame,
1463 const Code& code, 1861 const Code& code,
1464 const Array& deopt_frame, 1862 const Array& deopt_frame,
1465 intptr_t deopt_frame_offset) { 1863 intptr_t deopt_frame_offset,
1864 ActivationFrame::Kind kind) {
1466 ASSERT(code.ContainsInstructionAt(pc)); 1865 ASSERT(code.ContainsInstructionAt(pc));
1467 ActivationFrame* activation = new ActivationFrame( 1866 ActivationFrame* activation =
1468 pc, frame->fp(), frame->sp(), code, deopt_frame, deopt_frame_offset); 1867 new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame,
1868 deopt_frame_offset, kind);
1469 if (FLAG_trace_debugger_stacktrace) { 1869 if (FLAG_trace_debugger_stacktrace) {
1470 const Context& ctx = activation->GetSavedCurrentContext(); 1870 const Context& ctx = activation->GetSavedCurrentContext();
1471 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString()); 1871 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
1472 } 1872 }
1473 if (FLAG_trace_debugger_stacktrace) { 1873 if (FLAG_trace_debugger_stacktrace) {
1474 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); 1874 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
1475 } 1875 }
1476 return activation; 1876 return activation;
1477 } 1877 }
1478 1878
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 } else { 1939 } else {
1540 stack_trace->AddActivation(CollectDartFrame( 1940 stack_trace->AddActivation(CollectDartFrame(
1541 isolate, frame->pc(), frame, code, Object::null_array(), 0)); 1941 isolate, frame->pc(), frame, code, Object::null_array(), 0));
1542 } 1942 }
1543 } 1943 }
1544 } 1944 }
1545 return stack_trace; 1945 return stack_trace;
1546 } 1946 }
1547 1947
1548 1948
1949 DebuggerStackTrace* Debugger::CollectAsyncStackTrace() {
1950 if (!FLAG_sane_async_stacks) {
1951 return CollectStackTrace();
1952 }
1953 Thread* thread = Thread::Current();
1954 Zone* zone = thread->zone();
1955 Isolate* isolate = thread->isolate();
1956 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1957 StackFrameIterator iterator(false);
1958 Code& code = Code::Handle(zone);
1959 Smi& offset = Smi::Handle();
1960 Function& function = Function::Handle(zone);
1961 Code& inlined_code = Code::Handle(zone);
1962 Array& deopt_frame = Array::Handle(zone);
1963
1964 Function& async_function = Function::Handle(zone);
1965 Array& async_code_array = Array::Handle(zone);
1966 Array& async_pc_offset_array = Array::Handle(zone);
1967 const intptr_t async_stack_trace_length =
1968 StackTraceUtils::ExtractAsyncStackTraceInfo(
1969 thread, &async_function, &async_code_array, &async_pc_offset_array);
1970
1971 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
1972 frame = iterator.NextFrame()) {
1973 ASSERT(frame->IsValid());
1974 if (FLAG_trace_debugger_stacktrace) {
1975 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
1976 frame->ToCString());
1977 }
1978 if (frame->IsDartFrame()) {
1979 code = frame->LookupDartCode();
1980 if (code.is_optimized() && !FLAG_precompiled_runtime) {
1981 deopt_frame = DeoptimizeToArray(thread, frame, code);
1982 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
1983 it.Advance()) {
1984 inlined_code = it.code();
1985 if (FLAG_trace_debugger_stacktrace) {
1986 const Function& function =
1987 Function::Handle(zone, inlined_code.function());
1988 ASSERT(!function.IsNull());
1989 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
1990 function.ToFullyQualifiedCString());
1991 }
1992 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1993 ActivationFrame* activation_frame = CollectDartFrame(
1994 isolate, it.pc(), frame, inlined_code, deopt_frame,
1995 deopt_frame_offset, ActivationFrame::kAsyncLive);
1996 stack_trace->AddActivation(activation_frame);
1997 }
1998 } else {
1999 ActivationFrame* activation_frame = CollectDartFrame(
2000 isolate, frame->pc(), frame, code, Object::null_array(), 0,
2001 ActivationFrame::kAsyncLive);
2002 stack_trace->AddActivation(activation_frame);
2003 if (async_stack_trace_length > 0) {
2004 // Stop once we hit async closure.
2005 function = code.function();
2006 if (function.parent_function() == async_function.raw()) {
2007 break;
2008 }
2009 }
2010 }
2011 }
2012 }
2013 ASSERT((async_stack_trace_length == 0) ||
2014 (function.parent_function() == async_function.raw()));
2015 // Append the asynchronous stack trace.
2016 for (intptr_t i = 0; i < async_stack_trace_length; i++) {
2017 if (async_code_array.At(i) == Code::null()) {
2018 break;
2019 }
2020 if (async_code_array.At(i) ==
2021 StubCode::AsynchronousGapMarker_entry()->code()) {
2022 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
2023 } else {
2024 code = Code::RawCast(async_code_array.At(i));
2025 offset = Smi::RawCast(async_pc_offset_array.At(i));
2026 uword pc = code.PayloadStart() + offset.Value();
2027 if (code.is_optimized()) {
2028 for (InlinedFunctionsIterator it(code, pc); !it.Done(); it.Advance()) {
2029 inlined_code = it.code();
2030 stack_trace->AddAsyncHistoricalFrame(pc, inlined_code);
2031 }
2032 } else {
2033 stack_trace->AddAsyncHistoricalFrame(pc, code);
2034 }
2035 }
2036 }
2037 return stack_trace;
2038 }
2039
2040
2041 DebuggerStackTrace* Debugger::CollectAsyncReturnCallStack() {
2042 Thread* thread = Thread::Current();
2043 Zone* zone = thread->zone();
2044 Isolate* isolate = thread->isolate();
2045 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
2046 StackFrameIterator iterator(false);
2047 Code& code = Code::Handle(zone);
2048 Code& inlined_code = Code::Handle(zone);
2049 Array& deopt_frame = Array::Handle(zone);
2050 Function& function = Function::Handle(zone);
2051 Closure& async_activation = Closure::Handle(zone);
2052
2053 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2054 frame = iterator.NextFrame()) {
2055 ASSERT(frame->IsValid());
2056 if (FLAG_trace_debugger_stacktrace) {
2057 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
2058 frame->ToCString());
2059 }
2060 if (frame->IsDartFrame()) {
2061 code = frame->LookupDartCode();
2062 function = code.function();
2063 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2064 ActivationFrame* activation = CollectDartFrame(
2065 isolate, frame->pc(), frame, code, Object::null_array(), 0,
2066 ActivationFrame::kAsyncLive);
2067 ASSERT(activation != NULL);
2068 stack_trace->AddActivation(activation);
2069 // Grab the awaiter.
2070 async_activation ^= activation->GetAsyncAwaiter();
2071 break;
2072 }
2073 if (code.is_optimized() && !FLAG_precompiled_runtime) {
2074 deopt_frame = DeoptimizeToArray(thread, frame, code);
2075 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
2076 it.Advance()) {
2077 inlined_code = it.code();
2078 if (FLAG_trace_debugger_stacktrace) {
2079 function = inlined_code.function();
2080 ASSERT(!function.IsNull());
2081 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
2082 function.ToFullyQualifiedCString());
2083 }
2084 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
2085 stack_trace->AddActivation(CollectDartFrame(
2086 isolate, it.pc(), frame, inlined_code, deopt_frame,
2087 deopt_frame_offset, ActivationFrame::kAsyncLive));
2088 }
2089 } else {
2090 stack_trace->AddActivation(CollectDartFrame(
2091 isolate, frame->pc(), frame, code, Object::null_array(), 0,
2092 ActivationFrame::kAsyncLive));
2093 }
2094 }
2095 }
2096
2097 // Append the asynchronous return call stack.
2098 while (!async_activation.IsNull()) {
2099 ActivationFrame* activation = new ActivationFrame(async_activation);
2100 async_activation ^= activation->GetAsyncAwaiter();
2101 activation->ExtractTokenPositionFromAsyncClosure();
2102 stack_trace->AddActivation(activation);
2103 }
2104
2105 return stack_trace;
2106 }
2107
2108
1549 ActivationFrame* Debugger::TopDartFrame() const { 2109 ActivationFrame* Debugger::TopDartFrame() const {
1550 StackFrameIterator iterator(false); 2110 StackFrameIterator iterator(false);
1551 StackFrame* frame = iterator.NextFrame(); 2111 StackFrame* frame = iterator.NextFrame();
1552 while ((frame != NULL) && !frame->IsDartFrame()) { 2112 while ((frame != NULL) && !frame->IsDartFrame()) {
1553 frame = iterator.NextFrame(); 2113 frame = iterator.NextFrame();
1554 } 2114 }
1555 Code& code = Code::Handle(frame->LookupDartCode()); 2115 Code& code = Code::Handle(frame->LookupDartCode());
1556 ActivationFrame* activation = new ActivationFrame( 2116 ActivationFrame* activation = new ActivationFrame(
1557 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); 2117 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
1558 return activation; 2118 return activation;
1559 } 2119 }
1560 2120
1561 2121
1562 DebuggerStackTrace* Debugger::StackTrace() { 2122 DebuggerStackTrace* Debugger::StackTrace() {
1563 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace(); 2123 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace();
1564 } 2124 }
1565 2125
2126
1566 DebuggerStackTrace* Debugger::CurrentStackTrace() { 2127 DebuggerStackTrace* Debugger::CurrentStackTrace() {
1567 return CollectStackTrace(); 2128 return CollectStackTrace();
1568 } 2129 }
1569 2130
2131
2132 DebuggerStackTrace* Debugger::AsyncStackTrace() {
2133 return (async_stack_trace_ != NULL) ? async_stack_trace_
2134 : CollectAsyncStackTrace();
2135 }
2136
2137
2138 DebuggerStackTrace* Debugger::CurrentAsyncStackTrace() {
2139 return CollectAsyncStackTrace();
2140 }
2141
2142
2143 DebuggerStackTrace* Debugger::AsyncReturnStack() {
2144 return (async_return_call_stack_ != NULL) ? async_return_call_stack_
2145 : CollectAsyncReturnCallStack();
2146 }
2147
2148
2149 DebuggerStackTrace* Debugger::CurrentAsyncReturnStack() {
2150 return CollectAsyncReturnCallStack();
2151 }
2152
2153
1570 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { 2154 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) {
1571 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); 2155 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1572 Function& function = Function::Handle(); 2156 Function& function = Function::Handle();
1573 Code& code = Code::Handle(); 2157 Code& code = Code::Handle();
1574 2158
1575 const uword fp = 0; 2159 const uword fp = 0;
1576 const uword sp = 0; 2160 const uword sp = 0;
1577 const Array& deopt_frame = Array::Handle(); 2161 const Array& deopt_frame = Array::Handle();
1578 const intptr_t deopt_frame_offset = -1; 2162 const intptr_t deopt_frame_offset = -1;
1579 2163
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 void Debugger::PauseException(const Instance& exc) { 2236 void Debugger::PauseException(const Instance& exc) {
1653 // We ignore this exception event when the VM is executing code invoked 2237 // We ignore this exception event when the VM is executing code invoked
1654 // by the debugger to evaluate variables values, when we see a nested 2238 // by the debugger to evaluate variables values, when we see a nested
1655 // breakpoint or exception event, or if the debugger is not 2239 // breakpoint or exception event, or if the debugger is not
1656 // interested in exception events. 2240 // interested in exception events.
1657 if (ignore_breakpoints_ || IsPaused() || 2241 if (ignore_breakpoints_ || IsPaused() ||
1658 (exc_pause_info_ == kNoPauseOnExceptions)) { 2242 (exc_pause_info_ == kNoPauseOnExceptions)) {
1659 return; 2243 return;
1660 } 2244 }
1661 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2245 DebuggerStackTrace* stack_trace = CollectStackTrace();
2246 DebuggerStackTrace* async_stack_trace = CollectAsyncStackTrace();
2247 DebuggerStackTrace* async_return_call_stack = CollectAsyncReturnCallStack();
1662 if (!ShouldPauseOnException(stack_trace, exc)) { 2248 if (!ShouldPauseOnException(stack_trace, exc)) {
1663 return; 2249 return;
1664 } 2250 }
1665 ServiceEvent event(isolate_, ServiceEvent::kPauseException); 2251 ServiceEvent event(isolate_, ServiceEvent::kPauseException);
1666 event.set_exception(&exc); 2252 event.set_exception(&exc);
1667 if (stack_trace->Length() > 0) { 2253 if (stack_trace->Length() > 0) {
1668 event.set_top_frame(stack_trace->FrameAt(0)); 2254 event.set_top_frame(stack_trace->FrameAt(0));
1669 } 2255 }
1670 ASSERT(stack_trace_ == NULL); 2256 CacheStackTraces(stack_trace, async_stack_trace, async_return_call_stack);
1671 stack_trace_ = stack_trace;
1672 Pause(&event); 2257 Pause(&event);
1673 HandleSteppingRequest(stack_trace_); // we may get a rewind request 2258 HandleSteppingRequest(stack_trace_); // we may get a rewind request
1674 stack_trace_ = NULL; 2259 ClearCachedStackTraces();
1675 } 2260 }
1676 2261
1677 2262
1678 static TokenPosition LastTokenOnLine(Zone* zone, 2263 static TokenPosition LastTokenOnLine(Zone* zone,
1679 const TokenStream& tokens, 2264 const TokenStream& tokens,
1680 TokenPosition pos) { 2265 TokenPosition pos) {
1681 TokenStream::Iterator iter(zone, tokens, pos, 2266 TokenStream::Iterator iter(zone, tokens, pos,
1682 TokenStream::Iterator::kAllTokens); 2267 TokenStream::Iterator::kAllTokens);
1683 ASSERT(iter.IsValid()); 2268 ASSERT(iter.IsValid());
1684 TokenPosition last_pos = pos; 2269 TokenPosition last_pos = pos;
(...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after
2537 bpt = latent_locations_; 3122 bpt = latent_locations_;
2538 while (bpt != NULL) { 3123 while (bpt != NULL) {
2539 bpt->VisitObjectPointers(visitor); 3124 bpt->VisitObjectPointers(visitor);
2540 bpt = bpt->next(); 3125 bpt = bpt->next();
2541 } 3126 }
2542 CodeBreakpoint* cbpt = code_breakpoints_; 3127 CodeBreakpoint* cbpt = code_breakpoints_;
2543 while (cbpt != NULL) { 3128 while (cbpt != NULL) {
2544 cbpt->VisitObjectPointers(visitor); 3129 cbpt->VisitObjectPointers(visitor);
2545 cbpt = cbpt->next(); 3130 cbpt = cbpt->next();
2546 } 3131 }
3132 visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_frame_awaiter_));
2547 } 3133 }
2548 3134
2549 3135
2550 // static 3136 // static
2551 void Debugger::SetEventHandler(EventHandler* handler) { 3137 void Debugger::SetEventHandler(EventHandler* handler) {
2552 event_handler_ = handler; 3138 event_handler_ = handler;
2553 } 3139 }
2554 3140
2555 3141
2556 void Debugger::Pause(ServiceEvent* event) { 3142 void Debugger::Pause(ServiceEvent* event) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2596 resume_event.set_top_frame(event->top_frame()); 3182 resume_event.set_top_frame(event->top_frame());
2597 Service::HandleEvent(&resume_event); 3183 Service::HandleEvent(&resume_event);
2598 } 3184 }
2599 } 3185 }
2600 3186
2601 pause_event_ = NULL; 3187 pause_event_ = NULL;
2602 obj_cache_ = NULL; // Zone allocated 3188 obj_cache_ = NULL; // Zone allocated
2603 } 3189 }
2604 3190
2605 3191
3192 void Debugger::AsyncContinue() {
3193 SetResumeAction(kContinue);
3194 stepping_fp_ = 0;
3195 async_stepping_fp_ = 0;
3196 isolate_->set_single_step(false);
3197 }
3198
3199
3200 void Debugger::AsyncStepInto(const Closure& async_op) {
3201 SetBreakpointAtActivation(async_op, true);
3202 AsyncContinue();
3203 }
3204
3205
2606 void Debugger::EnterSingleStepMode() { 3206 void Debugger::EnterSingleStepMode() {
2607 stepping_fp_ = 0; 3207 stepping_fp_ = 0;
2608 DeoptimizeWorld(); 3208 DeoptimizeWorld();
2609 isolate_->set_single_step(true); 3209 isolate_->set_single_step(true);
2610 } 3210 }
2611 3211
2612 3212
2613 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, 3213 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace,
2614 bool skip_next_step) { 3214 bool skip_next_step) {
3215 top_frame_awaiter_ = stack_trace->FrameAt(0)->GetAsyncAwaiter();
2615 stepping_fp_ = 0; 3216 stepping_fp_ = 0;
3217 async_stepping_fp_ = 0;
2616 if (resume_action_ == kStepInto) { 3218 if (resume_action_ == kStepInto) {
2617 // When single stepping, we need to deoptimize because we might be 3219 // When single stepping, we need to deoptimize because we might be
2618 // stepping into optimized code. This happens in particular if 3220 // stepping into optimized code. This happens in particular if
2619 // the isolate has been interrupted, but can happen in other cases 3221 // the isolate has been interrupted, but can happen in other cases
2620 // as well. We need to deoptimize the world in case we are about 3222 // as well. We need to deoptimize the world in case we are about
2621 // to call an optimized function. 3223 // to call an optimized function.
2622 DeoptimizeWorld(); 3224 DeoptimizeWorld();
2623 isolate_->set_single_step(true); 3225 isolate_->set_single_step(true);
2624 skip_next_step_ = skip_next_step; 3226 skip_next_step_ = skip_next_step;
3227 if (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
3228 stack_trace->FrameAt(0)->function().IsAsyncGenClosure()) {
3229 async_stepping_fp_ = stack_trace->FrameAt(0)->fp();
3230 }
2625 if (FLAG_verbose_debug) { 3231 if (FLAG_verbose_debug) {
2626 OS::Print("HandleSteppingRequest- kStepInto\n"); 3232 OS::Print("HandleSteppingRequest- kStepInto\n");
2627 } 3233 }
2628 } else if (resume_action_ == kStepOver) { 3234 } else if (resume_action_ == kStepOver) {
2629 DeoptimizeWorld(); 3235 DeoptimizeWorld();
2630 isolate_->set_single_step(true); 3236 isolate_->set_single_step(true);
2631 skip_next_step_ = skip_next_step; 3237 skip_next_step_ = skip_next_step;
2632 ASSERT(stack_trace->Length() > 0); 3238 ASSERT(stack_trace->Length() > 0);
2633 stepping_fp_ = stack_trace->FrameAt(0)->fp(); 3239 stepping_fp_ = stack_trace->FrameAt(0)->fp();
3240 if (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
3241 stack_trace->FrameAt(0)->function().IsAsyncGenClosure()) {
3242 async_stepping_fp_ = stack_trace->FrameAt(0)->fp();
3243 }
2634 if (FLAG_verbose_debug) { 3244 if (FLAG_verbose_debug) {
2635 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_); 3245 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
2636 } 3246 }
2637 } else if (resume_action_ == kStepOut) { 3247 } else if (resume_action_ == kStepOut) {
3248 // Handle the async case first.
3249 if (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
3250 stack_trace->FrameAt(0)->function().IsAsyncGenClosure()) {
3251 if (top_frame_awaiter_ != Object::null()) {
3252 const Object& async_op = Object::Handle(top_frame_awaiter_);
3253 ASSERT(async_op.IsClosure());
3254 AsyncStepInto(Closure::Cast(async_op));
3255 return;
3256 } else {
3257 // No awaiter. Just continue execution.
3258 AsyncContinue();
3259 return;
3260 }
3261 }
3262 // Now the synchronous case.
2638 DeoptimizeWorld(); 3263 DeoptimizeWorld();
2639 isolate_->set_single_step(true); 3264 isolate_->set_single_step(true);
2640 // Find topmost caller that is debuggable. 3265 // Find topmost caller that is debuggable.
2641 for (intptr_t i = 1; i < stack_trace->Length(); i++) { 3266 for (intptr_t i = 1; i < stack_trace->Length(); i++) {
2642 ActivationFrame* frame = stack_trace->FrameAt(i); 3267 ActivationFrame* frame = stack_trace->FrameAt(i);
2643 if (frame->IsDebuggable()) { 3268 if (frame->IsDebuggable()) {
2644 stepping_fp_ = frame->fp(); 3269 stepping_fp_ = frame->fp();
2645 break; 3270 break;
2646 } 3271 }
2647 } 3272 }
(...skipping 25 matching lines...) Expand all
2673 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { 3298 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) {
2674 ActivationFrame* frame = stack->FrameAt(i); 3299 ActivationFrame* frame = stack->FrameAt(i);
2675 if (frame->IsRewindable()) { 3300 if (frame->IsRewindable()) {
2676 return i; 3301 return i;
2677 } 3302 }
2678 } 3303 }
2679 return -1; 3304 return -1;
2680 } 3305 }
2681 3306
2682 3307
3308 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
3309 DebuggerStackTrace* async_stack_trace,
3310 DebuggerStackTrace* async_return_call_stack) {
3311 ASSERT(stack_trace_ == NULL);
3312 stack_trace_ = stack_trace;
3313 ASSERT(async_stack_trace_ == NULL);
3314 async_stack_trace_ = async_stack_trace;
3315 ASSERT(async_return_call_stack_ == NULL);
3316 async_return_call_stack_ = async_return_call_stack;
3317 }
3318
3319
3320 void Debugger::ClearCachedStackTraces() {
3321 stack_trace_ = NULL;
3322 async_stack_trace_ = NULL;
3323 async_return_call_stack_ = NULL;
3324 }
3325
3326
2683 // Can the top frame be rewound? 3327 // Can the top frame be rewound?
2684 bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const { 3328 bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const {
2685 // check rewind pc is found 3329 // check rewind pc is found
2686 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); 3330 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
2687 intptr_t num_frames = stack->Length(); 3331 intptr_t num_frames = stack->Length();
2688 if (frame_index < 1 || frame_index >= num_frames) { 3332 if (frame_index < 1 || frame_index >= num_frames) {
2689 if (error) { 3333 if (error) {
2690 *error = Thread::Current()->zone()->PrintToString( 3334 *error = Thread::Current()->zone()->PrintToString(
2691 "Frame must be in bounds [1..%" Pd 3335 "Frame must be in bounds [1..%" Pd
2692 "]: " 3336 "]: "
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 } 3433 }
2790 } 3434 }
2791 } 3435 }
2792 UNIMPLEMENTED(); 3436 UNIMPLEMENTED();
2793 } 3437 }
2794 3438
2795 3439
2796 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) { 3440 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) {
2797 // We will be jumping out of the debugger rather than exiting this 3441 // We will be jumping out of the debugger rather than exiting this
2798 // function, so prepare the debugger state. 3442 // function, so prepare the debugger state.
2799 stack_trace_ = NULL; 3443 ClearCachedStackTraces();
2800 resume_action_ = kContinue; 3444 resume_action_ = kContinue;
2801 resume_frame_index_ = -1; 3445 resume_frame_index_ = -1;
2802 EnterSingleStepMode(); 3446 EnterSingleStepMode();
2803 3447
2804 uword rewind_pc = LookupRewindPc(code, frame->pc()); 3448 uword rewind_pc = LookupRewindPc(code, frame->pc());
2805 if (FLAG_trace_rewind && rewind_pc == 0) { 3449 if (FLAG_trace_rewind && rewind_pc == 0) {
2806 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc()); 3450 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc());
2807 } 3451 }
2808 ASSERT(rewind_pc != 0); 3452 ASSERT(rewind_pc != 0);
2809 if (FLAG_trace_rewind) { 3453 if (FLAG_trace_rewind) {
(...skipping 11 matching lines...) Expand all
2821 } 3465 }
2822 3466
2823 3467
2824 void Debugger::RewindToOptimizedFrame(StackFrame* frame, 3468 void Debugger::RewindToOptimizedFrame(StackFrame* frame,
2825 const Code& optimized_code, 3469 const Code& optimized_code,
2826 intptr_t sub_index) { 3470 intptr_t sub_index) {
2827 post_deopt_frame_index_ = sub_index; 3471 post_deopt_frame_index_ = sub_index;
2828 3472
2829 // We will be jumping out of the debugger rather than exiting this 3473 // We will be jumping out of the debugger rather than exiting this
2830 // function, so prepare the debugger state. 3474 // function, so prepare the debugger state.
2831 stack_trace_ = NULL; 3475 ClearCachedStackTraces();
2832 resume_action_ = kContinue; 3476 resume_action_ = kContinue;
2833 resume_frame_index_ = -1; 3477 resume_frame_index_ = -1;
2834 EnterSingleStepMode(); 3478 EnterSingleStepMode();
2835 3479
2836 if (FLAG_trace_rewind) { 3480 if (FLAG_trace_rewind) {
2837 OS::PrintErr( 3481 OS::PrintErr(
2838 "===============================\n" 3482 "===============================\n"
2839 "Deoptimizing frame for rewind:\n" 3483 "Deoptimizing frame for rewind:\n"
2840 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px 3484 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
2841 ")\n" 3485 ")\n"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2897 } 3541 }
2898 const Class& cls = Class::Handle(func.Owner()); 3542 const Class& cls = Class::Handle(func.Owner());
2899 const Library& lib = Library::Handle(cls.library()); 3543 const Library& lib = Library::Handle(cls.library());
2900 return lib.IsDebuggable(); 3544 return lib.IsDebuggable();
2901 } 3545 }
2902 3546
2903 3547
2904 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) { 3548 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
2905 resume_action_ = kContinue; 3549 resume_action_ = kContinue;
2906 stepping_fp_ = 0; 3550 stepping_fp_ = 0;
3551 async_stepping_fp_ = 0;
2907 isolate_->set_single_step(false); 3552 isolate_->set_single_step(false);
2908 ASSERT(!IsPaused()); 3553 ASSERT(!IsPaused());
2909 ASSERT(obj_cache_ == NULL); 3554 ASSERT(obj_cache_ == NULL);
2910 if ((bpt != NULL) && bpt->IsSingleShot()) { 3555 if ((bpt != NULL) && bpt->IsSingleShot()) {
2911 RemoveBreakpoint(bpt->id()); 3556 RemoveBreakpoint(bpt->id());
2912 bpt = NULL; 3557 bpt = NULL;
2913 } 3558 }
2914 3559
2915 ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint); 3560 ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint);
2916 event.set_top_frame(top_frame); 3561 event.set_top_frame(top_frame);
(...skipping 29 matching lines...) Expand all
2946 ASSERT(isolate_->single_step()); 3591 ASSERT(isolate_->single_step());
2947 // Don't pause recursively. 3592 // Don't pause recursively.
2948 if (IsPaused()) { 3593 if (IsPaused()) {
2949 return Error::null(); 3594 return Error::null();
2950 } 3595 }
2951 if (skip_next_step_) { 3596 if (skip_next_step_) {
2952 skip_next_step_ = false; 3597 skip_next_step_ = false;
2953 return Error::null(); 3598 return Error::null();
2954 } 3599 }
2955 3600
3601 ActivationFrame* frame = TopDartFrame();
3602 ASSERT(frame != NULL);
3603
3604 OS::PrintErr("top frame: %s\n", frame->ToCString());
3605 OS::PrintErr("async_stepping_fp: %" Px "\n", async_stepping_fp_);
3606 OS::PrintErr("IsInAsyncMachinery: %d\n", frame->IsInAsyncMachinery());
3607
3608 // Check if the user has single stepped out of an asynchronous function
3609 // with an awaiter. If so, the next point of execution will be in the awaiter.
3610 if (async_stepping_fp_ != 0) {
3611 // We have either single stepped into async machinery or we have
3612 // stepped out of the function.
3613 const bool exited_async_function =
3614 (IsCalleeFrameOf(async_stepping_fp_, frame->fp()) &&
3615 frame->IsInAsyncMachinery()) ||
3616 IsCalleeFrameOf(frame->fp(), async_stepping_fp_);
3617 OS::PrintErr("exited_async_function = %d\n", exited_async_function);
3618 if (exited_async_function) {
3619 // We returned from the asynchronous function.
3620 if (top_frame_awaiter_ == Object::null()) {
3621 AsyncContinue();
3622 return Error::null();
3623 } else {
3624 ASSERT(top_frame_awaiter_ != Object::null());
3625 const Object& async_op = Object::Handle(top_frame_awaiter_);
3626 ASSERT(async_op.IsClosure());
3627 top_frame_awaiter_ = Object::null();
3628 AsyncStepInto(Closure::Cast(async_op));
3629 return Error::null();
3630 }
3631 }
3632 }
3633
2956 // Check whether we are in a Dart function that the user is 3634 // Check whether we are in a Dart function that the user is
2957 // interested in. If we saved the frame pointer of a stack frame 3635 // interested in. If we saved the frame pointer of a stack frame
2958 // the user is interested in, we ignore the single step if we are 3636 // the user is interested in, we ignore the single step if we are
2959 // in a callee of that frame. Note that we assume that the stack 3637 // in a callee of that frame. Note that we assume that the stack
2960 // grows towards lower addresses. 3638 // grows towards lower addresses.
2961 ActivationFrame* frame = TopDartFrame();
2962 ASSERT(frame != NULL);
2963
2964 if (stepping_fp_ != 0) { 3639 if (stepping_fp_ != 0) {
2965 // There is an "interesting frame" set. Only pause at appropriate 3640 // There is an "interesting frame" set. Only pause at appropriate
2966 // locations in this frame. 3641 // locations in this frame.
2967 if (IsCalleeFrameOf(stepping_fp_, frame->fp())) { 3642 if (IsCalleeFrameOf(stepping_fp_, frame->fp())) {
2968 // We are in a callee of the frame we're interested in. 3643 // We are in a callee of the frame we're interested in.
2969 // Ignore this stepping break. 3644 // Ignore this stepping break.
2970 return Error::null(); 3645 return Error::null();
2971 } else if (IsCalleeFrameOf(frame->fp(), stepping_fp_)) { 3646 } else if (IsCalleeFrameOf(frame->fp(), stepping_fp_)) {
2972 // We returned from the "interesting frame", there can be no more 3647 // We returned from the "interesting frame", there can be no more
2973 // stepping breaks for it. Pause at the next appropriate location 3648 // stepping breaks for it. Pause at the next appropriate location
2974 // and let the user set the "interesting" frame again. 3649 // and let the user set the "interesting" frame again.
2975 stepping_fp_ = 0; 3650 stepping_fp_ = 0;
2976 } 3651 }
3652 } else if (FLAG_sane_async_stacks && !SteppedForSyntheticAsyncBreakpoint()) {
3653 const uword possible_stepping_fp =
3654 GetAsyncActivationGeneratorSteppingFramePointer();
3655 if (possible_stepping_fp > 0) {
3656 // We are currently executing in a callee of an async activation generator
3657 // function. We do not want the user to see any of this code, so we will
3658 // continue to step until we have exited the async activation generator.
3659 stepping_fp_ = possible_stepping_fp;
3660 return Error::null();
3661 }
2977 } 3662 }
2978 3663
2979 if (!frame->IsDebuggable()) { 3664 if (!frame->IsDebuggable()) {
2980 return Error::null(); 3665 return Error::null();
2981 } 3666 }
2982 if (!frame->TokenPos().IsDebugPause()) { 3667 if (!frame->TokenPos().IsDebugPause()) {
2983 return Error::null(); 3668 return Error::null();
2984 } 3669 }
2985 3670
2986 // If there is an active breakpoint at this pc, then we should have 3671 // If there is an active breakpoint at this pc, then we should have
2987 // already bailed out of this function in the skip_next_step_ test 3672 // already bailed out of this function in the skip_next_step_ test
2988 // above. 3673 // above.
2989 ASSERT(!HasActiveBreakpoint(frame->pc())); 3674 ASSERT(!HasActiveBreakpoint(frame->pc()));
2990 3675
2991 if (FLAG_verbose_debug) { 3676 if (FLAG_verbose_debug) {
2992 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", 3677 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n",
2993 String::Handle(frame->SourceUrl()).ToCString(), 3678 String::Handle(frame->SourceUrl()).ToCString(),
2994 frame->LineNumber(), 3679 frame->LineNumber(),
2995 String::Handle(frame->QualifiedFunctionName()).ToCString(), 3680 String::Handle(frame->QualifiedFunctionName()).ToCString(),
2996 frame->TokenPos().ToCString()); 3681 frame->TokenPos().ToCString());
2997 } 3682 }
2998 3683
2999 ASSERT(stack_trace_ == NULL); 3684 CacheStackTraces(CollectStackTrace(), CollectAsyncStackTrace(),
3000 stack_trace_ = CollectStackTrace(); 3685 CollectAsyncReturnCallStack());
3001 // If this step callback is part of stepping over an await statement, 3686 if (SteppedForSyntheticAsyncBreakpoint()) {
3002 // we saved the synthetic async breakpoint in PauseBreakpoint. We report 3687 CleanupSyntheticAsyncBreakpoint();
3003 // that we are paused at that breakpoint and then delete it after continuing.
3004 SignalPausedEvent(frame, synthetic_async_breakpoint_);
3005 if (synthetic_async_breakpoint_ != NULL) {
3006 RemoveBreakpoint(synthetic_async_breakpoint_->id());
3007 synthetic_async_breakpoint_ = NULL;
3008 } 3688 }
3689 SignalPausedEvent(frame, NULL);
3009 HandleSteppingRequest(stack_trace_); 3690 HandleSteppingRequest(stack_trace_);
3010 stack_trace_ = NULL; 3691 ClearCachedStackTraces();
3011 3692
3012 // If any error occurred while in the debug message loop, return it here. 3693 // If any error occurred while in the debug message loop, return it here.
3013 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 3694 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3014 Thread::Current()->clear_sticky_error(); 3695 Thread::Current()->clear_sticky_error();
3015 return error.raw(); 3696 return error.raw();
3016 } 3697 }
3017 3698
3018 3699
3019 RawError* Debugger::PauseBreakpoint() { 3700 RawError* Debugger::PauseBreakpoint() {
3020 // We ignore this breakpoint when the VM is executing code invoked 3701 // We ignore this breakpoint when the VM is executing code invoked
3021 // by the debugger to evaluate variables values, or when we see a nested 3702 // by the debugger to evaluate variables values, or when we see a nested
3022 // breakpoint or exception event. 3703 // breakpoint or exception event.
3023 if (ignore_breakpoints_ || IsPaused()) { 3704 if (ignore_breakpoints_ || IsPaused()) {
3024 return Error::null(); 3705 return Error::null();
3025 } 3706 }
3026 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3707 DebuggerStackTrace* stack_trace = CollectStackTrace();
3708 DebuggerStackTrace* async_stack_trace = CollectAsyncStackTrace();
3709 DebuggerStackTrace* async_return_call_stack = CollectAsyncReturnCallStack();
3027 ASSERT(stack_trace->Length() > 0); 3710 ASSERT(stack_trace->Length() > 0);
3028 ActivationFrame* top_frame = stack_trace->FrameAt(0); 3711 ActivationFrame* top_frame = stack_trace->FrameAt(0);
3029 ASSERT(top_frame != NULL); 3712 ASSERT(top_frame != NULL);
3030 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); 3713 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
3031 ASSERT(cbpt != NULL); 3714 ASSERT(cbpt != NULL);
3032 3715
3033 BreakpointLocation* bpt_location = cbpt->bpt_location_; 3716 Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame);
3034 Breakpoint* bpt_hit = NULL;
3035
3036 // There may be more than one applicable breakpoint at this location, but we
3037 // will report only one as reached. If there is a single-shot breakpoint, we
3038 // favor it; then a closure-specific breakpoint ; then an general breakpoint.
3039 if (bpt_location != NULL) {
3040 Breakpoint* bpt = bpt_location->breakpoints();
3041 while (bpt != NULL) {
3042 if (bpt->IsSingleShot()) {
3043 bpt_hit = bpt;
3044 break;
3045 }
3046 bpt = bpt->next();
3047 }
3048
3049 if (bpt_hit == NULL) {
3050 bpt = bpt_location->breakpoints();
3051 while (bpt != NULL) {
3052 if (bpt->IsPerClosure()) {
3053 Object& closure = Object::Handle(top_frame->GetClosure());
3054 ASSERT(closure.IsInstance());
3055 ASSERT(Instance::Cast(closure).IsClosure());
3056 if (closure.raw() == bpt->closure()) {
3057 bpt_hit = bpt;
3058 break;
3059 }
3060 }
3061 bpt = bpt->next();
3062 }
3063 }
3064
3065 if (bpt_hit == NULL) {
3066 bpt = bpt_location->breakpoints();
3067 while (bpt != NULL) {
3068 if (bpt->IsRepeated()) {
3069 bpt_hit = bpt;
3070 break;
3071 }
3072 bpt = bpt->next();
3073 }
3074 }
3075 }
3076
3077 if (bpt_hit == NULL) { 3717 if (bpt_hit == NULL) {
3078 return Error::null(); 3718 return Error::null();
3079 } 3719 }
3080 3720
3081 if (bpt_hit->is_synthetic_async()) { 3721 if (bpt_hit->is_synthetic_async()) {
3082 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3722 TD_Print("ASYNC: hit synthetic breakpoint: %s (address: %#" Px ")\n",
3083 ASSERT(stack_trace->Length() > 0); 3723 cbpt->ToCString(), top_frame->pc());
3084 ASSERT(stack_trace_ == NULL); 3724 return StepForSyntheticAsyncBreakpoint(bpt_hit);
3085 stack_trace_ = stack_trace;
3086
3087 // Hit a synthetic async breakpoint.
3088 if (FLAG_verbose_debug) {
3089 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd
3090 " "
3091 "(token %s) (address %#" Px ")\n",
3092 String::Handle(cbpt->SourceUrl()).ToCString(),
3093 cbpt->LineNumber(), cbpt->token_pos().ToCString(),
3094 top_frame->pc());
3095 }
3096
3097 ASSERT(synthetic_async_breakpoint_ == NULL);
3098 synthetic_async_breakpoint_ = bpt_hit;
3099 bpt_hit = NULL;
3100
3101 // We are at the entry of an async function.
3102 // We issue a step over to resume at the point after the await statement.
3103 SetResumeAction(kStepOver);
3104 // When we single step from a user breakpoint, our next stepping
3105 // point will be at the exact same pc. Skip it.
3106 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3107 stack_trace_ = NULL;
3108 return Error::null();
3109 } 3725 }
3110 3726
3111 if (FLAG_verbose_debug) { 3727 if (FLAG_verbose_debug) {
3112 OS::Print(">>> hit %s breakpoint at %s:%" Pd 3728 OS::Print(">>> hit %s breakpoint at %s:%" Pd
3113 " " 3729 " "
3114 "(token %s) (address %#" Px ")\n", 3730 "(token %s) (address %#" Px ")\n",
3115 cbpt->IsInternal() ? "internal" : "user", 3731 cbpt->IsInternal() ? "internal" : "user",
3116 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(), 3732 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(),
3117 cbpt->token_pos().ToCString(), top_frame->pc()); 3733 cbpt->token_pos().ToCString(), top_frame->pc());
3118 } 3734 }
3119 3735
3120 ASSERT(stack_trace_ == NULL); 3736 CacheStackTraces(stack_trace, async_stack_trace, async_return_call_stack);
3121 stack_trace_ = stack_trace;
3122 SignalPausedEvent(top_frame, bpt_hit); 3737 SignalPausedEvent(top_frame, bpt_hit);
3123 // When we single step from a user breakpoint, our next stepping 3738 // When we single step from a user breakpoint, our next stepping
3124 // point will be at the exact same pc. Skip it. 3739 // point will be at the exact same pc. Skip it.
3125 HandleSteppingRequest(stack_trace_, true /* skip next step */); 3740 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3126 stack_trace_ = NULL; 3741 ClearCachedStackTraces();
3127 if (cbpt->IsInternal()) { 3742 if (cbpt->IsInternal()) {
3128 RemoveInternalBreakpoints(); 3743 RemoveInternalBreakpoints();
3129 } 3744 }
3130 3745
3131 // If any error occurred while in the debug message loop, return it here. 3746 // If any error occurred while in the debug message loop, return it here.
3132 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 3747 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3133 Thread::Current()->clear_sticky_error(); 3748 Thread::Current()->clear_sticky_error();
3134 return error.raw(); 3749 return error.raw();
3135 } 3750 }
3136 3751
3137 3752
3753 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location,
3754 ActivationFrame* top_frame) {
3755 if (location == NULL) {
3756 return NULL;
3757 }
3758 // There may be more than one applicable breakpoint at this location, but we
3759 // will report only one as reached. ; then ; then an general breakpoint.
3760
3761 // First check for a single-shot breakpoint.
3762 Breakpoint* bpt = location->breakpoints();
3763 while (bpt != NULL) {
3764 if (bpt->IsSingleShot()) {
3765 return bpt;
3766 }
3767 bpt = bpt->next();
3768 }
3769
3770 // Now check for a closure-specific breakpoint.
3771 bpt = location->breakpoints();
3772 while (bpt != NULL) {
3773 if (bpt->IsPerClosure()) {
3774 Object& closure = Object::Handle(top_frame->GetClosure());
3775 ASSERT(closure.IsInstance());
3776 ASSERT(Instance::Cast(closure).IsClosure());
3777 if (closure.raw() == bpt->closure()) {
3778 return bpt;
3779 }
3780 }
3781 bpt = bpt->next();
3782 }
3783
3784 // Finally, check for a general breakpoint.
3785 bpt = location->breakpoints();
3786 while (bpt != NULL) {
3787 if (bpt->IsRepeated()) {
3788 return bpt;
3789 }
3790 bpt = bpt->next();
3791 }
3792
3793 return NULL;
3794 }
3795
3796
3138 void Debugger::PauseDeveloper(const String& msg) { 3797 void Debugger::PauseDeveloper(const String& msg) {
3139 // We ignore this breakpoint when the VM is executing code invoked 3798 // We ignore this breakpoint when the VM is executing code invoked
3140 // by the debugger to evaluate variables values, or when we see a nested 3799 // by the debugger to evaluate variables values, or when we see a nested
3141 // breakpoint or exception event. 3800 // breakpoint or exception event.
3142 if (ignore_breakpoints_ || IsPaused()) { 3801 if (ignore_breakpoints_ || IsPaused()) {
3143 return; 3802 return;
3144 } 3803 }
3145 3804
3146 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3805 CacheStackTraces(CollectStackTrace(), CollectAsyncStackTrace(),
3147 ASSERT(stack_trace->Length() > 0); 3806 CollectAsyncReturnCallStack());
3148 ASSERT(stack_trace_ == NULL);
3149 stack_trace_ = stack_trace;
3150 3807
3151 // TODO(johnmccutchan): Send |msg| to Observatory. 3808 // TODO(johnmccutchan): Send |msg| to Observatory.
3152 3809
3153 // We are in the native call to Developer_debugger. the developer 3810 // We are in the native call to Developer_debugger. the developer
3154 // gets a better experience by not seeing this call. To accomplish 3811 // gets a better experience by not seeing this call. To accomplish
3155 // this, we continue execution until the call exits (step out). 3812 // this, we continue execution until the call exits (step out).
3156 SetResumeAction(kStepOut); 3813 SetResumeAction(kStepOut);
3157 HandleSteppingRequest(stack_trace_); 3814 HandleSteppingRequest(stack_trace_);
3158 3815
3159 stack_trace_ = NULL; 3816 ClearCachedStackTraces();
3160 } 3817 }
3161 3818
3162 3819
3163 void Debugger::Initialize(Isolate* isolate) { 3820 void Debugger::Initialize(Isolate* isolate) {
3164 if (initialized_) { 3821 if (initialized_) {
3165 return; 3822 return;
3166 } 3823 }
3167 isolate_ = isolate; 3824 isolate_ = isolate;
3168 3825
3169 // Use the isolate's control port as the isolate_id for debugging. 3826 // Use the isolate's control port as the isolate_id for debugging.
3170 // This port will be used as a unique ID to represent the isolate in 3827 // This port will be used as a unique ID to represent the isolate in
3171 // the debugger embedder api. 3828 // the debugger embedder api.
3172 isolate_id_ = isolate_->main_port(); 3829 isolate_id_ = isolate_->main_port();
3173 initialized_ = true; 3830 initialized_ = true;
3174 } 3831 }
3175 3832
3176 3833
3834 void Debugger::WhenRunnable() {
3835 // Lookup some internal implementation functions and mark them as
3836 // not-debuggable (so the user never steps into them) and
3837 // not-inlinable (so that we can cheaply detect their presence on the stack).
3838 Thread::EnterIsolate(isolate_);
3839 Thread* thread = Thread::Current();
3840 ASSERT(thread != NULL);
3841 {
3842 StackZone zone(thread);
3843 HandleScope handle_scope(thread);
3844
3845 const Library& async_library =
3846 Library::Handle(isolate_->object_store()->async_library());
3847 ASSERT(!async_library.IsNull());
3848
3849 // This function is called when an async function completes their completer.
3850 const Function& complete_on_async_return_function =
3851 Function::Handle(async_library.LookupFunctionAllowPrivate(
3852 Symbols::CompleterCompleteOnAsyncReturn()));
3853 ASSERT(!complete_on_async_return_function.IsNull());
3854 complete_on_async_return_function.set_is_debuggable(false);
3855 complete_on_async_return_function.set_is_inlinable(false);
3856
3857 // Class used to implement async* functions.
3858 const Class& async_stream_controller =
3859 Class::Handle(async_library.LookupClassAllowPrivate(
3860 Symbols::_AsyncStarStreamController()));
3861 ASSERT(!async_stream_controller.IsNull());
3862 const Array& functions = Array::Handle(async_stream_controller.functions());
3863 ASSERT(!functions.IsNull());
3864 Function& function = Function::Handle();
3865 for (intptr_t i = 0; i < functions.Length(); i++) {
3866 function ^= functions.At(i);
3867 if (function.IsNull()) {
3868 // Skip padding.
3869 continue;
3870 }
3871 function.set_is_debuggable(false);
3872 function.set_is_inlinable(false);
3873 }
3874 }
3875 Thread::ExitIsolate();
3876 }
3877
3878
3177 void Debugger::NotifyIsolateCreated() { 3879 void Debugger::NotifyIsolateCreated() {
3178 if (NeedsIsolateEvents()) { 3880 if (NeedsIsolateEvents()) {
3179 ServiceEvent event(isolate_, ServiceEvent::kIsolateStart); 3881 ServiceEvent event(isolate_, ServiceEvent::kIsolateStart);
3180 InvokeEventHandler(&event); 3882 InvokeEventHandler(&event);
3181 } 3883 }
3182 } 3884 }
3183 3885
3184 3886
3185 // Return innermost closure contained in 'function' that contains 3887 // Return innermost closure contained in 'function' that contains
3186 // the given token position. 3888 // the given token position.
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
3599 4301
3600 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 4302 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3601 ASSERT(bpt->next() == NULL); 4303 ASSERT(bpt->next() == NULL);
3602 bpt->set_next(code_breakpoints_); 4304 bpt->set_next(code_breakpoints_);
3603 code_breakpoints_ = bpt; 4305 code_breakpoints_ = bpt;
3604 } 4306 }
3605 4307
3606 #endif // !PRODUCT 4308 #endif // !PRODUCT
3607 4309
3608 } // namespace dart 4310 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/flag_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698