* [PATCH] simplify bpstat_check_breakpoint_conditions
@ 2013-11-12 7:58 Doug Evans
2013-11-12 9:54 ` Pedro Alves
0 siblings, 1 reply; 4+ messages in thread
From: Doug Evans @ 2013-11-12 7:58 UTC (permalink / raw)
To: gdb-patches
Hi.
This patch simplifies bpstat_check_breakpoint_conditions a bit.
Regression tested on amd64-linux.
Ok to check in?
[Appended at the end is the same patch with diff's -b option added
to make the actual changes easier to see.]
2013-11-11 Doug Evans <xdje42@gmail.com>
* breakpoint.c (bpstat_check_breakpoint_conditions): Assert
bs->stop != 0 on entry. Update function comment. Simplify early
exit for frame mismatch. Reindent rest of function.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index ffe73fd..36252ee 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5099,8 +5099,8 @@ bpstat_check_watchpoint (bpstat bs)
}
}
-
-/* Check conditions (condition proper, frame, thread and ignore count)
+/* For breakpoints that are currently marked as telling gdb to stop,
+ check conditions (condition proper, frame, thread and ignore count)
of breakpoint referred to by BS. If we should not stop for this
breakpoint, set BS->stop to 0. */
@@ -5110,6 +5110,10 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
int thread_id = pid_to_thread_id (ptid);
const struct bp_location *bl;
struct breakpoint *b;
+ int value_is_zero = 0;
+ struct expression *cond;
+
+ gdb_assert (bs->stop);
/* BS is built for existing struct breakpoint. */
bl = bs->bp_location_at;
@@ -5123,109 +5127,106 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
if (frame_id_p (b->frame_id)
&& !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
- bs->stop = 0;
- else if (bs->stop)
{
- int value_is_zero = 0;
- struct expression *cond;
+ bs->stop = 0;
+ return;
+ }
- /* Evaluate Python breakpoints that have a "stop"
- method implemented. */
- if (b->py_bp_object)
- bs->stop = gdbpy_should_stop (b->py_bp_object);
+ /* Evaluate Python breakpoints that have a "stop" method implemented. */
+ if (b->py_bp_object)
+ bs->stop = gdbpy_should_stop (b->py_bp_object);
- if (is_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
+ if (is_watchpoint (b))
+ {
+ struct watchpoint *w = (struct watchpoint *) b;
- cond = w->cond_exp;
- }
+ cond = w->cond_exp;
+ }
+ else
+ cond = bl->cond;
+
+ if (cond && b->disposition != disp_del_at_next_stop)
+ {
+ int within_current_scope = 1;
+ struct watchpoint * w;
+
+ /* We use value_mark and value_free_to_mark because it could
+ be a long time before we return to the command level and
+ call free_all_values. We can't call free_all_values
+ because we might be in the middle of evaluating a
+ function call. */
+ struct value *mark = value_mark ();
+
+ if (is_watchpoint (b))
+ w = (struct watchpoint *) b;
else
- cond = bl->cond;
+ w = NULL;
- if (cond && b->disposition != disp_del_at_next_stop)
+ /* Need to select the frame, with all that implies so that
+ the conditions will have the right context. Because we
+ use the frame, we will not see an inlined function's
+ variables when we arrive at a breakpoint at the start
+ of the inlined function; the current frame will be the
+ call site. */
+ if (w == NULL || w->cond_exp_valid_block == NULL)
+ select_frame (get_current_frame ());
+ else
{
- int within_current_scope = 1;
- struct watchpoint * w;
-
- /* We use value_mark and value_free_to_mark because it could
- be a long time before we return to the command level and
- call free_all_values. We can't call free_all_values
- because we might be in the middle of evaluating a
- function call. */
- struct value *mark = value_mark ();
-
- if (is_watchpoint (b))
- w = (struct watchpoint *) b;
- else
- w = NULL;
-
- /* Need to select the frame, with all that implies so that
- the conditions will have the right context. Because we
- use the frame, we will not see an inlined function's
- variables when we arrive at a breakpoint at the start
- of the inlined function; the current frame will be the
- call site. */
- if (w == NULL || w->cond_exp_valid_block == NULL)
- select_frame (get_current_frame ());
- else
- {
- struct frame_info *frame;
-
- /* For local watchpoint expressions, which particular
- instance of a local is being watched matters, so we
- keep track of the frame to evaluate the expression
- in. To evaluate the condition however, it doesn't
- really matter which instantiation of the function
- where the condition makes sense triggers the
- watchpoint. This allows an expression like "watch
- global if q > 10" set in `func', catch writes to
- global on all threads that call `func', or catch
- writes on all recursive calls of `func' by a single
- thread. We simply always evaluate the condition in
- the innermost frame that's executing where it makes
- sense to evaluate the condition. It seems
- intuitive. */
- frame = block_innermost_frame (w->cond_exp_valid_block);
- if (frame != NULL)
- select_frame (frame);
- else
- within_current_scope = 0;
- }
- if (within_current_scope)
- value_is_zero
- = catch_errors (breakpoint_cond_eval, cond,
- "Error in testing breakpoint condition:\n",
- RETURN_MASK_ALL);
+ struct frame_info *frame;
+
+ /* For local watchpoint expressions, which particular
+ instance of a local is being watched matters, so we
+ keep track of the frame to evaluate the expression
+ in. To evaluate the condition however, it doesn't
+ really matter which instantiation of the function
+ where the condition makes sense triggers the
+ watchpoint. This allows an expression like "watch
+ global if q > 10" set in `func', catch writes to
+ global on all threads that call `func', or catch
+ writes on all recursive calls of `func' by a single
+ thread. We simply always evaluate the condition in
+ the innermost frame that's executing where it makes
+ sense to evaluate the condition. It seems
+ intuitive. */
+ frame = block_innermost_frame (w->cond_exp_valid_block);
+ if (frame != NULL)
+ select_frame (frame);
else
- {
- warning (_("Watchpoint condition cannot be tested "
- "in the current scope"));
- /* If we failed to set the right context for this
- watchpoint, unconditionally report it. */
- value_is_zero = 0;
- }
- /* FIXME-someday, should give breakpoint #. */
- value_free_to_mark (mark);
- }
-
- if (cond && value_is_zero)
- {
- bs->stop = 0;
+ within_current_scope = 0;
}
- else if (b->thread != -1 && b->thread != thread_id)
+ if (within_current_scope)
+ value_is_zero
+ = catch_errors (breakpoint_cond_eval, cond,
+ "Error in testing breakpoint condition:\n",
+ RETURN_MASK_ALL);
+ else
{
- bs->stop = 0;
+ warning (_("Watchpoint condition cannot be tested "
+ "in the current scope"));
+ /* If we failed to set the right context for this
+ watchpoint, unconditionally report it. */
+ value_is_zero = 0;
}
- else if (b->ignore_count > 0)
- {
- b->ignore_count--;
- bs->stop = 0;
- /* Increase the hit count even though we don't stop. */
- ++(b->hit_count);
- observer_notify_breakpoint_modified (b);
- }
+ /* FIXME-someday, should give breakpoint #. */
+ value_free_to_mark (mark);
+ }
+
+ if (cond && value_is_zero)
+ {
+ bs->stop = 0;
+ }
+ else if (b->thread != -1 && b->thread != thread_id)
+ {
+ bs->stop = 0;
}
+ else if (b->ignore_count > 0)
+ {
+ b->ignore_count--;
+ bs->stop = 0;
+ /* Increase the hit count even though we don't stop. */
+ ++(b->hit_count);
+ observer_notify_breakpoint_modified (b);
+ }
}
----- with -b added -----
--- breakpoint.c~ 2013-11-02 13:42:45.321034724 -0700
+++ breakpoint.c 2013-11-11 19:18:21.525399880 -0800
@@ -5099,8 +5099,8 @@ bpstat_check_watchpoint (bpstat bs)
}
}
-
-/* Check conditions (condition proper, frame, thread and ignore count)
+/* For breakpoints that are currently marked as telling gdb to stop,
+ check conditions (condition proper, frame, thread and ignore count)
of breakpoint referred to by BS. If we should not stop for this
breakpoint, set BS->stop to 0. */
@@ -5110,6 +5110,10 @@ bpstat_check_breakpoint_conditions (bpst
int thread_id = pid_to_thread_id (ptid);
const struct bp_location *bl;
struct breakpoint *b;
+ int value_is_zero = 0;
+ struct expression *cond;
+
+ gdb_assert (bs->stop);
/* BS is built for existing struct breakpoint. */
bl = bs->bp_location_at;
@@ -5123,14 +5127,12 @@ bpstat_check_breakpoint_conditions (bpst
if (frame_id_p (b->frame_id)
&& !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
- bs->stop = 0;
- else if (bs->stop)
{
- int value_is_zero = 0;
- struct expression *cond;
+ bs->stop = 0;
+ return;
+ }
- /* Evaluate Python breakpoints that have a "stop"
- method implemented. */
+ /* Evaluate Python breakpoints that have a "stop" method implemented. */
if (b->py_bp_object)
bs->stop = gdbpy_should_stop (b->py_bp_object);
@@ -5225,7 +5227,6 @@ bpstat_check_breakpoint_conditions (bpst
++(b->hit_count);
observer_notify_breakpoint_modified (b);
}
- }
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] simplify bpstat_check_breakpoint_conditions
2013-11-12 7:58 [PATCH] simplify bpstat_check_breakpoint_conditions Doug Evans
@ 2013-11-12 9:54 ` Pedro Alves
2013-11-13 3:03 ` [PATCH] Don't evaluate condition for non-matching thread Doug Evans
0 siblings, 1 reply; 4+ messages in thread
From: Pedro Alves @ 2013-11-12 9:54 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches
On 11/12/2013 04:05 AM, Doug Evans wrote:
> This patch simplifies bpstat_check_breakpoint_conditions a bit.
>
> Regression tested on amd64-linux.
> Ok to check in?
Looks good to me.
> [Appended at the end is the same patch with diff's -b option added
> to make the actual changes easier to see.]
Thanks, that's quite helpful.
>
> 2013-11-11 Doug Evans <xdje42@gmail.com>
>
> * breakpoint.c (bpstat_check_breakpoint_conditions): Assert
> bs->stop != 0 on entry. Update function comment. Simplify early
> exit for frame mismatch. Reindent rest of function.
--
Pedro Alves
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Don't evaluate condition for non-matching thread
2013-11-12 9:54 ` Pedro Alves
@ 2013-11-13 3:03 ` Doug Evans
2013-11-13 9:59 ` Pedro Alves
0 siblings, 1 reply; 4+ messages in thread
From: Doug Evans @ 2013-11-13 3:03 UTC (permalink / raw)
To: Pedro Alves, gdb-patches
Pedro Alves <palves@redhat.com> writes:
> On 11/12/2013 04:05 AM, Doug Evans wrote:
>
>> This patch simplifies bpstat_check_breakpoint_conditions a bit.
>>
>> Regression tested on amd64-linux.
>> Ok to check in?
>
> Looks good to me.
Thanks.
Next patch.
Is there a reason the current code is the way it is?
Evaluating breakpoint conditions is expensive,
and to do so for a thread-specific breakpoint on a non-matching
thread is an awful waste.
I read the thread-specific breakpoints section of the docs
and didn't find anything.
Regression tested on amd64-linux,
but no claim is made that I'm sure there isn't some gotcha
for why things are the way they are (including "Oops, but it's in the
wild now and reason X means we can't change it." :-)).
Thank goodness the ignore_count check is done after the thread-id check
so there's no change w.r.t. ignore counts.
[I realize conditions can have side-effects, to, e.g., collect data,
but the user has made the breakpoint thread-specific already.]
If you think this warrants a NEWS entry I can certainly add one.
Ok to check in?
2013-11-12 Doug Evans <xdje42@gmail.com>
* breakpoint.c (bpstat_check_breakpoint_conditions): For thread
specific breakpoints, don't evaluate breakpoint condition if
different thread.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 36252ee..ebb8336 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5132,6 +5132,14 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
return;
}
+ /* If this is a thread-specific breakpoint, don't waste cpu evaluating the
+ condition if this isn't the specified thread. */
+ if (b->thread != -1 && b->thread != thread_id)
+ {
+ bs->stop = 0;
+ return;
+ }
+
/* Evaluate Python breakpoints that have a "stop" method implemented. */
if (b->py_bp_object)
bs->stop = gdbpy_should_stop (b->py_bp_object);
@@ -5215,10 +5223,6 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
{
bs->stop = 0;
}
- else if (b->thread != -1 && b->thread != thread_id)
- {
- bs->stop = 0;
- }
else if (b->ignore_count > 0)
{
b->ignore_count--;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Don't evaluate condition for non-matching thread
2013-11-13 3:03 ` [PATCH] Don't evaluate condition for non-matching thread Doug Evans
@ 2013-11-13 9:59 ` Pedro Alves
0 siblings, 0 replies; 4+ messages in thread
From: Pedro Alves @ 2013-11-13 9:59 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches
On 11/13/2013 03:01 AM, Doug Evans wrote:
> Is there a reason the current code is the way it is?
I can't think of any. I'm actually surprised we do this.
We'd get the same effect if/when we push the thread check
down to the target, and I wouldn't imagine this "always eval
condition first" blocking such new feature.
> [I realize conditions can have side-effects, to, e.g., collect data,
> but the user has made the breakpoint thread-specific already.]
Yeah. There are several other ways to get to same result, so
it's not a real issue, IMO.
> If you think this warrants a NEWS entry I can certainly add one.
I don't think so.
> Ok to check in?
OK.
Thanks,
--
Pedro Alves
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-11-13 9:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-12 7:58 [PATCH] simplify bpstat_check_breakpoint_conditions Doug Evans
2013-11-12 9:54 ` Pedro Alves
2013-11-13 3:03 ` [PATCH] Don't evaluate condition for non-matching thread Doug Evans
2013-11-13 9:59 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).