Skip to content

Commit 222b9de

Browse files
authored
Merge pull request #28753 from mikeash/lazy-objc-class-names
[Runtime] When the ObjC runtime supports lazy class names, lazily create the ObjC names for generic classes.
2 parents 7cfd3cb + f32af9b commit 222b9de

File tree

3 files changed

+52
-49
lines changed

3 files changed

+52
-49
lines changed

include/swift/Demangling/Demangler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,6 @@ class Demangler : public NodeFactory {
563563
NodePointer demangleGenericType();
564564
NodePointer demangleValueWitness();
565565

566-
NodePointer demangleObjCTypeName();
567566
NodePointer demangleTypeMangling();
568567
NodePointer demangleSymbolicReference(unsigned char rawKind,
569568
const void *at);

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ NodePointer Demangler::demangleSymbol(StringRef MangledName,
529529
// Demangle old-style class and protocol names, which are still used in the
530530
// ObjC metadata.
531531
if (nextIf("_Tt"))
532-
return demangleObjCTypeName();
532+
return demangleOldSymbolAsNode(Text, *this);
533533

534534
unsigned PrefixLength = getManglingPrefixLength(MangledName);
535535
if (PrefixLength == 0)
@@ -3212,45 +3212,3 @@ NodePointer Demangler::demangleValueWitness() {
32123212
addChild(VW, createNode(Node::Kind::Index, unsigned(Kind)));
32133213
return addChild(VW, popNode(Node::Kind::Type));
32143214
}
3215-
3216-
NodePointer Demangler::demangleObjCTypeName() {
3217-
NodePointer Ty = createNode(Node::Kind::Type);
3218-
NodePointer Global = addChild(createNode(Node::Kind::Global),
3219-
addChild(createNode(Node::Kind::TypeMangling), Ty));
3220-
NodePointer Nominal = nullptr;
3221-
bool isProto = false;
3222-
if (nextIf('C')) {
3223-
Nominal = createNode(Node::Kind::Class);
3224-
addChild(Ty, Nominal);
3225-
} else if (nextIf('P')) {
3226-
isProto = true;
3227-
Nominal = createNode(Node::Kind::Protocol);
3228-
addChild(Ty, addChild(createNode(Node::Kind::ProtocolList),
3229-
addChild(createNode(Node::Kind::TypeList),
3230-
addChild(createNode(Node::Kind::Type), Nominal))));
3231-
} else {
3232-
return nullptr;
3233-
}
3234-
3235-
if (nextIf('s')) {
3236-
Nominal->addChild(createNode(Node::Kind::Module, "Swift"), *this);
3237-
} else {
3238-
NodePointer Module = demangleIdentifier();
3239-
if (!Module)
3240-
return nullptr;
3241-
Nominal->addChild(changeKind(Module, Node::Kind::Module), *this);
3242-
}
3243-
3244-
NodePointer Ident = demangleIdentifier();
3245-
if (!Ident)
3246-
return nullptr;
3247-
Nominal->addChild(Ident, *this);
3248-
3249-
if (isProto && !nextIf('_'))
3250-
return nullptr;
3251-
3252-
if (Pos < Text.size())
3253-
return nullptr;
3254-
3255-
return Global;
3256-
}

stdlib/public/runtime/Metadata.cpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,7 +2172,10 @@ namespace {
21722172
#if __POINTER_WIDTH__ == 64
21732173
uint32_t Reserved;
21742174
#endif
2175-
const uint8_t *IvarLayout;
2175+
union {
2176+
const uint8_t *IvarLayout;
2177+
ClassMetadata *NonMetaClass;
2178+
};
21762179
const char *Name;
21772180
const void *MethodList;
21782181
const void *ProtocolList;
@@ -2197,7 +2200,7 @@ static inline ClassROData *getROData(ClassMetadata *theClass) {
21972200
return (ClassROData*)(theClass->Data & ~uintptr_t(SWIFT_CLASS_IS_SWIFT_MASK));
21982201
}
21992202

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

@@ -2230,11 +2233,54 @@ static void initGenericClassObjCName(ClassMetadata *theClass) {
22302233
} else {
22312234
fullNameBuf[string.size()] = '\0';
22322235
}
2236+
return fullNameBuf;
2237+
}
22332238

2239+
static void initGenericClassObjCName(ClassMetadata *theClass) {
22342240
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
22352241

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+
}
22382284
}
22392285
#endif
22402286

@@ -2488,7 +2534,7 @@ initGenericObjCClass(ClassMetadata *self, size_t numFields,
24882534
const TypeLayout * const *fieldTypes,
24892535
size_t *fieldOffsets) {
24902536
// If the class is generic, we need to give it a name for Objective-C.
2491-
initGenericClassObjCName(self);
2537+
setUpGenericClassObjCName(self);
24922538

24932539
ClassROData *rodata = getROData(self);
24942540

0 commit comments

Comments
 (0)