[PATCH v4 10/12] btrace: Replace struct btrace_function::segment.

Tim Wiederhake
2017-05-10T11:48:01Z

This used to hold a pair of pointers to the previous and next function segment
that belong to this function call. Replace with a pair of indices into the
vector of function segments.

2017-05-10 Tim Wiederhake <tim.wiederhake@intel.com>

gdb/ChangeLog:

* btrace.c (ftrace_fixup_caller, ftrace_new_return, ftrace_connect_bfun,
ftrace_bridge_gap): Replace references to btrace_thread_info::segment
with btrace_thread_info::next_segment and
btrace_thread_info::prev_segment.
* btrace.h: Remove struct btrace_func_link.
(struct btrace_function): Replace pair of function segment pointers
with pair of indices.
* python/py-record-btrace.c (btpy_call_prev_sibling,
btpy_call_next_sibling): Replace references to
btrace_thread_info::segment with btrace_thread_info::next_segment and
btrace_thread_info::prev_segment.
* record-btrace.c (record_btrace_frame_this_id): Same.

---
gdb/btrace.c | 48 +++++++++++++++++++++++++------------------
gdb/btrace.h | 17 ++++++---------
gdb/python/py-record-btrace.c | 8 ++++----
gdb/record-btrace.c | 4 ++--
4 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index a5d246c..4841e90 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -271,20 +271,29 @@ ftrace_update_caller (struct btrace_function *bfun,
/* Fix up the caller for all segments of a function. */

static void
-ftrace_fixup_caller (struct btrace_function *bfun,
+ftrace_fixup_caller (struct btrace_thread_info *btinfo,
+ struct btrace_function *bfun,
struct btrace_function *caller,
enum btrace_function_flag flags)
{
- struct btrace_function *prev, *next;
+ unsigned int prev, next;

+ prev = bfun->prev;
+ next = bfun->next;
ftrace_update_caller (bfun, caller, flags);

/* Update all function segments belonging to the same function. */
- for (prev = bfun->segment.prev; prev != NULL; prev = prev->segment.prev)
- ftrace_update_caller (prev, caller, flags);
+ for (; prev != 0; prev = bfun->prev)
+ {
+ bfun = ftrace_find_call_by_number (btinfo, prev);
+ ftrace_update_caller (bfun, caller, flags);
+ }

- for (next = bfun->segment.next; next != NULL; next = next->segment.next)
- ftrace_update_caller (next, caller, flags);
+ for (; next != 0; next = bfun->next)
+ {
+ bfun = ftrace_find_call_by_number (btinfo, next);
+ ftrace_update_caller (bfun, caller, flags);
+ }
}

/* Add a new function segment for a call at the end of the trace.
@@ -414,10 +423,10 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
{
/* The caller of PREV is the preceding btrace function segment in this
function instance. */
- gdb_assert (caller->segment.next == NULL);
+ gdb_assert (caller->next == 0);

- caller->segment.next = bfun;
- bfun->segment.prev = caller;
+ caller->next = bfun->number;
+ bfun->prev = caller->number;

/* Maintain the function level. */
bfun->level = caller->level;
@@ -449,7 +458,7 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
bfun->level = prev->level - 1;

/* Fix up the call stack for PREV. */
- ftrace_fixup_caller (prev, bfun, BFUN_UP_LINKS_TO_RET);
+ ftrace_fixup_caller (btinfo, prev, bfun, BFUN_UP_LINKS_TO_RET);

ftrace_debug (bfun, "new return - no caller");
}
@@ -755,11 +764,11 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
ftrace_debug (next, "..next");

/* The function segments are not yet connected. */
- gdb_assert (prev->segment.next == NULL);
- gdb_assert (next->segment.prev == NULL);
+ gdb_assert (prev->next == 0);
+ gdb_assert (next->prev == 0);

- prev->segment.next = next;
- next->segment.prev = prev;
+ prev->next = next->number;
+ next->prev = prev->number;

/* We may have moved NEXT to a different function level. */
ftrace_fixup_level (btinfo, next, prev->level - next->level);
@@ -773,7 +782,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
if (next != NULL)
{
DEBUG_FTRACE ("using next's callers");
- ftrace_fixup_caller (prev, next, flags);
+ ftrace_fixup_caller (btinfo, prev, next, flags);
}
}
else if (next->up == 0)
@@ -784,7 +793,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
if (prev != NULL)
{
DEBUG_FTRACE ("using prev's callers");
- ftrace_fixup_caller (next, prev, flags);
+ ftrace_fixup_caller (btinfo, next, prev, flags);
}
}
else
@@ -812,7 +821,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
DEBUG_FTRACE ("adding prev's tail calls to next");

prev = ftrace_find_call_by_number (btinfo, prev->up);
- ftrace_fixup_caller (next, prev, prev_flags);
+ ftrace_fixup_caller (btinfo, next, prev, prev_flags);

for (; prev != NULL; prev = ftrace_find_call_by_number (btinfo,
prev->up))
@@ -824,7 +833,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
ftrace_debug (prev, "..top");
ftrace_debug (caller, "..up");

- ftrace_fixup_caller (prev, caller, next_flags);
+ ftrace_fixup_caller (btinfo, prev, caller, next_flags);

/* If we skipped any tail calls, this may move CALLER to a
different function level.
@@ -947,14 +956,13 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo,
static void
btrace_bridge_gaps (struct thread_info *tp, VEC (bfun_s) **gaps)
{
- struct btrace_thread_info *btinfo;
+ struct btrace_thread_info *btinfo = &tp->btrace;
VEC (bfun_s) *remaining;
struct cleanup *old_chain;
int min_matches;

DEBUG ("bridge gaps");

- btinfo = &tp->btrace;
remaining = NULL;
old_chain = make_cleanup (VEC_cleanup (bfun_s), &remaining);

diff --git a/gdb/btrace.h b/gdb/btrace.h
index d83e381..01f1888 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -85,13 +85,6 @@ struct btrace_insn
typedef struct btrace_insn btrace_insn_s;
DEF_VEC_O (btrace_insn_s);

-/* A doubly-linked list of branch trace function segments. */
-struct btrace_func_link
-{
- struct btrace_function *prev;
- struct btrace_function *next;
-};
-
/* Flags for btrace function segments. */
enum btrace_function_flag
{
@@ -146,10 +139,12 @@ struct btrace_function
struct minimal_symbol *msym;
struct symbol *sym;

- /* The previous and next segment belonging to the same function.
- If a function calls another function, the former will have at least
- two segments: one before the call and another after the return. */
- struct btrace_func_link segment;
+ /* The function segment numbers of the previous and next segment belonging to
+ the same function. If a function calls another function, the former will
+ have at least two segments: one before the call and another after the
+ return. Will be zero if there is no such function segment. */
+ unsigned int prev;
+ unsigned int next;

/* The function segment number of the directly preceding function segment in
a (fake) call stack. Will be zero if there is no such function segment in
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 9dd2199..cd2be9f 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -416,11 +416,11 @@ recpy_bt_func_prev (PyObject *self, void *closure)
if (func == NULL)
return NULL;

- if (func->segment.prev == NULL)
+ if (func->prev == 0)
Py_RETURN_NONE;

return recpy_func_new (((recpy_element_object *) self)->ptid,
- RECORD_METHOD_BTRACE, func->segment.prev->number);
+ RECORD_METHOD_BTRACE, func->prev);
}

/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
@@ -434,11 +434,11 @@ recpy_bt_func_next (PyObject *self, void *closure)
if (func == NULL)
return NULL;

- if (func->segment.next == NULL)
+ if (func->next == 0)
Py_RETURN_NONE;

return recpy_func_new (((recpy_element_object *) self)->ptid,
- RECORD_METHOD_BTRACE, func->segment.next->number);
+ RECORD_METHOD_BTRACE, func->next);
}

/* Implementation of BtraceList.__len__ (self) -> int. */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index a27521c..a66d32a 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1591,8 +1591,8 @@ record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
bfun = cache->bfun;
gdb_assert (bfun != NULL);

- while (bfun->segment.prev != NULL)
- bfun = bfun->segment.prev;
+ while (bfun->prev != 0)
+ bfun = cache->tp->btrace.functions[bfun->prev - 1];

code = get_frame_func (this_frame);
special = bfun->number;
--
2.7.4