Skip to content

Commit df1442a

Browse files
authored
Merge pull request #6623 from apple/🍒/5.9/730c8e160c9d
[lldb] Move "SelectMostRelevantFrame" from Thread::WillStop
2 parents a438cb3 + c0d6680 commit df1442a

File tree

4 files changed

+59
-38
lines changed

4 files changed

+59
-38
lines changed

lldb/include/lldb/Target/StackFrameList.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class StackFrameList {
4646
uint32_t SetSelectedFrame(lldb_private::StackFrame *frame);
4747

4848
/// Get the currently selected frame index.
49-
uint32_t GetSelectedFrameIndex() const;
49+
uint32_t GetSelectedFrameIndex();
5050

5151
/// Mark a stack frame as the currently selected frame using the frame index
5252
/// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected.
@@ -110,6 +110,8 @@ class StackFrameList {
110110

111111
void SetCurrentInlinedDepth(uint32_t new_depth);
112112

113+
void SelectMostRelevantFrame();
114+
113115
typedef std::vector<lldb::StackFrameSP> collection;
114116
typedef collection::iterator iterator;
115117
typedef collection::const_iterator const_iterator;
@@ -134,8 +136,10 @@ class StackFrameList {
134136
/// changes.
135137
collection m_frames;
136138

137-
/// The currently selected frame.
138-
uint32_t m_selected_frame_idx;
139+
/// The currently selected frame. An optional is used to record whether anyone
140+
/// has set the selected frame on this stack yet. We only let recognizers
141+
/// change the frame if this is the first time GetSelectedFrame is called.
142+
std::optional<uint32_t> m_selected_frame_idx;
139143

140144
/// The number of concrete frames fetched while filling the frame list. This
141145
/// is only used when synthetic frames are enabled.

lldb/include/lldb/Target/Thread.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,6 @@ class Thread : public std::enable_shared_from_this<Thread>,
217217

218218
virtual void RefreshStateAfterStop() = 0;
219219

220-
void SelectMostRelevantFrame();
221-
222220
std::string GetStopDescription();
223221

224222
std::string GetStopDescriptionRaw();

lldb/source/Target/StackFrameList.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "lldb/Target/Process.h"
1919
#include "lldb/Target/RegisterContext.h"
2020
#include "lldb/Target/StackFrame.h"
21+
#include "lldb/Target/StackFrameRecognizer.h"
2122
#include "lldb/Target/StopInfo.h"
2223
#include "lldb/Target/Target.h"
2324
#include "lldb/Target/Thread.h"
@@ -38,7 +39,7 @@ StackFrameList::StackFrameList(Thread &thread,
3839
const lldb::StackFrameListSP &prev_frames_sp,
3940
bool show_inline_frames)
4041
: m_thread(thread), m_prev_frames_sp(prev_frames_sp), m_mutex(), m_frames(),
41-
m_selected_frame_idx(0), m_concrete_frames_fetched(0),
42+
m_selected_frame_idx(), m_concrete_frames_fetched(0),
4243
m_current_inlined_depth(UINT32_MAX),
4344
m_current_inlined_pc(LLDB_INVALID_ADDRESS),
4445
m_show_inlined_frames(show_inline_frames) {
@@ -252,7 +253,7 @@ struct CallDescriptor {
252253
using CallSequence = std::vector<CallDescriptor>;
253254

254255
/// Find the unique path through the call graph from \p begin (with return PC
255-
/// \p return_pc) to \p end. On success this path is stored into \p path, and
256+
/// \p return_pc) to \p end. On success this path is stored into \p path, and
256257
/// on failure \p path is unchanged.
257258
static void FindInterveningFrames(Function &begin, Function &end,
258259
ExecutionContext &exe_ctx, Target &target,
@@ -776,9 +777,46 @@ bool StackFrameList::SetFrameAtIndex(uint32_t idx, StackFrameSP &frame_sp) {
776777
return false; // resize failed, out of memory?
777778
}
778779

779-
uint32_t StackFrameList::GetSelectedFrameIndex() const {
780+
void StackFrameList::SelectMostRelevantFrame() {
781+
// Don't call into the frame recognizers on the private state thread as
782+
// they can cause code to run in the target, and that can cause deadlocks
783+
// when fetching stop events for the expression.
784+
if (m_thread.GetProcess()->CurrentThreadIsPrivateStateThread())
785+
return;
786+
787+
Log *log = GetLog(LLDBLog::Thread);
788+
789+
// Only the top frame should be recognized.
790+
StackFrameSP frame_sp = GetFrameAtIndex(0);
791+
if (!frame_sp) {
792+
LLDB_LOG(log, "Failed to construct Frame #0");
793+
return;
794+
}
795+
796+
RecognizedStackFrameSP recognized_frame_sp = frame_sp->GetRecognizedFrame();
797+
798+
if (!recognized_frame_sp) {
799+
LLDB_LOG(log, "Frame #0 not recognized");
800+
return;
801+
}
802+
803+
if (StackFrameSP most_relevant_frame_sp =
804+
recognized_frame_sp->GetMostRelevantFrame()) {
805+
LLDB_LOG(log, "Found most relevant frame at index {0}",
806+
most_relevant_frame_sp->GetFrameIndex());
807+
SetSelectedFrame(most_relevant_frame_sp.get());
808+
} else {
809+
LLDB_LOG(log, "No relevant frame!");
810+
}
811+
}
812+
813+
uint32_t StackFrameList::GetSelectedFrameIndex() {
780814
std::lock_guard<std::recursive_mutex> guard(m_mutex);
781-
return m_selected_frame_idx;
815+
if (!m_selected_frame_idx)
816+
SelectMostRelevantFrame();
817+
if (!m_selected_frame_idx)
818+
m_selected_frame_idx = 0;
819+
return *m_selected_frame_idx;
782820
}
783821

784822
uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
@@ -787,17 +825,19 @@ uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
787825
const_iterator begin = m_frames.begin();
788826
const_iterator end = m_frames.end();
789827
m_selected_frame_idx = 0;
828+
790829
for (pos = begin; pos != end; ++pos) {
791830
if (pos->get() == frame) {
792831
m_selected_frame_idx = std::distance(begin, pos);
793832
uint32_t inlined_depth = GetCurrentInlinedDepth();
794833
if (inlined_depth != UINT32_MAX)
795-
m_selected_frame_idx -= inlined_depth;
834+
m_selected_frame_idx = *m_selected_frame_idx - inlined_depth;
796835
break;
797836
}
798837
}
838+
799839
SetDefaultFileAndLineToSelectedFrame();
800-
return m_selected_frame_idx;
840+
return *m_selected_frame_idx;
801841
}
802842

803843
bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
@@ -825,10 +865,16 @@ void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
825865

826866
// The thread has been run, reset the number stack frames to zero so we can
827867
// determine how many frames we have lazily.
868+
// Note, we don't actually re-use StackFrameLists, we always make a new
869+
// StackFrameList every time we stop, and then copy frame information frame
870+
// by frame from the old to the new StackFrameList. So the comment above,
871+
// does not describe how StackFrameLists are currently used.
872+
// Clear is currently only used to clear the list in the destructor.
828873
void StackFrameList::Clear() {
829874
std::lock_guard<std::recursive_mutex> guard(m_mutex);
830875
m_frames.clear();
831876
m_concrete_frames_fetched = 0;
877+
m_selected_frame_idx.reset();
832878
}
833879

834880
lldb::StackFrameSP

lldb/source/Target/Thread.cpp

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -605,36 +605,9 @@ std::string Thread::GetStopDescriptionRaw() {
605605
return raw_stop_description;
606606
}
607607

608-
void Thread::SelectMostRelevantFrame() {
609-
Log *log = GetLog(LLDBLog::Thread);
610-
611-
auto frames_list_sp = GetStackFrameList();
612-
613-
// Only the top frame should be recognized.
614-
auto frame_sp = frames_list_sp->GetFrameAtIndex(0);
615-
616-
auto recognized_frame_sp = frame_sp->GetRecognizedFrame();
617-
618-
if (!recognized_frame_sp) {
619-
LLDB_LOG(log, "Frame #0 not recognized");
620-
return;
621-
}
622-
623-
if (StackFrameSP most_relevant_frame_sp =
624-
recognized_frame_sp->GetMostRelevantFrame()) {
625-
LLDB_LOG(log, "Found most relevant frame at index {0}",
626-
most_relevant_frame_sp->GetFrameIndex());
627-
SetSelectedFrame(most_relevant_frame_sp.get());
628-
} else {
629-
LLDB_LOG(log, "No relevant frame!");
630-
}
631-
}
632-
633608
void Thread::WillStop() {
634609
ThreadPlan *current_plan = GetCurrentPlan();
635610

636-
SelectMostRelevantFrame();
637-
638611
// FIXME: I may decide to disallow threads with no plans. In which
639612
// case this should go to an assert.
640613

0 commit comments

Comments
 (0)