Skip to content

Commit 5141219

Browse files
Merge pull request #32506 from nate-chandler/runtime/add-swift_getCanonicalSpecializedMetadata
[Runtime] Add entry point to canonicalize metadata.
2 parents bcb6699 + b0fc8da commit 5141219

File tree

8 files changed

+148
-2
lines changed

8 files changed

+148
-2
lines changed

include/swift/ABI/Metadata.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,8 @@ template <typename Runtime> class TargetEnumDescriptor;
492492
template <typename Runtime> class TargetStructDescriptor;
493493
template <typename Runtime> struct TargetGenericMetadataPattern;
494494

495+
using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;
496+
495497
// FIXME: https://bugs.swift.org/browse/SR-1155
496498
#pragma clang diagnostic push
497499
#pragma clang diagnostic ignored "-Winvalid-offsetof"
@@ -723,6 +725,10 @@ struct TargetMetadata {
723725

724726
bool satisfiesClassConstraint() const;
725727

728+
const TypeContextDescriptor *getDescription() const;
729+
730+
bool isStaticallySpecializedGenericMetadata() const;
731+
726732
bool isCanonicalStaticallySpecializedGenericMetadata() const;
727733

728734
#if SWIFT_OBJC_INTEROP
@@ -1304,6 +1310,14 @@ struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
13041310
}
13051311
#endif
13061312

1313+
bool isStaticallySpecializedGenericMetadata() const {
1314+
auto *description = getDescription();
1315+
if (!description->isGeneric())
1316+
return false;
1317+
1318+
return this->Flags & ClassFlags::IsStaticSpecialization;
1319+
}
1320+
13071321
bool isCanonicalStaticallySpecializedGenericMetadata() const {
13081322
auto *description = getDescription();
13091323
if (!description->isGeneric())
@@ -1449,6 +1463,18 @@ struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
14491463
return reinterpret_cast<const uint32_t *>(asWords + offset);
14501464
}
14511465

1466+
bool isStaticallySpecializedGenericMetadata() const {
1467+
auto *description = getDescription();
1468+
if (!description->isGeneric())
1469+
return false;
1470+
1471+
auto *trailingFlags = getTrailingFlags();
1472+
if (trailingFlags == nullptr)
1473+
return false;
1474+
1475+
return trailingFlags->isStaticSpecialization();
1476+
}
1477+
14521478
bool isCanonicalStaticallySpecializedGenericMetadata() const {
14531479
auto *description = getDescription();
14541480
if (!description->isGeneric())
@@ -1525,6 +1551,18 @@ struct TargetEnumMetadata : public TargetValueMetadata<Runtime> {
15251551
return *asWords;
15261552
}
15271553

1554+
bool isStaticallySpecializedGenericMetadata() const {
1555+
auto *description = getDescription();
1556+
if (!description->isGeneric())
1557+
return false;
1558+
1559+
auto *trailingFlags = getTrailingFlags();
1560+
if (trailingFlags == nullptr)
1561+
return false;
1562+
1563+
return trailingFlags->isStaticSpecialization();
1564+
}
1565+
15281566
bool isCanonicalStaticallySpecializedGenericMetadata() const {
15291567
auto *description = getDescription();
15301568
if (!description->isGeneric())
@@ -3820,8 +3858,6 @@ class TargetTypeContextDescriptor
38203858
}
38213859
};
38223860

3823-
using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;
3824-
38253861
/// Storage for class metadata bounds. This is the variable returned
38263862
/// by getAddrOfClassMetadataBounds in the compiler.
38273863
///

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,10 @@ class ASTContext final {
658658
/// platform.
659659
AvailabilityContext getCompareProtocolConformanceDescriptorsAvailability();
660660

661+
/// Get the runtime availability of support for inter-module prespecialized
662+
/// generic metadata.
663+
AvailabilityContext getIntermodulePrespecializedGenericMetadataAvailability();
664+
661665
/// Get the runtime availability of features introduced in the Swift 5.2
662666
/// compiler for the target platform.
663667
AvailabilityContext getSwift52Availability();

include/swift/Runtime/Metadata.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,26 @@ MetadataResponse
320320
swift_getSingletonMetadata(MetadataRequest request,
321321
const TypeContextDescriptor *description);
322322

323+
/// Fetch a uniqued metadata object for the generic nominal type described by
324+
/// the provided candidate metadata, using that candidate metadata if there is
325+
/// not already a canonical metadata.
326+
///
327+
/// Runtime availability: Swift 5.4
328+
///
329+
/// \param candidate A prespecialized metadata record for a type which is not
330+
/// statically made to be canonical which will be canonicalized
331+
/// if no other canonical metadata exists for the type.
332+
/// \param cache A pointer to a cache which will be set to the canonical
333+
/// metadata record for the type described by the candidate
334+
/// metadata record. If the cache has already been populated, its
335+
/// contents will be returned.
336+
/// \returns The canonical metadata for the specialized generic type described
337+
/// by the provided candidate metadata.
338+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift) MetadataResponse
339+
swift_getCanonicalSpecializedMetadata(MetadataRequest request,
340+
const Metadata *candidate,
341+
const Metadata **cache);
342+
323343
/// Fetch a uniqued metadata object for a generic nominal type.
324344
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
325345
MetadataResponse

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,14 @@ FUNCTION(GetGenericMetadata, swift_getGenericMetadata,
645645
ARGS(SizeTy, Int8PtrTy, TypeContextDescriptorPtrTy),
646646
ATTRS(NoUnwind, ReadOnly))
647647

648+
// MetadataResponse swift_getCanonicalSpecializedMetadata(MetadataRequest request,
649+
// Metadata *candidate);
650+
FUNCTION(GetCanonicalSpecializedMetadata, swift_getCanonicalSpecializedMetadata,
651+
SwiftCC, GetCanonicalSpecializedMetadataAvailability,
652+
RETURNS(TypeMetadataResponseTy),
653+
ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrPtrTy),
654+
ATTRS(NoUnwind, ReadOnly))
655+
648656
// MetadataResponse swift_getOpaqueTypeMetadata(MetadataRequest request,
649657
// const void * const *arguments,
650658
// const OpaqueTypeDescriptor *descriptor,

lib/AST/Availability.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ ASTContext::getCompareProtocolConformanceDescriptorsAvailability() {
318318
return getSwiftFutureAvailability();
319319
}
320320

321+
AvailabilityContext
322+
ASTContext::getIntermodulePrespecializedGenericMetadataAvailability() {
323+
return getSwiftFutureAvailability();
324+
}
325+
321326
AvailabilityContext ASTContext::getSwift52Availability() {
322327
auto target = LangOpts.Target;
323328

lib/IRGen/IRGenModule.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
271271
MetadataKindTy // MetadataKind Kind;
272272
});
273273
TypeMetadataPtrTy = TypeMetadataStructTy->getPointerTo(DefaultAS);
274+
TypeMetadataPtrPtrTy = TypeMetadataPtrTy->getPointerTo(DefaultAS);
274275

275276
TypeMetadataResponseTy = createStructType(*this, "swift.metadata_response", {
276277
TypeMetadataPtrTy,
@@ -670,6 +671,16 @@ namespace RuntimeConstants {
670671
}
671672
return RuntimeAvailability::AlwaysAvailable;
672673
}
674+
675+
RuntimeAvailability
676+
GetCanonicalSpecializedMetadataAvailability(ASTContext &context) {
677+
auto featureAvailability =
678+
context.getIntermodulePrespecializedGenericMetadataAvailability();
679+
if (!isDeploymentAvailabilityContainedIn(context, featureAvailability)) {
680+
return RuntimeAvailability::ConditionallyAvailable;
681+
}
682+
return RuntimeAvailability::AlwaysAvailable;
683+
}
673684
} // namespace RuntimeConstants
674685

675686
// We don't use enough attributes to justify generalizing the

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ class IRGenModule {
635635
llvm::FunctionType *DeallocatingDtorTy; /// void (%swift.refcounted*)
636636
llvm::StructType *TypeMetadataStructTy; /// %swift.type = type { ... }
637637
llvm::PointerType *TypeMetadataPtrTy;/// %swift.type*
638+
llvm::PointerType *TypeMetadataPtrPtrTy; /// %swift.type**
638639
union {
639640
llvm::StructType *TypeMetadataResponseTy; /// { %swift.type*, iSize }
640641
llvm::StructType *TypeMetadataDependencyTy; /// { %swift.type*, iSize }

stdlib/public/runtime/Metadata.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ namespace {
268268
GenericCacheEntry(MetadataCacheKey key, Args &&...args)
269269
: VariadicMetadataCacheEntryBase(key) {}
270270

271+
AllocationResult allocate(const Metadata *candidate) {
272+
return {const_cast<Metadata *>(candidate),
273+
PrivateMetadataState::Complete};
274+
}
275+
271276
AllocationResult allocate(const TypeContextDescriptor *description,
272277
const void * const *arguments) {
273278
// Find a pattern. Currently we always use the default pattern.
@@ -436,6 +441,28 @@ SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END
436441
extern "C" void *_objc_empty_cache;
437442
#endif
438443

444+
template <> bool Metadata::isStaticallySpecializedGenericMetadata() const {
445+
if (auto *metadata = dyn_cast<StructMetadata>(this))
446+
return metadata->isStaticallySpecializedGenericMetadata();
447+
if (auto *metadata = dyn_cast<EnumMetadata>(this))
448+
return metadata->isStaticallySpecializedGenericMetadata();
449+
if (auto *metadata = dyn_cast<ClassMetadata>(this))
450+
return metadata->isStaticallySpecializedGenericMetadata();
451+
452+
return false;
453+
}
454+
455+
template <> const TypeContextDescriptor *Metadata::getDescription() const {
456+
if (auto *metadata = dyn_cast<StructMetadata>(this))
457+
return metadata->getDescription();
458+
if (auto *metadata = dyn_cast<EnumMetadata>(this))
459+
return metadata->getDescription();
460+
if (auto *metadata = dyn_cast<ClassMetadata>(this))
461+
return metadata->getDescription();
462+
463+
return nullptr;
464+
}
465+
439466
template <>
440467
bool Metadata::isCanonicalStaticallySpecializedGenericMetadata() const {
441468
if (auto *metadata = dyn_cast<StructMetadata>(this))
@@ -673,6 +700,40 @@ swift::swift_allocateGenericValueMetadata(const ValueTypeDescriptor *description
673700
return metadata;
674701
}
675702

703+
MetadataResponse swift::swift_getCanonicalSpecializedMetadata(
704+
MetadataRequest request, const Metadata *candidate,
705+
const Metadata **cacheMetadataPtr) {
706+
assert(candidate->isStaticallySpecializedGenericMetadata() &&
707+
!candidate->isCanonicalStaticallySpecializedGenericMetadata());
708+
auto *description = candidate->getDescription();
709+
assert(description);
710+
711+
using CachedMetadata = std::atomic<const Metadata *>;
712+
auto cachedMetadataAddr = ((CachedMetadata *)cacheMetadataPtr);
713+
auto *cachedMetadata = cachedMetadataAddr->load(SWIFT_MEMORY_ORDER_CONSUME);
714+
if (SWIFT_LIKELY(cachedMetadata != nullptr)) {
715+
// Cached metadata pointers are always complete.
716+
return MetadataResponse{(const Metadata *)cachedMetadata,
717+
MetadataState::Complete};
718+
}
719+
720+
auto &cache = getCache(*description);
721+
assert(description->getFullGenericContextHeader().Base.NumKeyArguments ==
722+
cache.NumKeyParameters + cache.NumWitnessTables);
723+
const void *const *arguments =
724+
reinterpret_cast<const void *const *>(candidate->getGenericArgs());
725+
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
726+
arguments);
727+
auto result = cache.getOrInsert(key, request, candidate);
728+
729+
assert(
730+
!result.second.Value->isCanonicalStaticallySpecializedGenericMetadata());
731+
732+
cachedMetadataAddr->store(result.second.Value, std::memory_order_release);
733+
734+
return result.second;
735+
}
736+
676737
/// The primary entrypoint.
677738
MetadataResponse
678739
swift::swift_getGenericMetadata(MetadataRequest request,

0 commit comments

Comments
 (0)