Skip to content

Commit 1da1825

Browse files
committed
[Runtime] When the ObjC runtime supports lazy class names, lazily create the ObjC names for generic classes.
rdar://problem/57674583
1 parent 9dab211 commit 1da1825

File tree

1 file changed

+39
-4
lines changed

1 file changed

+39
-4
lines changed

stdlib/public/runtime/Metadata.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,7 +2197,7 @@ static inline ClassROData *getROData(ClassMetadata *theClass) {
21972197
return (ClassROData*)(theClass->Data & ~uintptr_t(SWIFT_CLASS_IS_SWIFT_MASK));
21982198
}
21992199

2200-
static void initGenericClassObjCName(ClassMetadata *theClass) {
2200+
static char *copyGenericClassObjCName(ClassMetadata *theClass) {
22012201
// Use the remangler to generate a mangled name from the type metadata.
22022202
Demangle::StackAllocatedDemangler<4096> Dem;
22032203

@@ -2230,11 +2230,46 @@ static void initGenericClassObjCName(ClassMetadata *theClass) {
22302230
} else {
22312231
fullNameBuf[string.size()] = '\0';
22322232
}
2233+
return fullNameBuf;
2234+
}
22332235

2236+
static void initGenericClassObjCName(ClassMetadata *theClass) {
22342237
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
22352238

2236-
getROData(theClass)->Name = fullNameBuf;
2237-
getROData(theMetaclass)->Name = fullNameBuf;
2239+
char *name = copyGenericClassObjCName(theClass);
2240+
getROData(theClass)->Name = name;
2241+
getROData(theMetaclass)->Name = name;
2242+
}
2243+
2244+
static bool installLazyClassNameHandler() {
2245+
auto _objc_setLazyClassNamer =
2246+
(void (*)(char * (*)(Class)))
2247+
dlsym(RTLD_NEXT, "_objc_setLazyClassNamer");
2248+
if (_objc_setLazyClassNamer == nullptr)
2249+
return false;
2250+
2251+
_objc_setLazyClassNamer([](Class theClass) {
2252+
ClassMetadata *metadata;
2253+
if (class_isMetaClass(theClass)) {
2254+
metadata = (ClassMetadata *)class_getIvarLayout(theClass);
2255+
} else {
2256+
metadata = (ClassMetadata *)theClass;
2257+
}
2258+
return copyGenericClassObjCName(metadata);
2259+
});
2260+
return true;
2261+
}
2262+
2263+
static void setUpGenericClassObjCName(ClassMetadata *theClass) {
2264+
bool supportsLazyNames = SWIFT_LAZY_CONSTANT(installLazyClassNameHandler());
2265+
if (supportsLazyNames) {
2266+
getROData(theClass)->Name = nullptr;
2267+
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
2268+
getROData(theMetaclass)->Name = nullptr;
2269+
getROData(theMetaclass)->IvarLayout = (const uint8_t *)theClass;
2270+
} else {
2271+
initGenericClassObjCName(theClass);
2272+
}
22382273
}
22392274
#endif
22402275

@@ -2488,7 +2523,7 @@ initGenericObjCClass(ClassMetadata *self, size_t numFields,
24882523
const TypeLayout * const *fieldTypes,
24892524
size_t *fieldOffsets) {
24902525
// If the class is generic, we need to give it a name for Objective-C.
2491-
initGenericClassObjCName(self);
2526+
setUpGenericClassObjCName(self);
24922527

24932528
ClassROData *rodata = getROData(self);
24942529

0 commit comments

Comments
 (0)