|
24 | 24 | #import <objc/runtime.h>
|
25 | 25 | #include "swift/Runtime/Once.h"
|
26 | 26 | #include <dlfcn.h>
|
27 |
| -#include "swift/Runtime/Atomic.h" |
28 | 27 |
|
29 | 28 | typedef enum {
|
30 | 29 | dyld_objc_string_kind
|
31 | 30 | } DyldObjCConstantKind;
|
32 | 31 |
|
33 | 32 | using namespace swift;
|
34 | 33 |
|
35 |
| -typedef struct _CFBridgingState { |
36 |
| - long version; |
37 |
| - CFHashCode(*_CFStringHashCString)(const uint8_t *bytes, CFIndex len); |
38 |
| - CFHashCode(*_CFStringHashNSString)(id str); |
39 |
| - CFTypeID(*_CFGetTypeID)(CFTypeRef obj); |
40 |
| - CFTypeID _CFStringTypeID = 0; |
41 |
| - Class NSErrorClass; |
42 |
| - Class NSStringClass; |
43 |
| - Class NSArrayClass; |
44 |
| - Class NSMutableArrayClass; |
45 |
| - Class NSSetClass; |
46 |
| - Class NSDictionaryClass; |
47 |
| - Class NSEnumeratorClass; |
48 |
| - //version 0 ends here |
49 |
| -} CFBridgingState; |
50 |
| - |
51 |
| -static std::atomic<CFBridgingState const *> bridgingState; |
52 |
| -static swift_once_t initializeBridgingStateOnce; |
53 |
| - |
54 |
| -static CFBridgingState const *getBridgingState() { |
55 |
| - return bridgingState.load(SWIFT_MEMORY_ORDER_CONSUME); |
56 |
| -} |
| 34 | +static CFHashCode(*_CFStringHashCString)(const uint8_t *bytes, CFIndex len); |
| 35 | +static CFHashCode(*_CFStringHashNSString)(id str); |
| 36 | +static CFTypeID(*_CFGetTypeID)(CFTypeRef obj); |
| 37 | +static CFTypeID _CFStringTypeID = 0; |
| 38 | +static swift_once_t initializeBridgingFuncsOnce; |
57 | 39 |
|
58 | 40 | extern "C" bool _dyld_is_objc_constant(DyldObjCConstantKind kind,
|
59 | 41 | const void *addr) SWIFT_RUNTIME_WEAK_IMPORT;
|
60 | 42 |
|
61 |
| -@class __SwiftNativeNSStringBase, __SwiftNativeNSError, __SwiftNativeNSArrayBase, __SwiftNativeNSMutableArrayBase, __SwiftNativeNSDictionaryBase, __SwiftNativeNSSetBase, __SwiftNativeNSEnumeratorBase; |
62 |
| - |
63 |
| -static void _reparentClasses() { |
64 |
| - auto state = getBridgingState(); |
65 |
| -#pragma clang diagnostic push |
66 |
| -#pragma clang diagnostic ignored "-Wdeprecated-declarations" |
67 |
| - if (state->NSStringClass) { |
68 |
| - [state->NSStringClass class]; //make sure the class is realized |
69 |
| - class_setSuperclass([__SwiftNativeNSStringBase class], state->NSStringClass); |
70 |
| - } |
71 |
| - if (state->NSErrorClass) { |
72 |
| - [state->NSErrorClass class]; //make sure the class is realized |
73 |
| - class_setSuperclass([__SwiftNativeNSError class], state->NSErrorClass); |
74 |
| - } |
75 |
| - if (state->NSArrayClass) { |
76 |
| - [state->NSArrayClass class]; //make sure the class is realized |
77 |
| - class_setSuperclass([__SwiftNativeNSArrayBase class], state->NSArrayClass); |
78 |
| - } |
79 |
| - if (state->NSMutableArrayClass) { |
80 |
| - [state->NSMutableArrayClass class]; //make sure the class is realized |
81 |
| - class_setSuperclass([__SwiftNativeNSMutableArrayBase class], state->NSMutableArrayClass); |
82 |
| - } |
83 |
| - if (state->NSDictionaryClass) { |
84 |
| - [state->NSDictionaryClass class]; //make sure the class is realized |
85 |
| - class_setSuperclass([__SwiftNativeNSDictionaryBase class], state->NSDictionaryClass); |
86 |
| - } |
87 |
| - if (state->NSSetClass) { |
88 |
| - [state->NSSetClass class]; //make sure the class is realized |
89 |
| - class_setSuperclass([__SwiftNativeNSSetBase class], state->NSSetClass); |
90 |
| - } |
91 |
| - if (state->NSEnumeratorClass) { |
92 |
| - [state->NSEnumeratorClass class]; //make sure the class is realized |
93 |
| - class_setSuperclass([__SwiftNativeNSEnumeratorBase class], state->NSEnumeratorClass); |
94 |
| - } |
95 |
| -#pragma clang diagnostic pop |
96 |
| -} |
97 |
| - |
98 |
| -static inline bool initializeBridgingFunctions() { |
99 |
| - swift::once(initializeBridgingStateOnce, [](){ |
100 |
| - assert(!getBridgingState()); |
101 |
| - auto getStringTypeID = (CFTypeID(*)(void))dlsym(RTLD_DEFAULT, "CFStringGetTypeID"); |
102 |
| - if (!getStringTypeID) { |
103 |
| - return; //CF not loaded |
104 |
| - } |
105 |
| - auto state = (CFBridgingState *)calloc(1, sizeof(CFBridgingState)); |
106 |
| - state->version = 0; |
107 |
| - state->_CFStringTypeID = getStringTypeID(); |
108 |
| - state->_CFGetTypeID = (CFTypeID(*)(CFTypeRef obj))dlsym(RTLD_DEFAULT, "CFGetTypeID"); |
109 |
| - state->_CFStringHashNSString = (CFHashCode(*)(id))dlsym(RTLD_DEFAULT, "CFStringHashNSString"); |
110 |
| - state->_CFStringHashCString = (CFHashCode(*)(const uint8_t *, CFIndex))dlsym(RTLD_DEFAULT, "CFStringHashCString"); |
111 |
| - state->NSErrorClass = objc_lookUpClass("NSError"); |
112 |
| - state->NSStringClass = objc_lookUpClass("NSString"); |
113 |
| - state->NSArrayClass = objc_lookUpClass("NSArray"); |
114 |
| - state->NSMutableArrayClass = objc_lookUpClass("NSMutableArray"); |
115 |
| - state->NSSetClass = objc_lookUpClass("NSSet"); |
116 |
| - state->NSDictionaryClass = objc_lookUpClass("NSDictionary"); |
117 |
| - state->NSEnumeratorClass = objc_lookUpClass("NSEnumerator"); |
118 |
| - bridgingState.store(state, std::memory_order_relaxed); |
119 |
| - _reparentClasses(); |
120 |
| - }); |
121 |
| - auto state = getBridgingState(); |
122 |
| - return state && state->NSStringClass != nullptr; |
123 |
| -} |
124 |
| - |
125 |
| -SWIFT_RUNTIME_EXPORT void swift_initializeCoreFoundationState(CFBridgingState const * const state) { |
126 |
| - //Consume the once token to make sure that the lazy version of this in initializeBridgingFunctions only runs if we didn't hit this |
127 |
| - swift::once(initializeBridgingStateOnce, [state](){ |
128 |
| - bridgingState.store(state, std::memory_order_relaxed); |
129 |
| - }); |
130 |
| - //It's fine if this runs more than once, it's a noop if it's been done before |
131 |
| - //and we want to make sure it still happens if CF loads late after it failed initially |
132 |
| - bridgingState.store(state, std::memory_order_release); |
133 |
| - _reparentClasses(); |
134 |
| -} |
135 |
| - |
136 |
| -namespace swift { |
137 |
| -Class getNSErrorClass(); |
138 |
| -} |
139 |
| - |
140 |
| -Class swift::getNSErrorClass() { |
141 |
| - if (initializeBridgingFunctions()) { |
142 |
| - return getBridgingState()->NSErrorClass; |
143 |
| - } |
144 |
| - return nullptr; |
| 43 | +static void _initializeBridgingFunctionsImpl(void *ctxt) { |
| 44 | + auto getStringTypeID = |
| 45 | + (CFTypeID(*)(void)) |
| 46 | + dlsym(RTLD_DEFAULT, "CFStringGetTypeID"); |
| 47 | + assert(getStringTypeID); |
| 48 | + _CFStringTypeID = getStringTypeID(); |
| 49 | + |
| 50 | + _CFGetTypeID = (CFTypeID(*)(CFTypeRef obj))dlsym(RTLD_DEFAULT, "CFGetTypeID"); |
| 51 | + _CFStringHashNSString = (CFHashCode(*)(id))dlsym(RTLD_DEFAULT, |
| 52 | + "CFStringHashNSString"); |
| 53 | + _CFStringHashCString = (CFHashCode(*)(const uint8_t *, CFIndex))dlsym( |
| 54 | + RTLD_DEFAULT, |
| 55 | + "CFStringHashCString"); |
145 | 56 | }
|
146 | 57 |
|
147 |
| -SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_SPI |
148 |
| -bool |
149 |
| -swift_stdlib_connectNSBaseClasses() { |
150 |
| - return initializeBridgingFunctions(); |
| 58 | +static inline void initializeBridgingFunctions() { |
| 59 | + swift_once(&initializeBridgingFuncsOnce, |
| 60 | + _initializeBridgingFunctionsImpl, |
| 61 | + nullptr); |
151 | 62 | }
|
152 | 63 |
|
153 | 64 | __swift_uint8_t
|
154 | 65 | _swift_stdlib_isNSString(id obj) {
|
155 |
| - assert(initializeBridgingFunctions()); |
156 |
| - auto state = getBridgingState(); |
157 |
| - return state->_CFGetTypeID((CFTypeRef)obj) == state->_CFStringTypeID ? 1 : 0; |
| 66 | + initializeBridgingFunctions(); |
| 67 | + return _CFGetTypeID((CFTypeRef)obj) == _CFStringTypeID ? 1 : 0; |
158 | 68 | }
|
159 | 69 |
|
160 | 70 | _swift_shims_CFHashCode
|
161 | 71 | _swift_stdlib_CFStringHashNSString(id _Nonnull obj) {
|
162 |
| - assert(initializeBridgingFunctions()); |
163 |
| - return getBridgingState()->_CFStringHashNSString(obj); |
| 72 | + initializeBridgingFunctions(); |
| 73 | + return _CFStringHashNSString(obj); |
164 | 74 | }
|
165 | 75 |
|
166 | 76 | _swift_shims_CFHashCode
|
167 | 77 | _swift_stdlib_CFStringHashCString(const _swift_shims_UInt8 * _Nonnull bytes,
|
168 | 78 | _swift_shims_CFIndex length) {
|
169 |
| - assert(initializeBridgingFunctions()); |
170 |
| - return getBridgingState()->_CFStringHashCString(bytes, length); |
| 79 | + initializeBridgingFunctions(); |
| 80 | + return _CFStringHashCString(bytes, length); |
171 | 81 | }
|
172 | 82 |
|
173 | 83 | const __swift_uint8_t *
|
|
0 commit comments