Skip to content

[lldb] Update async step-in implementation #2835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lldb/include/lldb/Target/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -2211,6 +2211,10 @@ bool PruneThreadPlansForTID(lldb::tid_t tid);
/// Prune ThreadPlanStacks for all unreported threads.
void PruneThreadPlans();

void SynchronizeThreadPlans();

lldb::ThreadPlanSP FindDetachedPlanExplainingStop(Thread &thread, Event *event_ptr);

/// Find the thread plan stack associated with thread with \a tid.
///
/// \param[in] tid
Expand Down Expand Up @@ -2838,6 +2842,7 @@ void PruneThreadPlans();
/// threads in m_thread_list, as well as
/// threads we knew existed, but haven't
/// determined that they have died yet.
std::vector<ThreadPlanStack> m_async_thread_plans;
ThreadList m_extended_thread_list; ///< Owner for extended threads that may be
///generated, cleared on natural stops
uint32_t m_extended_thread_stop_id; ///< The natural stop id when
Expand Down
9 changes: 9 additions & 0 deletions lldb/include/lldb/Target/ThreadPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,15 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
return m_takes_iteration_count;
}

bool IsTID(lldb::tid_t tid) { return tid == m_tid; }
bool HasTID() { return m_tid != LLDB_INVALID_THREAD_ID; }
void ClearTID() { m_tid = LLDB_INVALID_THREAD_ID; }
lldb::tid_t GetTID() { return m_tid; }
void SetTID(lldb::tid_t tid) { m_tid = tid; }

friend lldb::ThreadPlanSP
Process::FindDetachedPlanExplainingStop(Thread &thread, Event *event_ptr);

protected:
// Constructors and Destructors
ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
Expand Down
32 changes: 31 additions & 1 deletion lldb/include/lldb/Target/ThreadPlanStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class ThreadPlanStack {
/// generated.
void ClearThreadCache();

bool IsTID(lldb::tid_t tid);
lldb::tid_t GetTID();
void SetTID(lldb::tid_t tid);

private:
void PrintOneStack(Stream &s, llvm::StringRef stack_name,
const PlanStack &stack, lldb::DescriptionLevel desc_level,
Expand Down Expand Up @@ -152,8 +156,34 @@ class ThreadPlanStackMap {
plan_list.second.ClearThreadCache();
}

// rename to Reactivate?
void Activate(ThreadPlanStack &&stack) {
if (m_plans_list.find(stack.GetTID()) == m_plans_list.end())
m_plans_list.emplace(stack.GetTID(), std::move(stack));
else
m_plans_list.at(stack.GetTID()) = std::move(stack);
}

// rename to ...?
std::vector<ThreadPlanStack> CleanUp() {
llvm::SmallVector<lldb::tid_t, 2> invalidated_tids;
for (auto &pair : m_plans_list)
if (pair.second.GetTID() != pair.first)
invalidated_tids.push_back(pair.first);

std::vector<ThreadPlanStack> detached_stacks;
detached_stacks.reserve(invalidated_tids.size());
for (auto tid : invalidated_tids) {
auto it = m_plans_list.find(tid);
auto stack = std::move(it->second);
m_plans_list.erase(it);
detached_stacks.emplace_back(std::move(stack));
}
return detached_stacks;
}

void Clear() {
for (auto plan : m_plans_list)
for (auto &plan : m_plans_list)
plan.second.ThreadDestroyed(nullptr);
m_plans_list.clear();
}
Expand Down
29 changes: 28 additions & 1 deletion lldb/source/Target/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,31 @@ void Process::UpdateThreadListIfNeeded() {
}
}

void Process::SynchronizeThreadPlans() {
for (auto &stack : m_thread_plans.CleanUp())
m_async_thread_plans.emplace_back(std::move(stack));
}

ThreadPlanSP Process::FindDetachedPlanExplainingStop(Thread &thread,
Event *event_ptr) {
auto end = m_async_thread_plans.end();
for (auto it = m_async_thread_plans.begin(); it != end; ++it) {
auto plan_sp = it->GetCurrentPlan();
plan_sp->SetTID(thread.GetID());
if (!plan_sp->DoPlanExplainsStop(event_ptr)) {
plan_sp->ClearTID();
continue;
}

auto stack = std::move(*it);
m_async_thread_plans.erase(it);
stack.SetTID(plan_sp->GetTID());
m_thread_plans.Activate(std::move(stack));
return plan_sp;
}
return {};
}

ThreadPlanStack *Process::FindThreadPlans(lldb::tid_t tid) {
return m_thread_plans.Find(tid);
}
Expand Down Expand Up @@ -3483,8 +3508,10 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
// restarted... Asking the thread list is also not likely to go well,
// since we are running again. So in that case just report the event.

if (!was_restarted)
if (!was_restarted) {
should_resume = !m_thread_list.ShouldStop(event_ptr);
SynchronizeThreadPlans();
}

if (was_restarted || should_resume || m_resume_requested) {
Vote report_stop_vote = m_thread_list.ShouldReportStop(event_ptr);
Expand Down
17 changes: 6 additions & 11 deletions lldb/source/Target/StackFrameList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,27 +725,22 @@ StackFrameList::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
return frame_sp;
}

static bool CompareStackID(const StackFrameSP &stack_sp,
const StackID &stack_id) {
return stack_sp->GetStackID() < stack_id;
}

StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) {
StackFrameSP frame_sp;

if (stack_id.IsValid()) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
uint32_t frame_idx = 0;
// Do a binary search in case the stack frame is already in our cache
// Do a search in case the stack frame is already in our cache.
collection::const_iterator begin = m_frames.begin();
collection::const_iterator end = m_frames.end();
if (begin != end) {
collection::const_iterator pos =
std::lower_bound(begin, end, stack_id, CompareStackID);
if (pos != end) {
if ((*pos)->GetStackID() == stack_id)
return *pos;
}
std::find_if(begin, end, [&](StackFrameSP frame_sp) {
return frame_sp->GetStackID() == stack_id;
});
if (pos != end)
return *pos;
}
do {
frame_sp = GetFrameAtIndex(frame_idx);
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Target/StackID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ bool lldb_private::operator<(const StackID &lhs, const StackID &rhs) {
const lldb::addr_t lhs_cfa = lhs.GetCallFrameAddress();
const lldb::addr_t rhs_cfa = rhs.GetCallFrameAddress();

// FIXME: rdar://76119439
// This heuristic is a *temporary* fallback while proper fixes are
// determined. The heuristic assumes the CFA of async functions is a low
// (heap) address, and for normal functions it's a high (stack) address.
if (lhs_cfa - rhs_cfa >= 0x00007ff000000000ULL)
return true;

// FIXME: We are assuming that the stacks grow downward in memory. That's not
// necessary, but true on
// all the machines we care about at present. If this changes, we'll have to
Expand Down
Loading