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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 len++; // String terminator. | 209 len++; // String terminator. |
| 210 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 210 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 211 OS::SNPrint(chars, len, kFormat, | 211 OS::SNPrint(chars, len, kFormat, |
| 212 func_class.IsTopLevel() ? "" : class_name.ToCString(), | 212 func_class.IsTopLevel() ? "" : class_name.ToCString(), |
| 213 func_class.IsTopLevel() ? "" : ".", | 213 func_class.IsTopLevel() ? "" : ".", |
| 214 func_name.ToCString()); | 214 func_name.ToCString()); |
| 215 return chars; | 215 return chars; |
| 216 } | 216 } |
| 217 | 217 |
| 218 | 218 |
| 219 bool Debugger::HasBreakpoint(const Function& func) { | |
| 220 if (!func.HasCode()) { | |
| 221 // If the function is not compiled yet, just check whether there | |
| 222 // is a user-defined latent breakpoint. | |
| 223 SourceBreakpoint* sbpt = src_breakpoints_; | |
| 224 while (sbpt != NULL) { | |
| 225 if (func.raw() == sbpt->function()) { | |
| 226 return true; | |
| 227 } | |
| 228 sbpt = sbpt->next_; | |
| 229 } | |
| 230 return false; | |
| 231 } | |
| 232 CodeBreakpoint* cbpt = code_breakpoints_; | |
| 233 while (cbpt != NULL) { | |
| 234 if (func.raw() == cbpt->function()) { | |
| 235 return true; | |
| 236 } | |
| 237 cbpt = cbpt->next_; | |
| 238 } | |
| 239 return false; | |
| 240 } | |
| 241 | |
| 242 | |
| 219 RawString* ActivationFrame::QualifiedFunctionName() { | 243 RawString* ActivationFrame::QualifiedFunctionName() { |
| 220 const Function& func = DartFunction(); | 244 const Function& func = DartFunction(); |
| 221 return String::New(Debugger::QualifiedFunctionName(func)); | 245 return String::New(Debugger::QualifiedFunctionName(func)); |
| 222 } | 246 } |
| 223 | 247 |
| 224 | 248 |
| 225 RawString* ActivationFrame::SourceUrl() { | 249 RawString* ActivationFrame::SourceUrl() { |
| 226 const Script& script = Script::Handle(SourceScript()); | 250 const Script& script = Script::Handle(SourceScript()); |
| 227 return script.url(); | 251 return script.url(); |
| 228 } | 252 } |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 696 CodeBreakpoint* bpt = code_breakpoints_; | 720 CodeBreakpoint* bpt = code_breakpoints_; |
| 697 code_breakpoints_ = code_breakpoints_->next(); | 721 code_breakpoints_ = code_breakpoints_->next(); |
| 698 bpt->Disable(); | 722 bpt->Disable(); |
| 699 delete bpt; | 723 delete bpt; |
| 700 } | 724 } |
| 701 // Signal isolate shutdown event. | 725 // Signal isolate shutdown event. |
| 702 SignalIsolateEvent(Debugger::kIsolateShutdown); | 726 SignalIsolateEvent(Debugger::kIsolateShutdown); |
| 703 } | 727 } |
| 704 | 728 |
| 705 | 729 |
| 706 bool Debugger::IsActive() { | |
| 707 // TODO(hausner): The code generator uses this function to prevent | |
| 708 // generation of optimized code when Dart code is being debugged. | |
| 709 // This is probably not conservative enough (we could set the first | |
| 710 // breakpoint after optimized code has already been produced). | |
| 711 // Long-term, we need to be able to de-optimize code. | |
| 712 return (src_breakpoints_ != NULL) || | |
| 713 (code_breakpoints_ != NULL) || | |
| 714 (exc_pause_info_ != kNoPauseOnExceptions); | |
| 715 } | |
| 716 | |
| 717 | |
| 718 static RawFunction* ResolveLibraryFunction( | 730 static RawFunction* ResolveLibraryFunction( |
| 719 const Library& library, | 731 const Library& library, |
| 720 const String& fname) { | 732 const String& fname) { |
| 721 ASSERT(!library.IsNull()); | 733 ASSERT(!library.IsNull()); |
| 722 const Object& object = Object::Handle(library.LookupObject(fname)); | 734 const Object& object = Object::Handle(library.LookupObject(fname)); |
| 723 if (!object.IsNull() && object.IsFunction()) { | 735 if (!object.IsNull() && object.IsFunction()) { |
| 724 return Function::Cast(object).raw(); | 736 return Function::Cast(object).raw(); |
| 725 } | 737 } |
| 726 return Function::null(); | 738 return Function::null(); |
| 727 } | 739 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 741 if (!cls.IsNull()) { | 753 if (!cls.IsNull()) { |
| 742 function = cls.LookupStaticFunction(function_name); | 754 function = cls.LookupStaticFunction(function_name); |
| 743 if (function.IsNull()) { | 755 if (function.IsNull()) { |
| 744 function = cls.LookupDynamicFunction(function_name); | 756 function = cls.LookupDynamicFunction(function_name); |
| 745 } | 757 } |
| 746 } | 758 } |
| 747 return function.raw(); | 759 return function.raw(); |
| 748 } | 760 } |
| 749 | 761 |
| 750 | 762 |
| 751 // Deoptimize function if necessary. Does not patch return addresses on the | 763 // Deoptimize all functions in the isolate. |
| 752 // stack. If there are activation frames of this function on the stack, | 764 void Debugger::DeoptimizeWorld() { |
| 753 // the optimized code will be executed when the callee returns. | 765 // Deoptimize all functions on in stack activation frames. |
|
srdjan
2013/01/08 18:03:57
Fix comment.
hausner
2013/01/08 18:37:57
Done.
| |
| 754 void Debugger::EnsureFunctionIsDeoptimized(const Function& func) { | 766 DeoptimizeAll(); |
|
srdjan
2013/01/08 18:03:57
Add a TODO to deoptimize only functions that have
hausner
2013/01/08 18:37:57
Done.
| |
| 755 if (func.HasOptimizedCode()) { | 767 // Iterate over all classes, deoptimize functions. |
| 756 if (FLAG_verbose_debug) { | 768 const ClassTable& class_table = *isolate_->class_table(); |
|
srdjan
2013/01/08 18:03:57
Add a TODO to factor it out with RemoveOptimizedC
hausner
2013/01/08 18:37:57
Done.
| |
| 757 OS::Print("Deoptimizing function %s\n", | 769 Class& cls = Class::Handle(); |
| 758 String::Handle(func.name()).ToCString()); | 770 Array& functions = Array::Handle(); |
| 771 Function& function = Function::Handle(); | |
| 772 intptr_t num_classes = class_table.NumCids(); | |
| 773 for (intptr_t i = 1; i < num_classes; i++) { | |
| 774 if (class_table.HasValidClassAt(i)) { | |
| 775 cls = class_table.At(i); | |
| 776 functions = cls.functions(); | |
| 777 intptr_t num_functions = functions.IsNull() ? 0 : functions.Length(); | |
| 778 for (intptr_t f = 0; f < num_functions; f++) { | |
| 779 function ^= functions.At(f); | |
| 780 ASSERT(!function.IsNull()); | |
| 781 if (function.HasOptimizedCode()) { | |
| 782 function.SwitchToUnoptimizedCode(); | |
| 783 } | |
| 784 } | |
| 759 } | 785 } |
| 760 func.set_usage_counter(0); | |
| 761 func.set_deoptimization_counter(func.deoptimization_counter() + 1); | |
| 762 Compiler::CompileFunction(func); | |
| 763 ASSERT(!func.HasOptimizedCode()); | |
| 764 } | 786 } |
| 765 } | 787 } |
| 766 | 788 |
| 767 | 789 |
| 768 void Debugger::InstrumentForStepping(const Function& target_function) { | 790 void Debugger::InstrumentForStepping(const Function& target_function) { |
| 769 if (target_function.HasCode()) { | 791 if (!target_function.HasCode()) { |
| 770 EnsureFunctionIsDeoptimized(target_function); | |
| 771 } else { | |
| 772 Compiler::CompileFunction(target_function); | 792 Compiler::CompileFunction(target_function); |
| 773 // If there were any errors, ignore them silently and return without | 793 // If there were any errors, ignore them silently and return without |
| 774 // adding breakpoints to target. | 794 // adding breakpoints to target. |
| 775 if (!target_function.HasCode()) { | 795 if (!target_function.HasCode()) { |
| 776 return; | 796 return; |
| 777 } | 797 } |
| 778 } | 798 } |
| 799 DeoptimizeWorld(); | |
| 800 ASSERT(!target_function.HasOptimizedCode()); | |
| 779 Code& code = Code::Handle(target_function.unoptimized_code()); | 801 Code& code = Code::Handle(target_function.unoptimized_code()); |
| 780 ASSERT(!code.IsNull()); | 802 ASSERT(!code.IsNull()); |
| 781 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 803 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 782 for (int i = 0; i < desc.Length(); i++) { | 804 for (int i = 0; i < desc.Length(); i++) { |
| 783 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); | 805 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); |
| 784 if (bpt != NULL) { | 806 if (bpt != NULL) { |
| 785 // There is already a breakpoint for this address. Make sure | 807 // There is already a breakpoint for this address. Make sure |
| 786 // it is enabled. | 808 // it is enabled. |
| 787 bpt->Enable(); | 809 bpt->Enable(); |
| 788 continue; | 810 continue; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 965 | 987 |
| 966 | 988 |
| 967 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function, | 989 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function, |
| 968 intptr_t first_token_pos, | 990 intptr_t first_token_pos, |
| 969 intptr_t last_token_pos) { | 991 intptr_t last_token_pos) { |
| 970 if ((last_token_pos < target_function.token_pos()) || | 992 if ((last_token_pos < target_function.token_pos()) || |
| 971 (target_function.end_token_pos() < first_token_pos)) { | 993 (target_function.end_token_pos() < first_token_pos)) { |
| 972 // The given token position is not within the target function. | 994 // The given token position is not within the target function. |
| 973 return NULL; | 995 return NULL; |
| 974 } | 996 } |
| 975 EnsureFunctionIsDeoptimized(target_function); | 997 DeoptimizeWorld(); |
| 998 ASSERT(!target_function.HasOptimizedCode()); | |
| 976 | 999 |
| 977 CodeBreakpoint* cbpt = NULL; | 1000 CodeBreakpoint* cbpt = NULL; |
| 978 SourceBreakpoint* source_bpt = NULL; | 1001 SourceBreakpoint* source_bpt = NULL; |
| 979 if (target_function.HasCode()) { | 1002 if (target_function.HasCode()) { |
| 980 cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos); | 1003 cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos); |
| 981 if (cbpt != NULL) { | 1004 if (cbpt != NULL) { |
| 982 if (cbpt->src_bpt() != NULL) { | 1005 if (cbpt->src_bpt() != NULL) { |
| 983 // There is already a source breakpoint for the location. | 1006 // There is already a source breakpoint for the location. |
| 984 ASSERT(cbpt->src_bpt() == | 1007 ASSERT(cbpt->src_bpt() == |
| 985 GetSourceBreakpoint(target_function, cbpt->token_pos())); | 1008 GetSourceBreakpoint(target_function, cbpt->token_pos())); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1020 } | 1043 } |
| 1021 } | 1044 } |
| 1022 | 1045 |
| 1023 if (target_function.HasImplicitClosureFunction()) { | 1046 if (target_function.HasImplicitClosureFunction()) { |
| 1024 // There is a closurized version of this function. If the closure | 1047 // There is a closurized version of this function. If the closure |
| 1025 // is already compiled, we need to set a code breakpoint in its | 1048 // is already compiled, we need to set a code breakpoint in its |
| 1026 // code. | 1049 // code. |
| 1027 const Function& closure = | 1050 const Function& closure = |
| 1028 Function::Handle(target_function.ImplicitClosureFunction()); | 1051 Function::Handle(target_function.ImplicitClosureFunction()); |
| 1029 if (closure.HasCode()) { | 1052 if (closure.HasCode()) { |
| 1030 EnsureFunctionIsDeoptimized(closure); | 1053 ASSERT(!closure.HasOptimizedCode()); |
| 1031 CodeBreakpoint* closure_bpt = | 1054 CodeBreakpoint* closure_bpt = |
| 1032 MakeCodeBreakpoint(closure, first_token_pos, last_token_pos); | 1055 MakeCodeBreakpoint(closure, first_token_pos, last_token_pos); |
| 1033 if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) { | 1056 if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) { |
| 1034 closure_bpt->set_src_bpt(source_bpt); | 1057 closure_bpt->set_src_bpt(source_bpt); |
| 1035 } | 1058 } |
| 1036 } | 1059 } |
| 1037 } | 1060 } |
| 1038 source_bpt->Enable(); | 1061 source_bpt->Enable(); |
| 1039 return source_bpt; | 1062 return source_bpt; |
| 1040 } | 1063 } |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1653 } | 1676 } |
| 1654 | 1677 |
| 1655 | 1678 |
| 1656 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1679 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 1657 ASSERT(bpt->next() == NULL); | 1680 ASSERT(bpt->next() == NULL); |
| 1658 bpt->set_next(code_breakpoints_); | 1681 bpt->set_next(code_breakpoints_); |
| 1659 code_breakpoints_ = bpt; | 1682 code_breakpoints_ = bpt; |
| 1660 } | 1683 } |
| 1661 | 1684 |
| 1662 } // namespace dart | 1685 } // namespace dart |
| OLD | NEW |