Skip to content

Commit 48a8b26

Browse files
authored
Merge pull request #13338 from slavapestov/class-resilience-part-4
Class resilience part 4
2 parents 7d0b73a + e04f6e8 commit 48a8b26

22 files changed

+265
-137
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Globals
5555
global ::= type 'ML' // type metadata lazy cache variable
5656
global ::= nominal-type 'Mm' // class metaclass
5757
global ::= nominal-type 'Mn' // nominal type descriptor
58+
global ::= nominal-type 'Mo' // class metadata immediate member base offset
5859
global ::= protocol 'Mp' // protocol descriptor
5960
global ::= type 'MF' // metadata for remote mirrors: field descriptor
6061
global ::= type 'MB' // metadata for remote mirrors: builtin type descriptor

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ NODE(BoundGenericStructure)
3737
NODE(BuiltinTypeName)
3838
NODE(CFunctionPointer)
3939
CONTEXT_NODE(Class)
40+
NODE(ClassMetadataBaseOffset)
4041
CONTEXT_NODE(Constructor)
4142
CONTEXT_NODE(Deallocator)
4243
NODE(DeclContext)

include/swift/IRGen/Linking.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ class LinkEntity {
110110
/// A swift metaclass-stub reference. The pointer is a ClassDecl*.
111111
SwiftMetaclassStub,
112112

113+
/// A class metadata base offset global variable. This stores the offset
114+
/// of the immediate members of a class (generic parameters, field offsets,
115+
/// vtable offsets) in the class's metadata. The immediate members begin
116+
/// immediately after the superclass members end.
117+
///
118+
/// The pointer is a ClassDecl*.
119+
ClassMetadataBaseOffset,
120+
113121
/// The nominal type descriptor for a nominal type.
114122
/// The pointer is a NominalTypeDecl*.
115123
NominalTypeDescriptor,
@@ -416,6 +424,12 @@ class LinkEntity {
416424
return entity;
417425
}
418426

427+
static LinkEntity forClassMetadataBaseOffset(ClassDecl *decl) {
428+
LinkEntity entity;
429+
entity.setForDecl(Kind::ClassMetadataBaseOffset, decl);
430+
return entity;
431+
}
432+
419433
static LinkEntity forNominalTypeDescriptor(NominalTypeDecl *decl) {
420434
LinkEntity entity;
421435
entity.setForDecl(Kind::NominalTypeDescriptor, decl);

include/swift/Runtime/Metadata.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,7 @@ struct TargetGenericMetadata {
22062206
(TargetGenericMetadata<Runtime> *pattern, const void *arguments);
22072207

22082208
/// The size of the template in bytes.
2209-
uint32_t MetadataSize;
2209+
uint32_t TemplateSize;
22102210

22112211
/// The number of generic arguments that we need to unique on,
22122212
/// in words. The first 'NumArguments * sizeof(void*)' bytes of
@@ -2223,7 +2223,7 @@ struct TargetGenericMetadata {
22232223
PrivateData[swift::NumGenericMetadataPrivateDataWords];
22242224

22252225
// Here there is a variably-sized field:
2226-
// char alignas(void*) MetadataTemplate[MetadataSize];
2226+
// char alignas(void*) MetadataTemplate[TemplateSize];
22272227

22282228
/// Return the starting address of the metadata template data.
22292229
TargetPointer<Runtime, const void> getMetadataTemplate() const {
@@ -2602,8 +2602,9 @@ using ProtocolConformanceRecord
26022602
/// if (metadata = getExistingMetadata(&header.PrivateData,
26032603
/// arguments[0..header.NumArguments]))
26042604
/// return metadata
2605-
/// metadata = malloc(header.MetadataSize)
2606-
/// memcpy(metadata, header.MetadataTemplate, header.MetadataSize)
2605+
/// metadata = malloc(superclass.MetadataSize +
2606+
/// numImmediateMembers * sizeof(void *))
2607+
/// memcpy(metadata, header.MetadataTemplate, header.TemplateSize)
26072608
/// for (i in 0..header.NumFillInstructions)
26082609
/// metadata[header.FillInstructions[i].ToIndex]
26092610
/// = arguments[header.FillInstructions[i].FromIndex]
@@ -2623,7 +2624,8 @@ SWIFT_RUNTIME_EXPORT
26232624
ClassMetadata *
26242625
swift_allocateGenericClassMetadata(GenericMetadata *pattern,
26252626
const void *arguments,
2626-
ClassMetadata *superclass);
2627+
ClassMetadata *superclass,
2628+
size_t numImmediateMembers);
26272629

26282630
// Callback to allocate a generic struct/enum metadata object.
26292631
SWIFT_RUNTIME_EXPORT
@@ -2867,6 +2869,16 @@ void swift_initStructMetadata_UniversalStrategy(size_t numFields,
28672869
size_t *fieldOffsets,
28682870
ValueWitnessTable *vwtable);
28692871

2872+
/// Relocate the metadata for a class and copy fields from the given template.
2873+
/// The final size of the metadata is calculated at runtime from the size of
2874+
/// the superclass metadata together with the given number of immediate
2875+
/// members.
2876+
SWIFT_RUNTIME_EXPORT
2877+
ClassMetadata *
2878+
swift_relocateClassMetadata(ClassMetadata *self,
2879+
size_t templateSize,
2880+
size_t numImmediateMembers);
2881+
28702882
/// Initialize the field offset vector for a dependent-layout class, using the
28712883
/// "Universal" layout strategy.
28722884
SWIFT_RUNTIME_EXPORT

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,10 +854,11 @@ FUNCTION(GetGenericMetadata, swift_getGenericMetadata, RegisterPreservingCC,
854854

855855
// Metadata *swift_allocateGenericClassMetadata(GenericMetadata *pattern,
856856
// const void * const *arguments,
857-
// objc_class *superclass);
857+
// objc_class *superclass,
858+
// size_t numImmediateMembers);
858859
FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
859860
DefaultCC, RETURNS(TypeMetadataPtrTy),
860-
ARGS(TypeMetadataPatternPtrTy, Int8PtrPtrTy, ObjCClassPtrTy),
861+
ARGS(TypeMetadataPatternPtrTy, Int8PtrPtrTy, ObjCClassPtrTy, SizeTy),
861862
ATTRS(NoUnwind))
862863

863864
// Metadata *swift_allocateGenericValueMetadata(GenericMetadata *pattern,
@@ -945,6 +946,15 @@ FUNCTION(GetExistentialMetadata,
945946
ProtocolDescriptorPtrTy->getPointerTo()),
946947
ATTRS(NoUnwind, ReadOnly))
947948

949+
// Metadata *swift_relocateClassMetadata(Metadata *self,
950+
// size_t templateSize,
951+
// size_t numImmediateMembers);
952+
FUNCTION(RelocateClassMetadata,
953+
swift_relocateClassMetadata, DefaultCC,
954+
RETURNS(TypeMetadataPtrTy),
955+
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy),
956+
ATTRS(NoUnwind))
957+
948958
// struct FieldInfo { size_t Size; size_t AlignMask; };
949959
// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
950960
// size_t numFields,

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,8 @@ NodePointer Demangler::demangleMetatype() {
10891089
return createWithPoppedType(Node::Kind::Metaclass);
10901090
case 'n':
10911091
return createWithPoppedType(Node::Kind::NominalTypeDescriptor);
1092+
case 'o':
1093+
return createWithPoppedType(Node::Kind::ClassMetadataBaseOffset);
10921094
case 'p':
10931095
return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
10941096
case 'B':

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ class NodePrinter {
291291
case Node::Kind::AssociatedTypeMetadataAccessor:
292292
case Node::Kind::AssociatedTypeWitnessTableAccessor:
293293
case Node::Kind::AutoClosureType:
294+
case Node::Kind::ClassMetadataBaseOffset:
294295
case Node::Kind::CFunctionPointer:
295296
case Node::Kind::Constructor:
296297
case Node::Kind::CurryThunk:
@@ -1372,6 +1373,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
13721373
Printer << " in ";
13731374
print(Node->getChild(0));
13741375
return nullptr;
1376+
case Node::Kind::ClassMetadataBaseOffset:
1377+
Printer << "class metadata base offset for ";
1378+
print(Node->getChild(0));
1379+
return nullptr;
13751380
case Node::Kind::NominalTypeDescriptor:
13761381
Printer << "nominal type descriptor for ";
13771382
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,11 @@ void Remangler::mangleMetaclass(Node *node) {
625625
mangleSingleChildNode(node); // type
626626
}
627627

628+
void Remangler::mangleClassMetadataBaseOffset(Node *node) {
629+
Out << "Mo";
630+
mangleSingleChildNode(node); // type
631+
}
632+
628633
void Remangler::mangleNominalTypeDescriptor(Node *node) {
629634
Out << "Mn";
630635
mangleSingleChildNode(node); // type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,11 @@ void Remangler::mangleNativePinningMutableAddressor(Node *node) {
13541354
mangleAbstractStorage(node->getFirstChild(), "aP");
13551355
}
13561356

1357+
void Remangler::mangleClassMetadataBaseOffset(Node *node) {
1358+
mangleSingleChildNode(node);
1359+
Buffer << "Mo";
1360+
}
1361+
13571362
void Remangler::mangleNominalTypeDescriptor(Node *node) {
13581363
mangleSingleChildNode(node);
13591364
Buffer << "Mn";

lib/IRGen/GenDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
12581258
case Kind::SwiftMetaclassStub:
12591259
case Kind::FieldOffset:
12601260
case Kind::NominalTypeDescriptor:
1261+
case Kind::ClassMetadataBaseOffset:
12611262
case Kind::ProtocolDescriptor:
12621263
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
12631264

@@ -1344,6 +1345,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
13441345
return true;
13451346

13461347
case Kind::SwiftMetaclassStub:
1348+
case Kind::ClassMetadataBaseOffset:
13471349
case Kind::NominalTypeDescriptor:
13481350
case Kind::ProtocolDescriptor:
13491351
return ::isAvailableExternally(IGM, getDecl());
@@ -2819,6 +2821,15 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
28192821
return addr;
28202822
}
28212823

2824+
/// Returns the address of a class metadata base offset.
2825+
llvm::Constant *
2826+
IRGenModule::getAddrOfClassMetadataBaseOffset(ClassDecl *D,
2827+
ForDefinition_t forDefinition) {
2828+
LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
2829+
return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
2830+
SizeTy, DebugTypeInfo());
2831+
}
2832+
28222833
/// Return the address of a nominal type descriptor. Right now, this
28232834
/// must always be for purposes of defining it.
28242835
llvm::Constant *IRGenModule::getAddrOfNominalTypeDescriptor(NominalTypeDecl *D,

lib/IRGen/GenMeta.cpp

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,7 +2926,7 @@ namespace {
29262926
// Metadata *(*CreateFunction)(GenericMetadata *, const void*);
29272927
B.fillPlaceholder(createFunctionField, emitCreateFunction());
29282928

2929-
// uint32_t MetadataSize;
2929+
// uint32_t TemplateSize;
29302930
// We compute this assuming that every entry in the metadata table
29312931
// is a pointer in size.
29322932
Size size = getNextOffsetFromTemplateHeader();
@@ -3141,7 +3141,6 @@ namespace {
31413141
/// size is not known at compile time.
31423142
class ResilientClassMemberBuilder {
31433143
IRGenModule &IGM;
3144-
ConstantStructBuilder &B;
31453144
SILVTable *VTable;
31463145

31473146
struct MethodOverride {
@@ -3156,23 +3155,13 @@ namespace {
31563155
ConstantStructBuilder &builder,
31573156
const StructLayout &layout,
31583157
const ClassLayout &fieldLayout)
3159-
: IGM(IGM), B(builder) {
3158+
: IGM(IGM) {
31603159
VTable = IGM.getSILModule().lookUpVTable(theClass);
31613160
}
31623161

3163-
void addFieldOffset(VarDecl *var) {
3164-
B.addInt(IGM.SizeTy, 0);
3165-
}
3162+
void addFieldOffset(VarDecl *var) {}
31663163

3167-
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
3168-
for (unsigned i = 0,
3169-
e = placeholder->getNumberOfFieldOffsetVectorEntries();
3170-
i < e; ++i) {
3171-
// Emit placeholder values for some number of stored properties we
3172-
// know exist but aren't able to reference directly.
3173-
B.addInt(IGM.SizeTy, 0);
3174-
}
3175-
}
3164+
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {}
31763165

31773166
void addMethod(SILDeclRef fn) {
31783167
// Find the vtable entry.
@@ -3192,8 +3181,6 @@ namespace {
31923181
// Record the override so that we can fill it in later.
31933182
Overrides.push_back({offset, entry->Implementation});
31943183
}
3195-
3196-
B.addNullPointer(IGM.FunctionPtrTy);
31973184
}
31983185

31993186
// Update vtable entries for method overrides. The runtime copies in
@@ -3223,14 +3210,10 @@ namespace {
32233210
// FIXME
32243211
}
32253212

3226-
void addGenericArgument(CanType argTy, ClassDecl *forClass) {
3227-
B.addNullPointer(IGM.TypeMetadataPtrTy);
3228-
}
3213+
void addGenericArgument(CanType argTy, ClassDecl *forClass) {}
32293214

32303215
void addGenericWitnessTable(CanType argTy, ProtocolConformanceRef conf,
3231-
ClassDecl *forClass) {
3232-
B.addNullPointer(IGM.WitnessTablePtrTy);
3233-
}
3216+
ClassDecl *forClass) {}
32343217
};
32353218

32363219
/// Base class for laying out class metadata.
@@ -3399,6 +3382,7 @@ namespace {
33993382
}
34003383

34013384
void addClassAddressPoint() {
3385+
// FIXME: Wrong
34023386
auto size = IGM.getMetadataLayout(Target).getSize();
34033387
B.addInt32(size.AddressPoint.getValue());
34043388
}
@@ -3720,10 +3704,21 @@ namespace {
37203704
Address superField =
37213705
emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
37223706
superField = IGF.Builder.CreateElementBitCast(superField,
3723-
IGF.IGM.TypeMetadataPtrTy);
3707+
IGM.TypeMetadataPtrTy);
37243708
IGF.Builder.CreateStore(superclassMetadata, superField);
37253709
}
37263710

3711+
// Relocate the metadata if it has a superclass that is resilient
3712+
// to us.
3713+
if (doesClassMetadataRequireDynamicInitialization(IGM, Target)) {
3714+
auto templateSize = IGM.getSize(Size(B.getNextOffsetFromGlobal()));
3715+
auto numImmediateMembers = IGM.getSize(
3716+
Size(IGM.getMetadataLayout(Target).getNumImmediateMembers()));
3717+
metadata = IGF.Builder.CreateCall(IGF.IGM.getRelocateClassMetadataFn(),
3718+
{metadata, templateSize,
3719+
numImmediateMembers});
3720+
}
3721+
37273722
return emitFinishInitializationOfClassMetadata(IGF, metadata);
37283723
}
37293724
};
@@ -3804,11 +3799,15 @@ namespace {
38043799
IGM.getObjCRuntimeBaseForSwiftRootClass(Target));
38053800
} else {
38063801
superMetadata
3807-
= llvm::ConstantPointerNull::get(IGF.IGM.ObjCClassPtrTy);
3802+
= llvm::ConstantPointerNull::get(IGM.ObjCClassPtrTy);
38083803
}
38093804

3805+
auto numImmediateMembers =
3806+
IGM.getSize(Size(IGM.getMetadataLayout(Target).getNumImmediateMembers()));
3807+
38103808
return IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
3811-
{metadataPattern, arguments, superMetadata});
3809+
{metadataPattern, arguments, superMetadata,
3810+
numImmediateMembers});
38123811
}
38133812

38143813
void addMetadataFlags() {

lib/IRGen/IRGenMangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class IRGenMangler : public Mangle::ASTMangler {
5252
return mangleNominalTypeSymbol(Decl, "Mm");
5353
}
5454

55+
std::string mangleClassMetadataBaseOffset(const ClassDecl *Decl) {
56+
return mangleNominalTypeSymbol(Decl, "Mo");
57+
}
58+
5559
std::string mangleNominalTypeDescriptor(const NominalTypeDecl *Decl) {
5660
return mangleNominalTypeSymbol(Decl, "Mn");
5761
}

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,8 @@ private: \
10551055
llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type,
10561056
ForDefinition_t forDefinition);
10571057
llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
1058+
llvm::Constant *getAddrOfClassMetadataBaseOffset(ClassDecl *D,
1059+
ForDefinition_t forDefinition);
10581060
llvm::Constant *getAddrOfNominalTypeDescriptor(NominalTypeDecl *D,
10591061
ConstantInitFuture definition);
10601062
llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D,

0 commit comments

Comments
 (0)