Skip to content

Commit 9a4540e

Browse files
committed
Split the instantiation function into two phases.
The allocation phase is guaranteed to succeed and just puts enough of the structure together to make things work. The completion phase does any component metadata lookups that are necessary (for the superclass, fields, etc.) and performs layout; it can fail and require restart. Next up is to support this in the runtime; then we can start the process of making metadata accessors actually allow incomplete metadata to be fetched.
1 parent 11e3d16 commit 9a4540e

22 files changed

+277
-34
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Globals
5353
global ::= type 'MP' // type metadata pattern
5454
global ::= type 'Ma' // type metadata access function
5555
global ::= type 'ML' // type metadata lazy cache variable
56+
global ::= nominal-type 'Mr' // generic type completion function
5657
global ::= nominal-type 'Mi' // generic type instantiation function
5758
global ::= nominal-type 'MI' // generic type instantiation cache
5859
global ::= nominal-type 'Mm' // class metaclass

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ enum {
3333
/// The number of words (pointers) in a value buffer.
3434
NumWords_ValueBuffer = 3,
3535

36+
/// The number of words in a metadata completion context.
37+
NumWords_MetadataCompletionContext = 4,
38+
3639
/// The number of words in a yield-once coroutine buffer.
3740
NumWords_YieldOnceBuffer = 4,
3841

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ NODE(TypeList)
173173
NODE(TypeMangling)
174174
NODE(TypeMetadata)
175175
NODE(TypeMetadataAccessFunction)
176+
NODE(TypeMetadataCompletionFunction)
176177
NODE(TypeMetadataInstantiationCache)
177178
NODE(TypeMetadataInstantiationFunction)
178179
NODE(TypeMetadataLazyCache)

include/swift/IRGen/Linking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ class LinkEntity {
159159
/// The pointer is a NominalTypeDecl*.
160160
TypeMetadataInstantiationFunction,
161161

162+
/// The completion function for a generic or resilient nominal type.
163+
/// The pointer is a NominalTypeDecl*.
164+
TypeMetadataCompletionFunction,
165+
162166
/// The module descriptor for a module.
163167
/// The pointer is a ModuleDecl*.
164168
ModuleDescriptor,
@@ -488,6 +492,12 @@ class LinkEntity {
488492
return entity;
489493
}
490494

495+
static LinkEntity forTypeMetadataCompletionFunction(NominalTypeDecl *decl) {
496+
LinkEntity entity;
497+
entity.setForDecl(Kind::TypeMetadataCompletionFunction, decl);
498+
return entity;
499+
}
500+
491501
static LinkEntity forTypeMetadataLazyCacheVariable(CanType type) {
492502
LinkEntity entity;
493503
entity.setForType(Kind::TypeMetadataLazyCacheVariable, type);

include/swift/Runtime/Metadata.h

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,18 +3067,71 @@ struct TargetGenericMetadataInstantiationCache {
30673067
using GenericMetadataInstantiationCache =
30683068
TargetGenericMetadataInstantiationCache<InProcess>;
30693069

3070+
/// A function that instantiates metadata. This function is required
3071+
/// to succeed.
3072+
///
3073+
/// In general, the metadata returned by this function should have all the
3074+
/// basic structure necessary to identify itself: that is, it must have a
3075+
/// type descriptor and generic arguments. However, it does not need to be
3076+
/// fully functional as type metadata; for example, it does not need to have
3077+
/// a meaningful value witness table, v-table entries, or a superclass.
3078+
///
3079+
/// Operations which may fail (due to e.g. recursive dependencies) but which
3080+
/// must be performed in order to prepare the metadata object to be fully
3081+
/// functional as type metadata should be delayed until the completion
3082+
/// function.
3083+
using MetadataInstantiator =
3084+
Metadata *(const TargetTypeContextDescriptor<InProcess> *type,
3085+
const void *arguments,
3086+
const TargetGenericMetadataPattern<InProcess> *pattern);
3087+
3088+
/// The opaque completion context of a metadata completion function.
3089+
/// A completion function that needs to report a completion dependency
3090+
/// can use this to figure out where it left off and thus avoid redundant
3091+
/// work when re-invoked. It will be zero on first entry for a type, and
3092+
/// the runtime is free to copy it to a different location between
3093+
/// invocations.
3094+
struct MetadataCompletionContext {
3095+
void *Data[NumWords_MetadataCompletionContext];
3096+
};
3097+
3098+
/// A function which attempts to complete the given metadata.
3099+
///
3100+
/// This function may fail due to a dependency on the completion of some
3101+
/// other metadata object. It can indicate this by returning the metadata
3102+
/// on which it depends. In this case, the function will be invoked again
3103+
/// when the dependency is resolved. The function must be careful not to
3104+
/// indicate a completion dependency on a type that has always been
3105+
/// completed; the runtime cannot reliably distinguish this sort of
3106+
/// programming failure from a race in which the dependent type was
3107+
/// completed immediately after it was observed to be incomplete, and so
3108+
/// the function will be repeatedly re-invoked.
3109+
///
3110+
/// The function will never be called multiple times simultaneously, but
3111+
/// it may be called many times as successive dependencies are resolved.
3112+
/// If the function ever completes successfully (by returning null), it
3113+
/// will not be called again for the same type.
3114+
///
3115+
/// \return null to indicate that the type has been completed, or a non-null
3116+
/// pointer to indicate that completion is blocked on the completion of
3117+
/// some other type
3118+
using MetadataCompleter =
3119+
Metadata *(const Metadata *type,
3120+
MetadataCompletionContext *context,
3121+
const TargetGenericMetadataPattern<InProcess> *pattern);
3122+
30703123
/// An instantiation pattern for type metadata.
30713124
template <typename Runtime>
30723125
struct TargetGenericMetadataPattern {
3073-
using InstantiationFunction_t =
3074-
TargetMetadata<Runtime> *(const TargetTypeContextDescriptor<Runtime> *type,
3075-
const void *arguments,
3076-
const TargetGenericMetadataPattern<Runtime> *pattern);
3077-
30783126
/// The function to call to instantiate the template.
3079-
TargetRelativeDirectPointer<Runtime, InstantiationFunction_t>
3127+
TargetRelativeDirectPointer<Runtime, MetadataInstantiator>
30803128
InstantiationFunction;
30813129

3130+
/// The function to call to complete the instantiation. If this is null,
3131+
/// the instantiation function must always generate complete metadata.
3132+
TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
3133+
CompletionFunction;
3134+
30823135
/// Flags describing the layout of this instantiation pattern.
30833136
GenericMetadataPatternFlags PatternFlags;
30843137

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,8 @@ NodePointer Demangler::demangleMetatype() {
14411441
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
14421442
case 'i':
14431443
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationFunction);
1444+
case 'r':
1445+
return createWithPoppedType(Node::Kind::TypeMetadataCompletionFunction);
14441446
case 'L':
14451447
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
14461448
case 'm':

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ class NodePrinter {
419419
case Node::Kind::TypeMangling:
420420
case Node::Kind::TypeMetadata:
421421
case Node::Kind::TypeMetadataAccessFunction:
422+
case Node::Kind::TypeMetadataCompletionFunction:
422423
case Node::Kind::TypeMetadataInstantiationCache:
423424
case Node::Kind::TypeMetadataInstantiationFunction:
424425
case Node::Kind::TypeMetadataLazyCache:
@@ -1456,6 +1457,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
14561457
Printer << "type metadata instantiation function for ";
14571458
print(Node->getChild(0));
14581459
return nullptr;
1460+
case Node::Kind::TypeMetadataCompletionFunction:
1461+
Printer << "type metadata completion function for ";
1462+
print(Node->getChild(0));
1463+
return nullptr;
14591464
case Node::Kind::TypeMetadataLazyCache:
14601465
Printer << "lazy cache variable for type metadata for ";
14611466
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
712712
mangleSingleChildNode(node); // type
713713
}
714714

715+
void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
716+
Out << "Mr";
717+
mangleSingleChildNode(node); // type
718+
}
719+
715720
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
716721
Out << "ML";
717722
mangleSingleChildNode(node); // type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
17121712
Buffer << "Mi";
17131713
}
17141714

1715+
void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
1716+
mangleSingleChildNode(node);
1717+
Buffer << "Mr";
1718+
}
1719+
17151720
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
17161721
mangleChildNodes(node);
17171722
Buffer << "ML";

lib/IRGen/GenDecl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
14591459

14601460
case Kind::TypeMetadataInstantiationCache:
14611461
case Kind::TypeMetadataInstantiationFunction:
1462+
case Kind::TypeMetadataCompletionFunction:
14621463
case Kind::TypeMetadataPattern:
14631464
return SILLinkage::Private;
14641465

@@ -1652,6 +1653,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16521653
case Kind::AnonymousDescriptor:
16531654
case Kind::TypeMetadataInstantiationCache:
16541655
case Kind::TypeMetadataInstantiationFunction:
1656+
case Kind::TypeMetadataCompletionFunction:
16551657
case Kind::TypeMetadataPattern:
16561658
return false;
16571659

@@ -3392,6 +3394,32 @@ IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
33923394
return entry;
33933395
}
33943396

3397+
llvm::Function *
3398+
IRGenModule::getAddrOfTypeMetadataCompletionFunction(NominalTypeDecl *D,
3399+
ForDefinition_t forDefinition) {
3400+
LinkEntity entity = LinkEntity::forTypeMetadataCompletionFunction(D);
3401+
llvm::Function *&entry = GlobalFuncs[entity];
3402+
if (entry) {
3403+
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
3404+
return entry;
3405+
}
3406+
3407+
llvm::Type *argTys[] = {
3408+
/// Type metadata.
3409+
TypeMetadataPtrTy,
3410+
/// Metadata completion context.
3411+
Int8PtrTy,
3412+
/// Generic metadata pattern.
3413+
Int8PtrPtrTy
3414+
};
3415+
auto fnType = llvm::FunctionType::get(TypeMetadataPtrTy,
3416+
argTys, /*isVarArg*/ false);
3417+
Signature signature(fnType, llvm::AttributeList(), DefaultCC);
3418+
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
3419+
entry = createFunction(*this, link, signature);
3420+
return entry;
3421+
}
3422+
33953423
/// Return the address of a nominal type descriptor.
33963424
llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
33973425
RequireMetadata_t requireMetadata,

0 commit comments

Comments
 (0)