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

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

Issue 9572022: Support breakpoints in closures (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | 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) 2011, 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 "vm/code_index_table.h" 7 #include "vm/code_index_table.h"
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
11 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 intptr_t len = 281 intptr_t len =
282 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line); 282 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line);
283 len++; // String terminator. 283 len++; // String terminator.
284 char* chars = reinterpret_cast<char*>( 284 char* chars = reinterpret_cast<char*>(
285 Isolate::Current()->current_zone()->Allocate(len)); 285 Isolate::Current()->current_zone()->Allocate(len));
286 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); 286 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line);
287 return chars; 287 return chars;
288 } 288 }
289 289
290 290
291 void StackTrace::AddActivation(ActivationFrame* frame) { 291 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
292 trace_.Add(frame); 292 trace_.Add(frame);
293 } 293 }
294 294
295 295
296 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) 296 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index)
297 : function_(func.raw()), 297 : function_(func.raw()),
298 pc_desc_index_(pc_desc_index), 298 pc_desc_index_(pc_desc_index),
299 pc_(0), 299 pc_(0),
300 line_number_(-1), 300 line_number_(-1),
301 is_enabled_(false), 301 is_enabled_(false),
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 (kind == PcDescriptors::kFuncCall) || 507 (kind == PcDescriptors::kFuncCall) ||
508 (kind == PcDescriptors::kReturn)) { 508 (kind == PcDescriptors::kReturn)) {
509 bpt = new CodeBreakpoint(target_function, i); 509 bpt = new CodeBreakpoint(target_function, i);
510 RegisterCodeBreakpoint(bpt); 510 RegisterCodeBreakpoint(bpt);
511 bpt->Enable(); 511 bpt->Enable();
512 } 512 }
513 } 513 }
514 } 514 }
515 515
516 516
517 CodeBreakpoint* Debugger::MakeCodeBreakpoint(SourceBreakpoint* src_bpt) { 517 CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func,
518 Function& func = Function::Handle(src_bpt->function()); 518 intptr_t token_index) {
519 ASSERT(func.HasCode()); 519 ASSERT(func.HasCode());
520 ASSERT(!func.HasOptimizedCode()); 520 ASSERT(!func.HasOptimizedCode());
521 Code& code = Code::Handle(func.unoptimized_code()); 521 Code& code = Code::Handle(func.unoptimized_code());
522 ASSERT(!code.IsNull()); 522 ASSERT(!code.IsNull());
523 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 523 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
524 intptr_t requested_token_index = src_bpt->token_index();
525 for (int i = 0; i < desc.Length(); i++) { 524 for (int i = 0; i < desc.Length(); i++) {
526 if (desc.TokenIndex(i) < requested_token_index) { 525 if (desc.TokenIndex(i) < token_index) {
527 continue; 526 continue;
528 } 527 }
529 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); 528 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i));
530 // We should only ever have one code breakpoint at the same address. 529 // We should only ever have one code breakpoint at the same address.
531 // If we find an existing breakpoint, it must be an internal one which 530 // If we find an existing breakpoint, it must be an internal one which
532 // is used for stepping. 531 // is used for stepping.
533 if (bpt != NULL) { 532 if (bpt != NULL) {
534 ASSERT(bpt->src_bpt() == NULL); 533 ASSERT(bpt->src_bpt() == NULL);
535 bpt->set_src_bpt(src_bpt);
536 return bpt; 534 return bpt;
537 } 535 }
538 536
539 PcDescriptors::Kind kind = desc.DescriptorKind(i); 537 PcDescriptors::Kind kind = desc.DescriptorKind(i);
540 if ((kind == PcDescriptors::kIcCall) || 538 if ((kind == PcDescriptors::kIcCall) ||
541 (kind == PcDescriptors::kFuncCall) || 539 (kind == PcDescriptors::kFuncCall) ||
542 (kind == PcDescriptors::kReturn)) { 540 (kind == PcDescriptors::kReturn)) {
543 bpt = new CodeBreakpoint(func, i); 541 bpt = new CodeBreakpoint(func, i);
544 bpt->set_src_bpt(src_bpt);
545 if (verbose) { 542 if (verbose) {
546 OS::Print("Setting breakpoint in function '%s' (%s:%d) (PC %p)\n", 543 OS::Print("Setting breakpoint in function '%s' (%s:%d) (PC %p)\n",
547 String::Handle(func.name()).ToCString(), 544 String::Handle(func.name()).ToCString(),
548 String::Handle(bpt->SourceUrl()).ToCString(), 545 String::Handle(bpt->SourceUrl()).ToCString(),
549 bpt->LineNumber(), 546 bpt->LineNumber(),
550 bpt->pc()); 547 bpt->pc());
551 } 548 }
552 RegisterCodeBreakpoint(bpt); 549 RegisterCodeBreakpoint(bpt);
553 return bpt; 550 return bpt;
554 } 551 }
(...skipping 18 matching lines...) Expand all
573 RegisterSourceBreakpoint(bpt); 570 RegisterSourceBreakpoint(bpt);
574 if (verbose && !target_function.HasCode()) { 571 if (verbose && !target_function.HasCode()) {
575 OS::Print("Registering breakpoint for uncompiled function '%s'" 572 OS::Print("Registering breakpoint for uncompiled function '%s'"
576 " (%s:%d)\n", 573 " (%s:%d)\n",
577 String::Handle(target_function.name()).ToCString(), 574 String::Handle(target_function.name()).ToCString(),
578 String::Handle(bpt->SourceUrl()).ToCString(), 575 String::Handle(bpt->SourceUrl()).ToCString(),
579 bpt->LineNumber()); 576 bpt->LineNumber());
580 } 577 }
581 578
582 if (target_function.HasCode()) { 579 if (target_function.HasCode()) {
583 CodeBreakpoint* cbpt = MakeCodeBreakpoint(bpt); 580 CodeBreakpoint* cbpt = MakeCodeBreakpoint(target_function, token_index);
584 if (cbpt == NULL) { 581 if (cbpt != NULL) {
582 ASSERT(cbpt->src_bpt() == NULL);
583 cbpt->set_src_bpt(bpt);
584 } else {
585 if (verbose) { 585 if (verbose) {
586 OS::Print("Failed to set breakpoint at '%s' line %d\n", 586 OS::Print("Failed to set breakpoint at '%s' line %d\n",
587 String::Handle(bpt->SourceUrl()).ToCString(), 587 String::Handle(bpt->SourceUrl()).ToCString(),
588 bpt->LineNumber()); 588 bpt->LineNumber());
589 } 589 }
590 } 590 }
591 } 591 }
592 bpt->Enable(); 592 bpt->Enable();
593 return bpt; 593 return bpt;
594 } 594 }
595 595
596 596
597 // Synchronize the enabled/disabled state of all code breakpoints
598 // associated with the source breakpoint bpt.
597 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) { 599 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) {
598 CodeBreakpoint* cbpt = code_breakpoints_; 600 CodeBreakpoint* cbpt = code_breakpoints_;
599 while (cbpt != NULL) { 601 while (cbpt != NULL) {
600 if (bpt == cbpt->src_bpt()) { 602 if (bpt == cbpt->src_bpt()) {
601 if (bpt->IsEnabled()) { 603 if (bpt->IsEnabled()) {
602 cbpt->Enable(); 604 cbpt->Enable();
603 } else { 605 } else {
604 cbpt->Disable(); 606 cbpt->Disable();
605 } 607 }
606 } 608 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 bpt = bpt->next(); 767 bpt = bpt->next();
766 } 768 }
767 CodeBreakpoint* cbpt = code_breakpoints_; 769 CodeBreakpoint* cbpt = code_breakpoints_;
768 while (cbpt != NULL) { 770 while (cbpt != NULL) {
769 cbpt->VisitObjectPointers(visitor); 771 cbpt->VisitObjectPointers(visitor);
770 cbpt = cbpt->next(); 772 cbpt = cbpt->next();
771 } 773 }
772 } 774 }
773 775
774 776
775 static void DefaultBreakpointHandler(SourceBreakpoint* bpt, StackTrace* stack) { 777 static void DefaultBreakpointHandler(SourceBreakpoint* bpt,
778 DebuggerStackTrace* stack) {
776 String& var_name = String::Handle(); 779 String& var_name = String::Handle();
777 Instance& value = Instance::Handle(); 780 Instance& value = Instance::Handle();
778 for (intptr_t i = 0; i < stack->Length(); i++) { 781 for (intptr_t i = 0; i < stack->Length(); i++) {
779 ActivationFrame* frame = stack->ActivationFrameAt(i); 782 ActivationFrame* frame = stack->ActivationFrameAt(i);
780 OS::Print(" %d. %s\n", 783 OS::Print(" %d. %s\n",
781 i + 1, frame->ToCString()); 784 i + 1, frame->ToCString());
782 intptr_t num_locals = frame->NumLocalVariables(); 785 intptr_t num_locals = frame->NumLocalVariables();
783 for (intptr_t i = 0; i < num_locals; i++) { 786 for (intptr_t i = 0; i < num_locals; i++) {
784 intptr_t token_pos, end_pos; 787 intptr_t token_pos, end_pos;
785 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value); 788 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value);
(...skipping 19 matching lines...) Expand all
805 ASSERT(frame != NULL); 808 ASSERT(frame != NULL);
806 CodeBreakpoint* bpt = GetCodeBreakpoint(frame->pc()); 809 CodeBreakpoint* bpt = GetCodeBreakpoint(frame->pc());
807 ASSERT(bpt != NULL); 810 ASSERT(bpt != NULL);
808 if (verbose) { 811 if (verbose) {
809 OS::Print(">>> %s breakpoint at %s:%d (Address %p)\n", 812 OS::Print(">>> %s breakpoint at %s:%d (Address %p)\n",
810 bpt->IsInternal() ? "hit internal" : "hit user", 813 bpt->IsInternal() ? "hit internal" : "hit user",
811 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?", 814 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?",
812 bpt ? bpt->LineNumber() : 0, 815 bpt ? bpt->LineNumber() : 0,
813 frame->pc()); 816 frame->pc());
814 } 817 }
815 StackTrace* stack_trace = new StackTrace(8); 818 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
816 while (frame != NULL) { 819 while (frame != NULL) {
817 ASSERT(frame->IsValid()); 820 ASSERT(frame->IsValid());
818 ASSERT(frame->IsDartFrame()); 821 ASSERT(frame->IsDartFrame());
819 ActivationFrame* activation = 822 ActivationFrame* activation =
820 new ActivationFrame(frame->pc(), frame->fp(), frame->sp()); 823 new ActivationFrame(frame->pc(), frame->fp(), frame->sp());
821 stack_trace->AddActivation(activation); 824 stack_trace->AddActivation(activation);
822 frame = iterator.NextFrame(); 825 frame = iterator.NextFrame();
823 } 826 }
824 827
825 resume_action_ = kContinue; 828 resume_action_ = kContinue;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 void Debugger::Initialize(Isolate* isolate) { 888 void Debugger::Initialize(Isolate* isolate) {
886 if (initialized_) { 889 if (initialized_) {
887 return; 890 return;
888 } 891 }
889 isolate_ = isolate; 892 isolate_ = isolate;
890 initialized_ = true; 893 initialized_ = true;
891 SetBreakpointHandler(DefaultBreakpointHandler); 894 SetBreakpointHandler(DefaultBreakpointHandler);
892 } 895 }
893 896
894 897
895 // TODO(hausner): handle closure functions.
896 void Debugger::NotifyCompilation(const Function& func) { 898 void Debugger::NotifyCompilation(const Function& func) {
899 if (src_breakpoints_ == NULL) {
900 // Return with minimal overhead if there are no breakpoints.
901 return;
902 }
903 Function& lookup_function = Function::Handle(func.raw());
904 if (func.IsClosureFunction()) {
905 // If the newly compiled function is a closure, we need to use
906 // the closure's parent function to see whether there are any
907 // breakpoints.
908 lookup_function = func.parent_function();
909 }
897 SourceBreakpoint* bpt = src_breakpoints_; 910 SourceBreakpoint* bpt = src_breakpoints_;
898 while (bpt != NULL) { 911 while (bpt != NULL) {
899 if (func.raw() == bpt->function()) { 912 if (lookup_function.raw() == bpt->function()) {
900 if (verbose) { 913 if (verbose) {
901 OS::Print("Enable latent breakpoint for function '%s'\n", 914 OS::Print("Enable latent breakpoint for function '%s'\n",
902 String::Handle(func.name()).ToCString()); 915 String::Handle(lookup_function.name()).ToCString());
903 } 916 }
904 MakeCodeBreakpoint(bpt); 917 // Set breakpoint in newly compiled code of function func.
918 CodeBreakpoint* cbpt = MakeCodeBreakpoint(func, bpt->token_index());
919 if (cbpt != NULL) {
920 cbpt->set_src_bpt(bpt);
921 }
905 bpt->Enable(); // Enables the code breakpoint as well. 922 bpt->Enable(); // Enables the code breakpoint as well.
906 } 923 }
907 bpt = bpt->next(); 924 bpt = bpt->next();
908 } 925 }
909 } 926 }
910 927
911 928
912 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { 929 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
913 CodeBreakpoint* bpt = code_breakpoints_; 930 CodeBreakpoint* bpt = code_breakpoints_;
914 while (bpt != NULL) { 931 while (bpt != NULL) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 } 1015 }
999 1016
1000 1017
1001 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1018 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1002 ASSERT(bpt->next() == NULL); 1019 ASSERT(bpt->next() == NULL);
1003 bpt->set_next(code_breakpoints_); 1020 bpt->set_next(code_breakpoints_);
1004 code_breakpoints_ = bpt; 1021 code_breakpoints_ = bpt;
1005 } 1022 }
1006 1023
1007 } // namespace dart 1024 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698