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 "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 | 294 |
| 295 intptr_t ActivationFrame::PcDescIndex() { | 295 intptr_t ActivationFrame::PcDescIndex() { |
| 296 if (pc_desc_index_ < 0) { | 296 if (pc_desc_index_ < 0) { |
| 297 TokenPos(); | 297 TokenPos(); |
| 298 ASSERT(pc_desc_index_ >= 0); | 298 ASSERT(pc_desc_index_ >= 0); |
| 299 } | 299 } |
| 300 return pc_desc_index_; | 300 return pc_desc_index_; |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 intptr_t ActivationFrame::TryIndex() { | |
| 305 intptr_t desc_index = PcDescIndex(); | |
| 306 return pc_desc_.TryIndex(desc_index); | |
| 307 } | |
| 308 | |
| 309 | |
| 304 intptr_t ActivationFrame::LineNumber() { | 310 intptr_t ActivationFrame::LineNumber() { |
| 305 // Compute line number lazily since it causes scanning of the script. | 311 // Compute line number lazily since it causes scanning of the script. |
| 306 if (line_number_ < 0) { | 312 if (line_number_ < 0) { |
| 307 const Script& script = Script::Handle(SourceScript()); | 313 const Script& script = Script::Handle(SourceScript()); |
| 308 intptr_t ignore_column; | 314 intptr_t ignore_column; |
| 309 script.GetTokenLocation(TokenPos(), &line_number_, &ignore_column); | 315 script.GetTokenLocation(TokenPos(), &line_number_, &ignore_column); |
| 310 } | 316 } |
| 311 return line_number_; | 317 return line_number_; |
| 312 } | 318 } |
| 313 | 319 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 var_descriptors_.GetInfo(i, &var_info); | 371 var_descriptors_.GetInfo(i, &var_info); |
| 366 if (var_info.kind == RawLocalVarDescriptors::kContextChain) { | 372 if (var_info.kind == RawLocalVarDescriptors::kContextChain) { |
| 367 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index)); | 373 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index)); |
| 368 } | 374 } |
| 369 } | 375 } |
| 370 // Caller uses same context chain. | 376 // Caller uses same context chain. |
| 371 return ctx_.raw(); | 377 return ctx_.raw(); |
| 372 } | 378 } |
| 373 | 379 |
| 374 | 380 |
| 381 // TODO(hausner): Eliminate this helper function by sorting the | |
| 382 // ExceptionHandlers entries by try_index and eliminating | |
| 383 // the try_index field altogether. | |
| 384 static intptr_t FindTryIndex(const ExceptionHandlers& handlers, | |
| 385 intptr_t try_index) { | |
| 386 intptr_t len = handlers.Length(); | |
| 387 for (int i = 0; i < len; i++) { | |
| 388 if (handlers.TryIndex(i) == try_index) return i; | |
| 389 } | |
| 390 UNREACHABLE(); | |
| 391 return -1; | |
| 392 } | |
| 393 | |
| 394 | |
| 395 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | |
| 396 const Instance& exc_obj) const { | |
| 397 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | |
| 398 Array& handled_types = Array::Handle(); | |
| 399 Type& type = Type::Handle(); | |
| 400 const TypeArguments& no_instantiator = TypeArguments::Handle(); | |
| 401 for (int frame_index = 0; frame_index < Length(); frame_index++) { | |
| 402 ActivationFrame* frame = trace_[frame_index]; | |
| 403 intptr_t try_index = frame->TryIndex(); | |
| 404 if (try_index < 0) continue; | |
| 405 const Code& code = frame->DartCode(); | |
| 406 handlers = code.exception_handlers(); | |
| 407 ASSERT(!handlers.IsNull()); | |
| 408 intptr_t num_handlers_checked = 0; | |
| 409 while (try_index >= 0) { | |
| 410 intptr_t i = FindTryIndex(handlers, try_index); | |
| 411 // Detect circles in the exception handler data. | |
| 412 num_handlers_checked++; | |
| 413 ASSERT(num_handlers_checked <= handlers.Length()); | |
| 414 handled_types = handlers.GetHandledTypes(i); | |
| 415 intptr_t num_types = handled_types.Length(); | |
|
srdjan
2013/01/16 21:12:16
const
hausner
2013/01/16 22:07:25
Done.
| |
| 416 for (int k = 0; k < num_types; k++) { | |
| 417 type ^= handled_types.At(k); | |
| 418 ASSERT(!type.IsNull()); | |
| 419 if (type.IsDynamicType()) return frame; | |
| 420 if (type.IsMalformed()) continue; | |
|
regis
2013/01/16 21:06:36
If the type is malformed, the test at run time wil
hausner
2013/01/16 22:07:25
I think 'continue' to the next type check is corre
| |
| 421 if (exc_obj.IsInstanceOf(type, no_instantiator, NULL)) { | |
|
regis
2013/01/16 21:06:36
How about a comment indicating you may get a false
hausner
2013/01/16 22:07:25
Done.
| |
| 422 return frame; | |
| 423 } | |
| 424 } | |
| 425 try_index = handlers.OuterTryIndex(i); | |
| 426 } | |
| 427 } | |
| 428 return NULL; | |
| 429 } | |
| 430 | |
| 431 | |
| 375 void ActivationFrame::GetDescIndices() { | 432 void ActivationFrame::GetDescIndices() { |
| 376 if (vars_initialized_) { | 433 if (vars_initialized_) { |
| 377 return; | 434 return; |
| 378 } | 435 } |
| 379 GetVarDescriptors(); | 436 GetVarDescriptors(); |
| 380 | 437 |
| 381 // We don't trust variable descriptors in optimized code. | 438 // We don't trust variable descriptors in optimized code. |
| 382 // Rather than potentially displaying incorrect values, we | 439 // Rather than potentially displaying incorrect values, we |
| 383 // pretend that there are no variables in the frame. | 440 // pretend that there are no variables in the frame. |
| 384 // We should be more clever about this in the future. | 441 // We should be more clever about this in the future. |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 859 (pause_info == kPauseOnAllExceptions)); | 916 (pause_info == kPauseOnAllExceptions)); |
| 860 exc_pause_info_ = pause_info; | 917 exc_pause_info_ = pause_info; |
| 861 } | 918 } |
| 862 | 919 |
| 863 | 920 |
| 864 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() { | 921 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() { |
| 865 return (Dart_ExceptionPauseInfo)exc_pause_info_; | 922 return (Dart_ExceptionPauseInfo)exc_pause_info_; |
| 866 } | 923 } |
| 867 | 924 |
| 868 | 925 |
| 869 // TODO(hausner): Determine whether the exception is handled or not. | |
| 870 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, | 926 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, |
| 871 const Object& exc) { | 927 const Instance& exc) { |
| 872 if (exc_pause_info_ == kNoPauseOnExceptions) { | 928 if (exc_pause_info_ == kNoPauseOnExceptions) { |
| 873 return false; | 929 return false; |
| 874 } | 930 } |
| 875 if ((exc_pause_info_ & kPauseOnAllExceptions) != 0) { | 931 if (exc_pause_info_ == kPauseOnAllExceptions) { |
| 876 return true; | 932 return true; |
| 877 } | 933 } |
| 878 // Assume TypeError and AssertionError exceptions are unhandled. | 934 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); |
| 879 const Class& exc_class = Class::Handle(exc.clazz()); | 935 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exc); |
| 880 const String& class_name = String::Handle(exc_class.Name()); | 936 if (handler_frame == NULL) { |
| 881 // TODO(hausner): Note the poor man's type test. This code will go | 937 // Did not find an exception handler that catches this exception. |
| 882 // away when we have a way to determine whether an exception is unhandled. | 938 // Note that this check is not precise, since we can't check |
| 883 if (class_name.Equals("TypeErrorImplementation")) { | 939 // uninstantiated types, i.e. types containing type parameters. |
| 884 return true; | 940 // Thus, we may report an exception as unhandled when in fact |
| 885 } | 941 // it will be caught once we unwind the stack. |
| 886 if (class_name.Equals("AssertionErrorImplementation")) { | |
| 887 return true; | 942 return true; |
| 888 } | 943 } |
| 889 return false; | 944 return false; |
| 890 } | 945 } |
| 891 | 946 |
| 892 | 947 |
| 893 void Debugger::SignalExceptionThrown(const Object& exc) { | 948 void Debugger::SignalExceptionThrown(const Instance& exc) { |
| 894 // We ignore this exception event when the VM is executing code invoked | 949 // We ignore this exception event when the VM is executing code invoked |
| 895 // by the debugger to evaluate variables values, when we see a nested | 950 // by the debugger to evaluate variables values, when we see a nested |
| 896 // breakpoint or exception event, or if the debugger is not | 951 // breakpoint or exception event, or if the debugger is not |
| 897 // interested in exception events. | 952 // interested in exception events. |
| 898 if (ignore_breakpoints_ || | 953 if (ignore_breakpoints_ || |
| 899 (stack_trace_ != NULL) || | 954 (stack_trace_ != NULL) || |
| 900 (event_handler_ == NULL) || | 955 (event_handler_ == NULL) || |
| 901 (exc_pause_info_ == kNoPauseOnExceptions)) { | 956 (exc_pause_info_ == kNoPauseOnExceptions)) { |
| 902 return; | 957 return; |
| 903 } | 958 } |
| (...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1680 } | 1735 } |
| 1681 | 1736 |
| 1682 | 1737 |
| 1683 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1738 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 1684 ASSERT(bpt->next() == NULL); | 1739 ASSERT(bpt->next() == NULL); |
| 1685 bpt->set_next(code_breakpoints_); | 1740 bpt->set_next(code_breakpoints_); |
| 1686 code_breakpoints_ = bpt; | 1741 code_breakpoints_ = bpt; |
| 1687 } | 1742 } |
| 1688 | 1743 |
| 1689 } // namespace dart | 1744 } // namespace dart |
| OLD | NEW |