Skip to content

Commit ca06ced

Browse files
committed
[Reflection] Cache the various DataQuery values.
We can end up querying the pointer size and similar things very frequently, which can be slow. These values don't change for any given reader, so call them once and cache the values locally instead. rdar://150221008
1 parent d203591 commit ca06ced

File tree

4 files changed

+101
-67
lines changed

4 files changed

+101
-67
lines changed

include/swift/Remote/CMemoryReader.h

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,38 +42,16 @@ namespace remote {
4242
class CMemoryReader final : public MemoryReader {
4343
MemoryReaderImpl Impl;
4444

45-
uint64_t ptrauthMask;
46-
47-
uint64_t getPtrauthMask() {
48-
if (ptrauthMask == 0) {
49-
int success;
50-
if (Impl.PointerSize == 4) {
51-
uint32_t ptrauthMask32 = 0;
52-
success = queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
53-
nullptr, &ptrauthMask32);
54-
ptrauthMask = ptrauthMask32;
55-
} else if (Impl.PointerSize == 8) {
56-
success = queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
57-
nullptr, &ptrauthMask);
58-
} else {
59-
success = 0;
60-
}
61-
62-
if (!success)
63-
ptrauthMask = ~0ull;
64-
}
65-
return ptrauthMask;
66-
}
67-
6845
// Check to see if an address has bits outside the ptrauth mask. This suggests
6946
// that we're likely failing to strip a signed pointer when reading from it.
7047
bool hasSignatureBits(RemoteAddress address) {
7148
uint64_t addressData = address.getAddressData();
72-
return addressData != (addressData & getPtrauthMask());
49+
uint64_t mask = getPtrAuthMask().value_or(~uint64_t(0));
50+
return addressData != (addressData & mask);
7351
}
7452

7553
public:
76-
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl), ptrauthMask(0) {
54+
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl) {
7755
assert(this->Impl.queryDataLayout && "No queryDataLayout implementation");
7856
assert(this->Impl.getStringLength && "No stringLength implementation");
7957
assert(this->Impl.readBytes && "No readBytes implementation");

include/swift/Remote/MemoryReader.h

Lines changed: 89 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/SwiftRemoteMirror/MemoryReaderInterface.h"
2323
#include <optional>
2424

25+
#include <cstdint>
2526
#include <cstdlib>
2627
#include <cstring>
2728
#include <functional>
@@ -37,7 +38,80 @@ namespace remote {
3738
/// This abstraction presents memory as if it were a read-only
3839
/// representation of the address space of a remote process.
3940
class MemoryReader {
41+
uint8_t cachedPointerSize = 0;
42+
uint8_t cachedSizeSize = 0;
43+
uint64_t cachedPtrAuthMask = 0;
44+
uint8_t cachedObjCReservedLowBits = 0xff;
45+
uint64_t cachedLeastValidPointerValue = 0;
46+
uint8_t cachedObjCInteropIsEnabled = 0xff;
47+
48+
protected:
49+
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
50+
void *outBuffer) = 0;
51+
4052
public:
53+
std::optional<uint8_t> getPointerSize() {
54+
if (cachedPointerSize == 0) {
55+
if (!queryDataLayout(DLQ_GetPointerSize, nullptr, &cachedPointerSize))
56+
return std::nullopt;
57+
}
58+
return cachedPointerSize;
59+
}
60+
61+
std::optional<uint8_t> getSizeSize() {
62+
if (cachedSizeSize == 0) {
63+
if (!queryDataLayout(DLQ_GetSizeSize, nullptr, &cachedSizeSize))
64+
return std::nullopt;
65+
}
66+
return cachedSizeSize;
67+
}
68+
69+
std::optional<uint64_t> getPtrAuthMask() {
70+
if (cachedPtrAuthMask == 0) {
71+
auto ptrSize = getPointerSize();
72+
if (!ptrSize)
73+
return std::nullopt;
74+
75+
if (ptrSize.value() == sizeof(uint64_t)) {
76+
if (!queryDataLayout(DLQ_GetPtrAuthMask, nullptr, &cachedPtrAuthMask))
77+
return std::nullopt;
78+
} else if (ptrSize.value() == sizeof(uint32_t)) {
79+
uint32_t mask;
80+
if (!queryDataLayout(DLQ_GetPtrAuthMask, nullptr, &mask))
81+
return std::nullopt;
82+
cachedPtrAuthMask = mask;
83+
}
84+
}
85+
return cachedPtrAuthMask;
86+
}
87+
88+
std::optional<uint8_t> getObjCReservedLowBits() {
89+
if (cachedObjCReservedLowBits == 0xff) {
90+
if (!queryDataLayout(DLQ_GetObjCReservedLowBits, nullptr,
91+
&cachedObjCReservedLowBits))
92+
return std::nullopt;
93+
}
94+
return cachedObjCReservedLowBits;
95+
}
96+
97+
std::optional<uint64_t> getLeastValidPointerValue() {
98+
if (cachedLeastValidPointerValue == 0) {
99+
if (!queryDataLayout(DLQ_GetLeastValidPointerValue, nullptr,
100+
&cachedLeastValidPointerValue))
101+
return std::nullopt;
102+
}
103+
return cachedLeastValidPointerValue;
104+
}
105+
106+
std::optional<bool> getObjCInteropIsEnabled() {
107+
if (cachedObjCInteropIsEnabled == 0xff) {
108+
if (!queryDataLayout(DLQ_GetObjCInteropIsEnabled, nullptr,
109+
&cachedObjCInteropIsEnabled))
110+
return std::nullopt;
111+
}
112+
return cachedObjCInteropIsEnabled;
113+
}
114+
41115
/// A convenient name for the return type from readBytes.
42116
using ReadBytesResult =
43117
std::unique_ptr<const void, std::function<void(const void *)>>;
@@ -46,9 +120,6 @@ class MemoryReader {
46120
using ReadObjResult =
47121
std::unique_ptr<const T, std::function<void(const void *)>>;
48122

49-
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
50-
void *outBuffer) = 0;
51-
52123
/// Look up the given public symbol name in the remote process.
53124
virtual RemoteAddress getSymbolAddress(const std::string &name) = 0;
54125

@@ -209,50 +280,37 @@ class MemoryReader {
209280
// index (counting from 0).
210281
bool readHeapObjectExtraInhabitantIndex(RemoteAddress address,
211282
int *extraInhabitantIndex) {
212-
uint8_t PointerSize;
213-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
214-
nullptr, &PointerSize)) {
215-
return false;
216-
}
217-
uint64_t LeastValidPointerValue;
218-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetLeastValidPointerValue,
219-
nullptr, &LeastValidPointerValue)) {
220-
return false;
221-
}
222-
uint8_t ObjCReservedLowBits;
223-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetObjCReservedLowBits,
224-
nullptr, &ObjCReservedLowBits)) {
283+
auto PointerSize = getPointerSize();
284+
auto LeastValidPointerValue = getLeastValidPointerValue();
285+
auto ObjCReservedLowBits = getObjCReservedLowBits();
286+
287+
if (!PointerSize || !LeastValidPointerValue || !ObjCReservedLowBits)
225288
return false;
226-
}
289+
227290
uint64_t RawPointerValue;
228-
if (!readInteger(address, PointerSize, &RawPointerValue)) {
291+
if (!readInteger(address, PointerSize.value(), &RawPointerValue)) {
229292
return false;
230293
}
231-
if (RawPointerValue >= LeastValidPointerValue) {
294+
if (RawPointerValue >= LeastValidPointerValue.value()) {
232295
*extraInhabitantIndex = -1; // Valid value, not an XI
233296
} else {
234-
*extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits);
297+
*extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits.value());
235298
}
236299
return true;
237300
}
238301

239302
bool readFunctionPointerExtraInhabitantIndex(RemoteAddress address,
240303
int *extraInhabitantIndex) {
241-
uint8_t PointerSize;
242-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
243-
nullptr, &PointerSize)) {
304+
auto PointerSize = getPointerSize();
305+
auto LeastValidPointerValue = getLeastValidPointerValue();
306+
if (!PointerSize || !LeastValidPointerValue)
244307
return false;
245-
}
246-
uint64_t LeastValidPointerValue;
247-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetLeastValidPointerValue,
248-
nullptr, &LeastValidPointerValue)) {
249-
return false;
250-
}
308+
251309
uint64_t RawPointerValue;
252-
if (!readInteger(address, PointerSize, &RawPointerValue)) {
310+
if (!readInteger(address, PointerSize.value(), &RawPointerValue)) {
253311
return false;
254312
}
255-
if (RawPointerValue >= LeastValidPointerValue) {
313+
if (RawPointerValue >= LeastValidPointerValue.value()) {
256314
*extraInhabitantIndex = -1; // Valid value, not an XI
257315
} else {
258316
*extraInhabitantIndex = RawPointerValue;

include/swift/Remote/MetadataReader.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,8 @@ class MetadataReader {
422422
}
423423

424424
StoredPointer queryPtrAuthMask() {
425-
StoredPointer QueryResult;
426-
if (Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
427-
nullptr, &QueryResult)) {
428-
return QueryResult;
429-
}
430-
return ~StoredPointer(0);
425+
auto QueryResult = Reader->getPtrAuthMask();
426+
return QueryResult.value_or(~StoredPointer(0));
431427
}
432428

433429
template <class... T>

lib/StaticMirror/ObjectFileContext.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -565,16 +565,18 @@ std::unique_ptr<ReflectionContextHolder> makeReflectionContextForObjectFiles(
565565
const std::vector<const ObjectFile *> &objectFiles, bool ObjCInterop) {
566566
auto Reader = std::make_shared<ObjectMemoryReader>(objectFiles);
567567

568-
uint8_t pointerSize;
569-
Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize, nullptr,
570-
&pointerSize);
568+
auto pointerSize = Reader->getPointerSize();
569+
if (!pointerSize) {
570+
fputs("unable to get target pointer size\n", stderr);
571+
abort();
572+
}
571573

572-
switch (pointerSize) {
574+
switch (pointerSize.value()) {
573575
case 4:
574576
#define MAKE_CONTEXT(INTEROP, PTRSIZE) \
575577
makeReflectionContextForMetadataReader< \
576578
External<INTEROP<RuntimeTarget<PTRSIZE>>>>(std::move(Reader), \
577-
pointerSize)
579+
pointerSize.value())
578580
#if SWIFT_OBJC_INTEROP
579581
if (ObjCInterop)
580582
return MAKE_CONTEXT(WithObjCInterop, 4);

0 commit comments

Comments
 (0)