@@ -411,28 +411,83 @@ template<typename Runtime>
411411struct GenericSignatureLayout {
412412 uint16_t NumKeyParameters = 0 ;
413413 uint16_t NumWitnessTables = 0 ;
414+ uint16_t NumPacks = 0 ;
415+ uint16_t NumShapeClasses = 0 ;
416+ const GenericPackShapeDescriptor *PackShapeDescriptors = nullptr ;
417+
418+ GenericSignatureLayout (const RuntimeGenericSignature<Runtime> &sig)
419+ : NumPacks(sig.getGenericPackShapeHeader().NumPacks),
420+ NumShapeClasses (sig.getGenericPackShapeHeader().NumShapeClasses),
421+ PackShapeDescriptors(sig.getGenericPackShapeDescriptors().data()) {
422+
423+ #ifndef NDEBUG
424+ unsigned numPacks = 0 ;
425+ #endif
414426
415- GenericSignatureLayout (const RuntimeGenericSignature<Runtime> &sig) {
416427 for (const auto &gp : sig.getParams ()) {
417- if (gp.hasKeyArgument ())
428+ if (gp.hasKeyArgument ()) {
418429 ++NumKeyParameters;
430+
431+ #ifndef NDEBUG
432+ if (gp.getKind () == GenericParamKind::TypePack) {
433+ assert (PackShapeDescriptors[numPacks].Kind
434+ == GenericPackKind::Metadata);
435+ assert (PackShapeDescriptors[numPacks].Index
436+ == NumKeyParameters);
437+ assert (PackShapeDescriptors[numPacks].ShapeClass
438+ < NumShapeClasses);
439+ ++numPacks;
440+ }
441+ #endif
442+ }
419443 }
420444 for (const auto &reqt : sig.getRequirements ()) {
421445 if (reqt.Flags .hasKeyArgument () &&
422- reqt.getKind () == GenericRequirementKind::Protocol)
446+ reqt.getKind () == GenericRequirementKind::Protocol) {
447+ #ifndef NDEBUG
448+ if (reqt.getFlags ().isPackRequirement ()) {
449+ assert (PackShapeDescriptors[numPacks].Kind
450+ == GenericPackKind::WitnessTable);
451+ assert (PackShapeDescriptors[numPacks].Index
452+ == NumKeyParameters + NumWitnessTables);
453+ assert (PackShapeDescriptors[numPacks].ShapeClass
454+ < NumShapeClasses);
455+ ++numPacks;
456+ }
457+ #endif
458+
423459 ++NumWitnessTables;
460+ }
424461 }
462+
463+ assert (numPacks == NumPacks);
425464 }
426465
427466 size_t sizeInWords () const {
428- return NumKeyParameters + NumWitnessTables;
467+ return NumShapeClasses + NumKeyParameters + NumWitnessTables;
429468 }
430469
431470 friend bool operator ==(const GenericSignatureLayout<Runtime> &lhs,
432471 const GenericSignatureLayout<Runtime> &rhs) {
433- return lhs.NumKeyParameters == rhs.NumKeyParameters &&
434- lhs.NumWitnessTables == rhs.NumWitnessTables ;
472+ if (lhs.NumKeyParameters != rhs.NumKeyParameters ||
473+ lhs.NumWitnessTables != rhs.NumWitnessTables ||
474+ lhs.NumShapeClasses != rhs.NumShapeClasses ||
475+ lhs.NumPacks != rhs.NumPacks ) {
476+ return false ;
477+ }
478+
479+ for (unsigned i = 0 ; i < lhs.NumPacks ; ++i) {
480+ const auto &lhsElt = lhs.PackShapeDescriptors [i];
481+ const auto &rhsElt = rhs.PackShapeDescriptors [i];
482+ if (lhsElt.Kind != rhsElt.Kind ||
483+ lhsElt.Index != rhsElt.Index ||
484+ lhsElt.ShapeClass != rhsElt.ShapeClass )
485+ return false ;
486+ }
487+
488+ return true ;
435489 }
490+
436491 friend bool operator !=(const GenericSignatureLayout<Runtime> &lhs,
437492 const GenericSignatureLayout<Runtime> &rhs) {
438493 return !(lhs == rhs);
@@ -445,6 +500,26 @@ struct GenericSignatureLayout {
445500 if (auto result = compareIntegers (NumWitnessTables, rhs.NumWitnessTables ))
446501 return result;
447502
503+ if (auto result = compareIntegers (NumShapeClasses, rhs.NumShapeClasses ))
504+ return result;
505+
506+ if (auto result = compareIntegers (NumPacks, rhs.NumPacks ))
507+ return result;
508+
509+ for (unsigned i = 0 ; i < NumPacks; ++i) {
510+ const auto &lhsElt = PackShapeDescriptors[i];
511+ const auto &rhsElt = rhs.PackShapeDescriptors [i];
512+
513+ if (auto result = compareIntegers (lhsElt.Kind , rhsElt.Kind ))
514+ return result;
515+
516+ if (auto result = compareIntegers (lhsElt.Index , rhsElt.Index ))
517+ return result;
518+
519+ if (auto result = compareIntegers (lhsElt.ShapeClass , rhsElt.ShapeClass ))
520+ return result;
521+ }
522+
448523 return 0 ;
449524 }
450525};
@@ -498,23 +573,106 @@ class MetadataCacheKey {
498573 }
499574
500575private:
576+ static int compareMetadataPacks (const void *lhsPtr,
577+ const void *rhsPtr,
578+ uintptr_t count) {
579+ MetadataPackPointer lhs (lhsPtr);
580+ MetadataPackPointer rhs (rhsPtr);
581+
582+ assert (lhs.getLifetime () == PackLifetime::OnHeap);
583+ assert (rhs.getLifetime () == PackLifetime::OnHeap);
584+
585+ auto *lhsElt = lhs.getElements ();
586+ auto *rhsElt = rhs.getElements ();
587+
588+ for (uintptr_t i = 0 ; i < count; ++i) {
589+ if (auto result = comparePointers (lhsElt[i], rhsElt[i]))
590+ return result;
591+ }
592+
593+ return 0 ;
594+ }
595+
596+ static int compareWitnessTablePacks (const void *lhsPtr,
597+ const void *rhsPtr,
598+ uintptr_t count) {
599+ WitnessTablePackPointer lhs (lhsPtr);
600+ WitnessTablePackPointer rhs (rhsPtr);
601+
602+ assert (lhs.getLifetime () == PackLifetime::OnHeap);
603+ assert (rhs.getLifetime () == PackLifetime::OnHeap);
604+
605+ auto *lhsElt = lhs.getElements ();
606+ auto *rhsElt = rhs.getElements ();
607+
608+ for (uintptr_t i = 0 ; i < count; ++i) {
609+ if (auto result = compareWitnessTables (lhsElt[i], rhsElt[i]))
610+ return result;
611+ }
612+
613+ return 0 ;
614+ }
615+
501616 // / Compare the content from two keys.
502617 static int compareContent (const void *const *adata, const void *const *bdata,
503618 const GenericSignatureLayout<InProcess> &layout) {
619+ const uintptr_t *packCounts = reinterpret_cast <const uintptr_t *>(adata);
620+
621+ // Compare pack lengths for shape classes.
622+ for (unsigned i = 0 ; i != layout.NumShapeClasses ; ++i) {
623+ if (auto result = compareIntegers (reinterpret_cast <uintptr_t >(*adata++),
624+ reinterpret_cast <uintptr_t >(*bdata++)))
625+ return result;
626+ }
627+
628+ auto *nextPack = layout.PackShapeDescriptors ;
629+ unsigned numPacks = 0 ;
630+
504631 // Compare generic arguments for key parameters.
505632 for (unsigned i = 0 ; i != layout.NumKeyParameters ; ++i) {
633+ // Is this entry a metadata pack?
634+ if (numPacks < layout.NumPacks &&
635+ nextPack->Kind == GenericPackKind::Metadata &&
636+ i == nextPack->Index ) {
637+ assert (nextPack->ShapeClass < layout.NumShapeClasses );
638+ uintptr_t count = packCounts[nextPack->ShapeClass ];
639+ ++numPacks;
640+ ++nextPack;
641+
642+ if (auto result = compareMetadataPacks (*adata++, *bdata++, count))
643+ return result;
644+
645+ continue ;
646+ }
647+
506648 if (auto result = comparePointers (*adata++, *bdata++))
507649 return result;
508650 }
509651
510652 // Compare witness tables.
511653 for (unsigned i = 0 ; i != layout.NumWitnessTables ; ++i) {
654+ // Is this entry a witness table pack?
655+ if (numPacks < layout.NumPacks &&
656+ nextPack->Kind == GenericPackKind::WitnessTable &&
657+ i == nextPack->Index ) {
658+ assert (nextPack->ShapeClass < layout.NumShapeClasses );
659+ uintptr_t count = packCounts[nextPack->ShapeClass ];
660+ ++numPacks;
661+ ++nextPack;
662+
663+ if (auto result = compareWitnessTablePacks (*adata++, *bdata++, count))
664+ return result;
665+
666+ continue ;
667+ }
668+
512669 if (auto result =
513670 compareWitnessTables ((const WitnessTable *)*adata++,
514671 (const WitnessTable *)*bdata++))
515672 return result;
516673 }
517674
675+ assert (numPacks == layout.NumPacks && " Missed a pack" );
518676 return 0 ;
519677 }
520678
@@ -573,16 +731,41 @@ class MetadataCacheKey {
573731private:
574732 uint32_t computeHash () const {
575733 size_t H = 0x56ba80d1u * Layout.NumKeyParameters ;
576- for (unsigned index = 0 ; index != Layout.NumKeyParameters ; ++index) {
577- H = (H >> 10 ) | (H << ((sizeof (size_t ) * 8 ) - 10 ));
578- H ^= (reinterpret_cast <size_t >(Data[index])
579- ^ (reinterpret_cast <size_t >(Data[index]) >> 19 ));
734+
735+ auto *nextPack = Layout.PackShapeDescriptors ;
736+ unsigned numPacks = 0 ;
737+
738+ auto update = [&H](uintptr_t value) {
739+ H = (H >> 10 ) | (H << ((sizeof (uintptr_t ) * 8 ) - 10 ));
740+ H ^= (value ^ (value >> 19 ));
741+ };
742+
743+ // FIXME: Incorporate NumShapeClasses into the hash
744+
745+ for (unsigned i = 0 ; i != Layout.NumKeyParameters ; ++i) {
746+ // Is this entry a metadata pack?
747+ if (numPacks < Layout.NumPacks &&
748+ nextPack->Kind == GenericPackKind::Metadata &&
749+ i == nextPack->Index ) {
750+ assert (nextPack->ShapeClass < Layout.NumShapeClasses );
751+ auto count = reinterpret_cast <uintptr_t >(Data[nextPack->ShapeClass ]);
752+ ++numPacks;
753+ ++nextPack;
754+
755+ MetadataPackPointer pack (Data[i]);
756+ for (unsigned j = 0 ; j < count; ++j)
757+ update (reinterpret_cast <uintptr_t >(pack.getElements ()[j]));
758+
759+ continue ;
760+ }
761+
762+ update (reinterpret_cast <uintptr_t >(Data[i]));
580763 }
581764
582765 H *= 0x27d4eb2d ;
583766
584767 // Rotate right by 10 and then truncate to 32 bits.
585- return uint32_t ((H >> 10 ) | (H << ((sizeof (size_t ) * 8 ) - 10 )));
768+ return uint32_t ((H >> 10 ) | (H << ((sizeof (uintptr_t ) * 8 ) - 10 )));
586769 }
587770};
588771
0 commit comments