Skip to content

Commit ac199ac

Browse files
committed
Runtime: Metadata cache key support for packs
1 parent e5eafbc commit ac199ac

File tree

2 files changed

+200
-12
lines changed

2 files changed

+200
-12
lines changed

include/swift/ABI/Metadata.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4915,23 +4915,28 @@ class TargetPackPointer {
49154915
public:
49164916
explicit TargetPackPointer(typename Runtime::StoredSize rawPtr) : Ptr(rawPtr) {}
49174917

4918+
explicit TargetPackPointer(const void *rawPtr)
4919+
: Ptr(reinterpret_cast<typename Runtime::StoredSize>(rawPtr)) {}
4920+
49184921
explicit TargetPackPointer(PointerType const *ptr, PackLifetime lifetime)
49194922
: Ptr(reinterpret_cast<typename Runtime::StoredSize>(ptr) |
49204923
(lifetime == PackLifetime::OnHeap ? 1 : 0)) {}
49214924

4925+
// Strips off the LSB.
49224926
const PointerType *getElements() const {
49234927
return reinterpret_cast<const PointerType *>(Ptr & ~1);
49244928
}
49254929

4930+
// Strips off the LSB.
49264931
PointerType *getElements() {
49274932
return reinterpret_cast<PointerType *>(Ptr & ~1);
49284933
}
49294934

4935+
// Leaves the LSB.
49304936
const PointerType *getPointer() const {
49314937
return reinterpret_cast<const PointerType *>(Ptr);
49324938
}
49334939

4934-
49354940
PackLifetime getLifetime() const {
49364941
return (bool)(Ptr & 1) ? PackLifetime::OnHeap : PackLifetime::OnStack;
49374942
}

stdlib/public/runtime/MetadataCache.h

Lines changed: 194 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -411,28 +411,83 @@ template<typename Runtime>
411411
struct 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

500575
private:
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 {
573731
private:
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

Comments
 (0)