[Lldb-commits] [lldb] [lldb] Reduce symbol table memory by storing `DemangledNameInfo` on heap (NFC) (PR #200495)
via lldb-commits
lldb-commits at lists.llvm.org
Fri May 29 13:51:58 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Dave Lee (kastiglione)
<details>
<summary>Changes</summary>
Change `m_demangled_info` from `std::optional<DemangledNameInfo>` to
`std::shared_ptr<DemangledNameInfo>`, which is a change from the unavoidable fixed costs
of inline storage, to lazy (dynamic cost) heap storage.
`DemangledNameInfo` is 128 bytes (8 pairs of size_t). After `std::optional` overhead,
the total is 136 bytes inline — regardless of whether the info is populated. This
dominates the size of `Mangled`, without it `Mangled` is just 16 bytes for two
`ConstString` instances.
By replacing optional with shared_ptr, the inline cost drops to 16 bytes, reducing
`Mangled` from 152 to 32 bytes — netting 120 bytes per `Symbol`.
The `DemangledNameInfo` is only applicable to Itanium-mangled C++ symbols, and is
produced on demand. Depending on the binary and the use, many (if not most) symbols will
have null for `DemangledNameInfo`.
shared_ptr is used instead of unique_ptr to preserve copyability of `Mangled`.
---
Full diff: https://github.com/llvm/llvm-project/pull/200495.diff
4 Files Affected:
- (modified) lldb/include/lldb/Core/Mangled.h (+2-2)
- (modified) lldb/source/Core/Mangled.cpp (+7-5)
- (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+1-1)
- (modified) lldb/unittests/Core/MangledTest.cpp (+17-17)
``````````diff
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 546d7a9b409ed..bf4a68370d5a1 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -279,7 +279,7 @@ class Mangled {
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;
/// Retrieve \c DemangledNameInfo of the demangled name held by this object.
- const std::optional<DemangledNameInfo> &GetDemangledInfo() const;
+ const DemangledNameInfo *GetDemangledInfo() const;
/// Compute the base name (without namespace/class qualifiers) from the
/// demangled name.
@@ -308,7 +308,7 @@ class Mangled {
/// If available, holds information about where in \c m_demangled certain
/// parts of the name (e.g., basename, arguments, etc.) begin and end.
- mutable std::optional<DemangledNameInfo> m_demangled_info = std::nullopt;
+ mutable std::shared_ptr<DemangledNameInfo> m_demangled_info;
};
Stream &operator<<(Stream &s, const Mangled &obj);
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 66c785d5871cc..47770649a90ea 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -25,6 +25,7 @@
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/Compiler.h"
+#include <memory>
#include <mutex>
#include <string>
#include <string_view>
@@ -285,11 +286,11 @@ ConstString Mangled::GetDemangledName() const {
return GetDemangledNameImpl(/*force=*/false);
}
-std::optional<DemangledNameInfo> const &Mangled::GetDemangledInfo() const {
+const DemangledNameInfo *Mangled::GetDemangledInfo() const {
if (!m_demangled_info)
GetDemangledNameImpl(/*force=*/true);
- return m_demangled_info;
+ return m_demangled_info.get();
}
// Generate the demangled name on demand using this accessor. Code in this
@@ -319,7 +320,8 @@ ConstString Mangled::GetDemangledNameImpl(bool force) const {
std::pair<char *, DemangledNameInfo> demangled =
GetItaniumDemangledStr(m_mangled.GetCString());
demangled_name = demangled.first;
- m_demangled_info.emplace(std::move(demangled.second));
+ if (demangled_name)
+ m_demangled_info = std::make_shared<DemangledNameInfo>(demangled.second);
break;
}
case eManglingSchemeRustV0:
@@ -556,8 +558,8 @@ void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const {
}
ConstString Mangled::GetBaseName() const {
- const auto &demangled_info = GetDemangledInfo();
- if (!demangled_info.has_value())
+ const auto *demangled_info = GetDemangledInfo();
+ if (!demangled_info)
return {};
ConstString demangled_name = GetDemangledName();
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 7e68d25c0110f..74a5a414de67b 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -269,7 +269,7 @@ GetAndValidateInfo(const SymbolContext &sc) {
"function '{0}' does not have a demangled name",
mangled.GetMangledName());
- const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
+ const DemangledNameInfo *info = mangled.GetDemangledInfo();
if (!info)
return llvm::createStringErrorV(
"function '{0}' does not have demangled info", demangled_name);
diff --git a/lldb/unittests/Core/MangledTest.cpp b/lldb/unittests/Core/MangledTest.cpp
index 706e67801e01a..97bd239c544b9 100644
--- a/lldb/unittests/Core/MangledTest.cpp
+++ b/lldb/unittests/Core/MangledTest.cpp
@@ -355,23 +355,24 @@ static bool NameInfoEquals(const DemangledNameInfo &lhs,
TEST(MangledTest, DemangledNameInfo_SetMangledResets) {
Mangled mangled;
- EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
+ EXPECT_EQ(mangled.GetDemangledInfo(), nullptr);
mangled.SetMangledName(ConstString("_Z3foov"));
ASSERT_TRUE(mangled);
- auto info1 = mangled.GetDemangledInfo();
- EXPECT_NE(info1, std::nullopt);
+ auto *info1 = mangled.GetDemangledInfo();
+ EXPECT_NE(info1, nullptr);
EXPECT_TRUE(info1->hasBasename());
+ DemangledNameInfo prev_info = *info1;
mangled.SetMangledName(ConstString("_Z4funcv"));
// Should have re-calculated demangled-info since mangled name changed.
- auto info2 = mangled.GetDemangledInfo();
- ASSERT_NE(info2, std::nullopt);
+ auto *info2 = mangled.GetDemangledInfo();
+ ASSERT_NE(info2, nullptr);
EXPECT_TRUE(info2->hasBasename());
- EXPECT_FALSE(NameInfoEquals(info1.value(), info2.value()));
+ EXPECT_FALSE(NameInfoEquals(prev_info, *info2));
EXPECT_EQ(mangled.GetDemangledName(), "func()");
}
@@ -383,45 +384,44 @@ TEST(MangledTest, DemangledNameInfo_SetDemangledResets) {
// Mangled name hasn't changed, so GetDemangledInfo causes re-demangling
// of previously set mangled name.
- EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
+ EXPECT_NE(mangled.GetDemangledInfo(), nullptr);
EXPECT_EQ(mangled.GetDemangledName(), "foo()");
}
TEST(MangledTest, DemangledNameInfo_Clear) {
Mangled mangled("_Z3foov");
ASSERT_TRUE(mangled);
- EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
+ EXPECT_NE(mangled.GetDemangledInfo(), nullptr);
mangled.Clear();
- EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
+ EXPECT_EQ(mangled.GetDemangledInfo(), nullptr);
}
TEST(MangledTest, DemangledNameInfo_SetValue) {
Mangled mangled("_Z4funcv");
ASSERT_TRUE(mangled);
- auto demangled_func = mangled.GetDemangledInfo();
+ DemangledNameInfo demangled_func = *mangled.GetDemangledInfo();
// SetValue(mangled) resets demangled-info
mangled.SetValue(ConstString("_Z3foov"));
- auto demangled_foo = mangled.GetDemangledInfo();
- EXPECT_NE(demangled_foo, std::nullopt);
- EXPECT_FALSE(NameInfoEquals(demangled_foo.value(), demangled_func.value()));
+ auto *demangled_foo = mangled.GetDemangledInfo();
+ EXPECT_NE(demangled_foo, nullptr);
+ EXPECT_FALSE(NameInfoEquals(*demangled_foo, demangled_func));
// SetValue(demangled) resets demangled-info
mangled.SetValue(ConstString("_Z4funcv"));
- EXPECT_TRUE(NameInfoEquals(mangled.GetDemangledInfo().value(),
- demangled_func.value()));
+ EXPECT_TRUE(NameInfoEquals(*mangled.GetDemangledInfo(), demangled_func));
// SetValue(empty) resets demangled-info
mangled.SetValue(ConstString());
- EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
+ EXPECT_EQ(mangled.GetDemangledInfo(), nullptr);
// Demangling invalid mangled name will set demangled-info
// (without a valid basename).
mangled.SetValue(ConstString("_Zinvalid"));
- ASSERT_NE(mangled.GetDemangledInfo(), std::nullopt);
+ ASSERT_NE(mangled.GetDemangledInfo(), nullptr);
EXPECT_FALSE(mangled.GetDemangledInfo()->hasBasename());
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/200495
More information about the lldb-commits
mailing list