innermost frame.
The current frame, which is the innermost frame, can be found at
- sentinel_frame->prev. */
+ sentinel_frame->prev.
+
+ This is an optimization to be able to find the sentinel frame quickly,
+ it could otherwise be found in the frame cache. */
static frame_info *sentinel_frame;
static bool
frame_stash_add (frame_info *frame)
{
- /* Do not try to stash the sentinel frame. */
- gdb_assert (frame->level >= 0);
+ /* Valid frame levels are -1 (sentinel frames) and above. */
+ gdb_assert (frame->level >= -1);
frame_info **slot = (frame_info **) htab_find_slot (frame_stash,
frame, INSERT);
}
const struct frame_id null_frame_id = { 0 }; /* All zeros. */
-const struct frame_id sentinel_frame_id = { 0, 0, 0, FID_STACK_SENTINEL, 0, 1, 0 };
const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_OUTER, 0, 1, 0 };
struct frame_id
return id;
}
+/* See frame.h. */
+
+frame_id
+frame_id_build_sentinel (CORE_ADDR stack_addr, CORE_ADDR code_addr)
+{
+ frame_id id = null_frame_id;
+
+ id.stack_status = FID_STACK_SENTINEL;
+ id.special_addr_p = 1;
+
+ if (stack_addr != 0 || code_addr != 0)
+ {
+ /* The purpose of saving these in the sentinel frame ID is to be able to
+ differentiate the IDs of several sentinel frames that could exist
+ simultaneously in the frame cache. */
+ id.stack_addr = stack_addr;
+ id.code_addr = code_addr;
+ id.code_addr_p = 1;
+ }
+
+ return id;
+}
+
bool
frame_id_p (frame_id l)
{
return NULL;
/* Check for the sentinel frame. */
- if (id == sentinel_frame_id)
+ if (id == frame_id_build_sentinel (0, 0))
return frame_info_ptr (sentinel_frame);
/* Try using the frame stash first. Finding it there removes the need
}
}
-/* Create a sentinel frame. */
+/* Create a sentinel frame.
-static frame_info *
-create_sentinel_frame (struct program_space *pspace, struct regcache *regcache)
+ See frame_id_build_sentinel for the description of STACK_ADDR and
+ CODE_ADDR. */
+
+static frame_info_ptr
+create_sentinel_frame (struct program_space *pspace, struct regcache *regcache,
+ CORE_ADDR stack_addr, CORE_ADDR code_addr)
{
frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
frame->next = frame;
/* The sentinel frame has a special ID. */
frame->this_id.p = frame_id_status::COMPUTED;
- frame->this_id.value = sentinel_frame_id;
+ frame->this_id.value = frame_id_build_sentinel (stack_addr, code_addr);
+
+ bool added = frame_stash_add (frame);
+ gdb_assert (added);
frame_debug_printf (" -> %s", frame->to_string ().c_str ());
- return frame;
+ return frame_info_ptr (frame);
}
/* Cache for frame addresses already read by gdb. Valid only while
if (sentinel_frame == NULL)
sentinel_frame =
- create_sentinel_frame (current_program_space, get_current_regcache ());
+ create_sentinel_frame (current_program_space, get_current_regcache (),
+ 0, 0).get ();
/* Set the current frame before computing the frame id, to avoid
recursion inside compute_frame_id, in case the frame's
frame_info *fi = FRAME_OBSTACK_ZALLOC (struct frame_info);
fi->next = create_sentinel_frame (current_program_space,
- get_current_regcache ());
+ get_current_regcache (),
+ id.stack_addr, id.code_addr).get ();
/* Set/update this frame's cached PC value, found in the next frame.
Do this before looking for this frame's unwinder. A sniffer is
is the sentinel frame. But we disallow it here anyway because
calling get_next_frame_sentinel_okay() on the sentinel frame
is likely a coding error. */
- gdb_assert (this_frame != sentinel_frame);
+ if (this_frame->this_id.p == frame_id_status::COMPUTED)
+ gdb_assert (!is_sentinel_frame_id (this_frame->this_id.value));
return frame_info_ptr (this_frame->next);
}
{
++frame_cache_generation;
- if (sentinel_frame != NULL)
+ if (htab_elements (frame_stash) > 0)
annotate_frames_invalid ();
invalidate_selected_frame ();