Skip to content

Commit 8731eb4

Browse files
committed
Runtime: On-heap packs know their own length
1 parent 1fe9620 commit 8731eb4

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

include/swift/ABI/Metadata.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4944,6 +4944,14 @@ class TargetPackPointer {
49444944
PackLifetime getLifetime() const {
49454945
return (bool)(Ptr & 1) ? PackLifetime::OnHeap : PackLifetime::OnStack;
49464946
}
4947+
4948+
// Get the number of elements in the pack, only valid for on-heap packs.
4949+
size_t getNumElements() const {
4950+
if (getLifetime() == PackLifetime::OnHeap)
4951+
return *(reinterpret_cast<const size_t *>(Ptr & ~1) - 1);
4952+
4953+
fatalError(0, "Cannot get length of on-stack pack");
4954+
}
49474955
};
49484956

49494957
/// A pointer to a metadata pack.

stdlib/public/runtime/Metadata.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,9 @@ swift_allocateMetadataPack(const Metadata * const *ptr, size_t count) {
12751275
PackCacheEntry<Metadata>::Key key{ptr, count};
12761276
auto bytes = MetadataPacks.getOrInsert(key).first->getElements();
12771277

1278-
return MetadataPackPointer(bytes, PackLifetime::OnHeap).getPointer();
1278+
MetadataPackPointer pack(bytes, PackLifetime::OnHeap);
1279+
assert(pack.getNumElements() == count);
1280+
return pack.getPointer();
12791281
}
12801282

12811283
/// The uniquing structure for witness table packs.
@@ -1292,7 +1294,9 @@ swift_allocateWitnessTablePack(const WitnessTable * const *ptr, size_t count) {
12921294
PackCacheEntry<WitnessTable>::Key key{ptr, count};
12931295
auto bytes = WitnessTablePacks.getOrInsert(key).first->getElements();
12941296

1295-
return WitnessTablePackPointer(bytes, PackLifetime::OnHeap).getPointer();
1297+
WitnessTablePackPointer pack(bytes, PackLifetime::OnHeap);
1298+
assert(pack.getNumElements() == count);
1299+
return pack.getPointer();
12961300
}
12971301

12981302
/***************************************************************************/

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,14 @@ _gatherGenericParameters(const ContextDescriptor *context,
12001200
auto generics = context->getGenericContext();
12011201
assert(generics);
12021202
{
1203+
// Add a placeholder length for each shape class.
1204+
auto packShapeHeader = generics->getGenericPackShapeHeader();
1205+
if (packShapeHeader.NumShapeClasses > 0) {
1206+
assert(allGenericArgsVec.empty());
1207+
allGenericArgsVec.resize(packShapeHeader.NumShapeClasses);
1208+
}
1209+
1210+
// If we have the wrong number of generic arguments, fail.
12031211
auto genericParams = generics->getGenericParams();
12041212
unsigned n = genericParams.size();
12051213
if (allGenericArgs.size() != n) {
@@ -1210,6 +1218,8 @@ _gatherGenericParameters(const ContextDescriptor *context,
12101218
"generic args, expected " + std::to_string(n);
12111219
});
12121220
}
1221+
1222+
// Add metadata for each canonical generic parameter.
12131223
for (unsigned i = 0; i != n; ++i) {
12141224
const auto &param = genericParams[i];
12151225
if (param.getKind() != GenericParamKind::Type) {
@@ -1223,9 +1233,23 @@ _gatherGenericParameters(const ContextDescriptor *context,
12231233
if (param.hasKeyArgument())
12241234
allGenericArgsVec.push_back(allGenericArgs[i]);
12251235
}
1226-
}
12271236

1228-
// If we have the wrong number of generic arguments, fail.
1237+
// Fill in the length for each shape class.
1238+
auto packShapeDescriptors = generics->getGenericPackShapeDescriptors();
1239+
for (auto packShapeDescriptor : packShapeDescriptors) {
1240+
if (packShapeDescriptor.Kind != GenericPackKind::Metadata)
1241+
continue;
1242+
1243+
assert(packShapeDescriptor.Index < allGenericArgsVec.size());
1244+
assert(packShapeDescriptor.ShapeClass < packShapeHeader.NumShapeClasses);
1245+
1246+
MetadataPackPointer pack(allGenericArgsVec[packShapeDescriptor.Index]);
1247+
assert(pack.getLifetime() == PackLifetime::OnHeap);
1248+
1249+
allGenericArgsVec[packShapeDescriptor.ShapeClass] =
1250+
reinterpret_cast<const void *>(pack.getNumElements());
1251+
}
1252+
}
12291253

12301254
// Check whether the generic requirements are satisfied, collecting
12311255
// any extra arguments we need for the instantiation function.

0 commit comments

Comments
 (0)