Skip to content

Commit 63a2c76

Browse files
committed
Introduce ExternalTypeRefCache
LLDB would like to cache typeref information to accelerate finding type information. This patch adds an optional interface that allows of typeref to register and provider field descriptor information for faster lookups.
1 parent fb1859d commit 63a2c76

File tree

5 files changed

+197
-44
lines changed

5 files changed

+197
-44
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,10 @@ class ReflectionContext
211211
uint32_t ThreadPort;
212212
};
213213

214-
explicit ReflectionContext(std::shared_ptr<MemoryReader> reader)
215-
: super(std::move(reader), *this)
216-
{}
214+
explicit ReflectionContext(
215+
std::shared_ptr<MemoryReader> reader,
216+
remote::ExternalTypeRefCache *externalCache = nullptr)
217+
: super(std::move(reader), *this, externalCache) {}
217218

218219
ReflectionContext(const ReflectionContext &other) = delete;
219220
ReflectionContext &operator=(const ReflectionContext &other) = delete;
@@ -227,8 +228,10 @@ class ReflectionContext
227228
return sizeof(StoredPointer) * 2;
228229
}
229230

231+
/// On success returns the ID of the newly registered Reflection Info.
230232
template <typename T>
231-
bool readMachOSections(
233+
llvm::Optional<uint32_t>
234+
readMachOSections(
232235
RemoteAddress ImageStart,
233236
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
234237
auto Buf =
@@ -350,7 +353,7 @@ class ReflectionContext
350353
{MPEnumMdSec.first, MPEnumMdSec.second},
351354
PotentialModuleNames};
352355

353-
this->addReflectionInfo(info);
356+
auto InfoID = this->addReflectionInfo(info);
354357

355358
// Find the __DATA segment.
356359
for (unsigned I = 0; I < NumCommands; ++I) {
@@ -374,10 +377,11 @@ class ReflectionContext
374377

375378
savedBuffers.push_back(std::move(Buf));
376379
savedBuffers.push_back(std::move(Sections));
377-
return true;
380+
return InfoID;
378381
}
379382

380-
bool readPECOFFSections(
383+
/// On success returns the ID of the newly registered Reflection Info.
384+
llvm::Optional<uint32_t> readPECOFFSections(
381385
RemoteAddress ImageStart,
382386
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
383387
auto DOSHdrBuf = this->getReader().readBytes(
@@ -477,11 +481,11 @@ class ReflectionContext
477481
{ConformMdSec.first, ConformMdSec.second},
478482
{MPEnumMdSec.first, MPEnumMdSec.second},
479483
PotentialModuleNames};
480-
this->addReflectionInfo(Info);
481-
return true;
484+
return this->addReflectionInfo(Info);
482485
}
483486

484-
bool readPECOFF(RemoteAddress ImageStart,
487+
/// On success returns the ID of the newly registered Reflection Info.
488+
llvm::Optional<uint32_t> readPECOFF(RemoteAddress ImageStart,
485489
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
486490
auto Buf = this->getReader().readBytes(ImageStart,
487491
sizeof(llvm::object::dos_header));
@@ -504,8 +508,9 @@ class ReflectionContext
504508
return readPECOFFSections(ImageStart, PotentialModuleNames);
505509
}
506510

511+
/// On success returns the ID of the newly registered Reflection Info.
507512
template <typename T>
508-
bool readELFSections(
513+
llvm::Optional<uint32_t> readELFSections(
509514
RemoteAddress ImageStart,
510515
llvm::Optional<llvm::sys::MemoryBlock> FileBuffer,
511516
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
@@ -673,8 +678,7 @@ class ReflectionContext
673678
{MPEnumMdSec.first, MPEnumMdSec.second},
674679
PotentialModuleNames};
675680

676-
this->addReflectionInfo(info);
677-
return true;
681+
return this->addReflectionInfo(info);
678682
}
679683

680684
/// Parses metadata information from an ELF image. Because the Section
@@ -693,22 +697,22 @@ class ReflectionContext
693697
/// instance's memory reader.
694698
///
695699
/// \return
696-
/// /b True if the metadata information was parsed successfully,
697-
/// /b false otherwise.
698-
bool
700+
/// \b The newly added reflection info ID if successful,
701+
/// \b llvm::None otherwise.
702+
llvm::Optional<uint32_t>
699703
readELF(RemoteAddress ImageStart,
700704
llvm::Optional<llvm::sys::MemoryBlock> FileBuffer,
701705
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
702706
auto Buf =
703707
this->getReader().readBytes(ImageStart, sizeof(llvm::ELF::Elf64_Ehdr));
704708
if (!Buf)
705-
return false;
709+
return llvm::None;
706710

707711
// Read the header.
708712
auto Hdr = reinterpret_cast<const llvm::ELF::Elf64_Ehdr *>(Buf.get());
709713

710714
if (!Hdr->checkMagic())
711-
return false;
715+
return llvm::None;
712716

713717
// Check if we have a ELFCLASS32 or ELFCLASS64
714718
unsigned char FileClass = Hdr->getFileClass();
@@ -719,11 +723,12 @@ class ReflectionContext
719723
return readELFSections<ELFTraits<llvm::ELF::ELFCLASS32>>(
720724
ImageStart, FileBuffer, PotentialModuleNames);
721725
} else {
722-
return false;
726+
return llvm::None;
723727
}
724728
}
725729

726-
bool
730+
/// On success returns the ID of the newly registered Reflection Info.
731+
llvm::Optional<uint32_t>
727732
addImage(RemoteAddress ImageStart,
728733
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames = {}) {
729734
// Read the first few bytes to look for a magic header.
@@ -761,7 +766,7 @@ class ReflectionContext
761766
}
762767

763768
// We don't recognize the format.
764-
return false;
769+
return llvm::None;
765770
}
766771

767772
/// Adds an image using the FindSection closure to find the swift metadata
@@ -770,9 +775,9 @@ class ReflectionContext
770775
/// of freeing the memory buffer in the RemoteRef return value.
771776
/// process.
772777
/// \return
773-
/// \b True if any of the reflection sections were registered,
774-
/// \b false otherwise.
775-
bool
778+
/// \b The newly added reflection info ID if successful,
779+
/// \b llvm::None otherwise.
780+
llvm::Optional<uint32_t>
776781
addImage(llvm::function_ref<
777782
std::pair<RemoteRef<void>, uint64_t>(ReflectionSectionKind)>
778783
FindSection,
@@ -798,7 +803,7 @@ class ReflectionContext
798803

799804
// If we didn't find any sections, return.
800805
if (llvm::all_of(Pairs, [](const auto &Pair) { return !Pair.first; }))
801-
return false;
806+
return {};
802807

803808
ReflectionInfo Info = {{Pairs[0].first, Pairs[0].second},
804809
{Pairs[1].first, Pairs[1].second},
@@ -809,12 +814,12 @@ class ReflectionContext
809814
{Pairs[6].first, Pairs[6].second},
810815
{Pairs[7].first, Pairs[7].second},
811816
PotentialModuleNames};
812-
this->addReflectionInfo(Info);
813-
return true;
817+
return addReflectionInfo(Info);
814818
}
815819

816-
void addReflectionInfo(ReflectionInfo I) {
817-
getBuilder().addReflectionInfo(I);
820+
/// Adds the reflection info and returns it's id.
821+
uint32_t addReflectionInfo(ReflectionInfo I) {
822+
return getBuilder().addReflectionInfo(I);
818823
}
819824

820825
bool ownsObject(RemoteAddress ObjectAddress) {

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef SWIFT_REFLECTION_TYPEREFBUILDER_H
1919
#define SWIFT_REFLECTION_TYPEREFBUILDER_H
2020

21+
#include "swift/Remote/ExternalTypeRefCache.h"
2122
#include "swift/Remote/MetadataReader.h"
2223
#include "swift/Reflection/MetadataSourceBuilder.h"
2324
#include "swift/Reflection/Records.h"
@@ -426,6 +427,8 @@ class TypeRefBuilder {
426427
TypeConverter TC;
427428
MetadataSourceBuilder MSB;
428429

430+
remote::ExternalTypeRefCache *ExternalTypeRefCache = nullptr;
431+
429432
#define TYPEREF(Id, Parent) \
430433
std::unordered_map<TypeRefID, const Id##TypeRef *, \
431434
TypeRefID::Hash, TypeRefID::Equal> Id##TypeRefs;
@@ -915,10 +918,17 @@ class TypeRefBuilder {
915918
/// Parsing reflection metadata
916919
///
917920

918-
void addReflectionInfo(ReflectionInfo I) {
921+
/// Add the ReflectionInfo and return a unique ID for the reflection image
922+
/// added. Since we only add reflection infos, the ID can be its index.
923+
/// We return a uint32_t since it's extremely unlikely we'll run out of
924+
/// indexes.
925+
uint32_t addReflectionInfo(ReflectionInfo I) {
919926
ReflectionInfos.push_back(I);
927+
auto InfoID = ReflectionInfos.size() - 1;
928+
assert(InfoID <= UINT32_MAX && "ReflectionInfo ID overflow");
929+
return InfoID;
920930
}
921-
931+
922932
const std::vector<ReflectionInfo> &getReflectionInfos() {
923933
return ReflectionInfos;
924934
}
@@ -943,6 +953,9 @@ class TypeRefBuilder {
943953
llvm::Optional<RemoteRef<FieldDescriptor>>
944954
findFieldDescriptorAtIndex(size_t Index, const std::string &MangledName);
945955

956+
llvm::Optional<RemoteRef<FieldDescriptor>>
957+
getFieldDescriptorFromExternalCache(const std::string &MangledName);
958+
946959
public:
947960
RemoteRef<char> readTypeRef(uint64_t remoteAddr);
948961

@@ -983,8 +996,9 @@ class TypeRefBuilder {
983996

984997
public:
985998
template<typename Runtime>
986-
TypeRefBuilder(remote::MetadataReader<Runtime, TypeRefBuilder> &reader)
987-
: TC(*this),
999+
TypeRefBuilder(remote::MetadataReader<Runtime, TypeRefBuilder> &reader,
1000+
remote::ExternalTypeRefCache *externalCache = nullptr)
1001+
: TC(*this), ExternalTypeRefCache(externalCache),
9881002
PointerSize(sizeof(typename Runtime::StoredPointer)),
9891003
TypeRefDemangler(
9901004
[this, &reader](RemoteRef<char> string, bool useOpaqueTypeSymbolicReferences) -> Demangle::Node * {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===--- ExternalTypeRefCache.h - Abstract access to external caches of
2+
//typeref ------*- C++ -*-===//
3+
//
4+
// This source file is part of the Swift.org open source project
5+
//
6+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
7+
// Licensed under Apache License v2.0 with Runtime Library Exception
8+
//
9+
// See https://swift.org/LICENSE.txt for license information
10+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
//
12+
//===----------------------------------------------------------------------===//
13+
//
14+
/// @file
15+
/// This file declares an abstract interface for external caches of
16+
/// typeref information.
17+
//
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef SWIFT_REMOTE_EXTERNALTYPEREFCACHE_H
21+
#define SWIFT_REMOTE_EXTERNALTYPEREFCACHE_H
22+
23+
#include "llvm/ADT/ArrayRef.h"
24+
#include "llvm/ADT/StringRef.h"
25+
#include "llvm/ADT/Optional.h"
26+
27+
#include <string>
28+
29+
namespace swift {
30+
namespace reflection {
31+
32+
template <typename T>
33+
class ReflectionSection;
34+
class FieldDescriptorIterator;
35+
using FieldSection = ReflectionSection<FieldDescriptorIterator>;
36+
}
37+
38+
namespace remote {
39+
/// A struct with the information required to locate a specific field
40+
/// descriptor.
41+
struct FieldDescriptorLocator {
42+
/// The reflection info ID the field descriptor belongs to.
43+
uint64_t InfoID;
44+
45+
/// The offset of the field descriptor in the FieldSection buffer.
46+
uint64_t Offset;
47+
};
48+
49+
/// An abstract interface for providing external type layout information.
50+
struct ExternalTypeRefCache {
51+
virtual ~ExternalTypeRefCache() = default;
52+
53+
/// Cache the field descriptors of a reflection info with a given id with
54+
/// their corresponding mangled names. The amount of field descriptors and
55+
/// mangled names must be the same. If a field descriptor does not have a
56+
/// mangled name a corresponding empty string must be in the mangled_names
57+
/// array.
58+
virtual void
59+
cacheFieldDescriptors(uint64_t InfoID,
60+
const swift::reflection::FieldSection &FieldDescriptors,
61+
llvm::ArrayRef<std::string> MangledNames) = 0;
62+
63+
/// Retrieve a pair representing the reflection info id and the offset of a
64+
/// field descriptor in the field section buffer, if available.
65+
virtual llvm::Optional<FieldDescriptorLocator>
66+
getFieldDescriptorLocator(const std::string &Name) = 0;
67+
68+
/// Returns whether the reflection info with the corresponding ID has been
69+
/// cached already.
70+
virtual bool isReflectionInfoCached(uint64_t InfoID) = 0;
71+
};
72+
73+
} // namespace remote
74+
} // namespace swift
75+
#endif

0 commit comments

Comments
 (0)