[Lldb-commits] [lldb] [lldb] Reduce size of Mangled class (PR #200181)

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Thu May 28 07:11:32 PDT 2026


https://github.com/Teemperor updated https://github.com/llvm/llvm-project/pull/200181

>From 32dd888227c812d1cdb5663ffcfbf00799a454fb Mon Sep 17 00:00:00 2001
From: Raphael Isemann <rise at apple.com>
Date: Thu, 28 May 2026 14:22:54 +0100
Subject: [PATCH] [lldb] Reduce size of Mangled class

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).
---
 lldb/include/lldb/Core/Mangled.h              | 26 +++++++++++++++++--
 lldb/source/Core/Mangled.cpp                  | 12 +++++----
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  |  2 +-
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 546d7a9b409ed..aa805cb108e63 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;
+  std::optional<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 794e94d4626fd..03ca35c17bbeb 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -285,11 +285,12 @@ ConstString Mangled::GetDemangledName() const {
   return GetDemangledNameImpl(/*force=*/false);
 }
 
-std::optional<DemangledNameInfo> const &Mangled::GetDemangledInfo() const {
+std::optional<DemangledNameInfo> Mangled::GetDemangledInfo() const {
   if (!m_demangled_info)
     GetDemangledNameImpl(/*force=*/true);
-
-  return m_demangled_info;
+  if (!m_demangled_info)
+    return std::nullopt;
+  return *m_demangled_info;
 }
 
 // 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));
+    m_demangled_info =
+        std::make_unique<DemangledNameInfo>(std::move(demangled.second));
     break;
   }
   case eManglingSchemeRustV0:
@@ -556,7 +558,7 @@ void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const {
 }
 
 ConstString Mangled::GetBaseName() const {
-  const auto &demangled_info = GetDemangledInfo();
+  const auto demangled_info = GetDemangledInfo();
   if (!demangled_info.has_value())
     return {};
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 7e68d25c0110f..389bb19c1bae5 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 std::optional<DemangledNameInfo> info = mangled.GetDemangledInfo();
   if (!info)
     return llvm::createStringErrorV(
         "function '{0}' does not have demangled info", demangled_name);



More information about the lldb-commits mailing list