[Lldb-commits] [lldb] bd1b3d4 - [lldb] Reduce size of Mangled class (#200181)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 1 03:27:14 PDT 2026
Author: Raphael Isemann
Date: 2026-06-01T10:27:08Z
New Revision: bd1b3d47462acf4f854f593bdd77b3f127adea46
URL: https://github.com/llvm/llvm-project/commit/bd1b3d47462acf4f854f593bdd77b3f127adea46
DIFF: https://github.com/llvm/llvm-project/commit/bd1b3d47462acf4f854f593bdd77b3f127adea46.diff
LOG: [lldb] Reduce size of Mangled class (#200181)
The Mangled class is used in several places in LLDB, most notably as a
direct member of Symbol. This makes this class one of the most
frequently long-lived allocations in LLDB.
In commit a2672250be871bdac18c1a955265a98704434218 , this class got a
(large) cache that stores information about demangled data. This cache
is stored in a std::optional member, which means the memory for the
class is allocated within our Mangled object. It should be noted that
this cache is only used when we actually demangle the name, which
doesn't happen for every mangled name we encounter.
The additional cache member caused that the size of Mangled went from
16B to 152B by default (that is, even if the Mangled name was never
demangled).
This patch replaces the std::optional with a unique_ptr which stores the
cache on first use in a separate heap allocation. This changes decreases
the amount of allocated memory when debugging a relatively small
Objective-C project from 1.57GiB to 1.18GiB (-400MiB).
Added:
Modified:
lldb/include/lldb/Core/Mangled.h
lldb/source/Core/Mangled.cpp
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/unittests/Core/MangledTest.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 546d7a9b409ed..e1ac0e8761f70 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -53,6 +53,28 @@ class Mangled {
/// Initialize with both mangled and demangled names empty.
Mangled() = default;
+ Mangled(const Mangled &other)
+ : m_mangled(other.m_mangled), m_demangled(other.m_demangled),
+ m_demangled_info(
+ other.m_demangled_info
+ ? std::make_unique<DemangledNameInfo>(*other.m_demangled_info)
+ : nullptr) {}
+
+ Mangled &operator=(const Mangled &other) {
+ if (this != &other) {
+ m_mangled = other.m_mangled;
+ m_demangled = other.m_demangled;
+ m_demangled_info =
+ other.m_demangled_info
+ ? std::make_unique<DemangledNameInfo>(*other.m_demangled_info)
+ : nullptr;
+ }
+ return *this;
+ }
+
+ Mangled(Mangled &&) = default;
+ Mangled &operator=(Mangled &&) = default;
+
/// Construct with name.
///
/// Constructor with an optional string and auto-detect if \a name is
@@ -279,7 +301,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 +330,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::unique_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..3f72571cee9ca 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -285,11 +285,10 @@ 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 +318,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));
+ m_demangled_info =
+ std::make_unique<DemangledNameInfo>(std::move(demangled.second));
break;
}
case eManglingSchemeRustV0:
@@ -556,8 +556,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 == nullptr)
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..530bc1950a2c8 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);
- EXPECT_TRUE(info1->hasBasename());
+ ASSERT_NE(mangled.GetDemangledInfo(), nullptr);
+ // Keep a copy of the original demangled info.
+ DemangledNameInfo info1 = *mangled.GetDemangledInfo();
+ EXPECT_TRUE(info1.hasBasename());
mangled.SetMangledName(ConstString("_Z4funcv"));
// Should have re-calculated demangled-info since mangled name changed.
- auto info2 = mangled.GetDemangledInfo();
- ASSERT_NE(info2, std::nullopt);
- EXPECT_TRUE(info2->hasBasename());
+ ASSERT_NE(mangled.GetDemangledInfo(), nullptr);
+ DemangledNameInfo info2 = *mangled.GetDemangledInfo();
+ EXPECT_TRUE(info2.hasBasename());
- EXPECT_FALSE(NameInfoEquals(info1.value(), info2.value()));
+ EXPECT_FALSE(NameInfoEquals(info1, info2));
EXPECT_EQ(mangled.GetDemangledName(), "func()");
}
@@ -383,45 +384,46 @@ 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();
+ ASSERT_NE(mangled.GetDemangledInfo(), nullptr);
+ // Keep a copy of the original demangled info.
+ 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()));
+ ASSERT_NE(mangled.GetDemangledInfo(), nullptr);
+ DemangledNameInfo demangled_foo = *mangled.GetDemangledInfo();
+ 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());
}
More information about the lldb-commits
mailing list