Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(576)

Side by Side Diff: runtime/vm/debugger.cc

Issue 2689623002: Delete Breakpoint objects, fixing memory leak (Closed)
Patch Set: wip Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 // Compute column number lazily since it causes scanning of the script. 189 // Compute column number lazily since it causes scanning of the script.
190 if (column_number_ < 0) { 190 if (column_number_ < 0) {
191 const Script& script = Script::Handle(this->script()); 191 const Script& script = Script::Handle(this->script());
192 script.GetTokenLocation(token_pos_, &line_number_, &column_number_); 192 script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
193 } 193 }
194 return column_number_; 194 return column_number_;
195 } 195 }
196 196
197 197
198 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { 198 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
199 ASSERT(bpt_location_->IsLatent()); // Only reason to move. 199 // Only latent breakpoints can be moved.
200 ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
200 bpt_location_ = new_bpt_location; 201 bpt_location_ = new_bpt_location;
201 } 202 }
202 203
203 204
204 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 205 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
205 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); 206 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_));
206 } 207 }
207 208
208 209
209 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) { 210 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 resume_action_(kContinue), 1347 resume_action_(kContinue),
1347 resume_frame_index_(-1), 1348 resume_frame_index_(-1),
1348 post_deopt_frame_index_(-1), 1349 post_deopt_frame_index_(-1),
1349 ignore_breakpoints_(false), 1350 ignore_breakpoints_(false),
1350 pause_event_(NULL), 1351 pause_event_(NULL),
1351 obj_cache_(NULL), 1352 obj_cache_(NULL),
1352 stack_trace_(NULL), 1353 stack_trace_(NULL),
1353 async_causal_stack_trace_(NULL), 1354 async_causal_stack_trace_(NULL),
1354 stepping_fp_(0), 1355 stepping_fp_(0),
1355 skip_next_step_(false), 1356 skip_next_step_(false),
1357 needs_breakpoint_cleanup_(false),
1356 synthetic_async_breakpoint_(NULL), 1358 synthetic_async_breakpoint_(NULL),
1357 exc_pause_info_(kNoPauseOnExceptions) {} 1359 exc_pause_info_(kNoPauseOnExceptions) {}
1358 1360
1359 1361
1360 Debugger::~Debugger() { 1362 Debugger::~Debugger() {
1361 isolate_id_ = ILLEGAL_ISOLATE_ID; 1363 isolate_id_ = ILLEGAL_ISOLATE_ID;
1362 ASSERT(!IsPaused()); 1364 ASSERT(!IsPaused());
1363 ASSERT(latent_locations_ == NULL); 1365 ASSERT(latent_locations_ == NULL);
1364 ASSERT(breakpoint_locations_ == NULL); 1366 ASSERT(breakpoint_locations_ == NULL);
1365 ASSERT(code_breakpoints_ == NULL); 1367 ASSERT(code_breakpoints_ == NULL);
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 error.IsUnhandledException()); 2781 error.IsUnhandledException());
2780 2782
2781 // Only send a resume event when the isolate is not unwinding. 2783 // Only send a resume event when the isolate is not unwinding.
2782 if (!error.IsUnwindError()) { 2784 if (!error.IsUnwindError()) {
2783 ServiceEvent resume_event(event->isolate(), ServiceEvent::kResume); 2785 ServiceEvent resume_event(event->isolate(), ServiceEvent::kResume);
2784 resume_event.set_top_frame(event->top_frame()); 2786 resume_event.set_top_frame(event->top_frame());
2785 Service::HandleEvent(&resume_event); 2787 Service::HandleEvent(&resume_event);
2786 } 2788 }
2787 } 2789 }
2788 2790
2791 if (needs_breakpoint_cleanup_) {
2792 RemoveUnlinkedCodeBreakpoints();
2793 }
2789 pause_event_ = NULL; 2794 pause_event_ = NULL;
2790 obj_cache_ = NULL; // Zone allocated 2795 obj_cache_ = NULL; // Zone allocated
2791 } 2796 }
2792 2797
2793 2798
2794 void Debugger::EnterSingleStepMode() { 2799 void Debugger::EnterSingleStepMode() {
2795 stepping_fp_ = 0; 2800 stepping_fp_ = 0;
2796 DeoptimizeWorld(); 2801 DeoptimizeWorld();
2797 isolate_->set_single_step(true); 2802 isolate_->set_single_step(true);
2798 } 2803 }
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
3269 // We issue a step over to resume at the point after the await statement. 3274 // We issue a step over to resume at the point after the await statement.
3270 SetResumeAction(kStepOver); 3275 SetResumeAction(kStepOver);
3271 // When we single step from a user breakpoint, our next stepping 3276 // When we single step from a user breakpoint, our next stepping
3272 // point will be at the exact same pc. Skip it. 3277 // point will be at the exact same pc. Skip it.
3273 HandleSteppingRequest(stack_trace_, true /* skip next step */); 3278 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3274 ClearCachedStackTraces(); 3279 ClearCachedStackTraces();
3275 return Error::null(); 3280 return Error::null();
3276 } 3281 }
3277 3282
3278 if (FLAG_verbose_debug) { 3283 if (FLAG_verbose_debug) {
3279 OS::Print(">>> hit %s breakpoint at %s:%" Pd 3284 OS::Print(">>> hit breakpoint at %s:%" Pd " (token %s) (address %#" Px
3280 " " 3285 ")\n",
3281 "(token %s) (address %#" Px ")\n",
3282 cbpt->IsInternal() ? "internal" : "user",
3283 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(), 3286 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(),
3284 cbpt->token_pos().ToCString(), top_frame->pc()); 3287 cbpt->token_pos().ToCString(), top_frame->pc());
3285 } 3288 }
3286 3289
3287 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); 3290 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace());
3288 SignalPausedEvent(top_frame, bpt_hit); 3291 SignalPausedEvent(top_frame, bpt_hit);
3289 // When we single step from a user breakpoint, our next stepping 3292 // When we single step from a user breakpoint, our next stepping
3290 // point will be at the exact same pc. Skip it. 3293 // point will be at the exact same pc. Skip it.
3291 HandleSteppingRequest(stack_trace_, true /* skip next step */); 3294 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3292 ClearCachedStackTraces(); 3295 ClearCachedStackTraces();
3293 if (cbpt->IsInternal()) {
3294 RemoveInternalBreakpoints();
3295 }
3296 3296
3297 // If any error occurred while in the debug message loop, return it here. 3297 // If any error occurred while in the debug message loop, return it here.
3298 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 3298 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3299 Thread::Current()->clear_sticky_error(); 3299 Thread::Current()->clear_sticky_error();
3300 return error.raw(); 3300 return error.raw();
3301 } 3301 }
3302 3302
3303 3303
3304 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location, 3304 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location,
3305 ActivationFrame* top_frame) { 3305 ActivationFrame* top_frame) {
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
3662 Breakpoint* prev_bpt = NULL; 3662 Breakpoint* prev_bpt = NULL;
3663 Breakpoint* curr_bpt = curr_loc->breakpoints(); 3663 Breakpoint* curr_bpt = curr_loc->breakpoints();
3664 while (curr_bpt != NULL) { 3664 while (curr_bpt != NULL) {
3665 if (curr_bpt->id() == bp_id) { 3665 if (curr_bpt->id() == bp_id) {
3666 if (prev_bpt == NULL) { 3666 if (prev_bpt == NULL) {
3667 curr_loc->set_breakpoints(curr_bpt->next()); 3667 curr_loc->set_breakpoints(curr_bpt->next());
3668 } else { 3668 } else {
3669 prev_bpt->set_next(curr_bpt->next()); 3669 prev_bpt->set_next(curr_bpt->next());
3670 } 3670 }
3671 3671
3672 // Send event to client before the breakpoint's fields are
3673 // poisoned and deleted.
3672 SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt); 3674 SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
3673 3675
3674 // Remove references from the current debugger pause event. 3676 curr_bpt->set_next(NULL);
3677 curr_bpt->set_bpt_location(NULL);
3678 // Remove possible references to the breakpoint.
3675 if (pause_event_ != NULL && pause_event_->breakpoint() == curr_bpt) { 3679 if (pause_event_ != NULL && pause_event_->breakpoint() == curr_bpt) {
3676 pause_event_->set_breakpoint(NULL); 3680 pause_event_->set_breakpoint(NULL);
3677 } 3681 }
3678 break; 3682 if (synthetic_async_breakpoint_ == curr_bpt) {
3683 synthetic_async_breakpoint_ = NULL;
3684 }
3685 delete curr_bpt;
3686 curr_bpt = NULL;
3687
3688 // Delete the breakpoint location object if there are no more
3689 // breakpoints at that location.
3690 if (curr_loc->breakpoints() == NULL) {
3691 if (prev_loc == NULL) {
3692 breakpoint_locations_ = curr_loc->next();
3693 } else {
3694 prev_loc->set_next(curr_loc->next());
3695 }
3696
3697 // Remove references from code breakpoints to this breakpoint
3698 // location and disable them.
3699 UnlinkCodeBreakpoints(curr_loc);
3700 BreakpointLocation* next_loc = curr_loc->next();
3701 delete curr_loc;
3702 curr_loc = next_loc;
3703 }
3704
3705 // The code breakpoints will be deleted when the VM resumes
3706 // after the pause event.
3707 return;
3679 } 3708 }
3680 3709
3681 prev_bpt = curr_bpt; 3710 prev_bpt = curr_bpt;
3682 curr_bpt = curr_bpt->next(); 3711 curr_bpt = curr_bpt->next();
3683 } 3712 }
3684 3713 prev_loc = curr_loc;
3685 if (curr_loc->breakpoints() == NULL) { 3714 curr_loc = curr_loc->next();
3686 if (prev_loc == NULL) {
3687 breakpoint_locations_ = curr_loc->next();
3688 } else {
3689 prev_loc->set_next(curr_loc->next());
3690 }
3691
3692 // Remove references from code breakpoints to this source breakpoint,
3693 // and disable the code breakpoints.
3694 UnlinkCodeBreakpoints(curr_loc);
3695 BreakpointLocation* next_loc = curr_loc->next();
3696 delete curr_loc;
3697 curr_loc = next_loc;
3698 } else {
3699 prev_loc = curr_loc;
3700 curr_loc = curr_loc->next();
3701 }
3702 } 3715 }
3703 // bpt is not a registered breakpoint, nothing to do. 3716 // breakpoint with bp_id does not exist, nothing to do.
3704 } 3717 }
3705 3718
3706 3719
3707 // Turn code breakpoints associated with the given source breakpoint into 3720 // Unlink code breakpoints from the the given breakpoint location.
3708 // internal breakpoints. They will later be deleted when control 3721 // They will later be deleted when control returns from the pause event
3709 // returns from the user-defined breakpoint callback. Also, disable the 3722 // callback. Also, disable the breakpoint so it no longer fires if it
3710 // breakpoint so it no longer fires if it should be hit before it gets 3723 // should be hit before it gets deleted.
3711 // deleted.
3712 void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) { 3724 void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) {
3713 ASSERT(bpt_location != NULL); 3725 ASSERT(bpt_location != NULL);
3714 CodeBreakpoint* curr_bpt = code_breakpoints_; 3726 CodeBreakpoint* curr_bpt = code_breakpoints_;
3715 while (curr_bpt != NULL) { 3727 while (curr_bpt != NULL) {
3716 if (curr_bpt->bpt_location() == bpt_location) { 3728 if (curr_bpt->bpt_location() == bpt_location) {
3717 curr_bpt->Disable(); 3729 curr_bpt->Disable();
3718 curr_bpt->set_bpt_location(NULL); 3730 curr_bpt->set_bpt_location(NULL);
3731 needs_breakpoint_cleanup_ = true;
3719 } 3732 }
3720 curr_bpt = curr_bpt->next(); 3733 curr_bpt = curr_bpt->next();
3721 } 3734 }
3722 } 3735 }
3723 3736
3724 3737
3725 // Remove and delete internal breakpoints, i.e. breakpoints that 3738 // Remove and delete unlinked code breakpoints, i.e. breakpoints that
3726 // are not associated with a source breakpoint. 3739 // are not associated with a breakpoint location.
3727 void Debugger::RemoveInternalBreakpoints() { 3740 void Debugger::RemoveUnlinkedCodeBreakpoints() {
3728 CodeBreakpoint* prev_bpt = NULL; 3741 CodeBreakpoint* prev_bpt = NULL;
3729 CodeBreakpoint* curr_bpt = code_breakpoints_; 3742 CodeBreakpoint* curr_bpt = code_breakpoints_;
3730 while (curr_bpt != NULL) { 3743 while (curr_bpt != NULL) {
3731 if (curr_bpt->bpt_location() == NULL) { 3744 if (curr_bpt->bpt_location() == NULL) {
3732 if (prev_bpt == NULL) { 3745 if (prev_bpt == NULL) {
3733 code_breakpoints_ = code_breakpoints_->next(); 3746 code_breakpoints_ = code_breakpoints_->next();
3734 } else { 3747 } else {
3735 prev_bpt->set_next(curr_bpt->next()); 3748 prev_bpt->set_next(curr_bpt->next());
3736 } 3749 }
3737 CodeBreakpoint* temp_bpt = curr_bpt; 3750 CodeBreakpoint* temp_bpt = curr_bpt;
3738 curr_bpt = curr_bpt->next(); 3751 curr_bpt = curr_bpt->next();
3739 temp_bpt->Disable(); 3752 temp_bpt->Disable();
3740 delete temp_bpt; 3753 delete temp_bpt;
3741 } else { 3754 } else {
3742 prev_bpt = curr_bpt; 3755 prev_bpt = curr_bpt;
3743 curr_bpt = curr_bpt->next(); 3756 curr_bpt = curr_bpt->next();
3744 } 3757 }
3745 } 3758 }
3759 needs_breakpoint_cleanup_ = false;
3746 } 3760 }
3747 3761
3748 3762
3749 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, 3763 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
3750 TokenPosition token_pos, 3764 TokenPosition token_pos,
3751 intptr_t requested_column) { 3765 intptr_t requested_column) {
3752 BreakpointLocation* bpt = breakpoint_locations_; 3766 BreakpointLocation* bpt = breakpoint_locations_;
3753 while (bpt != NULL) { 3767 while (bpt != NULL) {
3754 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos) && 3768 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos) &&
3755 (bpt->requested_column_number_ == requested_column)) { 3769 (bpt->requested_column_number_ == requested_column)) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3807 3821
3808 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3822 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3809 ASSERT(bpt->next() == NULL); 3823 ASSERT(bpt->next() == NULL);
3810 bpt->set_next(code_breakpoints_); 3824 bpt->set_next(code_breakpoints_);
3811 code_breakpoints_ = bpt; 3825 code_breakpoints_ = bpt;
3812 } 3826 }
3813 3827
3814 #endif // !PRODUCT 3828 #endif // !PRODUCT
3815 3829
3816 } // namespace dart 3830 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698