Index: lldb/trunk/include/lldb/Target/StackFrameList.h =================================================================== --- lldb/trunk/include/lldb/Target/StackFrameList.h +++ lldb/trunk/include/lldb/Target/StackFrameList.h @@ -10,14 +10,10 @@ #ifndef liblldb_StackFrameList_h_ #define liblldb_StackFrameList_h_ -// C Includes -// C++ Includes #include #include #include -// Other libraries and framework includes -// Project includes #include "lldb/Target/StackFrame.h" namespace lldb_private { @@ -32,22 +28,33 @@ ~StackFrameList(); + /// Get the number of visible frames. Frames may be created if \p can_create + /// is true. Synthetic (inline) frames expanded from the concrete frame #0 + /// (aka invisible frames) are not included in this count. uint32_t GetNumFrames(bool can_create = true); + /// Get the frame at index \p idx. Invisible frames cannot be indexed. lldb::StackFrameSP GetFrameAtIndex(uint32_t idx); + /// Get the first concrete frame with index greater than or equal to \p idx. + /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame. lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); + /// Retrieve the stack frame with the given ID \p stack_id. lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id); - // Mark a stack frame as the current frame + /// Mark a stack frame as the currently selected frame and return its index. uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); + /// Get the currently selected frame index. uint32_t GetSelectedFrameIndex() const; - // Mark a stack frame as the current frame using the frame index + /// Mark a stack frame as the currently selected frame using the frame index + /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected. bool SetSelectedFrameByIndex(uint32_t idx); + /// If the current inline depth (i.e the number of invisible frames) is valid, + /// subtract it from \p idx. Otherwise simply return \p idx. uint32_t GetVisibleStackFrameIndex(uint32_t idx) { if (m_current_inlined_depth < UINT32_MAX) return idx - m_current_inlined_depth; @@ -55,16 +62,23 @@ return idx; } + /// Calculate and set the current inline depth. This may be used to update + /// the StackFrameList's set of inline frames when execution stops, e.g when + /// a breakpoint is hit. void CalculateCurrentInlinedDepth(); + /// If the currently selected frame comes from the currently selected thread, + /// point the default file and line of the thread's target to the location + /// specified by the frame. void SetDefaultFileAndLineToSelectedFrame(); + /// Clear the cache of frames. void Clear(); - void InvalidateFrames(uint32_t start_idx); - void Dump(Stream *s); + /// If \p stack_frame_ptr is contained in this StackFrameList, return its + /// wrapping shared pointer. lldb::StackFrameSP GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr); @@ -101,14 +115,44 @@ typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; + /// The thread this frame list describes. Thread &m_thread; + + /// The old stack frame list. + // TODO: The old stack frame list is used to fill in missing frame info + // heuristically when it's otherwise unavailable (say, because the unwinder + // fails). We should have stronger checks to make sure that this is a valid + // source of information. lldb::StackFrameListSP m_prev_frames_sp; + + /// A mutex for this frame list. + // TODO: This mutex may not always be held when required. In particular, uses + // of the StackFrameList APIs in lldb_private::Thread look suspect. Consider + // passing around a lock_guard reference to enforce proper locking. mutable std::recursive_mutex m_mutex; + + /// A cache of frames. This may need to be updated when the program counter + /// changes. collection m_frames; + + /// The currently selected frame. uint32_t m_selected_frame_idx; + + /// The number of concrete frames fetched while filling the frame list. This + /// is only used when synthetic frames are enabled. uint32_t m_concrete_frames_fetched; + + /// The number of synthetic function activations (invisible frames) expanded + /// from the concrete frame #0 activation. + // TODO: Use an optional instead of UINT32_MAX to denote invalid values. uint32_t m_current_inlined_depth; + + /// The program counter value at the currently selected synthetic activation. + /// This is only valid if m_current_inlined_depth is valid. + // TODO: Use an optional instead of UINT32_MAX to denote invalid values. lldb::addr_t m_current_inlined_pc; + + /// Whether or not to show synthetic (inline) frames. Immutable. const bool m_show_inlined_frames; private: Index: lldb/trunk/source/Target/StackFrameList.cpp =================================================================== --- lldb/trunk/source/Target/StackFrameList.cpp +++ lldb/trunk/source/Target/StackFrameList.cpp @@ -436,11 +436,7 @@ if (can_create) GetFramesUpTo(UINT32_MAX); - uint32_t inlined_depth = GetCurrentInlinedDepth(); - if (inlined_depth == UINT32_MAX) - return m_frames.size(); - else - return m_frames.size() - inlined_depth; + return GetVisibleStackFrameIndex(m_frames.size()); } void StackFrameList::Dump(Stream *s) { @@ -620,7 +616,6 @@ return m_selected_frame_idx; } -// Mark a stack frame as the current frame using the frame index bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) { std::lock_guard guard(m_mutex); StackFrameSP frame_sp(GetFrameAtIndex(idx)); @@ -652,19 +647,6 @@ m_concrete_frames_fetched = 0; } -void StackFrameList::InvalidateFrames(uint32_t start_idx) { - std::lock_guard guard(m_mutex); - if (m_show_inlined_frames) { - Clear(); - } else { - const size_t num_frames = m_frames.size(); - while (start_idx < num_frames) { - m_frames[start_idx].reset(); - ++start_idx; - } - } -} - void StackFrameList::Merge(std::unique_ptr &curr_ap, lldb::StackFrameListSP &prev_sp) { std::unique_lock current_lock, previous_lock;