Skip to content

Commit 560aad7

Browse files
committed
Runtime: Wrap pack pointers in a fancy TargetPackPointer template instead of twiddling the LSB by hand
This is more type safe in theory, but in practice it's just catnip for C++ fans.
1 parent 5663910 commit 560aad7

File tree

3 files changed

+61
-18
lines changed

3 files changed

+61
-18
lines changed

include/swift/ABI/Metadata.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4863,6 +4863,50 @@ class RuntimeDiscoverableAttributeRecord
48634863
}
48644864
};
48654865

4866+
enum class PackLifetime : uint8_t {
4867+
OnStack = 0,
4868+
OnHeap = 1
4869+
};
4870+
4871+
/// A pointer to a metadata or witness table pack. If the LSB is set,
4872+
/// the pack is allocated on the heap; otherwise, it is allocated on
4873+
/// the stack.
4874+
template<typename Runtime, template <typename> class Pointee>
4875+
class TargetPackPointer {
4876+
typename Runtime::StoredSize Ptr;
4877+
4878+
using PointerType = typename Runtime::template Pointer<const Pointee<Runtime>>;
4879+
4880+
public:
4881+
explicit TargetPackPointer(PointerType const *ptr, PackLifetime lifetime)
4882+
: Ptr(reinterpret_cast<typename Runtime::StoredSize>(ptr) |
4883+
(lifetime == PackLifetime::OnHeap ? 1 : 0)) {}
4884+
4885+
const PointerType *getElements() const {
4886+
return reinterpret_cast<const PointerType *>(Ptr & ~1);
4887+
}
4888+
4889+
PointerType *getElements() {
4890+
return reinterpret_cast<PointerType *>(Ptr & ~1);
4891+
}
4892+
4893+
PackLifetime getLifetime() const {
4894+
return (bool)(Ptr & 1) ? PackLifetime::OnHeap : PackLifetime::OnStack;
4895+
}
4896+
};
4897+
4898+
/// A pointer to a metadata pack.
4899+
template<typename Runtime>
4900+
using TargetMetadataPackPointer = TargetPackPointer<Runtime, TargetMetadata>;
4901+
4902+
using MetadataPackPointer = TargetMetadataPackPointer<InProcess>;
4903+
4904+
/// A pointer to a witness table pack.
4905+
template<typename Runtime>
4906+
using TargetWitnessTablePackPointer = TargetPackPointer<Runtime, TargetWitnessTable>;
4907+
4908+
using WitnessTablePackPointer = TargetWitnessTablePackPointer<InProcess>;
4909+
48664910
} // end namespace swift
48674911

48684912
#pragma clang diagnostic pop

include/swift/Runtime/Metadata.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@ bool swift_compareProtocolConformanceDescriptors(
456456
/// \returns a metadata pack allocated on the heap, with the least significant
457457
/// bit set to true.
458458
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
459-
const Metadata * const *
460-
swift_allocateMetadataPack(const Metadata * const *pack, unsigned count);
459+
MetadataPackPointer
460+
swift_allocateMetadataPack(MetadataPackPointer pack, unsigned count);
461461

462462
/// Allocate a witness table pack on the heap, unless this pack is already on
463463
/// the heap.
@@ -471,8 +471,8 @@ swift_allocateMetadataPack(const Metadata * const *pack, unsigned count);
471471
/// \returns a witness table pack allocated on the heap, with the least
472472
/// significant bit set to true.
473473
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
474-
const WitnessTable * const *
475-
swift_allocateWitnessTablePack(const WitnessTable * const *pack, unsigned count);
474+
WitnessTablePackPointer
475+
swift_allocateWitnessTablePack(WitnessTablePackPointer pack, unsigned count);
476476

477477
/// Fetch a uniqued metadata for a function type.
478478
SWIFT_RUNTIME_EXPORT

stdlib/public/runtime/Metadata.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,32 +1231,31 @@ MetadataPackCacheEntry::MetadataPackCacheEntry(const Key &key) {
12311231
static SimpleGlobalCache<MetadataPackCacheEntry, MetadataPackTag> MetadataPacks;
12321232

12331233
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
1234-
const Metadata * const *
1235-
swift_allocateMetadataPack(const Metadata * const *pack, unsigned count) {
1236-
if (reinterpret_cast<uintptr_t>(pack) & 1)
1234+
MetadataPackPointer
1235+
swift_allocateMetadataPack(MetadataPackPointer pack, unsigned count) {
1236+
if (pack.getLifetime() == PackLifetime::OnHeap)
12371237
return pack;
12381238

1239-
MetadataPackCacheEntry::Key key{pack, count};
1239+
MetadataPackCacheEntry::Key key{pack.getElements(), count};
12401240
auto bytes = MetadataPacks.getOrInsert(key).first->getElements();
12411241

1242-
uintptr_t bytesWithLSBSet = reinterpret_cast<uintptr_t>(bytes) | 1;
1243-
return reinterpret_cast<const Metadata * const *>(bytesWithLSBSet);
1242+
return MetadataPackPointer(bytes, PackLifetime::OnHeap);
12441243
}
12451244

12461245
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
1247-
const WitnessTable * const *
1248-
swift_allocateWitnessTablePack(const WitnessTable * const *pack, unsigned count) {
1249-
if (reinterpret_cast<uintptr_t>(pack) & 1)
1246+
WitnessTablePackPointer
1247+
swift_allocateWitnessTablePack(WitnessTablePackPointer pack, unsigned count) {
1248+
if (pack.getLifetime() == PackLifetime::OnHeap)
12501249
return pack;
12511250

12521251
size_t totalSize = (size_t) count * sizeof(const WitnessTable *);
12531252

1254-
auto bytes = (char*) MetadataAllocator(WitnessTablePackTag)
1255-
.Allocate(totalSize, alignof(const WitnessTable *));
1256-
memcpy(bytes, pack, totalSize);
1253+
auto bytes = (const WitnessTable **)
1254+
MetadataAllocator(WitnessTablePackTag)
1255+
.Allocate(totalSize, alignof(const WitnessTable *));
1256+
memcpy((char*) bytes, pack.getElements(), totalSize);
12571257

1258-
uintptr_t bytesWithLSBSet = reinterpret_cast<uintptr_t>(bytes) | 1;
1259-
return reinterpret_cast<const WitnessTable * const *>(bytesWithLSBSet);
1258+
return WitnessTablePackPointer(bytes, PackLifetime::OnHeap);
12601259
}
12611260

12621261
/***************************************************************************/

0 commit comments

Comments
 (0)