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