Skip to content

[metadata prespecialization] Add canonical records to cache. #34490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ Globals

global ::= global 'MJ' // noncanonical specialized generic type metadata instantiation cache associated with global
global ::= global 'MN' // noncanonical specialized generic type metadata for global
global ::= global 'Mz' // canonical specialized generic type metadata caching token

#if SWIFT_RUNTIME_VERSION >= 5.4
global ::= context (decl-name '_')+ 'WZ' // global variable one-time initialization function
Expand Down
88 changes: 81 additions & 7 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "swift/Strings.h"
#include "swift/Runtime/Config.h"
#include "swift/Runtime/Once.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/ABI/System.h"
#include "swift/ABI/TrailingObjects.h"
Expand Down Expand Up @@ -3796,6 +3797,11 @@ struct TargetCanonicalSpecializedMetadataAccessorsListEntry {
TargetRelativeDirectPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false> accessor;
};

template <typename Runtime>
struct TargetCanonicalSpecializedMetadatasCachingOnceToken {
TargetRelativeDirectPointer<Runtime, swift_once_t, /*Nullable*/ false> token;
};

template <typename Runtime>
class TargetTypeContextDescriptor
: public TargetContextDescriptor<Runtime> {
Expand Down Expand Up @@ -3882,7 +3888,9 @@ class TargetTypeContextDescriptor
}

const llvm::ArrayRef<TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>>
getCanonicicalMetadataPrespecializations() const;
getCanonicicalMetadataPrespecializations() const;

swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const;

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() >= ContextDescriptorKind::Type_First
Expand Down Expand Up @@ -4024,7 +4032,8 @@ class TargetClassDescriptor final
TargetObjCResilientClassStubInfo<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>> {
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>> {
private:
using TrailingGenericContextObjects =
swift::TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
Expand All @@ -4039,7 +4048,8 @@ class TargetClassDescriptor final
TargetObjCResilientClassStubInfo<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>>;
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>>;

using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
Expand Down Expand Up @@ -4067,6 +4077,8 @@ class TargetClassDescriptor final
TargetRelativeDirectPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false>;
using MetadataAccessorListEntry =
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>;
using MetadataCachingOnceToken =
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;

using StoredPointer = typename Runtime::StoredPointer;
using StoredPointerDifference = typename Runtime::StoredPointerDifference;
Expand Down Expand Up @@ -4204,6 +4216,10 @@ class TargetClassDescriptor final
: 0;
}

size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
return this->hasCanonicicalMetadataPrespecializations() ? 1 : 0;
}

public:
const TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> &
getResilientSuperclass() const {
Expand Down Expand Up @@ -4367,6 +4383,14 @@ class TargetClassDescriptor final
);
}

swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return nullptr;
}
auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
return box->token.get();
}

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Class;
}
Expand Down Expand Up @@ -4394,7 +4418,8 @@ class TargetStructDescriptor final
TargetForeignMetadataInitialization<Runtime>,
TargetSingletonMetadataInitialization<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>> {
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>> {
public:
using ForeignMetadataInitialization =
TargetForeignMetadataInitialization<Runtime>;
Expand All @@ -4406,6 +4431,8 @@ class TargetStructDescriptor final
TargetCanonicalSpecializedMetadatasListCount<Runtime>;
using MetadataListEntry =
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
using MetadataCachingOnceToken =
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;

private:
using TrailingGenericContextObjects =
Expand All @@ -4414,7 +4441,8 @@ class TargetStructDescriptor final
ForeignMetadataInitialization,
SingletonMetadataInitialization,
MetadataListCount,
MetadataListEntry>;
MetadataListEntry,
MetadataCachingOnceToken>;

using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
Expand Down Expand Up @@ -4444,6 +4472,10 @@ class TargetStructDescriptor final
: 0;
}

size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
return this->hasCanonicicalMetadataPrespecializations() ? 1 : 0;
}

public:
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
Expand Down Expand Up @@ -4489,6 +4521,14 @@ class TargetStructDescriptor final
);
}

swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return nullptr;
}
auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
return box->token.get();
}

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Struct;
}
Expand All @@ -4505,7 +4545,8 @@ class TargetEnumDescriptor final
TargetForeignMetadataInitialization<Runtime>,
TargetSingletonMetadataInitialization<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>> {
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>> {
public:
using SingletonMetadataInitialization =
TargetSingletonMetadataInitialization<Runtime>;
Expand All @@ -4517,6 +4558,8 @@ class TargetEnumDescriptor final
TargetCanonicalSpecializedMetadatasListCount<Runtime>;
using MetadataListEntry =
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
using MetadataCachingOnceToken =
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;

private:
using TrailingGenericContextObjects =
Expand All @@ -4525,7 +4568,8 @@ class TargetEnumDescriptor final
ForeignMetadataInitialization,
SingletonMetadataInitialization,
MetadataListCount,
MetadataListEntry>;
MetadataListEntry,
MetadataCachingOnceToken>;

using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
Expand Down Expand Up @@ -4555,6 +4599,10 @@ class TargetEnumDescriptor final
: 0;
}

size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
return this->hasCanonicicalMetadataPrespecializations() ? 1 : 0;
}

public:
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
Expand Down Expand Up @@ -4614,6 +4662,14 @@ class TargetEnumDescriptor final
);
}

swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return nullptr;
}
auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
return box->token.get();
}

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Enum;
}
Expand Down Expand Up @@ -4766,6 +4822,24 @@ TargetTypeContextDescriptor<Runtime>::getCanonicicalMetadataPrespecializations()
}
}

template <typename Runtime>
inline swift_once_t *TargetTypeContextDescriptor<
Runtime>::getCanonicalMetadataPrespecializationCachingOnceToken() const {
switch (this->getKind()) {
case ContextDescriptorKind::Enum:
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
->getCanonicalMetadataPrespecializationCachingOnceToken();
case ContextDescriptorKind::Struct:
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
->getCanonicalMetadataPrespecializationCachingOnceToken();
case ContextDescriptorKind::Class:
return llvm::cast<TargetClassDescriptor<Runtime>>(this)
->getCanonicalMetadataPrespecializationCachingOnceToken();
default:
swift_unreachable("Not a type context descriptor.");
}
}

/// An entry in the chain of dynamic replacement functions.
struct DynamicReplacementChainEntry {
void *implementationFunction;
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ NODE(NoncanonicalSpecializedGenericTypeMetadataCache)
NODE(GlobalVariableOnceFunction)
NODE(GlobalVariableOnceToken)
NODE(GlobalVariableOnceDeclList)
NODE(CanonicalPrespecializedGenericTypeCachingOnceToken)

#undef CONTEXT_NODE
#undef NODE
19 changes: 17 additions & 2 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,13 @@ class LinkEntity {
/// The pointer is a AbstractStorageDecl*.
DynamicallyReplaceableFunctionImpl,

/// The once token used by cacheCanonicalSpecializedMetadata, by way of
/// swift_getCanonicalSpecializedMetadata and
/// swift_getCanonicalPrespecializedGenericMetadata, to
/// ensure that canonical prespecialized generic records are only added to
/// the metadata cache once.
CanonicalPrespecializedGenericTypeCachingOnceToken,

/// The pointer is a SILFunction*.
DynamicallyReplaceableFunctionKey,

Expand Down Expand Up @@ -399,7 +406,7 @@ class LinkEntity {
/// The pointer is a canonical TypeBase*.
NoncanonicalSpecializedGenericTypeMetadata,

/// A cache variable for noncanonical specialized type metadata, to be
/// A cache variable for noncanonical specialized type metadata, to be
/// passed to swift_getCanonicalSpecializedMetadata.
/// The pointer is a canonical TypeBase*.
NoncanonicalSpecializedGenericTypeMetadataCacheVariable,
Expand All @@ -411,7 +418,7 @@ class LinkEntity {
}

static bool isDeclKind(Kind k) {
return k <= Kind::DynamicallyReplaceableFunctionImpl;
return k <= Kind::CanonicalPrespecializedGenericTypeCachingOnceToken;
}
static bool isTypeKind(Kind k) {
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
Expand Down Expand Up @@ -1039,6 +1046,14 @@ class LinkEntity {
return entity;
}

static LinkEntity
forCanonicalPrespecializedGenericTypeCachingOnceToken(NominalTypeDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::CanonicalPrespecializedGenericTypeCachingOnceToken,
decl);
return entity;
}

static LinkEntity
forSpecializedGenericSwiftMetaclassStub(CanType concreteType) {
LinkEntity entity;
Expand Down
26 changes: 26 additions & 0 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "swift/ABI/Metadata.h"
#include "swift/Reflection/Records.h"
#include "swift/Runtime/Once.h"

namespace swift {

Expand Down Expand Up @@ -340,6 +341,31 @@ SWIFT_RUNTIME_EXPORT SWIFT_CC(swift) MetadataResponse
const Metadata *candidate,
const Metadata **cache);

/// Fetch a uniqued metadata object for the generic nominal type described by
/// the provided description and arguments, adding the canonical
/// prespecializations attached to the type descriptor to the metadata cache on
/// first run.
///
/// In contrast to swift_getGenericMetadata, this function is for use by
/// metadata accessors for which canonical generic metadata has been specialized
/// at compile time.
///
/// Runtime availability: Swift 5.4
///
/// \param request A specification of the metadata to be returned.
/// \param arguments The generic arguments--metadata and witness tables--which
/// the returned metadata is to have been instantiated with.
/// \param description The type descriptor for the generic type whose
/// generic metadata is to have been instantiated.
/// \param token The token that ensures that prespecialized records are added to
/// the metadata cache only once.
/// \returns The canonical metadata for the specialized generic type described
/// by the provided candidate metadata.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift) MetadataResponse
swift_getCanonicalPrespecializedGenericMetadata(
MetadataRequest request, const void *const *arguments,
const TypeContextDescriptor *description, swift_once_t *token);

/// Fetch a uniqued metadata object for a generic nominal type.
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
MetadataResponse
Expand Down
12 changes: 12 additions & 0 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,18 @@ FUNCTION(GetCanonicalSpecializedMetadata, swift_getCanonicalSpecializedMetadata,
ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrPtrTy),
ATTRS(NoUnwind, ReadOnly))

// MetadataResponse
// swift_getCanonicalPrespecializedGenericMetadata(MetadataRequest request,
// const void * const *arguments,
// const TypeContextDescriptor *description,
// swift_once_t *cachedFlag)
FUNCTION(GetCanonicalPrespecializedGenericMetadata,
swift_getCanonicalPrespecializedGenericMetadata,
SwiftCC, GetCanonicalPrespecializedGenericMetadataAvailability,
RETURNS(TypeMetadataResponseTy),
ARGS(SizeTy, Int8PtrTy, TypeContextDescriptorPtrTy, OnceTy->getPointerTo()),
ATTRS(NoUnwind, ReadOnly))

// MetadataResponse swift_getOpaqueTypeMetadata(MetadataRequest request,
// const void * const *arguments,
// const OpaqueTypeDescriptor *descriptor,
Expand Down
3 changes: 3 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,9 @@ NodePointer Demangler::demangleMetatype() {
popNode(isEntity));
case 'X':
return demanglePrivateContextDescriptor();
case 'z':
return createWithPoppedType(
Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken);
default:
return nullptr;
}
Expand Down
6 changes: 6 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ class NodePrinter {
case Node::Kind::GlobalVariableOnceDeclList:
case Node::Kind::GlobalVariableOnceFunction:
case Node::Kind::GlobalVariableOnceToken:
case Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
return false;
}
printer_unreachable("bad node kind");
Expand Down Expand Up @@ -2537,6 +2538,11 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
Printer << "@objc completion handler block implementation for ";
print(Node->getChild(0));
return nullptr;
case Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
Printer << "flag for loading of canonical specialized generic type "
"metadata for ";
print(Node->getChild(0));
return nullptr;
}
printer_unreachable("bad node kind!");
}
Expand Down
6 changes: 6 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2191,6 +2191,12 @@ void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache(Node *node
Buffer << "MJ";
}

void Remangler::mangleCanonicalPrespecializedGenericTypeCachingOnceToken(
Node *node) {
mangleSingleChildNode(node);
Buffer << "Mz";
}

/// The top-level interface to the remangler.
std::string Demangle::mangleNodeOld(NodePointer node) {
if (!node) return "";
Expand Down
6 changes: 6 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2633,6 +2633,12 @@ void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache(Node *node
Buffer << "MJ";
}

void Remangler::mangleCanonicalPrespecializedGenericTypeCachingOnceToken(
Node *node) {
mangleSingleChildNode(node);
Buffer << "Mz";
}

void Remangler::mangleGlobalVariableOnceToken(Node *node) {
mangleChildNodes(node);
Buffer << "Wz";
Expand Down
Loading