Skip to content

Commit 06807c2

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.
1 parent d00a7b7 commit 06807c2

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)