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

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

Issue 1610073002: [debugger] negative conditional break points mute breaks and exceptions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix test Created 4 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 "src/api.h" 7 #include "src/api.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // Get the debug info (create it if it does not exist). 437 // Get the debug info (create it if it does not exist).
438 Handle<JSFunction> function(frame->function()); 438 Handle<JSFunction> function(frame->function());
439 Handle<SharedFunctionInfo> shared(function->shared()); 439 Handle<SharedFunctionInfo> shared(function->shared());
440 if (!EnsureDebugInfo(shared, function)) { 440 if (!EnsureDebugInfo(shared, function)) {
441 // Return if we failed to retrieve the debug info. 441 // Return if we failed to retrieve the debug info.
442 return; 442 return;
443 } 443 }
444 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 444 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
445 445
446 // Find the break location where execution has stopped. 446 // Find the break location where execution has stopped.
447 // PC points to the instruction after the current one, possibly a break 447 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
448 // location as well. So the "- 1" to exclude it from the search.
449 Address call_pc = frame->pc() - 1;
450 BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
451 448
452 // Find actual break points, if any, and trigger debug break event. 449 // Find actual break points, if any, and trigger debug break event.
453 if (break_points_active_ && location.HasBreakPoint()) { 450 Handle<Object> break_points_hit = CheckBreakPoints(&location);
454 Handle<Object> break_point_objects = location.BreakPointObjects(); 451 if (!break_points_hit->IsUndefined()) {
455 Handle<Object> break_points_hit = CheckBreakPoints(break_point_objects); 452 // Clear all current stepping setup.
456 if (!break_points_hit->IsUndefined()) { 453 ClearStepping();
457 // Clear all current stepping setup. 454 // Notify the debug event listeners.
458 ClearStepping(); 455 OnDebugBreak(break_points_hit, false);
459 // Notify the debug event listeners. 456 return;
460 OnDebugBreak(break_points_hit, false);
461 return;
462 }
463 } 457 }
464 458
465 // No break point. Check for stepping. 459 // No break point. Check for stepping.
466 StepAction step_action = last_step_action(); 460 StepAction step_action = last_step_action();
467 Address current_fp = frame->UnpaddedFP(); 461 Address current_fp = frame->UnpaddedFP();
468 Address target_fp = thread_local_.target_fp_; 462 Address target_fp = thread_local_.target_fp_;
469 Address last_fp = thread_local_.last_fp_; 463 Address last_fp = thread_local_.last_fp_;
470 464
471 bool step_break = true; 465 bool step_break = true;
472 switch (step_action) { 466 switch (step_action) {
(...skipping 23 matching lines...) Expand all
496 if (step_break) { 490 if (step_break) {
497 // Notify the debug event listeners. 491 // Notify the debug event listeners.
498 OnDebugBreak(isolate_->factory()->undefined_value(), false); 492 OnDebugBreak(isolate_->factory()->undefined_value(), false);
499 } else { 493 } else {
500 // Re-prepare to continue. 494 // Re-prepare to continue.
501 PrepareStep(step_action); 495 PrepareStep(step_action);
502 } 496 }
503 } 497 }
504 498
505 499
506 // Check the break point objects for whether one or more are actually 500 // Find break point objects for this location, if any, and evaluate them.
507 // triggered. This function returns a JSArray with the break point objects 501 // Return an array of break point objects that evaluated true.
508 // which is triggered. 502 Handle<Object> Debug::CheckBreakPoints(BreakLocation* location,
509 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { 503 bool* has_break_points) {
510 Factory* factory = isolate_->factory(); 504 Factory* factory = isolate_->factory();
505 bool has_break_points_to_check =
506 break_points_active_ && location->HasBreakPoint();
507 if (has_break_points) *has_break_points = has_break_points_to_check;
508 if (!has_break_points_to_check) return factory->undefined_value();
511 509
510 Handle<Object> break_point_objects = location->BreakPointObjects();
512 // Count the number of break points hit. If there are multiple break points 511 // Count the number of break points hit. If there are multiple break points
513 // they are in a FixedArray. 512 // they are in a FixedArray.
514 Handle<FixedArray> break_points_hit; 513 Handle<FixedArray> break_points_hit;
515 int break_points_hit_count = 0; 514 int break_points_hit_count = 0;
516 DCHECK(!break_point_objects->IsUndefined()); 515 DCHECK(!break_point_objects->IsUndefined());
517 if (break_point_objects->IsFixedArray()) { 516 if (break_point_objects->IsFixedArray()) {
518 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); 517 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
519 break_points_hit = factory->NewFixedArray(array->length()); 518 break_points_hit = factory->NewFixedArray(array->length());
520 for (int i = 0; i < array->length(); i++) { 519 for (int i = 0; i < array->length(); i++) {
521 Handle<Object> o(array->get(i), isolate_); 520 Handle<Object> break_point_object(array->get(i), isolate_);
522 if (CheckBreakPoint(o)) { 521 if (CheckBreakPoint(break_point_object)) {
523 break_points_hit->set(break_points_hit_count++, *o); 522 break_points_hit->set(break_points_hit_count++, *break_point_object);
524 } 523 }
525 } 524 }
526 } else { 525 } else {
527 break_points_hit = factory->NewFixedArray(1); 526 break_points_hit = factory->NewFixedArray(1);
528 if (CheckBreakPoint(break_point_objects)) { 527 if (CheckBreakPoint(break_point_objects)) {
529 break_points_hit->set(break_points_hit_count++, *break_point_objects); 528 break_points_hit->set(break_points_hit_count++, *break_point_objects);
530 } 529 }
531 } 530 }
532 531 if (break_points_hit_count == 0) return factory->undefined_value();
533 // Return undefined if no break points were triggered.
534 if (break_points_hit_count == 0) {
535 return factory->undefined_value();
536 }
537 // Return break points hit as a JSArray.
538 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit); 532 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
539 result->set_length(Smi::FromInt(break_points_hit_count)); 533 result->set_length(Smi::FromInt(break_points_hit_count));
540 return result; 534 return result;
541 } 535 }
542 536
543 537
538 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
539 // A break location is considered muted if the break location has break
540 // points, but their conditions all evaluate to false.
541 // Aside from not triggering a debug break event at the break location,
542 // we also do not trigger one for debugger statements, nor an exception event
543 // on exception at this location.
544 Object* fun = frame->function();
545 if (!fun->IsJSFunction()) return false;
546 JSFunction* function = JSFunction::cast(fun);
547 if (!function->shared()->HasDebugInfo()) return false;
548 HandleScope scope(isolate_);
549 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
550 // Enter the debugger.
551 DebugScope debug_scope(this);
552 if (debug_scope.failed()) return false;
553 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
554 bool has_break_points;
555 Handle<Object> check_result = CheckBreakPoints(&location, &has_break_points);
556 return has_break_points && check_result->IsUndefined();
557 }
558
559
544 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, 560 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
545 Handle<Object> args[]) { 561 Handle<Object> args[]) {
546 PostponeInterruptsScope no_interrupts(isolate_); 562 PostponeInterruptsScope no_interrupts(isolate_);
547 AssertDebugContext(); 563 AssertDebugContext();
548 Handle<Object> holder = isolate_->natives_utils_object(); 564 Handle<Object> holder = isolate_->natives_utils_object();
549 Handle<JSFunction> fun = Handle<JSFunction>::cast( 565 Handle<JSFunction> fun = Handle<JSFunction>::cast(
550 Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked()); 566 Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked());
551 Handle<Object> undefined = isolate_->factory()->undefined_value(); 567 Handle<Object> undefined = isolate_->factory()->undefined_value();
552 return Execution::TryCall(isolate_, fun, undefined, argc, args); 568 return Execution::TryCall(isolate_, fun, undefined, argc, args);
553 } 569 }
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 // Return if ensuring debug info failed. 856 // Return if ensuring debug info failed.
841 return; 857 return;
842 } 858 }
843 859
844 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 860 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
845 // Refresh frame summary if the code has been recompiled for debugging. 861 // Refresh frame summary if the code has been recompiled for debugging.
846 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); 862 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
847 863
848 // PC points to the instruction after the current one, possibly a break 864 // PC points to the instruction after the current one, possibly a break
849 // location as well. So the "- 1" to exclude it from the search. 865 // location as well. So the "- 1" to exclude it from the search.
850 Address call_pc = summary.pc() - 1; 866 BreakLocation location = BreakLocation::FromFrame(debug_info, &summary);
851 BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
852 867
853 // At a return statement we will step out either way. 868 // At a return statement we will step out either way.
854 if (location.IsReturn()) step_action = StepOut; 869 if (location.IsReturn()) step_action = StepOut;
855 870
856 thread_local_.last_statement_position_ = 871 thread_local_.last_statement_position_ =
857 debug_info->code()->SourceStatementPosition(summary.pc()); 872 debug_info->code()->SourceStatementPosition(summary.pc());
858 thread_local_.last_fp_ = frame->UnpaddedFP(); 873 thread_local_.last_fp_ = frame->UnpaddedFP();
859 874
860 switch (step_action) { 875 switch (step_action) {
861 case StepNone: 876 case StepNone:
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 } 1627 }
1613 // Bail out if exception breaks are not active 1628 // Bail out if exception breaks are not active
1614 if (uncaught) { 1629 if (uncaught) {
1615 // Uncaught exceptions are reported by either flags. 1630 // Uncaught exceptions are reported by either flags.
1616 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 1631 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1617 } else { 1632 } else {
1618 // Caught exceptions are reported is activated. 1633 // Caught exceptions are reported is activated.
1619 if (!break_on_exception_) return; 1634 if (!break_on_exception_) return;
1620 } 1635 }
1621 1636
1637 {
1638 // Check whether the break location is muted.
1639 JavaScriptFrameIterator it(isolate_);
1640 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return;
1641 }
1642
1622 DebugScope debug_scope(this); 1643 DebugScope debug_scope(this);
1623 if (debug_scope.failed()) return; 1644 if (debug_scope.failed()) return;
1624 1645
1625 // Create the event data object. 1646 // Create the event data object.
1626 Handle<Object> event_data; 1647 Handle<Object> event_data;
1627 // Bail out and don't call debugger if exception. 1648 // Bail out and don't call debugger if exception.
1628 if (!MakeExceptionEvent( 1649 if (!MakeExceptionEvent(
1629 exception, uncaught, promise).ToHandle(&event_data)) { 1650 exception, uncaught, promise).ToHandle(&event_data)) {
1630 return; 1651 return;
1631 } 1652 }
1632 1653
1633 // Process debug event. 1654 // Process debug event.
1634 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 1655 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1635 // Return to continue execution from where the exception was thrown. 1656 // Return to continue execution from where the exception was thrown.
1636 } 1657 }
1637 1658
1638 1659
1639 void Debug::OnDebugBreak(Handle<Object> break_points_hit, 1660 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
1640 bool auto_continue) {
1641 // The caller provided for DebugScope. 1661 // The caller provided for DebugScope.
1642 AssertDebugContext(); 1662 AssertDebugContext();
1643 // Bail out if there is no listener for this event 1663 // Bail out if there is no listener for this event
1644 if (ignore_events()) return; 1664 if (ignore_events()) return;
1645 1665
1646 HandleScope scope(isolate_); 1666 HandleScope scope(isolate_);
1647 // Create the event data object. 1667 // Create the event data object.
1648 Handle<Object> event_data; 1668 Handle<Object> event_data;
1649 // Bail out and don't call debugger if exception. 1669 // Bail out and don't call debugger if exception.
1650 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1670 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
2064 { JavaScriptFrameIterator it(isolate_); 2084 { JavaScriptFrameIterator it(isolate_);
2065 DCHECK(!it.done()); 2085 DCHECK(!it.done());
2066 Object* fun = it.frame()->function(); 2086 Object* fun = it.frame()->function();
2067 if (fun && fun->IsJSFunction()) { 2087 if (fun && fun->IsJSFunction()) {
2068 // Don't stop in builtin functions. 2088 // Don't stop in builtin functions.
2069 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2089 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2070 JSGlobalObject* global = 2090 JSGlobalObject* global =
2071 JSFunction::cast(fun)->context()->global_object(); 2091 JSFunction::cast(fun)->context()->global_object();
2072 // Don't stop in debugger functions. 2092 // Don't stop in debugger functions.
2073 if (IsDebugGlobal(global)) return; 2093 if (IsDebugGlobal(global)) return;
2094 // Don't stop if the break location is muted.
2095 if (IsMutedAtCurrentLocation(it.frame())) return;
2074 } 2096 }
2075 } 2097 }
2076 2098
2077 // Collect the break state before clearing the flags. 2099 // Collect the break state before clearing the flags.
2078 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() && 2100 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2079 !isolate_->stack_guard()->CheckDebugBreak(); 2101 !isolate_->stack_guard()->CheckDebugBreak();
2080 2102
2081 isolate_->stack_guard()->ClearDebugBreak(); 2103 isolate_->stack_guard()->ClearDebugBreak();
2082 2104
2083 // Clear stepping to avoid duplicate breaks. 2105 // Clear stepping to avoid duplicate breaks.
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
2405 } 2427 }
2406 2428
2407 2429
2408 void LockingCommandMessageQueue::Clear() { 2430 void LockingCommandMessageQueue::Clear() {
2409 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2431 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2410 queue_.Clear(); 2432 queue_.Clear();
2411 } 2433 }
2412 2434
2413 } // namespace internal 2435 } // namespace internal
2414 } // namespace v8 2436 } // 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