[Lldb-commits] [lldb] 6891812 - [lldb] Improve memory usage by freeing CTF types (NFC)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Mon Jul 31 09:47:52 PDT 2023


Author: Jonas Devlieghere
Date: 2023-07-31T09:47:46-07:00
New Revision: 68918125c11648379b473d8b2d297872cea9f504

URL: https://github.com/llvm/llvm-project/commit/68918125c11648379b473d8b2d297872cea9f504
DIFF: https://github.com/llvm/llvm-project/commit/68918125c11648379b473d8b2d297872cea9f504.diff

LOG: [lldb] Improve memory usage by freeing CTF types (NFC)

Improve memory usage by reducing the lifetime of CTF types. Once a CTF
type has been converted to a (complete) LLDB type, there's no need to
keep it in memory anymore. For most types, we can free them right after
creating the corresponding LLDB types. The only exception is record
types, which are only completed lazily.

Differential revision: https://reviews.llvm.org/D156606

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
    lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
    lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
index 99a74dbe674aea..c1016b2af0c6bc 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
+++ b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
@@ -46,6 +46,8 @@ struct CTFInteger : public CTFType {
              uint32_t encoding)
       : CTFType(eInteger, uid, name), bits(bits), encoding(encoding) {}
 
+  static bool classof(const CTFType *T) { return T->kind == eInteger; }
+
   uint32_t bits;
   uint32_t encoding;
 };
@@ -55,6 +57,11 @@ struct CTFModifier : public CTFType {
   CTFModifier(Kind kind, lldb::user_id_t uid, uint32_t type)
       : CTFType(kind, uid, ""), type(type) {}
 
+  static bool classof(const CTFType *T) {
+    return T->kind == ePointer || T->kind == eConst || T->kind == eVolatile ||
+           T->kind == eRestrict;
+  }
+
 public:
   uint32_t type;
 };
@@ -62,27 +69,36 @@ struct CTFModifier : public CTFType {
 struct CTFPointer : public CTFModifier {
   CTFPointer(lldb::user_id_t uid, uint32_t type)
       : CTFModifier(ePointer, uid, type) {}
+
+  static bool classof(const CTFType *T) { return T->kind == ePointer; }
 };
 
 struct CTFConst : public CTFModifier {
   CTFConst(lldb::user_id_t uid, uint32_t type)
       : CTFModifier(eConst, uid, type) {}
+
+  static bool classof(const CTFType *T) { return T->kind == eConst; }
 };
 
 struct CTFVolatile : public CTFModifier {
   CTFVolatile(lldb::user_id_t uid, uint32_t type)
       : CTFModifier(eVolatile, uid, type) {}
+
+  static bool classof(const CTFType *T) { return T->kind == eVolatile; }
 };
 
 struct CTFRestrict : public CTFModifier {
   CTFRestrict(lldb::user_id_t uid, uint32_t type)
       : CTFModifier(eRestrict, uid, type) {}
+  static bool classof(const CTFType *T) { return T->kind == eRestrict; }
 };
 
 struct CTFTypedef : public CTFType {
   CTFTypedef(lldb::user_id_t uid, llvm::StringRef name, uint32_t type)
       : CTFType(eTypedef, uid, name), type(type) {}
 
+  static bool classof(const CTFType *T) { return T->kind == eTypedef; }
+
   uint32_t type;
 };
 
@@ -91,6 +107,8 @@ struct CTFArray : public CTFType {
            uint32_t index, uint32_t nelems)
       : CTFType(eArray, uid, name), type(type), index(index), nelems(nelems) {}
 
+  static bool classof(const CTFType *T) { return T->kind == eArray; }
+
   uint32_t type;
   uint32_t index;
   uint32_t nelems;
@@ -110,6 +128,8 @@ struct CTFEnum : public CTFType {
     assert(this->values.size() == nelems);
   }
 
+  static bool classof(const CTFType *T) { return T->kind == eEnum; }
+
   uint32_t nelems;
   uint32_t size;
   std::vector<Value> values;
@@ -121,6 +141,8 @@ struct CTFFunction : public CTFType {
       : CTFType(eFunction, uid, name), nargs(nargs), return_type(return_type),
         args(std::move(args)), variadic(variadic) {}
 
+  static bool classof(const CTFType *T) { return T->kind == eFunction; }
+
   uint32_t nargs;
   uint32_t return_type;
 
@@ -144,6 +166,10 @@ struct CTFRecord : public CTFType {
       : CTFType(kind, uid, name), nfields(nfields), size(size),
         fields(std::move(fields)) {}
 
+  static bool classof(const CTFType *T) {
+    return T->kind == eStruct || T->kind == eUnion;
+  }
+
   uint32_t nfields;
   uint32_t size;
   std::vector<Field> fields;
@@ -153,17 +179,23 @@ struct CTFStruct : public CTFRecord {
   CTFStruct(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields,
             uint32_t size, std::vector<Field> fields)
       : CTFRecord(eStruct, uid, name, nfields, size, std::move(fields)){};
+
+  static bool classof(const CTFType *T) { return T->kind == eStruct; }
 };
 
 struct CTFUnion : public CTFRecord {
   CTFUnion(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields,
            uint32_t size, std::vector<Field> fields)
       : CTFRecord(eUnion, uid, name, nfields, size, std::move(fields)){};
+
+  static bool classof(const CTFType *T) { return T->kind == eUnion; }
 };
 
 struct CTFForward : public CTFType {
   CTFForward(lldb::user_id_t uid, llvm::StringRef name)
       : CTFType(eForward, uid, name) {}
+
+  static bool classof(const CTFType *T) { return T->kind == eForward; }
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
index 55e3a1ddb96165..89329d1abf5dcb 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
@@ -523,8 +523,7 @@ bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {
   assert(ctf_type && "m_compiler_types should only contain valid CTF types");
 
   // We only support resolving record types.
-  assert(ctf_type->kind == CTFType::Kind::eStruct ||
-         ctf_type->kind == CTFType::Kind::eUnion);
+  assert(llvm::isa<CTFRecord>(ctf_type));
 
   // Cast to the appropriate CTF type.
   const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);
@@ -551,9 +550,10 @@ bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {
   }
   m_ast->CompleteTagDeclarationDefinition(compiler_type);
 
-  // Now that the compiler type is no longer incomplete we don't need to
-  // remember it anymore.
+  // Now that the compiler type is complete, we don't need to remember it
+  // anymore and can remove the CTF record type.
   m_compiler_types.erase(compiler_type.GetOpaqueQualType());
+  m_ctf_types.erase(ctf_type->uid);
 
   return true;
 }
@@ -727,9 +727,8 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {
     llvm::Expected<std::unique_ptr<CTFType>> type_or_error =
         ParseType(type_offset, type_uid);
     if (type_or_error) {
-      m_ctf_types.emplace_back(std::move(*type_or_error));
+      m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error);
     } else {
-      m_ctf_types.emplace_back(std::unique_ptr<CTFType>());
       LLDB_LOG_ERROR(log, type_or_error.takeError(),
                      "Failed to parse type {1} at offset {2}: {0}", type_uid,
                      type_offset);
@@ -982,16 +981,16 @@ void SymbolFileCTF::AddSymbols(Symtab &symtab) {
 }
 
 lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
-  auto find_result = m_types.find(type_uid);
-  if (find_result != m_types.end())
-    return find_result->second.get();
+  auto type_it = m_types.find(type_uid);
+  if (type_it != m_types.end())
+    return type_it->second.get();
 
-  if (type_uid == 0 || type_uid > m_ctf_types.size())
+  auto ctf_type_it = m_ctf_types.find(type_uid);
+  if (ctf_type_it == m_ctf_types.end())
     return nullptr;
 
-  CTFType *ctf_type = m_ctf_types[type_uid - 1].get();
-  if (!ctf_type)
-    return nullptr;
+  CTFType *ctf_type = ctf_type_it->second.get();
+  assert(ctf_type && "m_ctf_types should only contain valid CTF types");
 
   Log *log = GetLog(LLDBLog::Symbols);
 
@@ -1013,6 +1012,11 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
 
   m_types[type_uid] = type_sp;
 
+  // Except for record types which we'll need to complete later, we don't need
+  // the CTF type anymore.
+  if (!isa<CTFRecord>(ctf_type))
+    m_ctf_types.erase(type_uid);
+
   return type_sp.get();
 }
 

diff  --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
index 2b046708c6db3c..787dc1892bb3dd 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
@@ -245,15 +245,17 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon {
 
   std::optional<ctf_header_t> m_header;
 
-  std::vector<std::unique_ptr<CTFType>> m_ctf_types;
+  /// Parsed CTF types.
+  llvm::DenseMap<lldb::user_id_t, std::unique_ptr<CTFType>> m_ctf_types;
+
+  /// Parsed LLDB types.
+  llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
 
   /// To complete types, we need a way to map (imcomplete) compiler types back
   /// to parsed CTF types.
   llvm::DenseMap<lldb::opaque_compiler_type_t, const CTFType *>
       m_compiler_types;
 
-  llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
-
   std::vector<lldb::FunctionSP> m_functions;
   std::vector<lldb::VariableSP> m_variables;
 


        


More information about the lldb-commits mailing list