@@ -2172,7 +2172,10 @@ namespace {
2172
2172
#if __POINTER_WIDTH__ == 64
2173
2173
uint32_t Reserved;
2174
2174
#endif
2175
- const uint8_t *IvarLayout;
2175
+ union {
2176
+ const uint8_t *IvarLayout;
2177
+ ClassMetadata *NonMetaClass;
2178
+ };
2176
2179
const char *Name;
2177
2180
const void *MethodList;
2178
2181
const void *ProtocolList;
@@ -2197,7 +2200,7 @@ static inline ClassROData *getROData(ClassMetadata *theClass) {
2197
2200
return (ClassROData*)(theClass->Data & ~uintptr_t (SWIFT_CLASS_IS_SWIFT_MASK));
2198
2201
}
2199
2202
2200
- static void initGenericClassObjCName (ClassMetadata *theClass) {
2203
+ static char * copyGenericClassObjCName (ClassMetadata *theClass) {
2201
2204
// Use the remangler to generate a mangled name from the type metadata.
2202
2205
Demangle::StackAllocatedDemangler<4096 > Dem;
2203
2206
@@ -2230,11 +2233,54 @@ static void initGenericClassObjCName(ClassMetadata *theClass) {
2230
2233
} else {
2231
2234
fullNameBuf[string.size ()] = ' \0 ' ;
2232
2235
}
2236
+ return fullNameBuf;
2237
+ }
2233
2238
2239
+ static void initGenericClassObjCName (ClassMetadata *theClass) {
2234
2240
auto theMetaclass = (ClassMetadata *)object_getClass ((id)theClass);
2235
2241
2236
- getROData (theClass)->Name = fullNameBuf;
2237
- getROData (theMetaclass)->Name = fullNameBuf;
2242
+ char *name = copyGenericClassObjCName (theClass);
2243
+ getROData (theClass)->Name = name;
2244
+ getROData (theMetaclass)->Name = name;
2245
+ }
2246
+
2247
+ static bool installLazyClassNameHook () {
2248
+ #if !OBJC_SETHOOK_LAZYCLASSNAMER_DEFINED
2249
+ using objc_hook_lazyClassNamer =
2250
+ const char * _Nullable (*)(_Nonnull Class cls);
2251
+ auto objc_setHook_lazyClassNamer =
2252
+ (void (*)(objc_hook_lazyClassNamer, objc_hook_lazyClassNamer *))
2253
+ dlsym (RTLD_NEXT, " objc_setHook_lazyClassNamer" );
2254
+ #endif
2255
+
2256
+ static objc_hook_lazyClassNamer oldHook;
2257
+ auto myHook = [](Class theClass) -> const char * {
2258
+ ClassMetadata *metadata = (ClassMetadata *)theClass;
2259
+ if (metadata->isTypeMetadata ())
2260
+ return copyGenericClassObjCName (metadata);
2261
+ return oldHook (theClass);
2262
+ };
2263
+
2264
+ #pragma clang diagnostic push
2265
+ #pragma clang diagnostic ignored "-Wunguarded-availability"
2266
+ if (objc_setHook_lazyClassNamer == nullptr )
2267
+ return false ;
2268
+ objc_setHook_lazyClassNamer (myHook, &oldHook);
2269
+ #pragma clang diagnostic pop
2270
+
2271
+ return true ;
2272
+ }
2273
+
2274
+ static void setUpGenericClassObjCName (ClassMetadata *theClass) {
2275
+ bool supportsLazyNames = SWIFT_LAZY_CONSTANT (installLazyClassNameHook ());
2276
+ if (supportsLazyNames) {
2277
+ getROData (theClass)->Name = nullptr ;
2278
+ auto theMetaclass = (ClassMetadata *)object_getClass ((id)theClass);
2279
+ getROData (theMetaclass)->Name = nullptr ;
2280
+ getROData (theMetaclass)->NonMetaClass = theClass;
2281
+ } else {
2282
+ initGenericClassObjCName (theClass);
2283
+ }
2238
2284
}
2239
2285
#endif
2240
2286
@@ -2488,7 +2534,7 @@ initGenericObjCClass(ClassMetadata *self, size_t numFields,
2488
2534
const TypeLayout * const *fieldTypes,
2489
2535
size_t *fieldOffsets) {
2490
2536
// If the class is generic, we need to give it a name for Objective-C.
2491
- initGenericClassObjCName (self);
2537
+ setUpGenericClassObjCName (self);
2492
2538
2493
2539
ClassROData *rodata = getROData (self);
2494
2540
0 commit comments