Skip to content

Commit 040323e

Browse files
committed
IRGen: Introduce ClassMetadataStrategy to clean up some checks
This consolidates the various doesClassMetadataRequire*() checks, making them more managable. This also adds a forth state, ClassMetadataStrategy::Update. This will be used when deploying to the new Objective-C runtime. For now it's not plumbed through. Progress on <rdar://problem/47649465>.
1 parent 8fa74fa commit 040323e

File tree

7 files changed

+202
-117
lines changed

7 files changed

+202
-117
lines changed

include/swift/IRGen/Linking.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ class LinkEntity {
158158
SwiftMetaclassStub,
159159

160160
/// A callback used by newer Objective-C runtimes to initialize class
161-
/// metadata for classes where doesClassMetadataRequireUpdate() is true
162-
/// but doesClassMetadataRequireInitialization() is false.
161+
/// metadata for classes where getClassMetadataStrategy() is equal to
162+
/// ClassMetadataStrategy::Update or ::FixedOrUpdate.
163163
ObjCMetadataUpdateFunction,
164164

165165
/// A class metadata base offset global variable. This stores the offset

lib/IRGen/GenClass.cpp

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ namespace {
105105
} // end anonymous namespace
106106

107107
/// Return the lowered type for the class's 'self' type within its context.
108-
static SILType getSelfType(ClassDecl *base) {
108+
static SILType getSelfType(const ClassDecl *base) {
109109
auto loweredTy = base->getDeclaredTypeInContext()->getCanonicalType();
110110
return SILType::getPrimitiveObjectType(loweredTy);
111111
}
@@ -2131,10 +2131,17 @@ llvm::Constant *irgen::emitClassPrivateData(IRGenModule &IGM,
21312131
builder.buildMetaclassStub();
21322132

21332133
HasUpdateCallback_t hasUpdater = DoesNotHaveUpdateCallback;
2134-
if (doesClassMetadataRequireUpdate(IGM, cls) &&
2135-
!doesClassMetadataRequireInitialization(IGM, cls)) {
2134+
2135+
switch (IGM.getClassMetadataStrategy(cls)) {
2136+
case ClassMetadataStrategy::Resilient:
2137+
case ClassMetadataStrategy::Singleton:
2138+
case ClassMetadataStrategy::Fixed:
2139+
break;
2140+
case ClassMetadataStrategy::Update:
2141+
case ClassMetadataStrategy::FixedOrUpdate:
21362142
hasUpdater = HasUpdateCallback;
21372143
emitObjCMetadataUpdateFunction(IGM, cls);
2144+
break;
21382145
}
21392146

21402147
// Then build the class RO-data.
@@ -2293,40 +2300,26 @@ ClassDecl *irgen::getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *C) {
22932300
IGM.Context.Id_SwiftObject);
22942301
}
22952302

2296-
bool irgen::doesClassMetadataRequireRelocation(IRGenModule &IGM,
2297-
ClassDecl *theClass) {
2303+
ClassMetadataStrategy
2304+
IRGenModule::getClassMetadataStrategy(const ClassDecl *theClass) {
22982305
SILType selfType = getSelfType(theClass);
2299-
auto &selfTI = IGM.getTypeInfo(selfType).as<ClassTypeInfo>();
2300-
2301-
// A completely fragile layout does not change whether the metadata
2302-
// requires *relocation*, since that only depends on resilient class
2303-
// ancestry, or the class itself being generic.
2304-
auto &layout = selfTI.getClassLayout(IGM, selfType,
2305-
/*forBackwardDeployment=*/false);
2306-
return layout.doesMetadataRequireRelocation();
2307-
}
2306+
auto &selfTI = getTypeInfo(selfType).as<ClassTypeInfo>();
23082307

2309-
bool irgen::doesClassMetadataRequireInitialization(IRGenModule &IGM,
2310-
ClassDecl *theClass) {
2311-
SILType selfType = getSelfType(theClass);
2312-
auto &selfTI = IGM.getTypeInfo(selfType).as<ClassTypeInfo>();
2313-
2314-
// If we have a fragile layout used for backward deployment, we must use
2315-
// idempotent initialization; swift_initClassMetadata() does not work with
2316-
// statically registered classes.
2317-
auto &layout = selfTI.getClassLayout(IGM, selfType,
2318-
/*forBackwardDeployment=*/true);
2319-
return layout.doesMetadataRequireInitialization();
2320-
}
2308+
auto &resilientLayout = selfTI.getClassLayout(*this, selfType,
2309+
/*forBackwardDeployment=*/false);
2310+
auto &fragileLayout = selfTI.getClassLayout(*this, selfType,
2311+
/*forBackwardDeployment=*/true);
23212312

2322-
bool irgen::doesClassMetadataRequireUpdate(IRGenModule &IGM,
2323-
ClassDecl *theClass) {
2324-
SILType selfType = getSelfType(theClass);
2325-
auto &selfTI = IGM.getTypeInfo(selfType).as<ClassTypeInfo>();
2313+
if (resilientLayout.doesMetadataRequireRelocation())
2314+
return ClassMetadataStrategy::Resilient;
2315+
2316+
if (fragileLayout.doesMetadataRequireInitialization())
2317+
return ClassMetadataStrategy::Singleton;
2318+
2319+
if (resilientLayout.doesMetadataRequireInitialization())
2320+
return ClassMetadataStrategy::FixedOrUpdate;
23262321

2327-
auto &layout = selfTI.getClassLayout(IGM, selfType,
2328-
/*forBackwardDeployment=*/false);
2329-
return layout.doesMetadataRequireInitialization();
2322+
return ClassMetadataStrategy::Fixed;
23302323
}
23312324

23322325
bool irgen::hasKnownSwiftMetadata(IRGenModule &IGM, CanType type) {

lib/IRGen/GenClass.h

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,45 @@ namespace irgen {
7575
HasUpdateCallback = true
7676
};
7777

78+
/// Creates a layout for the class \p classType with allocated tail elements
79+
/// \p tailTypes.
80+
///
81+
/// The caller is responsible for deleting the returned StructLayout.
82+
StructLayout *getClassLayoutWithTailElems(IRGenModule &IGM, SILType classType,
83+
llvm::ArrayRef<SILType> tailTypes);
84+
85+
ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
86+
87+
enum class ClassMetadataStrategy {
88+
/// Does the given class have resilient ancestry, or is the class itself
89+
/// generic?
90+
Resilient,
91+
92+
/// Does the class require at in-place initialization because of
93+
/// non-fixed size properties or generic ancestry? The class does not
94+
/// export a static symbol visible to Objective-C code.
95+
Singleton,
96+
97+
/// A more restricted case of the above. Does the class require at in-place
98+
/// initialization because of non-fixed size properties, while exporting a
99+
/// static symbol visible to Objective-C code? The Objective-C runtime is
100+
/// able to initialize the metadata by calling the update callback stored
101+
/// in rodata. This strategy can only be used if the class availability
102+
/// restricts its use to newer Objective-C runtimes that support this
103+
/// feature.
104+
Update,
105+
106+
/// An even more restricted case of the above. The class requires in-place
107+
/// initialization on newer Objective-C runtimes, but the metadata is
108+
/// statically valid on older runtimes because field offsets were computed
109+
/// assuming type layouts loaded from a legacy type info YAML file.
110+
FixedOrUpdate,
111+
112+
/// The class metadata is completely static and only Objective-C runtime
113+
/// realization (and possibly field offset sliding) must be performed.
114+
Fixed
115+
};
116+
78117
std::pair<Size,Size>
79118
emitClassPrivateDataFields(IRGenModule &IGM,
80119
ConstantStructBuilder &builder,
@@ -146,32 +185,6 @@ namespace irgen {
146185
SILType baseType,
147186
VarDecl *field);
148187

149-
/// Creates a layout for the class \p classType with allocated tail elements
150-
/// \p tailTypes.
151-
///
152-
/// The caller is responsible for deleting the returned StructLayout.
153-
StructLayout *getClassLayoutWithTailElems(IRGenModule &IGM, SILType classType,
154-
llvm::ArrayRef<SILType> tailTypes);
155-
156-
ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
157-
158-
/// Does the given class have resilient ancestry, or is the class itself
159-
/// generic?
160-
bool doesClassMetadataRequireRelocation(IRGenModule &IGM,
161-
ClassDecl *theClass);
162-
163-
/// Does the class require at least in-place initialization because of
164-
/// non-fixed size properties or generic ancestry? If the class requires
165-
/// relocation, this also returns true.
166-
bool doesClassMetadataRequireInitialization(IRGenModule &IGM,
167-
ClassDecl *theClass);
168-
169-
/// Does the class require at least an in-place update on newer Objective-C
170-
/// runtimes? If the class requires full initialization or relocation, this
171-
/// also returns true.
172-
bool doesClassMetadataRequireUpdate(IRGenModule &IGM,
173-
ClassDecl *theClass);
174-
175188
/// Load the instance size and alignment mask from a reference to
176189
/// class type metadata of the given type.
177190
std::pair<llvm::Value *, llvm::Value *>

0 commit comments

Comments
 (0)