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

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

Issue 9271008: Implement deletion of breakpoints (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 "vm/code_index_table.h" 7 #include "vm/code_index_table.h"
8 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
11 #include "vm/globals.h" 11 #include "vm/globals.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/os.h" 14 #include "vm/os.h"
15 #include "vm/stack_frame.h" 15 #include "vm/stack_frame.h"
16 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
17 #include "vm/visitor.h" 17 #include "vm/visitor.h"
18 18
19 19
20 namespace dart { 20 namespace dart {
21 21
22 static const bool verbose = false; 22 static const bool verbose = false;
23 23
24 Breakpoint::Breakpoint(const Function& func, intptr_t pc_desc_index) 24 Breakpoint::Breakpoint(const Function& func, intptr_t pc_desc_index)
25 : function_(func.raw()), 25 : function_(func.raw()),
26 pc_desc_index_(pc_desc_index), 26 pc_desc_index_(pc_desc_index),
27 pc_(0), 27 pc_(0),
28 saved_bytes_(0),
28 line_number_(-1), 29 line_number_(-1),
29 next_(NULL) { 30 next_(NULL) {
30 Code& code = Code::Handle(func.code()); 31 Code& code = Code::Handle(func.code());
31 ASSERT(!code.IsNull()); // Function must be compiled. 32 ASSERT(!code.IsNull()); // Function must be compiled.
32 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 33 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
33 ASSERT(pc_desc_index < desc.Length()); 34 ASSERT(pc_desc_index < desc.Length());
34 this->token_index_ = desc.TokenIndex(pc_desc_index); 35 this->token_index_ = desc.TokenIndex(pc_desc_index);
35 ASSERT(this->token_index_ > 0); 36 ASSERT(this->token_index_ > 0);
36 this->pc_ = desc.PC(pc_desc_index); 37 this->pc_ = desc.PC(pc_desc_index);
37 ASSERT(this->pc_ != 0); 38 ASSERT(this->pc_ != 0);
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 224 }
224 225
225 226
226 Debugger::Debugger() 227 Debugger::Debugger()
227 : initialized_(false), 228 : initialized_(false),
228 bp_handler_(NULL), 229 bp_handler_(NULL),
229 breakpoints_(NULL) { 230 breakpoints_(NULL) {
230 } 231 }
231 232
232 233
234 Debugger::~Debugger() {
235 ASSERT(breakpoints_ == NULL);
236 }
237
238
239 void Debugger::Shutdown() {
240 while (breakpoints_ != NULL) {
241 Breakpoint* bpt = breakpoints_;
242 breakpoints_ = breakpoints_->next();
243 UnsetBreakpoint(bpt);
244 delete bpt;
245 }
246 }
247
248
233 bool Debugger::IsActive() { 249 bool Debugger::IsActive() {
234 // TODO(hausner): The code generator uses this function to prevent 250 // TODO(hausner): The code generator uses this function to prevent
235 // generation of optimized code when Dart code is being debugged. 251 // generation of optimized code when Dart code is being debugged.
236 // This is probably not conservative enough (we could set the first 252 // This is probably not conservative enough (we could set the first
237 // breakpoint after optimized code has already been produced). 253 // breakpoint after optimized code has already been produced).
238 // Long-term, we need to be able to de-optimize code. 254 // Long-term, we need to be able to de-optimize code.
239 return breakpoints_ != NULL; 255 return breakpoints_ != NULL;
240 } 256 }
241 257
242 258
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 Code& code = Code::Handle(target_function.code()); 306 Code& code = Code::Handle(target_function.code());
291 ASSERT(!code.IsNull()); 307 ASSERT(!code.IsNull());
292 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 308 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
293 for (int i = 0; i < desc.Length(); i++) { 309 for (int i = 0; i < desc.Length(); i++) {
294 if (desc.TokenIndex(i) < token_index) { 310 if (desc.TokenIndex(i) < token_index) {
295 continue; 311 continue;
296 } 312 }
297 PcDescriptors::Kind kind = desc.DescriptorKind(i); 313 PcDescriptors::Kind kind = desc.DescriptorKind(i);
298 Breakpoint* bpt = NULL; 314 Breakpoint* bpt = NULL;
299 if (kind == PcDescriptors::kIcCall) { 315 if (kind == PcDescriptors::kIcCall) {
316 bpt = GetBreakpoint(desc.PC(i));
317 if (bpt != NULL) {
318 // There is an existing breakpoint at this token position.
319 break;
320 }
321 bpt = new Breakpoint(target_function, i);
322 RegisterBreakpoint(bpt);
siva 2012/01/20 21:26:29 Should the register happen after the code patching
hausner 2012/01/20 22:20:32 Done.
323 String& func_name = String::Handle();
324 int num_args, num_named_args;
325 CodePatcher::GetInstanceCallAt(desc.PC(i),
326 &func_name, &num_args, &num_named_args, &bpt->saved_bytes_);
300 CodePatcher::PatchInstanceCallAt( 327 CodePatcher::PatchInstanceCallAt(
301 desc.PC(i), StubCode::BreakpointDynamicEntryPoint()); 328 desc.PC(i), StubCode::BreakpointDynamicEntryPoint());
302 bpt = new Breakpoint(target_function, i);
303 } else if (kind == PcDescriptors::kOther) { 329 } else if (kind == PcDescriptors::kOther) {
304 if ((desc.TokenIndex(i) > 0) && CodePatcher::IsDartCall(desc.PC(i))) { 330 if ((desc.TokenIndex(i) > 0) && CodePatcher::IsDartCall(desc.PC(i))) {
331 bpt = GetBreakpoint(desc.PC(i));
332 if (bpt != NULL) {
333 // There is an existing breakpoint at this token position.
334 break;
335 }
336 bpt = new Breakpoint(target_function, i);
337 RegisterBreakpoint(bpt);
338 Function& func = Function::Handle();
339 CodePatcher::GetStaticCallAt(desc.PC(i), &func, &bpt->saved_bytes_);
305 CodePatcher::PatchStaticCallAt( 340 CodePatcher::PatchStaticCallAt(
306 desc.PC(i), StubCode::BreakpointStaticEntryPoint()); 341 desc.PC(i), StubCode::BreakpointStaticEntryPoint());
307 bpt = new Breakpoint(target_function, i);
308 } 342 }
309 } 343 }
310 if (bpt != NULL) { 344 if (bpt != NULL) {
311 if (verbose) { 345 if (verbose) {
312 OS::Print("Setting breakpoint at '%s' line %d (PC %p)\n", 346 OS::Print("Setting breakpoint at '%s' line %d (PC %p)\n",
313 String::Handle(bpt->SourceUrl()).ToCString(), 347 String::Handle(bpt->SourceUrl()).ToCString(),
314 bpt->LineNumber(), 348 bpt->LineNumber(),
315 bpt->pc()); 349 bpt->pc());
siva 2012/01/20 21:26:29 Both newly set breakpoints and existing breakpoint
hausner 2012/01/20 22:20:32 Added a todo to determine later. The idea sounds r
316 } 350 }
317 AddBreakpoint(bpt);
318 return bpt; 351 return bpt;
319 } 352 }
320 } 353 }
321 return NULL; 354 return NULL;
322 } 355 }
323 356
324 357
358 void Debugger::UnsetBreakpoint(Breakpoint* bpt) {
359 const Function& func = Function::Handle(bpt->function());
360 const Code& code = Code::Handle(func.code());
361 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
362 intptr_t desc_index = bpt->pc_desc_index();
363 ASSERT(desc_index < desc.Length());
364 ASSERT(bpt->pc() == desc.PC(desc_index));
365 PcDescriptors::Kind kind = desc.DescriptorKind(desc_index);
366 if (kind == PcDescriptors::kIcCall) {
367 CodePatcher::PatchInstanceCallAt(desc.PC(desc_index), bpt->saved_bytes_);
368 } else {
369 CodePatcher::PatchStaticCallAt(desc.PC(desc_index), bpt->saved_bytes_);
370 }
371 }
372
373
325 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function) { 374 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function) {
326 ASSERT(!target_function.IsNull()); 375 ASSERT(!target_function.IsNull());
327 return SetBreakpoint(target_function, target_function.token_index()); 376 return SetBreakpoint(target_function, target_function.token_index());
328 } 377 }
329 378
330 379
331 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 380 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
332 intptr_t line_number) { 381 intptr_t line_number) {
333 Library& lib = Library::Handle(); 382 Library& lib = Library::Handle();
334 Script& script = Script::Handle(); 383 Script& script = Script::Handle();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 while (bpt != NULL) { 487 while (bpt != NULL) {
439 if (bpt->pc() == breakpoint_address) { 488 if (bpt->pc() == breakpoint_address) {
440 return bpt; 489 return bpt;
441 } 490 }
442 bpt = bpt->next(); 491 bpt = bpt->next();
443 } 492 }
444 return NULL; 493 return NULL;
445 } 494 }
446 495
447 496
448 void Debugger::AddBreakpoint(Breakpoint* bpt) { 497 bool Debugger::IsRegisteredBreakpoint(Breakpoint* bpt) {
siva 2012/01/20 21:26:29 Where is this function used?
hausner 2012/01/20 22:20:32 Not used at the moment. At first I wanted to make
498 Breakpoint* known_bpt = this->breakpoints_;
499 while (known_bpt != NULL) {
500 if (bpt == known_bpt) {
501 return true;
502 }
503 known_bpt = known_bpt->next();
504 }
505 return false;
506 }
507
508
509 void Debugger::RemoveBreakpoint(Breakpoint* bpt) {
510 ASSERT(breakpoints_ != NULL);
511 if (breakpoints_ == NULL) {
512 return;
513 }
siva 2012/01/20 21:26:29 There is an assertion that breakpoints_ is not NUL
hausner 2012/01/20 22:20:32 Similar to the above comment: Most likely it is an
514 if (bpt == breakpoints_) {
515 breakpoints_ = breakpoints_->next();
516 UnsetBreakpoint(bpt);
517 delete bpt;
518 return;
519 }
520 // There is at least one breakpoint in the list, and the one we're
521 // looking for is not at the head of the list.
522 Breakpoint* prev_bpt = this->breakpoints_;
523 Breakpoint* curr_bpt = prev_bpt->next();
524 while (curr_bpt != NULL) {
525 if (bpt == curr_bpt) {
526 // Unlink curr_bpt from list and delete the breakpoint.
siva 2012/01/20 21:26:29 Can we roll the two delete points you have into th
hausner 2012/01/20 22:20:32 Ok, done. I thought the code would be easier to un
527 prev_bpt->set_next(curr_bpt->next());
528 UnsetBreakpoint(bpt);
529 delete bpt;
530 return;
531 }
532 prev_bpt = curr_bpt;
533 curr_bpt = curr_bpt->next();
534 }
535 // bpt is not a registered breakpoint, nothing to do.
536 }
537
538
539 Breakpoint* Debugger::GetBreakpointByFunction(const Function& func,
540 intptr_t token_index) {
541 Breakpoint* bpt = this->breakpoints_;
542 while (bpt != NULL) {
543 if ((bpt->function() == func.raw()) &&
544 (bpt->token_index() == token_index)) {
545 return bpt;
546 }
547 bpt = bpt->next();
548 }
549 return NULL;
550 }
551
552
553 void Debugger::RegisterBreakpoint(Breakpoint* bpt) {
449 ASSERT(bpt->next() == NULL); 554 ASSERT(bpt->next() == NULL);
450 bpt->set_next(this->breakpoints_); 555 bpt->set_next(this->breakpoints_);
451 this->breakpoints_ = bpt; 556 this->breakpoints_ = bpt;
452 } 557 }
453 558
454 559
455 } // namespace dart 560 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698