@@ -353,26 +353,103 @@ class SimpleLockingCacheEntryBase {
353
353
354
354
// / A key value as provided to the concurrent map.
355
355
class MetadataCacheKey {
356
+ const TypeContextDescriptor *Description;
356
357
const void * const *Data;
357
358
uint32_t Length;
358
359
uint32_t Hash;
359
360
361
+ // / Compare two witness tables, which may involving checking the
362
+ // / contents of their conformance descriptors.
363
+ static int compareWitnessTables (const WitnessTable *awt,
364
+ const WitnessTable *bwt) {
365
+ if (awt == bwt)
366
+ return 0 ;
367
+
368
+ auto *aDescription = awt->Description ;
369
+ auto *bDescription = bwt->Description ;
370
+ if (aDescription == bDescription)
371
+ return 0 ;
372
+
373
+ if (!aDescription->isSynthesizedNonUnique () ||
374
+ !bDescription->isSynthesizedNonUnique ())
375
+ return comparePointers (aDescription, bDescription);
376
+
377
+ auto aType = aDescription->getCanonicalTypeMetadata ();
378
+ auto bType = bDescription->getCanonicalTypeMetadata ();
379
+ if (!aType || !bType)
380
+ return comparePointers (aDescription, bDescription);
381
+
382
+ if (int result = comparePointers (aType, bType))
383
+ return result;
384
+
385
+ return comparePointers (aDescription->getProtocol (),
386
+ bDescription->getProtocol ());
387
+ }
388
+
389
+ // / 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
+ }
409
+ }
410
+
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
+ }
426
+ }
427
+
428
+ assert (size == 0 );
429
+ return 0 ;
430
+ }
431
+
360
432
public:
361
- MetadataCacheKey (const void * const *data, size_t size)
362
- : Data(data), Length(size), Hash(computeHash()) {}
363
- MetadataCacheKey (const void * const *data, size_t size, uint32_t hash)
364
- : Data(data), Length(size), Hash(hash) {}
433
+ MetadataCacheKey (const TypeContextDescriptor *description,
434
+ 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) {}
365
440
366
441
bool operator ==(MetadataCacheKey rhs) const {
442
+ assert (Description == rhs.Description );
443
+
444
+ // Compare the hashes.
445
+ if (hash () != rhs.hash ()) return false ;
446
+
367
447
// Compare the sizes.
368
448
unsigned asize = size (), bsize = rhs.size ();
369
449
if (asize != bsize) return false ;
370
450
371
451
// Compare the content.
372
- auto abegin = begin (), bbegin = rhs.begin ();
373
- for (unsigned i = 0 ; i < asize; ++i)
374
- if (abegin[i] != bbegin[i]) return false ;
375
- return true ;
452
+ return compareContent (Description, begin (), rhs.begin (), asize) == 0 ;
376
453
}
377
454
378
455
int compare (const MetadataCacheKey &rhs) const {
@@ -387,16 +464,11 @@ class MetadataCacheKey {
387
464
}
388
465
389
466
// Compare the content.
390
- auto lbegin = begin (), rbegin = rhs.begin ();
391
- for (unsigned i = 0 , e = size (); i != e; ++i) {
392
- if (auto ptrComparison = comparePointers (lbegin[i], rbegin[i]))
393
- return ptrComparison;
394
- }
395
-
396
- // Equal.
397
- return 0 ;
467
+ return compareContent (Description, begin (), rhs.begin (), size ());
398
468
}
399
469
470
+ const TypeContextDescriptor *description () const { return Description; }
471
+
400
472
uint32_t hash () const {
401
473
return Hash;
402
474
}
@@ -408,11 +480,23 @@ class MetadataCacheKey {
408
480
private:
409
481
uint32_t computeHash () const {
410
482
size_t H = 0x56ba80d1 * Length;
411
- for ( unsigned i = 0 ; i < Length; i++ ) {
483
+ auto addValue = [&]( const void *ptr ) {
412
484
H = (H >> 10 ) | (H << ((sizeof (size_t ) * 8 ) - 10 ));
413
- H ^= (reinterpret_cast <size_t >(Data[i])
414
- ^ (reinterpret_cast <size_t >(Data[i]) >> 19 ));
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
+ }
415
498
}
499
+
416
500
H *= 0x27d4eb2d ;
417
501
418
502
// Rotate right by 10 and then truncate to 32 bits.
@@ -1287,6 +1371,8 @@ class VariadicMetadataCacheEntryBase :
1287
1371
const uint16_t KeyLength;
1288
1372
const uint32_t Hash;
1289
1373
1374
+ const TypeContextDescriptor *Description;
1375
+
1290
1376
// / Valid if TrackingInfo.getState() >= PrivateMetadataState::Abstract.
1291
1377
ValueType Value;
1292
1378
@@ -1300,13 +1386,14 @@ class VariadicMetadataCacheEntryBase :
1300
1386
1301
1387
public:
1302
1388
VariadicMetadataCacheEntryBase (const MetadataCacheKey &key)
1303
- : KeyLength(key.size()), Hash(key.hash()) {
1389
+ : KeyLength(key.size()), Hash(key.hash()), Description(key.description ()) {
1304
1390
memcpy (this ->template getTrailingObjects <const void *>(),
1305
1391
key.begin (), key.size () * sizeof (const void *));
1306
1392
}
1307
1393
1308
1394
MetadataCacheKey getKey () const {
1309
- return MetadataCacheKey (this ->template getTrailingObjects <const void *>(),
1395
+ return MetadataCacheKey (Description,
1396
+ this ->template getTrailingObjects <const void *>(),
1310
1397
KeyLength, Hash);
1311
1398
}
1312
1399
0 commit comments