diff options
-rw-r--r-- | gdb/frame-info.c | 26 | ||||
-rw-r--r-- | gdb/frame-info.h | 20 |
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. */ |