aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/frame-info.c26
-rw-r--r--gdb/frame-info.h20
2 files changed, 40 insertions, 6 deletions
diff --git a/gdb/frame-info.c b/gdb/frame-info.c
index 584222d..40a872e 100644
--- a/gdb/frame-info.c
+++ b/gdb/frame-info.c
@@ -31,7 +31,10 @@ intrusive_list<frame_info_ptr> frame_info_ptr::frame_list;
void
frame_info_ptr::prepare_reinflate ()
{
- m_cached_id = get_frame_id (*this);
+ m_cached_level = frame_relative_level (*this);
+
+ if (m_cached_level != 0)
+ m_cached_id = get_frame_id (*this);
}
/* See frame-info-ptr.h. */
@@ -39,9 +42,24 @@ frame_info_ptr::prepare_reinflate ()
void
frame_info_ptr::reinflate ()
{
- gdb_assert (frame_id_p (m_cached_id));
+ /* Ensure we have a valid frame level (sentinel frame or above), indicating
+ prepare_reinflate was called. */
+ gdb_assert (m_cached_level >= -1);
+
+ if (m_ptr != nullptr)
+ {
+ /* The frame_info wasn't invalidated, no need to reinflate. */
+ return;
+ }
+
+ /* Frame #0 needs special handling, see comment in select_frame. */
+ if (m_cached_level == 0)
+ m_ptr = get_current_frame ().get ();
+ else
+ {
+ gdb_assert (frame_id_p (m_cached_id));
+ m_ptr = frame_find_by_id (m_cached_id).get ();
+ }
- if (m_ptr == nullptr)
- m_ptr = frame_find_by_id (m_cached_id).get ();
gdb_assert (m_ptr != nullptr);
}
diff --git a/gdb/frame-info.h b/gdb/frame-info.h
index 1d2d4bd..3369b11 100644
--- a/gdb/frame-info.h
+++ b/gdb/frame-info.h
@@ -56,16 +56,21 @@ public:
}
frame_info_ptr (const frame_info_ptr &other)
- : m_ptr (other.m_ptr), m_cached_id (other.m_cached_id)
+ : m_ptr (other.m_ptr),
+ m_cached_id (other.m_cached_id),
+ m_cached_level (other.m_cached_level)
{
frame_list.push_back (*this);
}
frame_info_ptr (frame_info_ptr &&other)
- : m_ptr (other.m_ptr), m_cached_id (other.m_cached_id)
+ : m_ptr (other.m_ptr),
+ m_cached_id (other.m_cached_id),
+ m_cached_level (other.m_cached_level)
{
other.m_ptr = nullptr;
other.m_cached_id = null_frame_id;
+ other.m_cached_level = invalid_level;
frame_list.push_back (*this);
}
@@ -78,6 +83,7 @@ public:
{
m_ptr = other.m_ptr;
m_cached_id = other.m_cached_id;
+ m_cached_level = other.m_cached_level;
return *this;
}
@@ -85,6 +91,7 @@ public:
{
m_ptr = nullptr;
m_cached_id = null_frame_id;
+ m_cached_level = invalid_level;
return *this;
}
@@ -92,8 +99,10 @@ public:
{
m_ptr = other.m_ptr;
m_cached_id = other.m_cached_id;
+ m_cached_level = other.m_cached_level;
other.m_ptr = nullptr;
other.m_cached_id = null_frame_id;
+ other.m_cached_level = invalid_level;
return *this;
}
@@ -136,6 +145,10 @@ public:
void reinflate ();
private:
+ /* We sometimes need to construct frame_info_ptr objects around the
+ sentinel_frame, which has level -1. Therefore, make the invalid frame
+ level value -2. */
+ static constexpr int invalid_level = -2;
/* The underlying pointer. */
frame_info *m_ptr = nullptr;
@@ -143,6 +156,9 @@ private:
/* The frame_id of the underlying pointer. */
frame_id m_cached_id = null_frame_id;
+ /* The frame level of the underlying pointer. */
+ int m_cached_level = invalid_level;
+
/* All frame_info_ptr objects are kept on an intrusive list.
This keeps their construction and destruction costs
reasonably small. */