Skip to content

Commit 80e10a6

Browse files
committed
[lldb] Implement cache for swift typeref metadata
Implement a mechanism to cache field descriptor location information. One of the main problems of using type metadata as debug info, when in comes to field descriptors in particular, is that there's no easy way to find the correct type given a (string key), so a linear search over every source of reflection information must be done. This patch implements a cache which allows for field descriptors to be found in a more efficient manner.
1 parent 5e60c0a commit 80e10a6

File tree

14 files changed

+620
-30
lines changed

14 files changed

+620
-30
lines changed

lldb/include/lldb/Core/ModuleList.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ class ModuleListProperties : public Properties {
6565
bool GetSwiftValidateTypeSystem() const;
6666
SwiftModuleLoadingMode GetSwiftModuleLoadingMode() const;
6767
bool SetSwiftModuleLoadingMode(SwiftModuleLoadingMode);
68+
69+
bool GetEnableSwiftMetadataCache() const;
70+
uint64_t GetSwiftMetadataCacheMaxByteSize();
71+
uint64_t GetSwiftMetadataCacheExpirationDays();
72+
FileSpec GetSwiftMetadataCachePath() const;
73+
bool SetSwiftMetadataCachePath(const FileSpec &path);
6874
// END SWIFT
6975

7076
FileSpec GetClangModulesCachePath() const;

lldb/packages/Python/lldbsuite/test/lldbtest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,12 @@ def setUpCommands(cls):
735735
'settings set symbols.clang-modules-cache-path "{}"'.format(
736736
configuration.lldb_module_cache_dir),
737737

738+
# Enable the swift metadata cache in order to speed up tests.
739+
'settings set symbols.enable-swift-metadata-cache true',
740+
741+
'settings set symbols.swift-metadata-cache-path "{}"'.format(
742+
configuration.lldb_module_cache_dir),
743+
738744
# Enable expensive validations in TypeSystemSwiftTypeRef.
739745
'settings set symbols.swift-validate-typesystem true',
740746

lldb/source/Core/CoreProperties.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ let Definition = "modulelist" in {
3030
DefaultEnumValue<"eSwiftModuleLoadingModePreferSerialized">,
3131
EnumValues<"OptionEnumValues(g_swift_module_loading_mode_enums)">,
3232
Desc<"The module loading mode to use when loading modules for Swift.">;
33+
def EnableSwiftMetadataCache: Property<"enable-swift-metadata-cache", "Boolean">,
34+
Global,
35+
DefaultFalse,
36+
Desc<"Enable caching for Swift reflection metadata in LLDB.">;
37+
def SwiftMetadataCachePath: Property<"swift-metadata-cache-path", "FileSpec">,
38+
Global,
39+
DefaultStringValue<"">,
40+
Desc<"The path to LLDB's Swift reflection cache directory.">;
41+
def SwiftMetadataCacheMaxByteSize: Property<"swift-metadata-cache-max-byte-size", "UInt64">,
42+
Global,
43+
DefaultUnsignedValue<0>,
44+
Desc<"The maximum size for LLDB's Swift reflection cache directory in bytes. A value over the amount of available space on the disk will be reduced to the amount of available space. A value of 0 disables the absolute size-based pruning.">;
45+
def SwiftMetadataCacheExpirationDays: Property<"swift-metadata-cache-expiration-days", "UInt64">,
46+
Global,
47+
DefaultUnsignedValue<7>,
48+
Desc<"The expiration time in days for a Swift reflection cache file. When a file hasn't been accessed for the specified amount of days, it is removed from the cache. A value of 0 disables the expiration-based pruning.">;
3349
// END SWIFT
3450
def SymLinkPaths: Property<"debug-info-symlink-paths", "FileSpecList">,
3551
Global,

lldb/source/Core/ModuleList.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ ModuleListProperties::ModuleListProperties() {
108108

109109
// BEGIN SWIFT
110110
SetSwiftModuleLoadingMode(eSwiftModuleLoadingModePreferSerialized);
111+
112+
path.clear();
113+
if (llvm::sys::path::cache_directory(path)) {
114+
llvm::sys::path::append(path, "lldb");
115+
llvm::sys::path::append(path, "SwiftMetadataCache");
116+
lldbassert(SetLLDBIndexCachePath(FileSpec(path)));
117+
}
111118
// END SWIFT
112119

113120
path.clear();
@@ -194,6 +201,36 @@ bool ModuleListProperties::SetSwiftModuleLoadingMode(SwiftModuleLoadingMode mode
194201
return m_collection_sp->SetPropertyAtIndexAsEnumeration(
195202
nullptr, ePropertySwiftModuleLoadingMode, mode);
196203
}
204+
205+
FileSpec ModuleListProperties::GetSwiftMetadataCachePath() const {
206+
return m_collection_sp
207+
->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false,
208+
ePropertySwiftMetadataCachePath)
209+
->GetCurrentValue();
210+
}
211+
212+
bool ModuleListProperties::SetSwiftMetadataCachePath(const FileSpec &path) {
213+
return m_collection_sp->SetPropertyAtIndexAsFileSpec(
214+
nullptr, ePropertySwiftMetadataCachePath, path);
215+
}
216+
217+
bool ModuleListProperties::GetEnableSwiftMetadataCache() const {
218+
const uint32_t idx = ePropertyEnableSwiftMetadataCache;
219+
return m_collection_sp->GetPropertyAtIndexAsBoolean(
220+
nullptr, idx, g_modulelist_properties[idx].default_uint_value != 0);
221+
}
222+
223+
uint64_t ModuleListProperties::GetSwiftMetadataCacheMaxByteSize() {
224+
const uint32_t idx = ePropertySwiftMetadataCacheMaxByteSize;
225+
return m_collection_sp->GetPropertyAtIndexAsUInt64(
226+
nullptr, idx, g_modulelist_properties[idx].default_uint_value);
227+
}
228+
229+
uint64_t ModuleListProperties::GetSwiftMetadataCacheExpirationDays() {
230+
const uint32_t idx = ePropertySwiftMetadataCacheExpirationDays;
231+
return m_collection_sp->GetPropertyAtIndexAsUInt64(
232+
nullptr, idx, g_modulelist_properties[idx].default_uint_value);
233+
}
197234
// END SWIFT
198235

199236
FileSpec ModuleListProperties::GetLLDBIndexCachePath() const {

lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_lldb_library(lldbPluginSwiftLanguageRuntime PLUGIN
33
SwiftLanguageRuntime.cpp
44
SwiftLanguageRuntimeDynamicTypeResolution.cpp
55
SwiftLanguageRuntimeNames.cpp
6+
SwiftMetadataCache.cpp
67

78
LINK_LIBS
89
swiftAST

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "SwiftLanguageRuntime.h"
1414
#include "Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h"
1515
#include "SwiftLanguageRuntimeImpl.h"
16+
#include "SwiftMetadataCache.h"
1617

1718
#include "Plugins/Process/Utility/RegisterContext_x86.h"
1819
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -442,6 +443,13 @@ SwiftLanguageRuntimeImpl::GetReflectionContext() {
442443
return m_reflection_ctx.get();
443444
}
444445

446+
SwiftMetadataCache *
447+
SwiftLanguageRuntimeImpl::GetSwiftMetadataCache() {
448+
if (!m_swift_metadata_cache.is_enabled())
449+
return {};
450+
return &m_swift_metadata_cache;
451+
}
452+
445453
void SwiftLanguageRuntimeImpl::SetupReflection() {
446454
LLDB_SCOPED_TIMER();
447455

@@ -481,13 +489,13 @@ void SwiftLanguageRuntimeImpl::SetupReflection() {
481489
"Initializing a 64-bit reflection context (%s) for \"%s\"",
482490
triple.str().c_str(), objc_interop_msg);
483491
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64(
484-
this->GetMemoryReader(), objc_interop);
492+
this->GetMemoryReader(), objc_interop, GetSwiftMetadataCache());
485493
} else if (triple.isArch32Bit()) {
486494
LLDB_LOGF(GetLog(LLDBLog::Types),
487495
"Initializing a 32-bit reflection context (%s) for \"%s\"",
488496
triple.str().c_str(), objc_interop_msg);
489497
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32(
490-
this->GetMemoryReader(), objc_interop);
498+
this->GetMemoryReader(), objc_interop, GetSwiftMetadataCache());
491499
} else {
492500
LLDB_LOGF(GetLog(LLDBLog::Types),
493501
"Could not initialize reflection context for \"%s\"",
@@ -649,7 +657,7 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext(
649657
if (!obj_file_format)
650658
return false;
651659

652-
return m_reflection_ctx->addImage(
660+
auto reflection_info_id = m_reflection_ctx->addImage(
653661
[&](swift::ReflectionSectionKind section_kind)
654662
-> std::pair<swift::remote::RemoteRef<void>, uint64_t> {
655663
auto section_name = obj_file_format->getSectionName(section_kind);
@@ -676,9 +684,13 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext(
676684
return {};
677685
},
678686
likely_module_names);
687+
// We don't care to cache modules generated by the jit, because they will
688+
// only be used by the current process.
689+
return reflection_info_id.hasValue();
679690
}
680691

681-
bool SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext(
692+
llvm::Optional<uint32_t>
693+
SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext(
682694
ModuleSP module,
683695
llvm::SmallVector<llvm::StringRef, 1> likely_module_names) {
684696
auto obj_format_type =
@@ -856,27 +868,35 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext(
856868

857869
auto read_from_file_cache =
858870
GetMemoryReader()->readMetadataFromFileCacheEnabled();
871+
872+
llvm::Optional<uint32_t> info_id;
859873
// When dealing with ELF, we need to pass in the contents of the on-disk
860874
// file, since the Section Header Table is not present in the child process
861875
if (obj_file->GetPluginName().equals("elf")) {
862876
DataExtractor extractor;
863877
auto size = obj_file->GetData(0, obj_file->GetByteSize(), extractor);
864878
const uint8_t *file_data = extractor.GetDataStart();
865879
llvm::sys::MemoryBlock file_buffer((void *)file_data, size);
866-
m_reflection_ctx->readELF(
880+
info_id = m_reflection_ctx->readELF(
867881
swift::remote::RemoteAddress(load_ptr),
868882
llvm::Optional<llvm::sys::MemoryBlock>(file_buffer),
869883
likely_module_names);
870884
} else if (read_from_file_cache &&
871885
obj_file->GetPluginName().equals("mach-o")) {
872-
if (!AddObjectFileToReflectionContext(module_sp, likely_module_names)) {
873-
m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr),
886+
info_id = AddObjectFileToReflectionContext(module_sp, likely_module_names);
887+
if (!info_id)
888+
info_id = m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr),
874889
likely_module_names);
875-
}
876890
} else {
877-
m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr),
891+
info_id = m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr),
878892
likely_module_names);
879893
}
894+
895+
if (info_id)
896+
if (auto *swift_metadata_cache = GetSwiftMetadataCache())
897+
swift_metadata_cache->registerModuleWithReflectionInfoID(module_sp,
898+
*info_id);
899+
880900
return true;
881901
}
882902

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "LLDBMemoryReader.h"
14-
#include "SwiftLanguageRuntimeImpl.h"
1514
#include "SwiftLanguageRuntime.h"
15+
#include "SwiftLanguageRuntimeImpl.h"
16+
#include "SwiftMetadataCache.h"
1617

1718
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
1819
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -24,12 +25,13 @@
2425
#include "lldb/Utility/LLDBLog.h"
2526
#include "lldb/Utility/Log.h"
2627
#include "lldb/Utility/Timer.h"
27-
#include "swift/AST/Types.h"
28+
#include "llvm/ADT/STLExtras.h"
2829

2930
#include "swift/AST/ASTContext.h"
3031
#include "swift/AST/ASTMangler.h"
3132
#include "swift/AST/ASTWalker.h"
3233
#include "swift/AST/Decl.h"
34+
#include "swift/AST/Types.h"
3335
#include "swift/Demangling/Demangle.h"
3436
#include "swift/Reflection/ReflectionContext.h"
3537
#include "swift/Reflection/TypeRefBuilder.h"
@@ -241,24 +243,25 @@ class TargetReflectionContext
241243

242244
public:
243245
TargetReflectionContext(
244-
std::shared_ptr<swift::reflection::MemoryReader> reader)
245-
: m_reflection_ctx(reader) {}
246+
std::shared_ptr<swift::reflection::MemoryReader> reader,
247+
SwiftMetadataCache *swift_metadata_cache)
248+
: m_reflection_ctx(reader, swift_metadata_cache) {}
246249

247-
bool addImage(
250+
llvm::Optional<uint32_t> addImage(
248251
llvm::function_ref<std::pair<swift::remote::RemoteRef<void>, uint64_t>(
249252
swift::ReflectionSectionKind)>
250253
find_section,
251254
llvm::SmallVector<llvm::StringRef, 1> likely_module_names) override {
252255
return m_reflection_ctx.addImage(find_section, likely_module_names);
253256
}
254257

255-
bool
258+
llvm::Optional<uint32_t>
256259
addImage(swift::remote::RemoteAddress image_start,
257260
llvm::SmallVector<llvm::StringRef, 1> likely_module_names) override {
258261
return m_reflection_ctx.addImage(image_start, likely_module_names);
259262
}
260263

261-
bool readELF(
264+
llvm::Optional<uint32_t> readELF(
262265
swift::remote::RemoteAddress ImageStart,
263266
llvm::Optional<llvm::sys::MemoryBlock> FileBuffer,
264267
llvm::SmallVector<llvm::StringRef, 1> likely_module_names = {}) override {
@@ -361,30 +364,36 @@ class TargetReflectionContext
361364

362365
std::unique_ptr<SwiftLanguageRuntimeImpl::ReflectionContextInterface>
363366
SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext32(
364-
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop) {
367+
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop,
368+
SwiftMetadataCache *swift_metadata_cache) {
365369
using ReflectionContext32ObjCInterop =
366370
TargetReflectionContext<swift::reflection::ReflectionContext<
367371
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<4>>>>>;
368372
using ReflectionContext32NoObjCInterop =
369373
TargetReflectionContext<swift::reflection::ReflectionContext<
370374
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<4>>>>>;
371-
if (ObjCInterop)
372-
return std::make_unique<ReflectionContext32ObjCInterop>(reader);
373-
return std::make_unique<ReflectionContext32NoObjCInterop>(reader);
375+
if (ObjCInterop)
376+
return std::make_unique<ReflectionContext32ObjCInterop>(
377+
reader, swift_metadata_cache);
378+
return std::make_unique<ReflectionContext32NoObjCInterop>(
379+
reader, swift_metadata_cache);
374380
}
375381

376382
std::unique_ptr<SwiftLanguageRuntimeImpl::ReflectionContextInterface>
377383
SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext64(
378-
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop) {
384+
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop,
385+
SwiftMetadataCache *swift_metadata_cache) {
379386
using ReflectionContext64ObjCInterop =
380387
TargetReflectionContext<swift::reflection::ReflectionContext<
381388
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<8>>>>>;
382389
using ReflectionContext64NoObjCInterop =
383390
TargetReflectionContext<swift::reflection::ReflectionContext<
384391
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<8>>>>>;
385392
if (ObjCInterop)
386-
return std::make_unique<ReflectionContext64ObjCInterop>(reader);
387-
return std::make_unique<ReflectionContext64NoObjCInterop>(reader);
393+
return std::make_unique<ReflectionContext64ObjCInterop>(
394+
reader, swift_metadata_cache);
395+
return std::make_unique<ReflectionContext64NoObjCInterop>(
396+
reader, swift_metadata_cache);
388397
}
389398

390399
SwiftLanguageRuntimeImpl::ReflectionContextInterface::

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "LLDBMemoryReader.h"
1717
#include "SwiftLanguageRuntime.h"
18+
#include "SwiftMetadataCache.h"
1819
#include "swift/Reflection/TypeLowering.h"
1920
#include "llvm/Support/Memory.h"
2021

@@ -201,24 +202,26 @@ class SwiftLanguageRuntimeImpl {
201202
/// Return a 32-bit reflection context.
202203
static std::unique_ptr<ReflectionContextInterface>
203204
CreateReflectionContext32(
204-
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop);
205+
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop,
206+
SwiftMetadataCache *swift_metadata_cache);
205207

206208
/// Return a 64-bit reflection context.
207209
static std::unique_ptr<ReflectionContextInterface>
208210
CreateReflectionContext64(
209-
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop);
211+
std::shared_ptr<swift::remote::MemoryReader> reader, bool ObjCInterop,
212+
SwiftMetadataCache *swift_metadata_cache);
210213

211214
virtual ~ReflectionContextInterface();
212215

213-
virtual bool addImage(
216+
virtual llvm::Optional<uint32_t> addImage(
214217
llvm::function_ref<std::pair<swift::remote::RemoteRef<void>, uint64_t>(
215218
swift::ReflectionSectionKind)>
216219
find_section,
217220
llvm::SmallVector<llvm::StringRef, 1> likely_module_names = {}) = 0;
218-
virtual bool addImage(
221+
virtual llvm::Optional<uint32_t> addImage(
219222
swift::remote::RemoteAddress image_start,
220223
llvm::SmallVector<llvm::StringRef, 1> likely_module_names = {}) = 0;
221-
virtual bool
224+
virtual llvm::Optional<uint32_t>
222225
readELF(swift::remote::RemoteAddress ImageStart,
223226
llvm::Optional<llvm::sys::MemoryBlock> FileBuffer,
224227
llvm::SmallVector<llvm::StringRef, 1> likely_module_names = {}) = 0;
@@ -365,6 +368,8 @@ class SwiftLanguageRuntimeImpl {
365368
/// Lazily initialize and return \p m_SwiftNativeNSErrorISA.
366369
llvm::Optional<lldb::addr_t> GetSwiftNativeNSErrorISA();
367370

371+
SwiftMetadataCache *GetSwiftMetadataCache();
372+
368373
/// These members are used to track and toggle the state of the "dynamic
369374
/// exclusivity enforcement flag" in the swift runtime. This flag is set to
370375
/// true when an LLDB expression starts running, and reset to its original
@@ -382,6 +387,8 @@ class SwiftLanguageRuntimeImpl {
382387
/// \{
383388
std::unique_ptr<ReflectionContextInterface> m_reflection_ctx;
384389

390+
SwiftMetadataCache m_swift_metadata_cache;
391+
385392
/// Record modules added through ModulesDidLoad, which are to be
386393
/// added to the reflection context once it's being initialized.
387394
ModuleList m_modules_to_add;
@@ -400,8 +407,9 @@ class SwiftLanguageRuntimeImpl {
400407

401408
/// Add the reflections sections to the reflection context by extracting
402409
/// the directly from the object file.
403-
/// \return true on success.
404-
bool AddObjectFileToReflectionContext(
410+
/// \return the info id of the newly registered reflection info on success, or
411+
/// llvm::None otherwise.
412+
llvm::Optional<uint32_t> AddObjectFileToReflectionContext(
405413
lldb::ModuleSP module,
406414
llvm::SmallVector<llvm::StringRef, 1> likely_module_names);
407415

0 commit comments

Comments
 (0)