OLD | NEW |
---|---|
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 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 column_number_(-1), | 290 column_number_(-1), |
291 context_level_(-1), | 291 context_level_(-1), |
292 deopt_frame_(Array::ZoneHandle()), | 292 deopt_frame_(Array::ZoneHandle()), |
293 deopt_frame_offset_(0), | 293 deopt_frame_offset_(0), |
294 kind_(kind), | 294 kind_(kind), |
295 vars_initialized_(false), | 295 vars_initialized_(false), |
296 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 296 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
297 desc_indices_(8), | 297 desc_indices_(8), |
298 pc_desc_(PcDescriptors::ZoneHandle()) {} | 298 pc_desc_(PcDescriptors::ZoneHandle()) {} |
299 | 299 |
300 | |
301 ActivationFrame::ActivationFrame(const Closure& async_activation) | |
302 : pc_(0), | |
303 fp_(0), | |
304 sp_(0), | |
305 ctx_(Context::ZoneHandle()), | |
306 code_(Code::ZoneHandle()), | |
307 function_(Function::ZoneHandle()), | |
308 live_frame_(false), | |
309 token_pos_initialized_(false), | |
310 token_pos_(TokenPosition::kNoSource), | |
311 try_index_(-1), | |
312 line_number_(-1), | |
313 column_number_(-1), | |
314 context_level_(-1), | |
315 deopt_frame_(Array::ZoneHandle()), | |
316 deopt_frame_offset_(0), | |
317 kind_(kAsyncActivation), | |
318 vars_initialized_(false), | |
319 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | |
320 desc_indices_(8), | |
321 pc_desc_(PcDescriptors::ZoneHandle()) { | |
322 // Extract the function and the code from the asynchronous activation. | |
323 function_ = async_activation.function(); | |
324 code_ = function_.unoptimized_code(); | |
325 ctx_ = async_activation.context(); | |
326 } | |
327 | |
328 | |
300 bool Debugger::NeedsIsolateEvents() { | 329 bool Debugger::NeedsIsolateEvents() { |
301 return ((isolate_ != Dart::vm_isolate()) && | 330 return ((isolate_ != Dart::vm_isolate()) && |
302 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && | 331 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && |
303 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); | 332 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); |
304 } | 333 } |
305 | 334 |
306 | 335 |
307 bool Debugger::NeedsDebugEvents() { | 336 bool Debugger::NeedsDebugEvents() { |
308 ASSERT(isolate_ != Dart::vm_isolate() && | 337 ASSERT(isolate_ != Dart::vm_isolate() && |
309 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); | 338 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
672 innermost_begin_pos = var_info.begin_pos; | 701 innermost_begin_pos = var_info.begin_pos; |
673 context_level_ = var_info.index(); | 702 context_level_ = var_info.index(); |
674 } | 703 } |
675 } | 704 } |
676 } | 705 } |
677 ASSERT(context_level_ >= 0); | 706 ASSERT(context_level_ >= 0); |
678 } | 707 } |
679 return context_level_; | 708 return context_level_; |
680 } | 709 } |
681 | 710 |
711 RawObject* ActivationFrame::GetAsyncCompleter() { | |
712 if (!function_.IsAsyncClosure()) { | |
713 return Object::null(); | |
714 } | |
715 GetVarDescriptors(); | |
716 intptr_t var_desc_len = var_descriptors_.Length(); | |
717 if (fp() == 0) { | |
rmacnak
2017/02/23 17:50:56
if (!live_frame) {
...
} else {
ASSERT(fp != 0
Cutch
2017/02/24 20:19:21
Done.
| |
718 // Not actually on the stack. Pull it out of the closure's context. | |
719 intptr_t var_desc_len = var_descriptors_.Length(); | |
720 for (intptr_t i = 0; i < var_desc_len; i++) { | |
721 RawLocalVarDescriptors::VarInfo var_info; | |
722 var_descriptors_.GetInfo(i, &var_info); | |
723 const int8_t kind = var_info.kind(); | |
724 if (var_descriptors_.GetName(i) == Symbols::AsyncCompleter().raw()) { | |
725 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
726 ASSERT(!ctx_.IsNull()); | |
727 return ctx_.At(var_info.index()); | |
728 } | |
729 } | |
730 } else { | |
731 // On the stack. | |
732 for (intptr_t i = 0; i < var_desc_len; i++) { | |
733 RawLocalVarDescriptors::VarInfo var_info; | |
734 var_descriptors_.GetInfo(i, &var_info); | |
735 if (var_descriptors_.GetName(i) == Symbols::AsyncCompleter().raw()) { | |
736 const int8_t kind = var_info.kind(); | |
737 if (kind == RawLocalVarDescriptors::kStackVar) { | |
738 return GetStackVar(var_info.index()); | |
739 } else { | |
740 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
741 return GetContextVar(var_info.scope_id, var_info.index()); | |
742 } | |
743 } | |
744 } | |
745 } | |
746 return Object::null(); | |
747 } | |
748 | |
749 | |
750 RawObject* ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) { | |
751 const Class& sync_completer_cls = Class::Handle(completer.clazz()); | |
752 ASSERT(!sync_completer_cls.IsNull()); | |
753 const Class& completer_cls = Class::Handle(sync_completer_cls.SuperClass()); | |
754 const Field& future_field = | |
755 Field::Handle(completer_cls.LookupInstanceFieldAllowPrivate( | |
756 Symbols::CompleterFuture())); | |
757 ASSERT(!future_field.IsNull()); | |
758 Instance& future = Instance::Handle(); | |
759 future ^= Instance::Cast(completer).GetField(future_field); | |
760 ASSERT(!future.IsNull()); | |
761 const Class& future_cls = Class::Handle(future.clazz()); | |
762 ASSERT(!future_cls.IsNull()); | |
763 const Field& awaiter_field = Field::Handle( | |
764 future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); | |
765 ASSERT(!awaiter_field.IsNull()); | |
766 return future.GetField(awaiter_field); | |
767 } | |
768 | |
769 | |
770 RawObject* ActivationFrame::GetAsyncStreamControllerStream() { | |
771 if (!function_.IsAsyncGenClosure()) { | |
772 return Object::null(); | |
773 } | |
774 GetVarDescriptors(); | |
775 intptr_t var_desc_len = var_descriptors_.Length(); | |
776 if (fp() == 0) { | |
rmacnak
2017/02/23 17:50:56
live_frame
Cutch
2017/02/24 20:19:21
Done.
| |
777 // Not actually on the stack. Pull it out of the closure's context. | |
778 intptr_t var_desc_len = var_descriptors_.Length(); | |
779 for (intptr_t i = 0; i < var_desc_len; i++) { | |
780 RawLocalVarDescriptors::VarInfo var_info; | |
781 var_descriptors_.GetInfo(i, &var_info); | |
782 const int8_t kind = var_info.kind(); | |
783 if (var_descriptors_.GetName(i) == Symbols::ControllerStream().raw()) { | |
784 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
785 ASSERT(!ctx_.IsNull()); | |
786 return ctx_.At(var_info.index()); | |
787 } | |
788 } | |
789 } else { | |
790 // On the stack. | |
791 for (intptr_t i = 0; i < var_desc_len; i++) { | |
792 RawLocalVarDescriptors::VarInfo var_info; | |
793 var_descriptors_.GetInfo(i, &var_info); | |
794 if (var_descriptors_.GetName(i) == Symbols::ControllerStream().raw()) { | |
795 const int8_t kind = var_info.kind(); | |
796 if (kind == RawLocalVarDescriptors::kStackVar) { | |
797 return GetStackVar(var_info.index()); | |
798 } else { | |
799 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
800 return GetContextVar(var_info.scope_id, var_info.index()); | |
801 } | |
802 } | |
803 } | |
804 } | |
805 return Object::null(); | |
806 } | |
807 | |
808 | |
809 RawObject* ActivationFrame::GetAsyncStreamControllerStreamAwaiter( | |
810 const Object& stream) { | |
811 const Class& stream_cls = Class::Handle(stream.clazz()); | |
812 ASSERT(!stream_cls.IsNull()); | |
813 const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass()); | |
814 const Field& awaiter_field = Field::Handle( | |
815 stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); | |
816 ASSERT(!awaiter_field.IsNull()); | |
817 return Instance::Cast(stream).GetField(awaiter_field); | |
818 } | |
819 | |
820 | |
821 RawObject* ActivationFrame::GetAsyncAwaiter() { | |
822 const Object& completer = Object::Handle(GetAsyncCompleter()); | |
823 if (!completer.IsNull()) { | |
824 return GetAsyncCompleterAwaiter(completer); | |
825 } | |
826 const Object& async_stream_controller_stream = | |
827 Object::Handle(GetAsyncStreamControllerStream()); | |
828 if (!async_stream_controller_stream.IsNull()) { | |
829 return GetAsyncStreamControllerStreamAwaiter( | |
830 async_stream_controller_stream); | |
831 } | |
832 return Object::null(); | |
833 } | |
834 | |
835 | |
836 bool ActivationFrame::HandlesException(const Instance& exc_obj) { | |
rmacnak
2017/02/23 17:50:56
How much slower is ParserCombinators with the debu
| |
837 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | |
rmacnak
2017/02/23 17:50:56
Move handle creation below the fast exit.
Cutch
2017/02/24 20:19:21
Done.
| |
838 Array& handled_types = Array::Handle(); | |
839 AbstractType& type = Type::Handle(); | |
840 const TypeArguments& no_instantiator = TypeArguments::Handle(); | |
841 intptr_t try_index = TryIndex(); | |
842 if (try_index < 0) { | |
843 return false; | |
844 } | |
845 const intptr_t try_index_threshold = CatchClauseNode::kImplicitAsyncTryIndex; | |
846 const bool is_async = | |
847 function().IsAsyncClosure() || function().IsAsyncGenClosure(); | |
848 handlers = code().exception_handlers(); | |
849 ASSERT(!handlers.IsNull()); | |
850 intptr_t num_handlers_checked = 0; | |
851 while (try_index >= try_index_threshold) { | |
852 // Detect circles in the exception handler data. | |
853 num_handlers_checked++; | |
854 ASSERT(num_handlers_checked <= handlers.num_entries()); | |
855 // Only consider user written handlers for async methods. | |
856 if (!is_async || !handlers.IsGenerated(try_index)) { | |
857 handled_types = handlers.GetHandledTypes(try_index); | |
858 const intptr_t num_types = handled_types.Length(); | |
859 for (intptr_t k = 0; k < num_types; k++) { | |
860 type ^= handled_types.At(k); | |
861 ASSERT(!type.IsNull()); | |
862 // Uninstantiated types are not added to ExceptionHandlers data. | |
863 ASSERT(type.IsInstantiated()); | |
864 if (type.IsMalformed()) { | |
865 continue; | |
866 } | |
867 if (type.IsDynamicType()) { | |
868 return true; | |
869 } | |
870 if (exc_obj.IsInstanceOf(type, no_instantiator, NULL)) { | |
871 return true; | |
872 } | |
873 } | |
874 } | |
875 try_index = handlers.OuterTryIndex(try_index); | |
876 } | |
877 return false; | |
878 } | |
879 | |
880 | |
881 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() { | |
882 // Attempt to determine the token position from the async closure. | |
883 ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure()); | |
884 // This should only be called on frames that aren't active on the stack. | |
885 ASSERT(fp() == 0); | |
886 const Array& await_to_token_map = | |
887 Array::Handle(code_.await_token_positions()); | |
888 if (await_to_token_map.IsNull()) { | |
889 // No mapping. | |
890 return; | |
891 } | |
892 GetVarDescriptors(); | |
893 GetPcDescriptors(); | |
894 intptr_t var_desc_len = var_descriptors_.Length(); | |
895 intptr_t await_jump_var = -1; | |
896 for (intptr_t i = 0; i < var_desc_len; i++) { | |
897 RawLocalVarDescriptors::VarInfo var_info; | |
898 var_descriptors_.GetInfo(i, &var_info); | |
899 const int8_t kind = var_info.kind(); | |
900 if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().raw()) { | |
901 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
902 ASSERT(!ctx_.IsNull()); | |
903 Object& await_jump_index = Object::Handle(ctx_.At(var_info.index())); | |
904 ASSERT(await_jump_index.IsSmi()); | |
905 await_jump_var = Smi::Cast(await_jump_index).Value(); | |
906 } | |
907 } | |
908 if (await_jump_var < 0) { | |
909 return; | |
910 } | |
911 ASSERT(await_jump_var < await_to_token_map.Length()); | |
912 const Object& token_pos = | |
913 Object::Handle(await_to_token_map.At(await_jump_var)); | |
914 if (token_pos.IsNull()) { | |
915 return; | |
916 } | |
917 ASSERT(token_pos.IsSmi()); | |
918 token_pos_ = TokenPosition(Smi::Cast(token_pos).Value()); | |
919 token_pos_initialized_ = true; | |
920 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | |
921 while (iter.MoveNext()) { | |
922 if (iter.TokenPos() == token_pos_) { | |
923 // Match the lowest try index at this token position. | |
924 // TODO(johnmccutchan): Is this heuristic precise enough? | |
925 if (iter.TryIndex() != CatchClauseNode::kInvalidTryIndex) { | |
926 if ((try_index_ == -1) || (iter.TryIndex() < try_index_)) { | |
927 try_index_ = iter.TryIndex(); | |
928 } | |
929 } | |
930 } | |
931 } | |
932 } | |
933 | |
682 | 934 |
683 // Get the saved current context of this activation. | 935 // Get the saved current context of this activation. |
684 const Context& ActivationFrame::GetSavedCurrentContext() { | 936 const Context& ActivationFrame::GetSavedCurrentContext() { |
685 if (!ctx_.IsNull()) return ctx_; | 937 if (!ctx_.IsNull()) return ctx_; |
686 GetVarDescriptors(); | 938 GetVarDescriptors(); |
687 intptr_t var_desc_len = var_descriptors_.Length(); | 939 intptr_t var_desc_len = var_descriptors_.Length(); |
688 for (intptr_t i = 0; i < var_desc_len; i++) { | 940 for (intptr_t i = 0; i < var_desc_len; i++) { |
689 RawLocalVarDescriptors::VarInfo var_info; | 941 RawLocalVarDescriptors::VarInfo var_info; |
690 var_descriptors_.GetInfo(i, &var_info); | 942 var_descriptors_.GetInfo(i, &var_info); |
691 const int8_t kind = var_info.kind(); | 943 const int8_t kind = var_info.kind(); |
(...skipping 25 matching lines...) Expand all Loading... | |
717 return GetContextVar(var_info.scope_id, var_info.index()); | 969 return GetContextVar(var_info.scope_id, var_info.index()); |
718 } | 970 } |
719 } | 971 } |
720 } | 972 } |
721 return Object::null(); | 973 return Object::null(); |
722 } | 974 } |
723 | 975 |
724 | 976 |
725 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 977 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
726 const Instance& exc_obj) const { | 978 const Instance& exc_obj) const { |
727 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | |
728 Array& handled_types = Array::Handle(); | |
729 AbstractType& type = Type::Handle(); | |
730 const TypeArguments& no_instantiator = TypeArguments::Handle(); | |
731 for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) { | 979 for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) { |
732 ActivationFrame* frame = FrameAt(frame_index); | 980 ActivationFrame* frame = FrameAt(frame_index); |
733 intptr_t try_index = frame->TryIndex(); | 981 if (frame->HandlesException(exc_obj)) { |
734 if (try_index < 0) continue; | 982 return frame; |
735 handlers = frame->code().exception_handlers(); | |
736 ASSERT(!handlers.IsNull()); | |
737 intptr_t num_handlers_checked = 0; | |
738 while (try_index >= 0) { | |
739 // Detect circles in the exception handler data. | |
740 num_handlers_checked++; | |
741 ASSERT(num_handlers_checked <= handlers.num_entries()); | |
742 handled_types = handlers.GetHandledTypes(try_index); | |
743 const intptr_t num_types = handled_types.Length(); | |
744 for (intptr_t k = 0; k < num_types; k++) { | |
745 type ^= handled_types.At(k); | |
746 ASSERT(!type.IsNull()); | |
747 // Uninstantiated types are not added to ExceptionHandlers data. | |
748 ASSERT(type.IsInstantiated()); | |
749 if (type.IsMalformed()) continue; | |
750 if (type.IsDynamicType()) return frame; | |
751 if (exc_obj.IsInstanceOf(type, no_instantiator, NULL)) { | |
752 return frame; | |
753 } | |
754 } | |
755 try_index = handlers.OuterTryIndex(try_index); | |
756 } | 983 } |
757 } | 984 } |
758 return NULL; | 985 return NULL; |
759 } | 986 } |
760 | 987 |
761 | 988 |
762 void ActivationFrame::GetDescIndices() { | 989 void ActivationFrame::GetDescIndices() { |
763 if (vars_initialized_) { | 990 if (vars_initialized_) { |
764 return; | 991 return; |
765 } | 992 } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1145 JSONArray jsvars(jsobj, "vars"); | 1372 JSONArray jsvars(jsobj, "vars"); |
1146 const int num_vars = NumLocalVariables(); | 1373 const int num_vars = NumLocalVariables(); |
1147 for (intptr_t v = 0; v < num_vars; v++) { | 1374 for (intptr_t v = 0; v < num_vars; v++) { |
1148 String& var_name = String::Handle(); | 1375 String& var_name = String::Handle(); |
1149 Instance& var_value = Instance::Handle(); | 1376 Instance& var_value = Instance::Handle(); |
1150 TokenPosition declaration_token_pos; | 1377 TokenPosition declaration_token_pos; |
1151 TokenPosition visible_start_token_pos; | 1378 TokenPosition visible_start_token_pos; |
1152 TokenPosition visible_end_token_pos; | 1379 TokenPosition visible_end_token_pos; |
1153 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos, | 1380 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos, |
1154 &visible_end_token_pos, &var_value); | 1381 &visible_end_token_pos, &var_value); |
1155 if (var_name.raw() != Symbols::AsyncOperation().raw()) { | 1382 if ((var_name.raw() != Symbols::AsyncOperation().raw()) && |
1383 (var_name.raw() != Symbols::AsyncCompleter().raw()) && | |
1384 (var_name.raw() != Symbols::ControllerStream().raw()) && | |
1385 (var_name.raw() != Symbols::AwaitJumpVar().raw())) { | |
1156 JSONObject jsvar(&jsvars); | 1386 JSONObject jsvar(&jsvars); |
1157 jsvar.AddProperty("type", "BoundVariable"); | 1387 jsvar.AddProperty("type", "BoundVariable"); |
1158 var_name = String::ScrubName(var_name); | 1388 var_name = String::ScrubName(var_name); |
1159 jsvar.AddProperty("name", var_name.ToCString()); | 1389 jsvar.AddProperty("name", var_name.ToCString()); |
1160 jsvar.AddProperty("value", var_value, !full); | 1390 jsvar.AddProperty("value", var_value, !full); |
1161 // Where was the variable declared? | 1391 // Where was the variable declared? |
1162 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); | 1392 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); |
1163 // When the variable becomes visible to the scope. | 1393 // When the variable becomes visible to the scope. |
1164 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); | 1394 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); |
1165 // When the variable stops being visible to the scope. | 1395 // When the variable stops being visible to the scope. |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1541 } | 1771 } |
1542 } | 1772 } |
1543 } | 1773 } |
1544 | 1774 |
1545 | 1775 |
1546 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1776 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
1547 uword pc, | 1777 uword pc, |
1548 StackFrame* frame, | 1778 StackFrame* frame, |
1549 const Code& code, | 1779 const Code& code, |
1550 const Array& deopt_frame, | 1780 const Array& deopt_frame, |
1551 intptr_t deopt_frame_offset) { | 1781 intptr_t deopt_frame_offset, |
1782 ActivationFrame::Kind kind) { | |
1552 ASSERT(code.ContainsInstructionAt(pc)); | 1783 ASSERT(code.ContainsInstructionAt(pc)); |
1553 ActivationFrame* activation = new ActivationFrame( | 1784 ActivationFrame* activation = |
1554 pc, frame->fp(), frame->sp(), code, deopt_frame, deopt_frame_offset); | 1785 new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame, |
1786 deopt_frame_offset, kind); | |
1555 if (FLAG_trace_debugger_stacktrace) { | 1787 if (FLAG_trace_debugger_stacktrace) { |
1556 const Context& ctx = activation->GetSavedCurrentContext(); | 1788 const Context& ctx = activation->GetSavedCurrentContext(); |
1557 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString()); | 1789 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString()); |
1558 } | 1790 } |
1559 if (FLAG_trace_debugger_stacktrace) { | 1791 if (FLAG_trace_debugger_stacktrace) { |
1560 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); | 1792 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); |
1561 } | 1793 } |
1562 return activation; | 1794 return activation; |
1563 } | 1795 } |
1564 | 1796 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1721 } | 1953 } |
1722 } | 1954 } |
1723 } | 1955 } |
1724 // Follow the link. | 1956 // Follow the link. |
1725 async_stack_trace = async_stack_trace.async_link(); | 1957 async_stack_trace = async_stack_trace.async_link(); |
1726 } | 1958 } |
1727 | 1959 |
1728 return stack_trace; | 1960 return stack_trace; |
1729 } | 1961 } |
1730 | 1962 |
1963 | |
1964 DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() { | |
1965 if (!FLAG_causal_async_stacks) { | |
1966 return NULL; | |
1967 } | |
1968 Thread* thread = Thread::Current(); | |
1969 Zone* zone = thread->zone(); | |
1970 Isolate* isolate = thread->isolate(); | |
1971 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | |
1972 | |
1973 StackFrameIterator iterator(false); | |
1974 | |
1975 Code& code = Code::Handle(zone); | |
1976 Function& function = Function::Handle(zone); | |
1977 Code& inlined_code = Code::Handle(zone); | |
1978 Closure& async_activation = Closure::Handle(zone); | |
1979 Array& deopt_frame = Array::Handle(zone); | |
1980 | |
1981 for (StackFrame* frame = iterator.NextFrame(); frame != NULL; | |
1982 frame = iterator.NextFrame()) { | |
1983 ASSERT(frame->IsValid()); | |
1984 if (frame->IsDartFrame()) { | |
1985 code = frame->LookupDartCode(); | |
1986 function = code.function(); | |
1987 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { | |
1988 ActivationFrame* activation = CollectDartFrame( | |
1989 isolate, frame->pc(), frame, code, Object::null_array(), 0, | |
1990 ActivationFrame::kAsyncActivation); | |
1991 ASSERT(activation != NULL); | |
1992 stack_trace->AddActivation(activation); | |
1993 // Grab the awaiter. | |
1994 async_activation ^= activation->GetAsyncAwaiter(); | |
1995 break; | |
1996 } else { | |
1997 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code, | |
1998 &inlined_code, &deopt_frame); | |
1999 } | |
2000 } | |
2001 } | |
2002 | |
2003 // Return NULL to indicate that there is no useful information in this stack | |
2004 // trace because we never found an awaiter. | |
2005 if (async_activation.IsNull()) { | |
2006 return NULL; | |
2007 } | |
2008 | |
2009 // Append the awaiter return call stack. | |
2010 while (!async_activation.IsNull()) { | |
2011 ActivationFrame* activation = new ActivationFrame(async_activation); | |
2012 async_activation ^= activation->GetAsyncAwaiter(); | |
2013 activation->ExtractTokenPositionFromAsyncClosure(); | |
2014 stack_trace->AddActivation(activation); | |
2015 } | |
2016 | |
2017 return stack_trace; | |
2018 } | |
2019 | |
2020 | |
1731 ActivationFrame* Debugger::TopDartFrame() const { | 2021 ActivationFrame* Debugger::TopDartFrame() const { |
1732 StackFrameIterator iterator(false); | 2022 StackFrameIterator iterator(false); |
1733 StackFrame* frame = iterator.NextFrame(); | 2023 StackFrame* frame = iterator.NextFrame(); |
1734 while ((frame != NULL) && !frame->IsDartFrame()) { | 2024 while ((frame != NULL) && !frame->IsDartFrame()) { |
1735 frame = iterator.NextFrame(); | 2025 frame = iterator.NextFrame(); |
1736 } | 2026 } |
1737 Code& code = Code::Handle(frame->LookupDartCode()); | 2027 Code& code = Code::Handle(frame->LookupDartCode()); |
1738 ActivationFrame* activation = new ActivationFrame( | 2028 ActivationFrame* activation = new ActivationFrame( |
1739 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); | 2029 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); |
1740 return activation; | 2030 return activation; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1821 (pause_info == kPauseOnAllExceptions)); | 2111 (pause_info == kPauseOnAllExceptions)); |
1822 exc_pause_info_ = pause_info; | 2112 exc_pause_info_ = pause_info; |
1823 } | 2113 } |
1824 | 2114 |
1825 | 2115 |
1826 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const { | 2116 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const { |
1827 return exc_pause_info_; | 2117 return exc_pause_info_; |
1828 } | 2118 } |
1829 | 2119 |
1830 | 2120 |
2121 bool Debugger::ShouldPauseOnAsyncException(DebuggerStackTrace* stack_trace, | |
2122 const Instance& exc) { | |
2123 if (exc_pause_info_ == kNoPauseOnExceptions) { | |
2124 return false; | |
2125 } | |
2126 if (exc_pause_info_ == kPauseOnAllExceptions) { | |
2127 return true; | |
2128 } | |
2129 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); | |
2130 for (intptr_t i = 0; i < stack_trace->Length(); i++) { | |
2131 ActivationFrame* frame = stack_trace->FrameAt(i); | |
2132 if (frame->HandlesException(exc)) { | |
2133 OS::PrintErr("%s is caught by frame %s\n", exc.ToCString(), | |
rmacnak
2017/02/23 17:50:56
if (FLAG_verbose_debug)
Cutch
2017/02/24 20:19:21
Done.
| |
2134 frame->ToCString()); | |
2135 return false; | |
2136 } | |
2137 } | |
2138 return true; | |
2139 } | |
2140 | |
2141 | |
1831 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, | 2142 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, |
1832 const Instance& exception) { | 2143 const Instance& exception) { |
1833 if (exc_pause_info_ == kNoPauseOnExceptions) { | 2144 if (exc_pause_info_ == kNoPauseOnExceptions) { |
1834 return false; | 2145 return false; |
1835 } | 2146 } |
1836 if (exc_pause_info_ == kPauseOnAllExceptions) { | 2147 if (exc_pause_info_ == kPauseOnAllExceptions) { |
1837 return true; | 2148 return true; |
1838 } | 2149 } |
1839 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); | 2150 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); |
1840 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception); | 2151 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception); |
(...skipping 11 matching lines...) Expand all Loading... | |
1852 | 2163 |
1853 void Debugger::PauseException(const Instance& exc) { | 2164 void Debugger::PauseException(const Instance& exc) { |
1854 // We ignore this exception event when the VM is executing code invoked | 2165 // We ignore this exception event when the VM is executing code invoked |
1855 // by the debugger to evaluate variables values, when we see a nested | 2166 // by the debugger to evaluate variables values, when we see a nested |
1856 // breakpoint or exception event, or if the debugger is not | 2167 // breakpoint or exception event, or if the debugger is not |
1857 // interested in exception events. | 2168 // interested in exception events. |
1858 if (ignore_breakpoints_ || IsPaused() || | 2169 if (ignore_breakpoints_ || IsPaused() || |
1859 (exc_pause_info_ == kNoPauseOnExceptions)) { | 2170 (exc_pause_info_ == kNoPauseOnExceptions)) { |
1860 return; | 2171 return; |
1861 } | 2172 } |
2173 DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace(); | |
1862 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2174 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1863 if (!ShouldPauseOnException(stack_trace, exc)) { | 2175 if (awaiter_stack_trace != NULL) { |
1864 return; | 2176 if (!ShouldPauseOnAsyncException(awaiter_stack_trace, exc)) { |
2177 return; | |
2178 } | |
2179 } else { | |
2180 if (!ShouldPauseOnException(stack_trace, exc)) { | |
2181 return; | |
2182 } | |
1865 } | 2183 } |
1866 ServiceEvent event(isolate_, ServiceEvent::kPauseException); | 2184 ServiceEvent event(isolate_, ServiceEvent::kPauseException); |
1867 event.set_exception(&exc); | 2185 event.set_exception(&exc); |
1868 if (stack_trace->Length() > 0) { | 2186 if (stack_trace->Length() > 0) { |
1869 event.set_top_frame(stack_trace->FrameAt(0)); | 2187 event.set_top_frame(stack_trace->FrameAt(0)); |
1870 } | 2188 } |
1871 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); | 2189 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); |
1872 Pause(&event); | 2190 Pause(&event); |
1873 HandleSteppingRequest(stack_trace_); // we may get a rewind request | 2191 HandleSteppingRequest(stack_trace_); // we may get a rewind request |
1874 ClearCachedStackTraces(); | 2192 ClearCachedStackTraces(); |
(...skipping 1956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3831 | 4149 |
3832 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 4150 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
3833 ASSERT(bpt->next() == NULL); | 4151 ASSERT(bpt->next() == NULL); |
3834 bpt->set_next(code_breakpoints_); | 4152 bpt->set_next(code_breakpoints_); |
3835 code_breakpoints_ = bpt; | 4153 code_breakpoints_ = bpt; |
3836 } | 4154 } |
3837 | 4155 |
3838 #endif // !PRODUCT | 4156 #endif // !PRODUCT |
3839 | 4157 |
3840 } // namespace dart | 4158 } // namespace dart |
OLD | NEW |