Skip to content

Commit 1921073

Browse files
committed
[Runtime] Only scan the type descriptor once for metadata cache entries.
Rather than scanning the type descriptor each time we perform a comparison or hash of a metadata cache entry, do so only once to establish the number of key parameters and the number of witness tables. Use those values to more efficiently compare keys. (cherry picked from commit 06807c2)
1 parent 76ad389 commit 1921073

File tree

1 file changed

+74
-77
lines changed

1 file changed

+74
-77
lines changed

stdlib/public/runtime/MetadataCache.h

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,9 @@ class SimpleLockingCacheEntryBase {
353353

354354
/// A key value as provided to the concurrent map.
355355
class MetadataCacheKey {
356-
const TypeContextDescriptor *Description;
357356
const void * const *Data;
358-
uint32_t Length;
357+
uint16_t NumKeyParameters;
358+
uint16_t NumWitnessTables;
359359
uint32_t Hash;
360360

361361
/// Compare two witness tables, which may involving checking the
@@ -387,69 +387,68 @@ class MetadataCacheKey {
387387
}
388388

389389
/// Compare the content from two keys.
390-
static int compareContent(
391-
const TypeContextDescriptor *description,
392-
const void * const *adata,
393-
const void * const *bdata,
394-
unsigned size) {
395-
auto genericContext = description->getGenericContext();
396-
if (!genericContext) {
397-
assert(size == 0);
398-
return 0;
399-
}
400-
401-
// Compare generic parameters.
402-
for (const auto &gp : genericContext->getGenericParams()) {
403-
if (gp.hasKeyArgument()) {
404-
assert(size > 0);
405-
--size;
406-
if (auto result = comparePointers(*adata++, *bdata++))
407-
return result;
408-
}
390+
static int compareContent(const void * const *adata,
391+
const void * const *bdata,
392+
unsigned numKeyParameters,
393+
unsigned numWitnessTables) {
394+
// Compare generic arguments for key parameters.
395+
for (unsigned i = 0; i != numKeyParameters; ++i) {
396+
if (auto result = comparePointers(*adata++, *bdata++))
397+
return result;
409398
}
410399

411-
// Compare generic requirements.
412-
for (const auto &req : genericContext->getGenericRequirements()) {
413-
if (req.Flags.hasKeyArgument()) {
414-
assert(size > 0);
415-
--size;
416-
if (req.getKind() == GenericRequirementKind::Protocol) {
417-
if (auto result =
418-
compareWitnessTables((const WitnessTable *)*adata++,
419-
(const WitnessTable *)*bdata++))
420-
return result;
421-
} else {
422-
if (auto result = comparePointers(*adata++, *bdata++))
423-
return result;
424-
}
425-
}
400+
// Compare witness tables.
401+
for (unsigned i = 0; i != numWitnessTables; ++i) {
402+
if (auto result =
403+
compareWitnessTables((const WitnessTable *)*adata++,
404+
(const WitnessTable *)*bdata++))
405+
return result;
426406
}
427407

428-
assert(size == 0);
429408
return 0;
430409
}
431410

432411
public:
433412
MetadataCacheKey(const TypeContextDescriptor *description,
434413
const void * const *data, size_t size)
435-
: Description(description), Data(data), Length(size),
436-
Hash(computeHash()) {}
437-
MetadataCacheKey(const TypeContextDescriptor *description,
438-
const void * const *data, size_t size, uint32_t hash)
439-
: Description(description), Data(data), Length(size), Hash(hash) {}
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+
}
440422

441-
bool operator==(MetadataCacheKey rhs) const {
442-
assert(Description == rhs.Description);
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+
}
443430

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)
438+
: Data(data), NumKeyParameters(numKeyParams),
439+
NumWitnessTables(numWitnessTables), Hash(hash) {}
440+
441+
bool operator==(MetadataCacheKey rhs) const {
444442
// Compare the hashes.
445443
if (hash() != rhs.hash()) return false;
446444

447445
// Compare the sizes.
448-
unsigned asize = size(), bsize = rhs.size();
449-
if (asize != bsize) return false;
446+
if (NumKeyParameters != rhs.NumKeyParameters) return false;
447+
if (NumWitnessTables != rhs.NumWitnessTables) return false;
450448

451449
// Compare the content.
452-
return compareContent(Description, begin(), rhs.begin(), asize) == 0;
450+
return compareContent(begin(), rhs.begin(), NumKeyParameters,
451+
NumWitnessTables) == 0;
453452
}
454453

455454
int compare(const MetadataCacheKey &rhs) const {
@@ -458,43 +457,41 @@ class MetadataCacheKey {
458457
return hashComparison;
459458
}
460459

461-
// Compare the sizes.
462-
if (auto sizeComparison = compareIntegers(size(), rhs.size())) {
463-
return sizeComparison;
460+
// Compare the # of key parameters.
461+
if (auto keyParamsComparison =
462+
compareIntegers(NumKeyParameters, rhs.NumKeyParameters)) {
463+
return keyParamsComparison;
464+
}
465+
466+
// Compare the # of witness tables.
467+
if (auto witnessTablesComparison =
468+
compareIntegers(NumWitnessTables, rhs.NumWitnessTables)) {
469+
return witnessTablesComparison;
464470
}
465471

466472
// Compare the content.
467-
return compareContent(Description, begin(), rhs.begin(), size());
473+
return compareContent(begin(), rhs.begin(), NumKeyParameters,
474+
NumWitnessTables);
468475
}
469476

470-
const TypeContextDescriptor *description() const { return Description; }
477+
uint16_t numKeyParameters() const { return NumKeyParameters; }
478+
uint16_t numWitnessTables() const { return NumWitnessTables; }
471479

472480
uint32_t hash() const {
473481
return Hash;
474482
}
475483

476484
const void * const *begin() const { return Data; }
477-
const void * const *end() const { return Data + Length; }
478-
unsigned size() const { return Length; }
485+
const void * const *end() const { return Data + size(); }
486+
unsigned size() const { return NumKeyParameters + NumWitnessTables; }
479487

480488
private:
481489
uint32_t computeHash() const {
482-
size_t H = 0x56ba80d1 * Length;
483-
auto addValue = [&](const void *ptr) {
490+
size_t H = 0x56ba80d1 * NumKeyParameters;
491+
for (unsigned index = 0; index != NumKeyParameters; ++index) {
484492
H = (H >> 10) | (H << ((sizeof(size_t) * 8) - 10));
485-
H ^= (reinterpret_cast<size_t>(ptr)
486-
^ (reinterpret_cast<size_t>(ptr) >> 19));
487-
};
488-
489-
// Hash only the generic arguments; the witness tables need a deeper
490-
// comparison.
491-
if (auto genericContext = Description->getGenericContext()) {
492-
unsigned index = 0;
493-
for (const auto &gp : genericContext->getGenericParams()) {
494-
if (gp.hasKeyArgument()) {
495-
addValue(Data[index++]);
496-
}
497-
}
493+
H ^= (reinterpret_cast<size_t>(Data[index])
494+
^ (reinterpret_cast<size_t>(Data[index]) >> 19));
498495
}
499496

500497
H *= 0x27d4eb2d;
@@ -1354,7 +1351,7 @@ class VariadicMetadataCacheEntryBase :
13541351
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
13551352

13561353
size_t numTrailingObjects(OverloadToken<const void *>) const {
1357-
return KeyLength;
1354+
return NumKeyParameters + NumWitnessTables;
13581355
}
13591356

13601357
template <class... Args>
@@ -1368,11 +1365,10 @@ class VariadicMetadataCacheEntryBase :
13681365
// These are arranged to fit into the tail-padding of the superclass.
13691366

13701367
/// These are set during construction and never changed.
1371-
const uint16_t KeyLength;
1368+
const uint16_t NumKeyParameters;
1369+
const uint16_t NumWitnessTables;
13721370
const uint32_t Hash;
13731371

1374-
const TypeContextDescriptor *Description;
1375-
13761372
/// Valid if TrackingInfo.getState() >= PrivateMetadataState::Abstract.
13771373
ValueType Value;
13781374

@@ -1386,15 +1382,16 @@ class VariadicMetadataCacheEntryBase :
13861382

13871383
public:
13881384
VariadicMetadataCacheEntryBase(const MetadataCacheKey &key)
1389-
: KeyLength(key.size()), Hash(key.hash()), Description(key.description()) {
1385+
: NumKeyParameters(key.numKeyParameters()),
1386+
NumWitnessTables(key.numWitnessTables()),
1387+
Hash(key.hash()) {
13901388
memcpy(this->template getTrailingObjects<const void *>(),
13911389
key.begin(), key.size() * sizeof(const void *));
13921390
}
13931391

13941392
MetadataCacheKey getKey() const {
1395-
return MetadataCacheKey(Description,
1396-
this->template getTrailingObjects<const void*>(),
1397-
KeyLength, Hash);
1393+
return MetadataCacheKey(this->template getTrailingObjects<const void*>(),
1394+
NumKeyParameters, NumWitnessTables, Hash);
13981395
}
13991396

14001397
intptr_t getKeyIntValueForDump() const {

0 commit comments

Comments
 (0)