Skip to content

Commit 21ac407

Browse files
committed
<rdar://64939529> Convert unnecessary dlsym() calls into direct references.
Added SWIFT_RUNTIME_WEAK_IMPORT/CHECK/USE macros. Everything supports fast dealloc except x86 iOS simulators, so we no longer need to look up objc_has_weak_formation_callout. Added direct references for objc_setHook_lazyClassNamer _objc_realizeClassFromSwift objc_setHook_getClass os_system_version_get_current_version _dyld_is_objc_constant
1 parent b7de0be commit 21ac407

File tree

6 files changed

+59
-80
lines changed

6 files changed

+59
-80
lines changed

include/swift/Runtime/Config.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,39 @@
2020
#include "swift/Basic/Compiler.h"
2121
#include "swift/Runtime/CMakeConfig.h"
2222

23+
/// SWIFT_RUNTIME_WEAK_IMPORT - Marks a symbol for weak import.
24+
#if (__has_attribute(weak_import))
25+
#define SWIFT_RUNTIME_WEAK_IMPORT __attribute__((weak_import))
26+
#else
27+
#define SWIFT_RUNTIME_WEAK_IMPORT
28+
#endif
29+
30+
/// SWIFT_RUNTIME_WEAK_CHECK - Tests if a potentially weakly linked function
31+
/// is linked into the runtime. This is useful on Apple platforms where it is
32+
/// possible that system functions are only available on newer versions.
33+
#ifdef __clang__
34+
#define SWIFT_RUNTIME_WEAK_CHECK(x) \
35+
_Pragma("clang diagnostic push") \
36+
_Pragma("clang diagnostic ignored \"-Wunguarded-availability\"") \
37+
_Pragma("clang diagnostic ignored \"-Wunguarded-availability-new\"") \
38+
(&x) \
39+
_Pragma("clang diagnostic pop")
40+
#else
41+
#define SWIFT_RUNTIME_WEAK_CHECK(x) &x
42+
#endif
43+
44+
/// SWIFT_RUNTIME_WEAK_USE - Use a potentially weakly imported symbol.
45+
#ifdef __clang__
46+
#define SWIFT_RUNTIME_WEAK_USE(x) \
47+
_Pragma("clang diagnostic push") \
48+
_Pragma("clang diagnostic ignored \"-Wunguarded-availability\"") \
49+
_Pragma("clang diagnostic ignored \"-Wunguarded-availability-new\"") \
50+
(x) \
51+
_Pragma("clang diagnostic pop")
52+
#else
53+
#define SWIFT_RUNTIME_WEAK_USE(x) x
54+
#endif
55+
2356
/// SWIFT_RUNTIME_LIBRARY_VISIBILITY - If a class marked with this attribute is
2457
/// linked into a shared library, then the class should be private to the
2558
/// library and not accessible from outside it. Can also be used to mark

stdlib/public/runtime/HeapObject.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -694,24 +694,22 @@ void swift::swift_rootObjCDealloc(HeapObject *self) {
694694
}
695695
#endif
696696

697-
#if SWIFT_OBJC_INTEROP
698-
static bool _check_fast_dealloc() {
699-
return dlsym(RTLD_NEXT, "_objc_has_weak_formation_callout") != nullptr;
700-
}
701-
#endif
702-
703697
void swift::swift_deallocClassInstance(HeapObject *object,
704698
size_t allocatedSize,
705699
size_t allocatedAlignMask) {
706-
707700
#if SWIFT_OBJC_INTEROP
708701
// We need to let the ObjC runtime clean up any associated objects or weak
709702
// references associated with this object.
710-
const bool fastDeallocSupported = SWIFT_LAZY_CONSTANT(_check_fast_dealloc());
703+
#if !TARGET_OS_SIMULATOR || !__x86_64__
704+
const bool fastDeallocSupported = true;
705+
#else
706+
const bool fastDeallocSupported = false;
707+
#endif
711708
if (!fastDeallocSupported || !object->refCounts.getPureSwiftDeallocation()) {
712709
objc_destructInstance((id)object);
713710
}
714711
#endif
712+
715713
swift_deallocObject(object, allocatedSize, allocatedAlignMask);
716714
}
717715

stdlib/public/runtime/Metadata.cpp

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,14 +2580,6 @@ static void initGenericClassObjCName(ClassMetadata *theClass) {
25802580
}
25812581

25822582
static bool installLazyClassNameHook() {
2583-
#if !OBJC_SETHOOK_LAZYCLASSNAMER_DEFINED
2584-
using objc_hook_lazyClassNamer =
2585-
const char * _Nullable (*)(_Nonnull Class cls);
2586-
auto objc_setHook_lazyClassNamer =
2587-
(void (*)(objc_hook_lazyClassNamer, objc_hook_lazyClassNamer *))
2588-
dlsym(RTLD_NEXT, "objc_setHook_lazyClassNamer");
2589-
#endif
2590-
25912583
static objc_hook_lazyClassNamer oldHook;
25922584
auto myHook = [](Class theClass) -> const char * {
25932585
ClassMetadata *metadata = (ClassMetadata *)theClass;
@@ -2596,14 +2588,12 @@ static bool installLazyClassNameHook() {
25962588
return oldHook(theClass);
25972589
};
25982590

2599-
#pragma clang diagnostic push
2600-
#pragma clang diagnostic ignored "-Wunguarded-availability"
2601-
if (objc_setHook_lazyClassNamer == nullptr)
2602-
return false;
2603-
objc_setHook_lazyClassNamer(myHook, &oldHook);
2604-
#pragma clang diagnostic pop
2591+
if (SWIFT_RUNTIME_WEAK_CHECK(objc_setHook_lazyClassNamer)) {
2592+
SWIFT_RUNTIME_WEAK_USE(objc_setHook_lazyClassNamer(myHook, &oldHook));
2593+
return true;
2594+
}
26052595

2606-
return true;
2596+
return false;
26072597
}
26082598

26092599
__attribute__((constructor)) SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE static bool
@@ -3077,11 +3067,6 @@ getSuperclassMetadata(ClassMetadata *self, bool allowDependency) {
30773067
return {MetadataDependency(), second};
30783068
}
30793069

3080-
// Suppress diagnostic about the availability of _objc_realizeClassFromSwift.
3081-
// We test availability with a nullptr check, but the compiler doesn't see that.
3082-
#pragma clang diagnostic push
3083-
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
3084-
30853070
static SWIFT_CC(swift) MetadataDependency
30863071
_swift_initClassMetadataImpl(ClassMetadata *self,
30873072
ClassLayoutFlags layoutFlags,
@@ -3108,11 +3093,6 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
31083093
(void)unused;
31093094
setUpObjCRuntimeGetImageNameFromClass();
31103095
}, nullptr);
3111-
3112-
// Temporary workaround until objc_loadClassref is in the SDK.
3113-
static auto objc_loadClassref =
3114-
(Class (*)(void *))
3115-
dlsym(RTLD_NEXT, "objc_loadClassref");
31163096
#endif
31173097

31183098
// Copy field offsets, generic arguments and (if necessary) vtable entries
@@ -3149,10 +3129,8 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
31493129
// The compiler enforces that @objc methods in extensions of classes
31503130
// with resilient ancestry have the correct availability, so it should
31513131
// be safe to ignore the stub in this case.
3152-
if (stub != nullptr &&
3153-
objc_loadClassref != nullptr &&
3154-
&_objc_realizeClassFromSwift != nullptr) {
3155-
_objc_realizeClassFromSwift((Class) self, const_cast<void *>(stub));
3132+
if (stub != nullptr && SWIFT_RUNTIME_WEAK_CHECK(_objc_realizeClassFromSwift)) {
3133+
SWIFT_RUNTIME_WEAK_USE(_objc_realizeClassFromSwift((Class) self, const_cast<void *>(stub)));
31563134
} else {
31573135
swift_instantiateObjCClass(self);
31583136
}
@@ -3164,8 +3142,6 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
31643142
return MetadataDependency();
31653143
}
31663144

3167-
#pragma clang diagnostic pop
3168-
31693145
void swift::swift_initClassMetadata(ClassMetadata *self,
31703146
ClassLayoutFlags layoutFlags,
31713147
size_t numFields,
@@ -3189,20 +3165,14 @@ swift::swift_initClassMetadata2(ClassMetadata *self,
31893165

31903166
#if SWIFT_OBJC_INTEROP
31913167

3192-
// Suppress diagnostic about the availability of _objc_realizeClassFromSwift.
3193-
// We test availability with a nullptr check, but the compiler doesn't see that.
3194-
#pragma clang diagnostic push
3195-
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
3196-
3197-
31983168
static SWIFT_CC(swift) MetadataDependency
31993169
_swift_updateClassMetadataImpl(ClassMetadata *self,
32003170
ClassLayoutFlags layoutFlags,
32013171
size_t numFields,
32023172
const TypeLayout * const *fieldTypes,
32033173
size_t *fieldOffsets,
32043174
bool allowDependency) {
3205-
bool requiresUpdate = (&_objc_realizeClassFromSwift != nullptr);
3175+
bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK(_objc_realizeClassFromSwift);
32063176

32073177
// If we're on a newer runtime, we're going to be initializing the
32083178
// field offset vector. Realize the superclass metadata first, even
@@ -3250,7 +3220,7 @@ _swift_updateClassMetadataImpl(ClassMetadata *self,
32503220
initObjCClass(self, numFields, fieldTypes, fieldOffsets);
32513221

32523222
// See remark above about how this slides field offset globals.
3253-
_objc_realizeClassFromSwift((Class)self, (Class)self);
3223+
SWIFT_RUNTIME_WEAK_USE(_objc_realizeClassFromSwift((Class)self, (Class)self));
32543224
}
32553225

32563226
return MetadataDependency();
@@ -3277,7 +3247,6 @@ swift::swift_updateClassMetadata2(ClassMetadata *self,
32773247
/*allowDependency*/ true);
32783248
}
32793249

3280-
#pragma clang diagnostic pop
32813250
#endif
32823251

32833252
#ifndef NDEBUG

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,23 +1959,9 @@ getObjCClassByMangledName(const char * _Nonnull typeName,
19591959

19601960
__attribute__((constructor))
19611961
static void installGetClassHook() {
1962-
// FIXME: delete this #if and dlsym once we don't
1963-
// need to build with older libobjc headers
1964-
#if !OBJC_GETCLASSHOOK_DEFINED
1965-
using objc_hook_getClass = BOOL(*)(const char * _Nonnull name,
1966-
Class _Nullable * _Nonnull outClass);
1967-
auto objc_setHook_getClass =
1968-
(void(*)(objc_hook_getClass _Nonnull,
1969-
objc_hook_getClass _Nullable * _Nonnull))
1970-
dlsym(RTLD_DEFAULT, "objc_setHook_getClass");
1971-
#endif
1972-
1973-
#pragma clang diagnostic push
1974-
#pragma clang diagnostic ignored "-Wunguarded-availability"
1975-
if (&objc_setHook_getClass) {
1976-
objc_setHook_getClass(getObjCClassByMangledName, &OldGetClassHook);
1962+
if (SWIFT_RUNTIME_WEAK_CHECK(objc_setHook_getClass)) {
1963+
SWIFT_RUNTIME_WEAK_USE(objc_setHook_getClass(getObjCClassByMangledName, &OldGetClassHook));
19771964
}
1978-
#pragma clang diagnostic pop
19791965
}
19801966

19811967
#endif

stdlib/public/stubs/Availability.mm

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,19 @@
2121
#include "swift/Runtime/Debug.h"
2222
#include <TargetConditionals.h>
2323
#include "../SwiftShims/FoundationShims.h"
24-
#include <dlfcn.h>
2524

2625
struct os_system_version_s {
2726
unsigned int major;
2827
unsigned int minor;
2928
unsigned int patch;
3029
};
3130

31+
// This is in libSystem, so it's OK to refer to it directly here
32+
extern "C" int os_system_version_get_current_version(struct os_system_version_s * _Nonnull) SWIFT_RUNTIME_WEAK_IMPORT;
33+
3234
static os_system_version_s getOSVersion() {
33-
auto lookup =
34-
(int(*)(struct os_system_version_s * _Nonnull))
35-
dlsym(RTLD_DEFAULT, "os_system_version_get_current_version");
36-
3735
struct os_system_version_s vers = { 0, 0, 0 };
38-
lookup(&vers);
36+
os_system_version_get_current_version(&vers);
3937
return vers;
4038
}
4139

stdlib/public/stubs/FoundationHelpers.mm

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@
3535
static CFHashCode(*_CFStringHashNSString)(id str);
3636
static CFTypeID(*_CFGetTypeID)(CFTypeRef obj);
3737
static CFTypeID _CFStringTypeID = 0;
38-
static bool(*dyld_is_objc_constant)(DyldObjCConstantKind kind,
39-
const void *addr);
4038
static swift_once_t initializeBridgingFuncsOnce;
4139

40+
extern "C" bool _dyld_is_objc_constant(DyldObjCConstantKind kind,
41+
const void *addr) SWIFT_RUNTIME_WEAK_IMPORT;
42+
4243
static void _initializeBridgingFunctionsImpl(void *ctxt) {
4344
auto getStringTypeID =
4445
(CFTypeID(*)(void))
@@ -52,11 +53,6 @@ static void _initializeBridgingFunctionsImpl(void *ctxt) {
5253
_CFStringHashCString = (CFHashCode(*)(const uint8_t *, CFIndex))dlsym(
5354
RTLD_DEFAULT,
5455
"CFStringHashCString");
55-
if (dlsym(RTLD_NEXT, "objc_debug_tag60_permutations") /* tagged constant strings available */) {
56-
dyld_is_objc_constant = (bool(*)(DyldObjCConstantKind, const void *))dlsym(
57-
RTLD_NEXT,
58-
"_dyld_is_objc_constant");
59-
}
6056
}
6157

6258
static inline void initializeBridgingFunctions() {
@@ -112,9 +108,8 @@ typedef __swift_uint8_t (*getCStringImplPtr)(id,
112108

113109
__swift_uint8_t
114110
_swift_stdlib_dyld_is_objc_constant_string(const void *addr) {
115-
initializeBridgingFunctions();
116-
if (!dyld_is_objc_constant) return false;
117-
return dyld_is_objc_constant(dyld_objc_string_kind, addr) ? 1 : 0;
111+
return (SWIFT_RUNTIME_WEAK_CHECK(_dyld_is_objc_constant)
112+
&& SWIFT_RUNTIME_WEAK_USE(_dyld_is_objc_constant(dyld_objc_string_kind, addr))) ? 1 : 0;
118113
}
119114

120115
#endif

0 commit comments

Comments
 (0)