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

Side by Side Diff: src/debug/debug.cc

Issue 2621953002: [debug] Untangle BreakLocation and DebugInfo (Closed)
Patch Set: Rebase Created 3 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
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-scopes.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/debug.h" 5 #include "src/debug/debug.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 break_points_active_(true), 48 break_points_active_(true),
49 in_debug_event_listener_(false), 49 in_debug_event_listener_(false),
50 break_on_exception_(false), 50 break_on_exception_(false),
51 break_on_uncaught_exception_(false), 51 break_on_uncaught_exception_(false),
52 debug_info_list_(NULL), 52 debug_info_list_(NULL),
53 feature_tracker_(isolate), 53 feature_tracker_(isolate),
54 isolate_(isolate) { 54 isolate_(isolate) {
55 ThreadInit(); 55 ThreadInit();
56 } 56 }
57 57
58 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, 58 BreakLocation BreakLocation::FromFrame(StandardFrame* frame) {
59 JavaScriptFrame* frame) { 59 // TODO(clemensh): Handle Wasm frames.
60 FrameSummary summary = FrameSummary::GetFirst(frame); 60 DCHECK(!frame->is_wasm());
61
62 auto summary = FrameSummary::GetFirst(frame).AsJavaScript();
61 int offset = summary.code_offset(); 63 int offset = summary.code_offset();
62 Handle<AbstractCode> abstract_code = summary.AsJavaScript().abstract_code(); 64 Handle<AbstractCode> abstract_code = summary.abstract_code();
63 if (abstract_code->IsCode()) offset = offset - 1; 65 if (abstract_code->IsCode()) offset = offset - 1;
66 Handle<DebugInfo> debug_info(summary.function()->shared()->GetDebugInfo());
64 auto it = BreakIterator::GetIterator(debug_info, abstract_code); 67 auto it = BreakIterator::GetIterator(debug_info, abstract_code);
65 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); 68 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
66 return it->GetBreakLocation(); 69 return it->GetBreakLocation();
67 } 70 }
68 71
69 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, 72 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
70 JavaScriptFrame* frame, 73 JavaScriptFrame* frame,
71 List<BreakLocation>* result_out) { 74 List<BreakLocation>* result_out) {
72 auto summary = FrameSummary::GetFirst(frame).AsJavaScript(); 75 auto summary = FrameSummary::GetFirst(frame).AsJavaScript();
73 int offset = summary.code_offset(); 76 int offset = summary.code_offset();
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 // Just continue if breaks are disabled or debugger cannot be loaded. 504 // Just continue if breaks are disabled or debugger cannot be loaded.
502 if (break_disabled()) return; 505 if (break_disabled()) return;
503 506
504 // Enter the debugger. 507 // Enter the debugger.
505 DebugScope debug_scope(this); 508 DebugScope debug_scope(this);
506 if (debug_scope.failed()) return; 509 if (debug_scope.failed()) return;
507 510
508 // Postpone interrupt during breakpoint processing. 511 // Postpone interrupt during breakpoint processing.
509 PostponeInterruptsScope postpone(isolate_); 512 PostponeInterruptsScope postpone(isolate_);
510 513
511 // Get the debug info (create it if it does not exist). 514 // Return if we fail to retrieve debug info for javascript frames.
512 Handle<JSFunction> function(frame->function()); 515 if (frame->is_java_script()) {
513 Handle<SharedFunctionInfo> shared(function->shared()); 516 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
Yang 2017/01/12 12:50:21 Currently frame has the type JavaScriptFrame*. I a
Clemens Hammacher 2017/01/12 14:11:38 That's right. This will change in one of the follo
Yang 2017/01/12 14:18:19 right... but currently we do the check for is_java
514 if (!EnsureDebugInfo(shared, function)) { 517
515 // Return if we failed to retrieve the debug info. 518 // Get the debug info (create it if it does not exist).
516 return; 519 Handle<JSFunction> function(js_frame->function());
520 Handle<SharedFunctionInfo> shared(function->shared());
521 if (!EnsureDebugInfo(shared, function)) return;
517 } 522 }
518 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
519 523
520 // Find the break location where execution has stopped. 524 BreakLocation location = BreakLocation::FromFrame(frame);
521 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
522 525
523 // Find actual break points, if any, and trigger debug break event. 526 // Find actual break points, if any, and trigger debug break event.
524 Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location); 527 MaybeHandle<FixedArray> break_points_hit;
525 if (!break_points_hit->IsUndefined(isolate_)) { 528 if (!break_points_active()) {
529 // Don't try to find hit breakpoints.
530 } else if (frame->is_wasm_interpreter_entry()) {
531 // TODO(clemensh): Find hit breakpoints for wasm.
532 UNIMPLEMENTED();
533 } else {
534 // Get the debug info, which must exist if we reach here.
535 Handle<DebugInfo> debug_info(
536 JavaScriptFrame::cast(frame)->function()->shared()->GetDebugInfo(),
537 isolate_);
538
539 break_points_hit = CheckBreakPoints(debug_info, &location);
540 }
541
542 if (!break_points_hit.is_null()) {
526 // Clear all current stepping setup. 543 // Clear all current stepping setup.
527 ClearStepping(); 544 ClearStepping();
528 // Notify the debug event listeners. 545 // Notify the debug event listeners.
529 OnDebugBreak(break_points_hit, false); 546 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements(
547 break_points_hit.ToHandleChecked());
548 OnDebugBreak(jsarr, false);
530 return; 549 return;
531 } 550 }
532 551
533 // No break point. Check for stepping. 552 // No break point. Check for stepping.
534 StepAction step_action = last_step_action(); 553 StepAction step_action = last_step_action();
535 Address current_fp = frame->UnpaddedFP(); 554 Address current_fp = frame->UnpaddedFP();
536 Address target_fp = thread_local_.target_fp_; 555 Address target_fp = thread_local_.target_fp_;
537 Address last_fp = thread_local_.last_fp_; 556 Address last_fp = thread_local_.last_fp_;
538 557
539 bool step_break = false; 558 bool step_break = false;
(...skipping 30 matching lines...) Expand all
570 // Notify the debug event listeners. 589 // Notify the debug event listeners.
571 OnDebugBreak(isolate_->factory()->undefined_value(), false); 590 OnDebugBreak(isolate_->factory()->undefined_value(), false);
572 } else { 591 } else {
573 // Re-prepare to continue. 592 // Re-prepare to continue.
574 PrepareStep(step_action); 593 PrepareStep(step_action);
575 } 594 }
576 } 595 }
577 596
578 597
579 // Find break point objects for this location, if any, and evaluate them. 598 // Find break point objects for this location, if any, and evaluate them.
580 // Return an array of break point objects that evaluated true. 599 // Return an array of break point objects that evaluated true, or an empty
581 Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info, 600 // handle if none evaluated true.
582 BreakLocation* location, 601 MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
583 bool* has_break_points) { 602 BreakLocation* location,
584 Factory* factory = isolate_->factory(); 603 bool* has_break_points) {
585 bool has_break_points_to_check = 604 bool has_break_points_to_check =
586 break_points_active_ && location->HasBreakPoint(debug_info); 605 break_points_active_ && location->HasBreakPoint(debug_info);
587 if (has_break_points) *has_break_points = has_break_points_to_check; 606 if (has_break_points) *has_break_points = has_break_points_to_check;
588 if (!has_break_points_to_check) return factory->undefined_value(); 607 if (!has_break_points_to_check) return {};
589 608
590 Handle<Object> break_point_objects = 609 Handle<Object> break_point_objects =
591 debug_info->GetBreakPointObjects(location->position()); 610 debug_info->GetBreakPointObjects(location->position());
592 // Count the number of break points hit. If there are multiple break points 611 return Debug::GetHitBreakPointObjects(break_point_objects);
593 // they are in a FixedArray.
594 Handle<FixedArray> break_points_hit;
595 int break_points_hit_count = 0;
596 DCHECK(!break_point_objects->IsUndefined(isolate_));
597 if (break_point_objects->IsFixedArray()) {
598 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
599 break_points_hit = factory->NewFixedArray(array->length());
600 for (int i = 0; i < array->length(); i++) {
601 Handle<Object> break_point_object(array->get(i), isolate_);
602 if (CheckBreakPoint(break_point_object)) {
603 break_points_hit->set(break_points_hit_count++, *break_point_object);
604 }
605 }
606 } else {
607 break_points_hit = factory->NewFixedArray(1);
608 if (CheckBreakPoint(break_point_objects)) {
609 break_points_hit->set(break_points_hit_count++, *break_point_objects);
610 }
611 }
612 if (break_points_hit_count == 0) return factory->undefined_value();
613 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
614 result->set_length(Smi::FromInt(break_points_hit_count));
615 return result;
616 } 612 }
617 613
618 614
619 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { 615 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
620 // A break location is considered muted if break locations on the current 616 // A break location is considered muted if break locations on the current
621 // statement have at least one break point, and all of these break points 617 // statement have at least one break point, and all of these break points
622 // evaluate to false. Aside from not triggering a debug break event at the 618 // evaluate to false. Aside from not triggering a debug break event at the
623 // break location, we also do not trigger one for debugger statements, nor 619 // break location, we also do not trigger one for debugger statements, nor
624 // an exception event on exception at this location. 620 // an exception event on exception at this location.
625 Object* fun = frame->function(); 621 Object* fun = frame->function();
626 if (!fun->IsJSFunction()) return false; 622 if (!fun->IsJSFunction()) return false;
627 JSFunction* function = JSFunction::cast(fun); 623 JSFunction* function = JSFunction::cast(fun);
628 if (!function->shared()->HasDebugInfo()) return false; 624 if (!function->shared()->HasDebugInfo()) return false;
629 HandleScope scope(isolate_); 625 HandleScope scope(isolate_);
630 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); 626 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
631 // Enter the debugger. 627 // Enter the debugger.
632 DebugScope debug_scope(this); 628 DebugScope debug_scope(this);
633 if (debug_scope.failed()) return false; 629 if (debug_scope.failed()) return false;
634 List<BreakLocation> break_locations; 630 List<BreakLocation> break_locations;
635 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); 631 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
636 bool has_break_points_at_all = false; 632 bool has_break_points_at_all = false;
637 for (int i = 0; i < break_locations.length(); i++) { 633 for (int i = 0; i < break_locations.length(); i++) {
638 bool has_break_points; 634 bool has_break_points;
639 Handle<Object> check_result = 635 MaybeHandle<FixedArray> check_result =
640 CheckBreakPoints(debug_info, &break_locations[i], &has_break_points); 636 CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
641 has_break_points_at_all |= has_break_points; 637 has_break_points_at_all |= has_break_points;
642 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; 638 if (has_break_points && !check_result.is_null()) return false;
643 } 639 }
644 return has_break_points_at_all; 640 return has_break_points_at_all;
645 } 641 }
646 642
647 643
648 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, 644 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
649 Handle<Object> args[]) { 645 Handle<Object> args[]) {
650 PostponeInterruptsScope no_interrupts(isolate_); 646 PostponeInterruptsScope no_interrupts(isolate_);
651 AssertDebugContext(); 647 AssertDebugContext();
652 Handle<JSReceiver> holder = 648 Handle<JSReceiver> holder =
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 889
894 890
895 bool Debug::IsBreakOnException(ExceptionBreakType type) { 891 bool Debug::IsBreakOnException(ExceptionBreakType type) {
896 if (type == BreakUncaughtException) { 892 if (type == BreakUncaughtException) {
897 return break_on_uncaught_exception_; 893 return break_on_uncaught_exception_;
898 } else { 894 } else {
899 return break_on_exception_; 895 return break_on_exception_;
900 } 896 }
901 } 897 }
902 898
899 MaybeHandle<FixedArray> Debug::GetHitBreakPointObjects(
900 Handle<Object> break_point_objects) {
901 DCHECK(!break_point_objects->IsUndefined(isolate_));
902 if (!break_point_objects->IsFixedArray()) {
903 if (!CheckBreakPoint(break_point_objects)) return {};
904 Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
905 break_points_hit->set(0, *break_point_objects);
906 return break_points_hit;
907 }
908
909 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
910 int num_objects = array->length();
911 Handle<FixedArray> break_points_hit =
912 isolate_->factory()->NewFixedArray(num_objects);
913 int break_points_hit_count = 0;
914 for (int i = 0; i < num_objects; ++i) {
915 Handle<Object> break_point_object(array->get(i), isolate_);
916 if (CheckBreakPoint(break_point_object)) {
917 break_points_hit->set(break_points_hit_count++, *break_point_object);
918 }
919 }
920 if (break_points_hit_count == 0) return {};
921 break_points_hit->Shrink(break_points_hit_count);
922 return break_points_hit;
923 }
903 924
904 void Debug::PrepareStepIn(Handle<JSFunction> function) { 925 void Debug::PrepareStepIn(Handle<JSFunction> function) {
905 CHECK(last_step_action() >= StepIn); 926 CHECK(last_step_action() >= StepIn);
906 if (!is_active()) return; 927 if (!is_active()) return;
907 if (in_debug_scope()) return; 928 if (in_debug_scope()) return;
908 FloodWithOneShot(function); 929 FloodWithOneShot(function);
909 } 930 }
910 931
911 void Debug::PrepareStepInSuspendedGenerator() { 932 void Debug::PrepareStepInSuspendedGenerator() {
912 CHECK(has_suspended_generator()); 933 CHECK(has_suspended_generator());
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 // Step out: Find the calling JavaScript frame and flood it with 1002 // Step out: Find the calling JavaScript frame and flood it with
982 // breakpoints. 1003 // breakpoints.
983 frames_it.Advance(); 1004 frames_it.Advance();
984 // Fill the function to return to with one-shot break points. 1005 // Fill the function to return to with one-shot break points.
985 JSFunction* function = frames_it.frame()->function(); 1006 JSFunction* function = frames_it.frame()->function();
986 FloodWithOneShot(Handle<JSFunction>(function)); 1007 FloodWithOneShot(Handle<JSFunction>(function));
987 return; 1008 return;
988 } 1009 }
989 1010
990 // Get the debug info (create it if it does not exist). 1011 // Get the debug info (create it if it does not exist).
991 auto summary = FrameSummary::GetFirst(frame).AsJavaScript(); 1012 auto summary = FrameSummary::GetFirst(frame).AsJavaScript();
Yang 2017/01/12 12:50:21 These few lines could be dropped if we already hav
Clemens Hammacher 2017/01/12 14:11:38 Same problem.
992 Handle<JSFunction> function(summary.function()); 1013 Handle<JSFunction> function(summary.function());
993 Handle<SharedFunctionInfo> shared(function->shared()); 1014 Handle<SharedFunctionInfo> shared(function->shared());
994 if (!EnsureDebugInfo(shared, function)) { 1015 if (!EnsureDebugInfo(shared, function)) {
995 // Return if ensuring debug info failed. 1016 // Return if ensuring debug info failed.
996 return; 1017 return;
997 } 1018 }
998 1019
999 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1020 BreakLocation location = BreakLocation::FromFrame(frame);
1000 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1001 1021
1002 // Any step at a return is a step-out. 1022 // Any step at a return is a step-out.
1003 if (location.IsReturn()) step_action = StepOut; 1023 if (location.IsReturn()) step_action = StepOut;
1004 // A step-next at a tail call is a step-out. 1024 // A step-next at a tail call is a step-out.
1005 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; 1025 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
1006 1026
1007 thread_local_.last_statement_position_ = 1027 thread_local_.last_statement_position_ =
1008 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); 1028 summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1009 thread_local_.last_fp_ = frame->UnpaddedFP(); 1029 thread_local_.last_fp_ = frame->UnpaddedFP();
1010 // No longer perform the current async step. 1030 // No longer perform the current async step.
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 after_break_target_ = NULL; 1576 after_break_target_ = NULL;
1557 if (!LiveEdit::SetAfterBreakTarget(this)) { 1577 if (!LiveEdit::SetAfterBreakTarget(this)) {
1558 // Continue just after the slot. 1578 // Continue just after the slot.
1559 after_break_target_ = frame->pc(); 1579 after_break_target_ = frame->pc();
1560 } 1580 }
1561 } 1581 }
1562 1582
1563 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { 1583 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1564 HandleScope scope(isolate_); 1584 HandleScope scope(isolate_);
1565 1585
1566 // Get the executing function in which the debug break occurred.
1567 Handle<SharedFunctionInfo> shared(frame->function()->shared());
1568
1569 // With no debug info there are no break points, so we can't be at a return. 1586 // With no debug info there are no break points, so we can't be at a return.
1570 if (!shared->HasDebugInfo()) return false; 1587 if (!frame->function()->shared()->HasDebugInfo()) return false;
1571 1588
1572 DCHECK(!frame->is_optimized()); 1589 DCHECK(!frame->is_optimized());
1573 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1590 BreakLocation location = BreakLocation::FromFrame(frame);
1574 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1575 return location.IsReturn() || location.IsTailCall(); 1591 return location.IsReturn() || location.IsTailCall();
1576 } 1592 }
1577 1593
1578 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 1594 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1579 LiveEditFrameDropMode mode) { 1595 LiveEditFrameDropMode mode) {
1580 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) { 1596 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) {
1581 thread_local_.frame_drop_mode_ = mode; 1597 thread_local_.frame_drop_mode_ = mode;
1582 } 1598 }
1583 thread_local_.break_frame_id_ = new_break_frame_id; 1599 thread_local_.break_frame_id_ = new_break_frame_id;
1584 } 1600 }
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
2550 logger_->DebugEvent("Put", message.text()); 2566 logger_->DebugEvent("Put", message.text());
2551 } 2567 }
2552 2568
2553 void LockingCommandMessageQueue::Clear() { 2569 void LockingCommandMessageQueue::Clear() {
2554 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2570 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2555 queue_.Clear(); 2571 queue_.Clear();
2556 } 2572 }
2557 2573
2558 } // namespace internal 2574 } // namespace internal
2559 } // namespace v8 2575 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698