| 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 2631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2642 *best_fit = func->raw(); | 2642 *best_fit = func->raw(); |
| 2643 } else { | 2643 } else { |
| 2644 if ((func->token_pos() > best_fit->token_pos()) && | 2644 if ((func->token_pos() > best_fit->token_pos()) && |
| 2645 ((func->end_token_pos() <= best_fit->end_token_pos()))) { | 2645 ((func->end_token_pos() <= best_fit->end_token_pos()))) { |
| 2646 *best_fit = func->raw(); | 2646 *best_fit = func->raw(); |
| 2647 } | 2647 } |
| 2648 } | 2648 } |
| 2649 } | 2649 } |
| 2650 | 2650 |
| 2651 | 2651 |
| 2652 static bool IsTokenPosWithinFunction(const Function& func, TokenPosition pos) { |
| 2653 return (func.token_pos() <= pos && pos <= func.end_token_pos()); |
| 2654 } |
| 2655 |
| 2656 |
| 2652 RawFunction* Debugger::FindBestFit(const Script& script, | 2657 RawFunction* Debugger::FindBestFit(const Script& script, |
| 2653 TokenPosition token_pos) { | 2658 TokenPosition token_pos) { |
| 2654 Zone* zone = Thread::Current()->zone(); | 2659 Zone* zone = Thread::Current()->zone(); |
| 2655 Class& cls = Class::Handle(zone); | 2660 Class& cls = Class::Handle(zone); |
| 2656 Array& functions = Array::Handle(zone); | 2661 Array& functions = Array::Handle(zone); |
| 2657 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 2662 const GrowableObjectArray& closures = GrowableObjectArray::Handle( |
| 2663 zone, isolate_->object_store()->closure_functions()); |
| 2658 Function& function = Function::Handle(zone); | 2664 Function& function = Function::Handle(zone); |
| 2659 Function& best_fit = Function::Handle(zone); | 2665 Function& best_fit = Function::Handle(zone); |
| 2660 Error& error = Error::Handle(zone); | 2666 Error& error = Error::Handle(zone); |
| 2661 | 2667 |
| 2662 closures = isolate_->object_store()->closure_functions(); | |
| 2663 const intptr_t num_closures = closures.Length(); | 2668 const intptr_t num_closures = closures.Length(); |
| 2664 for (intptr_t i = 0; i < num_closures; i++) { | 2669 for (intptr_t i = 0; i < num_closures; i++) { |
| 2665 function ^= closures.At(i); | 2670 function ^= closures.At(i); |
| 2666 if (FunctionContains(function, script, token_pos)) { | 2671 if (function.script() != script.raw()) { |
| 2672 continue; |
| 2673 } |
| 2674 if (IsTokenPosWithinFunction(function, token_pos)) { |
| 2675 // Select the inner most closure. |
| 2667 SelectBestFit(&best_fit, &function); | 2676 SelectBestFit(&best_fit, &function); |
| 2668 } | 2677 } |
| 2669 } | 2678 } |
| 2679 if (!best_fit.IsNull()) { |
| 2680 // The inner most closure found will be the best fit. Going |
| 2681 // over class functions below will not help in any further |
| 2682 // narrowing. |
| 2683 return best_fit.raw(); |
| 2684 } |
| 2670 | 2685 |
| 2671 const ClassTable& class_table = *isolate_->class_table(); | 2686 const ClassTable& class_table = *isolate_->class_table(); |
| 2672 const intptr_t num_classes = class_table.NumCids(); | 2687 const intptr_t num_classes = class_table.NumCids(); |
| 2673 for (intptr_t i = 1; i < num_classes; i++) { | 2688 for (intptr_t i = 1; i < num_classes; i++) { |
| 2674 if (class_table.HasValidClassAt(i)) { | 2689 if (class_table.HasValidClassAt(i)) { |
| 2675 cls = class_table.At(i); | 2690 cls = class_table.At(i); |
| 2676 // Note: if this class has been parsed and finalized already, | 2691 if (cls.script() != script.raw()) { |
| 2677 // we need to check the functions of this class even if | |
| 2678 // it is defined in a different 'script'. There could | |
| 2679 // be mixin functions from the given script in this class. | |
| 2680 // However, if this class is not parsed yet (not finalized), | |
| 2681 // we can ignore it and avoid the side effect of parsing it. | |
| 2682 if ((cls.script() != script.raw()) && !cls.is_finalized()) { | |
| 2683 continue; | 2692 continue; |
| 2684 } | 2693 } |
| 2685 // Parse class definition if not done yet. | 2694 // Parse class definition if not done yet. |
| 2686 error = cls.EnsureIsFinalized(Thread::Current()); | 2695 error = cls.EnsureIsFinalized(Thread::Current()); |
| 2687 if (!error.IsNull()) { | 2696 if (!error.IsNull()) { |
| 2688 // Ignore functions in this class. | 2697 // Ignore functions in this class. |
| 2689 // TODO(hausner): Should we propagate this error? How? | 2698 // TODO(hausner): Should we propagate this error? How? |
| 2690 // EnsureIsFinalized only returns an error object if there | 2699 // EnsureIsFinalized only returns an error object if there |
| 2691 // is no longjump base on the stack. | 2700 // is no longjump base on the stack. |
| 2692 continue; | 2701 continue; |
| 2693 } | 2702 } |
| 2694 functions = cls.functions(); | 2703 functions = cls.functions(); |
| 2695 if (!functions.IsNull()) { | 2704 if (!functions.IsNull()) { |
| 2696 const intptr_t num_functions = functions.Length(); | 2705 const intptr_t num_functions = functions.Length(); |
| 2697 for (intptr_t pos = 0; pos < num_functions; pos++) { | 2706 for (intptr_t pos = 0; pos < num_functions; pos++) { |
| 2698 function ^= functions.At(pos); | 2707 function ^= functions.At(pos); |
| 2699 ASSERT(!function.IsNull()); | 2708 ASSERT(!function.IsNull()); |
| 2700 if (FunctionContains(function, script, token_pos)) { | 2709 if (IsTokenPosWithinFunction(function, token_pos)) { |
| 2701 SelectBestFit(&best_fit, &function); | 2710 // Closures and inner functions within a class method are not |
| 2711 // present in the functions of a class. Hence, we can return |
| 2712 // right away as looking through other functions of a class |
| 2713 // will not narrow down to any inner function/closure. |
| 2714 return function.raw(); |
| 2702 } | 2715 } |
| 2703 } | 2716 } |
| 2704 } | 2717 } |
| 2705 } | 2718 } |
| 2706 } | 2719 } |
| 2707 return best_fit.raw(); | 2720 return Function::null(); |
| 2708 } | 2721 } |
| 2709 | 2722 |
| 2710 | 2723 |
| 2711 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, | 2724 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, |
| 2712 TokenPosition token_pos, | 2725 TokenPosition token_pos, |
| 2713 TokenPosition last_token_pos, | 2726 TokenPosition last_token_pos, |
| 2714 intptr_t requested_line, | 2727 intptr_t requested_line, |
| 2715 intptr_t requested_column) { | 2728 intptr_t requested_column) { |
| 2716 Function& func = Function::Handle(); | 2729 Function& func = Function::Handle(); |
| 2717 func = FindBestFit(script, token_pos); | 2730 func = FindBestFit(script, token_pos); |
| (...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4428 | 4441 |
| 4429 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 4442 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 4430 ASSERT(bpt->next() == NULL); | 4443 ASSERT(bpt->next() == NULL); |
| 4431 bpt->set_next(code_breakpoints_); | 4444 bpt->set_next(code_breakpoints_); |
| 4432 code_breakpoints_ = bpt; | 4445 code_breakpoints_ = bpt; |
| 4433 } | 4446 } |
| 4434 | 4447 |
| 4435 #endif // !PRODUCT | 4448 #endif // !PRODUCT |
| 4436 | 4449 |
| 4437 } // namespace dart | 4450 } // namespace dart |
| OLD | NEW |