Skip to content

Commit 74b2769

Browse files
authored
Merge pull request #64547 from slavapestov/metadata-cache-key-oops
Runtime: Fix MetadataCacheKey::installInto() for variadic generics
2 parents edfd3fd + 5f0d732 commit 74b2769

File tree

3 files changed

+59
-22
lines changed

3 files changed

+59
-22
lines changed

stdlib/public/runtime/Metadata.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -155,28 +155,20 @@ Metadata *TargetSingletonMetadataInitialization<InProcess>::allocate(
155155
return metadata;
156156
}
157157

158-
/// Copy the generic arguments into place in a newly-allocated metadata.
159-
static void installGenericArguments(Metadata *metadata,
160-
const TypeContextDescriptor *description,
161-
const void *arguments) {
162-
const auto &genericContext = *description->getGenericContext();
163-
const auto &header = genericContext.getGenericContextHeader();
164-
165-
auto dst = (reinterpret_cast<const void **>(metadata) +
166-
description->getGenericArgumentOffset());
167-
memcpy(dst,
168-
reinterpret_cast<const void * const *>(arguments),
169-
header.NumKeyArguments * sizeof(void *));
158+
void MetadataCacheKey::installGenericArguments(
159+
uint16_t numKeyArguments,
160+
uint16_t numPacks,
161+
const GenericPackShapeDescriptor *PackShapeDescriptors,
162+
const void **dst, const void * const *src) {
163+
memcpy(dst, src, numKeyArguments * sizeof(void *));
170164

171165
// If we don't have any pack arguments, there is nothing more to do.
172-
auto packShapeHeader = genericContext.getGenericPackShapeHeader();
173-
if (packShapeHeader.NumPacks == 0)
166+
if (numPacks == 0)
174167
return;
175168

176169
// Heap-allocate all installed metadata and witness table packs.
177-
for (auto pack : genericContext.getGenericPackShapeDescriptors()) {
178-
assert(pack.ShapeClass < packShapeHeader.NumShapeClasses);
179-
170+
for (unsigned i = 0; i < numPacks; ++i) {
171+
auto pack = PackShapeDescriptors[i];
180172
size_t count = reinterpret_cast<size_t>(dst[pack.ShapeClass]);
181173

182174
switch (pack.Kind) {
@@ -195,6 +187,26 @@ static void installGenericArguments(Metadata *metadata,
195187
}
196188
}
197189

190+
/// Copy the generic arguments into place in a newly-allocated metadata.
191+
static void installGenericArguments(Metadata *metadata,
192+
const TypeContextDescriptor *description,
193+
const void *arguments) {
194+
const auto &genericContext = *description->getGenericContext();
195+
const auto &header = genericContext.getGenericContextHeader();
196+
197+
auto dst = (reinterpret_cast<const void **>(metadata) +
198+
description->getGenericArgumentOffset());
199+
auto src = reinterpret_cast<const void * const *>(arguments);
200+
201+
auto packShapeHeader = genericContext.getGenericPackShapeHeader();
202+
203+
MetadataCacheKey::installGenericArguments(
204+
header.NumKeyArguments,
205+
packShapeHeader.NumPacks,
206+
genericContext.getGenericPackShapeDescriptors().data(),
207+
dst, src);
208+
}
209+
198210
#if SWIFT_OBJC_INTEROP
199211
static ClassMetadataBounds computeMetadataBoundsForObjCClass(Class cls) {
200212
cls = swift_getInitializedObjCClass(cls);

stdlib/public/runtime/MetadataCache.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,10 @@ class MetadataCacheKey {
521521
}
522522

523523
public:
524+
static void installGenericArguments(uint16_t numKeyArguments, uint16_t numPacks,
525+
const GenericPackShapeDescriptor *packShapeDescriptors,
526+
const void **dst, const void * const *src);
527+
524528
/// Compare two conformance descriptors, checking their contents if necessary.
525529
static bool areConformanceDescriptorsEqual(
526530
const ProtocolConformanceDescriptor *aDescription,
@@ -548,7 +552,8 @@ class MetadataCacheKey {
548552
MetadataPackPointer lhs(lhsPtr);
549553
MetadataPackPointer rhs(rhsPtr);
550554

551-
assert(lhs.getLifetime() == PackLifetime::OnHeap);
555+
// lhs is the user-supplied key, which might be on the stack.
556+
// rhs is the stored key in the cache.
552557
assert(rhs.getLifetime() == PackLifetime::OnHeap);
553558

554559
auto *lhsElt = lhs.getElements();
@@ -568,7 +573,8 @@ class MetadataCacheKey {
568573
WitnessTablePackPointer lhs(lhsPtr);
569574
WitnessTablePackPointer rhs(rhsPtr);
570575

571-
assert(lhs.getLifetime() == PackLifetime::OnHeap);
576+
// lhs is the user-supplied key, which might be on the stack.
577+
// rhs is the stored key in the cache.
572578
assert(rhs.getLifetime() == PackLifetime::OnHeap);
573579

574580
auto *lhsElt = lhs.getElements();
@@ -591,7 +597,7 @@ class MetadataCacheKey {
591597
const void *const *data, uint32_t hash)
592598
: Data(data), Layout(layout), Hash(hash) {}
593599

594-
bool operator==(MetadataCacheKey rhs) const {
600+
bool operator==(const MetadataCacheKey &rhs) const {
595601
// Compare the hashes.
596602
if (hash() != rhs.hash()) return false;
597603

@@ -682,8 +688,11 @@ class MetadataCacheKey {
682688
unsigned size() const { return Layout.sizeInWords(); }
683689

684690
void installInto(const void **buffer) const {
685-
// FIXME: variadic-parameter-packs
686-
memcpy(buffer, Data, size() * sizeof(const void *));
691+
MetadataCacheKey::installGenericArguments(
692+
Layout.sizeInWords(),
693+
Layout.NumPacks,
694+
Layout.PackShapeDescriptors,
695+
buffer, Data);
687696
}
688697

689698
private:

test/Interpreter/variadic_generic_types.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ public struct Outer<each U> {
2626
public struct InnerSameShape<each V> where (repeat (each U, each V)): Any {}
2727
}
2828

29+
func makeMetatype<each T>(_: repeat (each T).Type) -> Any.Type {
30+
return Outer<repeat each T>.self
31+
}
32+
33+
func blackHole<T>(_: T) {}
34+
35+
types.test("OuterRepeated") {
36+
// Instantiate a type containing type parameters to avoid caching
37+
blackHole(makeMetatype())
38+
blackHole(makeMetatype())
39+
blackHole(makeMetatype(Int.self))
40+
blackHole(makeMetatype(Int.self))
41+
blackHole(makeMetatype(String.self, Substring.self))
42+
blackHole(makeMetatype(String.self, Substring.self))
43+
}
44+
2945
types.test("Outer") {
3046
expectEqual("main.Outer<Pack{}>", _typeName(Outer< >.self))
3147
expectEqual("main.Outer<Pack{Swift.Int}>", _typeName(Outer<Int>.self))

0 commit comments

Comments
 (0)