Skip to content
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

[lldb] Remove UnwindPlan::Row shared_ptrs #132370

Merged
merged 1 commit into from
Mar 27, 2025
Merged

[lldb] Remove UnwindPlan::Row shared_ptrs #132370

merged 1 commit into from
Mar 27, 2025

Conversation

labath
Copy link
Collaborator

@labath labath commented Mar 21, 2025

The surrounding code doesn't use them anymore. This removes the internal usages.

This patch makes the Rows actual values. An alternative would be to make them unique_ptrs. That would make vector resizes faster at the cost of more pointer chasing and heap fragmentation. I don't know which one is better so I picked the simpler option.

The surrounding code doesn't use them anymore. This removes the internal
usages.

This patch makes the Rows actual values. An alternative would be to make
them unique_ptrs. That would make vector resizes faster at the cost of
more pointer chasing and heap fragmentation. I don't know which one is
better so I picked the simpler option.
@labath labath requested a review from JDevlieghere as a code owner March 21, 2025 10:32
@llvmbot llvmbot added the lldb label Mar 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 21, 2025

@llvm/pr-subscribers-lldb

Author: Pavel Labath (labath)

Changes

The surrounding code doesn't use them anymore. This removes the internal usages.

This patch makes the Rows actual values. An alternative would be to make them unique_ptrs. That would make vector resizes faster at the cost of more pointer chasing and heap fragmentation. I don't know which one is better so I picked the simpler option.


Full diff: https://github.com/llvm/llvm-project/pull/132370.diff

2 Files Affected:

  • (modified) lldb/include/lldb/Symbol/UnwindPlan.h (+5-22)
  • (modified) lldb/source/Symbol/UnwindPlan.cpp (+16-16)
diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h
index db9aade93b6ba..ddc54a9fdc8ae 100644
--- a/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -428,8 +428,6 @@ class UnwindPlan {
     bool m_unspecified_registers_are_undefined = false;
   }; // class Row
 
-  typedef std::shared_ptr<Row> RowSP;
-
   UnwindPlan(lldb::RegisterKind reg_kind)
       : m_register_kind(reg_kind), m_return_addr_register(LLDB_INVALID_REGNUM),
         m_plan_is_sourced_from_compiler(eLazyBoolCalculate),
@@ -437,25 +435,10 @@ class UnwindPlan {
         m_plan_is_for_signal_trap(eLazyBoolCalculate) {}
 
   // Performs a deep copy of the plan, including all the rows (expensive).
-  UnwindPlan(const UnwindPlan &rhs)
-      : m_plan_valid_ranges(rhs.m_plan_valid_ranges),
-        m_register_kind(rhs.m_register_kind),
-        m_return_addr_register(rhs.m_return_addr_register),
-        m_source_name(rhs.m_source_name),
-        m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler),
-        m_plan_is_valid_at_all_instruction_locations(
-            rhs.m_plan_is_valid_at_all_instruction_locations),
-        m_plan_is_for_signal_trap(rhs.m_plan_is_for_signal_trap),
-        m_lsda_address(rhs.m_lsda_address),
-        m_personality_func_addr(rhs.m_personality_func_addr) {
-    m_row_list.reserve(rhs.m_row_list.size());
-    for (const RowSP &row_sp : rhs.m_row_list)
-      m_row_list.emplace_back(new Row(*row_sp));
-  }
+  UnwindPlan(const UnwindPlan &rhs) = default;
+  UnwindPlan &operator=(const UnwindPlan &rhs) = default;
+
   UnwindPlan(UnwindPlan &&rhs) = default;
-  UnwindPlan &operator=(const UnwindPlan &rhs) {
-    return *this = UnwindPlan(rhs); // NB: moving from a temporary (deep) copy
-  }
   UnwindPlan &operator=(UnwindPlan &&) = default;
 
   ~UnwindPlan() = default;
@@ -486,7 +469,7 @@ class UnwindPlan {
   uint32_t GetInitialCFARegister() const {
     if (m_row_list.empty())
       return LLDB_INVALID_REGNUM;
-    return m_row_list.front()->GetCFAValue().GetRegisterNumber();
+    return m_row_list.front().GetCFAValue().GetRegisterNumber();
   }
 
   // This UnwindPlan may not be valid at every address of the function span.
@@ -569,7 +552,7 @@ class UnwindPlan {
   }
 
 private:
-  std::vector<RowSP> m_row_list;
+  std::vector<Row> m_row_list;
   std::vector<AddressRange> m_plan_valid_ranges;
   lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
                                       // are in terms of - will need to be
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index 48089cbdecd97..92daf29630ab6 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -391,29 +391,29 @@ bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
 }
 
 void UnwindPlan::AppendRow(Row row) {
-  if (m_row_list.empty() || m_row_list.back()->GetOffset() != row.GetOffset())
-    m_row_list.push_back(std::make_shared<Row>(std::move(row)));
+  if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
+    m_row_list.push_back(std::move(row));
   else
-    *m_row_list.back() = std::move(row);
+    m_row_list.back() = std::move(row);
 }
 
 struct RowLess {
-  bool operator()(addr_t a, const UnwindPlan::RowSP &b) const {
-    return a < b->GetOffset();
+  bool operator()(addr_t a, const UnwindPlan::Row &b) const {
+    return a < b.GetOffset();
   }
-  bool operator()(const UnwindPlan::RowSP &a, addr_t b) const {
-    return a->GetOffset() < b;
+  bool operator()(const UnwindPlan::Row &a, addr_t b) const {
+    return a.GetOffset() < b;
   }
 };
 
 void UnwindPlan::InsertRow(Row row, bool replace_existing) {
   auto it = llvm::lower_bound(m_row_list, row.GetOffset(), RowLess());
-  if (it == m_row_list.end() || it->get()->GetOffset() > row.GetOffset())
-    m_row_list.insert(it, std::make_shared<Row>(std::move(row)));
+  if (it == m_row_list.end() || it->GetOffset() > row.GetOffset())
+    m_row_list.insert(it, std::move(row));
   else {
-    assert(it->get()->GetOffset() == row.GetOffset());
+    assert(it->GetOffset() == row.GetOffset());
     if (replace_existing)
-      **it = std::move(row);
+      *it = std::move(row);
   }
 }
 
@@ -424,7 +424,7 @@ const UnwindPlan::Row *UnwindPlan::GetRowForFunctionOffset(int offset) const {
     return nullptr;
   // upper_bound returns the row strictly greater than our desired offset, which
   // means that the row before it is a match.
-  return std::prev(it)->get();
+  return &*std::prev(it);
 }
 
 bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
@@ -433,7 +433,7 @@ bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
 
 const UnwindPlan::Row *UnwindPlan::GetRowAtIndex(uint32_t idx) const {
   if (idx < m_row_list.size())
-    return m_row_list[idx].get();
+    return &m_row_list[idx];
   LLDB_LOG(GetLog(LLDBLog::Unwind),
            "error: UnwindPlan::GetRowAtIndex(idx = {0}) invalid index "
            "(number rows is {1})",
@@ -447,7 +447,7 @@ const UnwindPlan::Row *UnwindPlan::GetLastRow() const {
              "UnwindPlan::GetLastRow() when rows are empty");
     return nullptr;
   }
-  return m_row_list.back().get();
+  return &m_row_list.back();
 }
 
 bool UnwindPlan::PlanValidAtAddress(Address addr) {
@@ -566,9 +566,9 @@ void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
       range.Dump(&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
     s.EOL();
   }
-  for (const auto &[index, row_sp] : llvm::enumerate(m_row_list)) {
+  for (const auto &[index, row] : llvm::enumerate(m_row_list)) {
     s.Format("row[{0}]: ", index);
-    row_sp->Dump(s, this, thread, base_addr);
+    row.Dump(s, this, thread, base_addr);
     s << "\n";
   }
 }

Copy link
Member

@bulbazord bulbazord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems ok to me. I think a good follow-up might be to stop handing out row pointers in case somebody tries to store one in the future. The pointers won't be stable as the vector resizes, but rows in unique_ptrs seems like a poor use of memory as well.

Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no one uses the SP stuff this is a good change.

@labath
Copy link
Collaborator Author

labath commented Mar 26, 2025

This seems ok to me. I think a good follow-up might be to stop handing out row pointers in case somebody tries to store one in the future.

How would you achieve that? By returning copies of the Row? That seems wasteful..

I don't think there's much risk in persisting row. There are many places that construct unwind plans, but there's basically just one user of it -- RegisterContextUnwind. And if someone really wants to store them, he has two options -- make a copy of the row, or store a (shared) pointer to the entire unwind plan.

The pointers won't be stable as the vector resizes, but rows in unique_ptrs seems like a poor use of memory as well.

They are unstable, but only during construction. What I'm actually thinking is to guarantee that UnwindPlans are immutable after construction. That's very important since they are cached, accessed from multiple threads and whatnot, and it would also guarantee pointer stability.

If no one uses the SP stuff this is a good change.

They aren't, because I removed all the uses earlier :D

@labath labath merged commit d7cea2b into llvm:main Mar 27, 2025
12 checks passed
@labath labath deleted the rm-sp branch March 27, 2025 10:26
@Michael137
Copy link
Member

Still double checking but i think this may have broken a couple of macOS x86_64 tests: https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/lldb-cmake/10909/

TestTsanMultiple.test_dsym/a.out")

runCmd: env TSAN_OPTIONS=abort_on_error=0

output: 

runCmd: run

warning: libclang_rt.tsan_osx_dynamic.dylib was compiled with optimization - stepping may behave oddly; variables may not be available.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  liblldb.21.0.99git.dylib 0x000000011c97b778 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 40
1  liblldb.21.0.99git.dylib 0x000000011c979789 llvm::sys::RunSignalHandlers() + 233
2  liblldb.21.0.99git.dylib 0x000000011c97bdd6 SignalHandler(int, __siginfo*, void*) + 278
3  libsystem_platform.dylib 0x00007ff80b4d0e9d _sigtramp + 29
4  libsystem_platform.dylib 0x0000700007db4860 _sigtramp + 18446726515825457632
5  liblldb.21.0.99git.dylib 0x0000000118618347 lldb_private::x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(unsigned char*, unsigned long, lldb_private::AddressRange&, lldb_private::UnwindPlan&, std::__1::shared_ptr<lldb_private::RegisterContext>&) + 919
6  liblldb.21.0.99git.dylib 0x0000000118614045 UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(lldb_private::AddressRange&, lldb_private::Thread&, lldb_private::UnwindPlan&) + 997
7  liblldb.21.0.99git.dylib 0x0000000119819113 lldb_private::FuncUnwinders::GetEHFrameAugmentedUnwindPlan(lldb_private::Target&, lldb_private::Thread&) + 387
8  liblldb.21.0.99git.dylib 0x0000000119819ace lldb_private::FuncUnwinders::GetUnwindPlanAtNonCallSite(lldb_private::Target&, lldb_private::Thread&) + 446
9  liblldb.21.0.99git.dylib 0x0000000119898102 lldb_private::RegisterContextUnwind::GetFullUnwindPlanForFrame() + 2978
10 liblldb.21.0.99git.dylib 0x00000001198952a7 lldb_private::RegisterContextUnwind::InitializeZerothFrame() + 1383
11 liblldb.21.0.99git.dylib 0x0000000119896e23 lldb_private::RegisterContextUnwind::RegisterContextUnwind(lldb_private::Thread&, std::__1::shared_ptr<lldb_private::RegisterContextUnwind> const&, lldb_private::SymbolContext&, unsigned int, lldb_private::UnwindLLDB&) + 243
12 liblldb.21.0.99git.dylib
...

rupprecht added a commit to rupprecht/llvm-project that referenced this pull request Mar 27, 2025
This reverts commit d7cea2b. It causes crashes in API tests.
rupprecht added a commit that referenced this pull request Mar 27, 2025
This reverts commit d7cea2b. It causes
crashes in API tests.
@rupprecht
Copy link
Collaborator

Saw the same thing running tests internally; reverted.

@labath
Copy link
Collaborator Author

labath commented Mar 31, 2025

Thanks for reverting this while I was gone. It looks like there's still some pointer persistence. I'll take a look at that a bit later...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants