Index: src/debug/debug.cc |
diff --git a/src/debug/debug.cc b/src/debug/debug.cc |
index bd45b71551f94a08c6e1049fd8dc64cfba96731c..347d9b6b6d668b3fcea88460947a4755a4269fd8 100644 |
--- a/src/debug/debug.cc |
+++ b/src/debug/debug.cc |
@@ -444,22 +444,16 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
// Find the break location where execution has stopped. |
- // PC points to the instruction after the current one, possibly a break |
- // location as well. So the "- 1" to exclude it from the search. |
- Address call_pc = frame->pc() - 1; |
- BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc); |
+ BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
// Find actual break points, if any, and trigger debug break event. |
- if (break_points_active_ && location.HasBreakPoint()) { |
- Handle<Object> break_point_objects = location.BreakPointObjects(); |
- Handle<Object> break_points_hit = CheckBreakPoints(break_point_objects); |
- if (!break_points_hit->IsUndefined()) { |
- // Clear all current stepping setup. |
- ClearStepping(); |
- // Notify the debug event listeners. |
- OnDebugBreak(break_points_hit, false); |
- return; |
- } |
+ Handle<Object> break_points_hit = CheckBreakPoints(&location); |
+ if (!break_points_hit->IsUndefined()) { |
+ // Clear all current stepping setup. |
+ ClearStepping(); |
+ // Notify the debug event listeners. |
+ OnDebugBreak(break_points_hit, false); |
+ return; |
} |
// No break point. Check for stepping. |
@@ -503,12 +497,17 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
} |
-// Check the break point objects for whether one or more are actually |
-// triggered. This function returns a JSArray with the break point objects |
-// which is triggered. |
-Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { |
+// Find break point objects for this location, if any, and evaluate them. |
+// Return an array of break point objects that evaluated true. |
+Handle<Object> Debug::CheckBreakPoints(BreakLocation* location, |
+ bool* has_break_points) { |
Factory* factory = isolate_->factory(); |
+ bool has_break_points_to_check = |
+ break_points_active_ && location->HasBreakPoint(); |
+ if (has_break_points) *has_break_points = has_break_points_to_check; |
+ if (!has_break_points_to_check) return factory->undefined_value(); |
+ Handle<Object> break_point_objects = location->BreakPointObjects(); |
// Count the number of break points hit. If there are multiple break points |
// they are in a FixedArray. |
Handle<FixedArray> break_points_hit; |
@@ -518,9 +517,9 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { |
Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); |
break_points_hit = factory->NewFixedArray(array->length()); |
for (int i = 0; i < array->length(); i++) { |
- Handle<Object> o(array->get(i), isolate_); |
- if (CheckBreakPoint(o)) { |
- break_points_hit->set(break_points_hit_count++, *o); |
+ Handle<Object> break_point_object(array->get(i), isolate_); |
+ if (CheckBreakPoint(break_point_object)) { |
+ break_points_hit->set(break_points_hit_count++, *break_point_object); |
} |
} |
} else { |
@@ -529,18 +528,35 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { |
break_points_hit->set(break_points_hit_count++, *break_point_objects); |
} |
} |
- |
- // Return undefined if no break points were triggered. |
- if (break_points_hit_count == 0) { |
- return factory->undefined_value(); |
- } |
- // Return break points hit as a JSArray. |
+ if (break_points_hit_count == 0) return factory->undefined_value(); |
Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit); |
result->set_length(Smi::FromInt(break_points_hit_count)); |
return result; |
} |
+bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { |
+ // A break location is considered muted if the break location has break |
+ // points, but their conditions all evaluate to false. |
+ // Aside from not triggering a debug break event at the break location, |
+ // we also do not trigger one for debugger statements, nor an exception event |
+ // on exception at this location. |
+ Object* fun = frame->function(); |
+ if (!fun->IsJSFunction()) return false; |
+ JSFunction* function = JSFunction::cast(fun); |
+ if (!function->shared()->HasDebugInfo()) return false; |
+ HandleScope scope(isolate_); |
+ Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); |
+ // Enter the debugger. |
+ DebugScope debug_scope(this); |
+ if (debug_scope.failed()) return false; |
+ BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
+ bool has_break_points; |
+ Handle<Object> check_result = CheckBreakPoints(&location, &has_break_points); |
+ return has_break_points && check_result->IsUndefined(); |
+} |
+ |
+ |
MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, |
Handle<Object> args[]) { |
PostponeInterruptsScope no_interrupts(isolate_); |
@@ -847,8 +863,7 @@ void Debug::PrepareStep(StepAction step_action) { |
// PC points to the instruction after the current one, possibly a break |
// location as well. So the "- 1" to exclude it from the search. |
- Address call_pc = summary.pc() - 1; |
- BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc); |
+ BreakLocation location = BreakLocation::FromFrame(debug_info, &summary); |
// At a return statement we will step out either way. |
if (location.IsReturn()) step_action = StepOut; |
@@ -1619,6 +1634,12 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { |
if (!break_on_exception_) return; |
} |
+ { |
+ // Check whether the break location is muted. |
+ JavaScriptFrameIterator it(isolate_); |
+ if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; |
+ } |
+ |
DebugScope debug_scope(this); |
if (debug_scope.failed()) return; |
@@ -1636,8 +1657,7 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { |
} |
-void Debug::OnDebugBreak(Handle<Object> break_points_hit, |
- bool auto_continue) { |
+void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { |
// The caller provided for DebugScope. |
AssertDebugContext(); |
// Bail out if there is no listener for this event |
@@ -2071,6 +2091,8 @@ void Debug::HandleDebugBreak() { |
JSFunction::cast(fun)->context()->global_object(); |
// Don't stop in debugger functions. |
if (IsDebugGlobal(global)) return; |
+ // Don't stop if the break location is muted. |
+ if (IsMutedAtCurrentLocation(it.frame())) return; |
} |
} |