Skip to content

Commit 163dc92

Browse files
committed
[Runtime] Compute generic metadata cache info once per type.
Rather than scanning through the generic parameters and generic requirements each time we form a key for the generic metadata cache, compute these values once, when the cache itself is first initialized. (cherry picked from commit 3948114)
1 parent 1921073 commit 163dc92

File tree

3 files changed

+74
-37
lines changed

3 files changed

+74
-37
lines changed

include/swift/Basic/Lazy.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ template <class T> class Lazy {
5858

5959
T &get(void (*initCallback)(void *) = defaultInitCallback);
6060

61+
template<typename Arg1>
62+
T &getWithInit(Arg1 &&arg1);
63+
6164
/// Get the value, assuming it must have already been initialized by this
6265
/// point.
6366
T &unsafeGetAlreadyInitialized() { return *reinterpret_cast<T *>(&Value); }
@@ -80,6 +83,22 @@ template <typename T> inline T &Lazy<T>::get(void (*initCallback)(void*)) {
8083
return unsafeGetAlreadyInitialized();
8184
}
8285

86+
template <typename T>
87+
template <typename Arg1> inline T &Lazy<T>::getWithInit(Arg1 &&arg1) {
88+
struct Data {
89+
void *address;
90+
Arg1 &&arg1;
91+
92+
static void init(void *context) {
93+
Data *data = static_cast<Data *>(context);
94+
::new (data->address) T(static_cast<Arg1&&>(data->arg1));
95+
}
96+
} data{&Value, static_cast<Arg1&&>(arg1)};
97+
98+
SWIFT_ONCE_F(OnceToken, &Data::init, &data);
99+
return unsafeGetAlreadyInitialized();
100+
}
101+
83102
} // end namespace swift
84103

85104
#define SWIFT_LAZY_CONSTANT(INITIAL_VALUE) \

stdlib/public/runtime/Metadata.cpp

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,39 @@ namespace {
268268
};
269269
} // end anonymous namespace
270270

271-
using GenericMetadataCache = MetadataCache<GenericCacheEntry, false>;
272-
using LazyGenericMetadataCache = Lazy<GenericMetadataCache>;
271+
namespace {
272+
class GenericMetadataCache : public MetadataCache<GenericCacheEntry, false> {
273+
public:
274+
uint16_t NumKeyParameters;
275+
uint16_t NumWitnessTables;
276+
277+
GenericMetadataCache(const TargetGenericContext<InProcess> &genericContext)
278+
: NumKeyParameters(0), NumWitnessTables(0) {
279+
// Count up the # of key parameters and # of witness tables.
280+
281+
// Find key generic parameters.
282+
for (const auto &gp : genericContext.getGenericParams()) {
283+
if (gp.hasKeyArgument())
284+
++NumKeyParameters;
285+
}
286+
287+
// Find witness tables.
288+
for (const auto &req : genericContext.getGenericRequirements()) {
289+
if (req.Flags.hasKeyArgument() &&
290+
req.getKind() == GenericRequirementKind::Protocol)
291+
++NumWitnessTables;
292+
}
293+
}
294+
};
295+
296+
using LazyGenericMetadataCache = Lazy<GenericMetadataCache>;
297+
}
273298

274299
/// Fetch the metadata cache for a generic metadata structure.
275300
static GenericMetadataCache &getCache(
276-
const TypeGenericContextDescriptorHeader &generics) {
301+
const TypeContextDescriptor &description) {
302+
auto &generics = description.getFullGenericContextHeader();
303+
277304
// Keep this assert even if you change the representation above.
278305
static_assert(sizeof(LazyGenericMetadataCache) <=
279306
sizeof(GenericMetadataInstantiationCache::PrivateData),
@@ -282,7 +309,7 @@ static GenericMetadataCache &getCache(
282309
auto lazyCache =
283310
reinterpret_cast<LazyGenericMetadataCache*>(
284311
generics.getInstantiationCache()->PrivateData);
285-
return lazyCache->get();
312+
return lazyCache->getWithInit(*description.getGenericContext());
286313
}
287314

288315
/// Fetch the metadata cache for a generic metadata structure,
@@ -527,9 +554,11 @@ swift::swift_getGenericMetadata(MetadataRequest request,
527554
auto &generics = description->getFullGenericContextHeader();
528555
size_t numGenericArgs = generics.Base.NumKeyArguments;
529556

530-
auto key = MetadataCacheKey(description, arguments, numGenericArgs);
531-
auto result =
532-
getCache(generics).getOrInsert(key, request, description, arguments);
557+
auto &cache = getCache(*description);
558+
assert(numGenericArgs == cache.NumKeyParameters + cache.NumWitnessTables);
559+
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
560+
arguments);
561+
auto result = cache.getOrInsert(key, request, description, arguments);
533562

534563
return result.second;
535564
}
@@ -4337,11 +4366,15 @@ static Result performOnMetadataCache(const Metadata *metadata,
43374366
auto genericArgs =
43384367
reinterpret_cast<const void * const *>(
43394368
description->getGenericArguments(metadata));
4369+
auto &cache = getCache(*description);
43404370
size_t numGenericArgs = generics.Base.NumKeyArguments;
4341-
auto key = MetadataCacheKey(description, genericArgs, numGenericArgs);
4371+
assert(numGenericArgs == cache.NumKeyParameters + cache.NumWitnessTables);
4372+
(void)numGenericArgs;
4373+
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
4374+
genericArgs);
43424375

43434376
return std::move(callbacks).forGenericMetadata(metadata, description,
4344-
getCache(generics), key);
4377+
cache, key);
43454378
}
43464379

43474380
bool swift::addToMetadataQueue(MetadataCompletionQueueEntry *queueEntry,

stdlib/public/runtime/MetadataCache.h

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -409,32 +409,16 @@ class MetadataCacheKey {
409409
}
410410

411411
public:
412-
MetadataCacheKey(const TypeContextDescriptor *description,
413-
const void * const *data, size_t size)
414-
: Data(data), NumKeyParameters(0), NumWitnessTables(0) {
415-
// Count up the # of key parameters and # of witness tables.
416-
if (auto genericContext = description->getGenericContext()) {
417-
// Find key generic parameters.
418-
for (const auto &gp : genericContext->getGenericParams()) {
419-
if (gp.hasKeyArgument())
420-
++NumKeyParameters;
421-
}
422-
423-
// Find witness tables.
424-
for (const auto &req : genericContext->getGenericRequirements()) {
425-
if (req.Flags.hasKeyArgument() &&
426-
req.getKind() == GenericRequirementKind::Protocol)
427-
++NumWitnessTables;
428-
}
429-
}
430-
431-
assert(size == NumKeyParameters + NumWitnessTables);
432-
433-
Hash = computeHash();
434-
}
435-
436-
MetadataCacheKey(const void * const *data, uint16_t numKeyParams,
437-
uint16_t numWitnessTables, uint32_t hash)
412+
MetadataCacheKey(uint16_t numKeyParams,
413+
uint16_t numWitnessTables,
414+
const void * const *data)
415+
: Data(data), NumKeyParameters(numKeyParams),
416+
NumWitnessTables(numWitnessTables), Hash(computeHash()) { }
417+
418+
MetadataCacheKey(uint16_t numKeyParams,
419+
uint16_t numWitnessTables,
420+
const void * const *data,
421+
uint32_t hash)
438422
: Data(data), NumKeyParameters(numKeyParams),
439423
NumWitnessTables(numWitnessTables), Hash(hash) {}
440424

@@ -1390,8 +1374,9 @@ class VariadicMetadataCacheEntryBase :
13901374
}
13911375

13921376
MetadataCacheKey getKey() const {
1393-
return MetadataCacheKey(this->template getTrailingObjects<const void*>(),
1394-
NumKeyParameters, NumWitnessTables, Hash);
1377+
return MetadataCacheKey(NumKeyParameters, NumWitnessTables,
1378+
this->template getTrailingObjects<const void*>(),
1379+
Hash);
13951380
}
13961381

13971382
intptr_t getKeyIntValueForDump() const {

0 commit comments

Comments
 (0)