Skip to content

Commit bb394a0

Browse files
committed
Use proper atomics instead of trying to do it with explicit barriers
1 parent 53d308a commit bb394a0

File tree

1 file changed

+38
-32
lines changed

1 file changed

+38
-32
lines changed

stdlib/public/stubs/FoundationHelpers.mm

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -47,51 +47,56 @@
4747
//version 0 ends here
4848
} CFBridgingState;
4949

50-
static CFBridgingState const * bridgingState;
50+
static std::atomic<CFBridgingState const *> bridgingState;
5151
static swift_once_t initializeBridgingStateOnce;
5252

53+
static CFBridgingState const *getBridgingState() {
54+
return bridgingState.load(std::memory_order_acquire);
55+
}
56+
5357
extern "C" bool _dyld_is_objc_constant(DyldObjCConstantKind kind,
5458
const void *addr) SWIFT_RUNTIME_WEAK_IMPORT;
5559

5660
@class __SwiftNativeNSStringBase, __SwiftNativeNSError, __SwiftNativeNSArrayBase, __SwiftNativeNSMutableArrayBase, __SwiftNativeNSDictionaryBase, __SwiftNativeNSSetBase, __SwiftNativeNSEnumeratorBase;
5761

5862
static void _reparentClasses() {
63+
auto state = getBridgingState();
5964
#pragma clang diagnostic push
6065
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
61-
if (bridgingState->NSStringClass) {
62-
[bridgingState->NSStringClass class]; //make sure the class is realized
63-
class_setSuperclass([__SwiftNativeNSStringBase class], bridgingState->NSStringClass);
66+
if (state->NSStringClass) {
67+
[state->NSStringClass class]; //make sure the class is realized
68+
class_setSuperclass([__SwiftNativeNSStringBase class], state->NSStringClass);
6469
}
65-
if (bridgingState->NSErrorClass) {
66-
[bridgingState->NSErrorClass class]; //make sure the class is realized
67-
class_setSuperclass([__SwiftNativeNSError class], bridgingState->NSErrorClass);
70+
if (state->NSErrorClass) {
71+
[state->NSErrorClass class]; //make sure the class is realized
72+
class_setSuperclass([__SwiftNativeNSError class], state->NSErrorClass);
6873
}
69-
if (bridgingState->NSArrayClass) {
70-
[bridgingState->NSArrayClass class]; //make sure the class is realized
71-
class_setSuperclass([__SwiftNativeNSArrayBase class], bridgingState->NSArrayClass);
74+
if (state->NSArrayClass) {
75+
[state->NSArrayClass class]; //make sure the class is realized
76+
class_setSuperclass([__SwiftNativeNSArrayBase class], state->NSArrayClass);
7277
}
73-
if (bridgingState->NSMutableArrayClass) {
74-
[bridgingState->NSMutableArrayClass class]; //make sure the class is realized
75-
class_setSuperclass([__SwiftNativeNSMutableArrayBase class], bridgingState->NSMutableArrayClass);
78+
if (state->NSMutableArrayClass) {
79+
[state->NSMutableArrayClass class]; //make sure the class is realized
80+
class_setSuperclass([__SwiftNativeNSMutableArrayBase class], state->NSMutableArrayClass);
7681
}
77-
if (bridgingState->NSDictionaryClass) {
78-
[bridgingState->NSDictionaryClass class]; //make sure the class is realized
79-
class_setSuperclass([__SwiftNativeNSDictionaryBase class], bridgingState->NSDictionaryClass);
82+
if (state->NSDictionaryClass) {
83+
[state->NSDictionaryClass class]; //make sure the class is realized
84+
class_setSuperclass([__SwiftNativeNSDictionaryBase class], state->NSDictionaryClass);
8085
}
81-
if (bridgingState->NSSetClass) {
82-
[bridgingState->NSSetClass class]; //make sure the class is realized
83-
class_setSuperclass([__SwiftNativeNSSetBase class], bridgingState->NSSetClass);
86+
if (state->NSSetClass) {
87+
[state->NSSetClass class]; //make sure the class is realized
88+
class_setSuperclass([__SwiftNativeNSSetBase class], state->NSSetClass);
8489
}
85-
if (bridgingState->NSEnumeratorClass) {
86-
[bridgingState->NSEnumeratorClass class]; //make sure the class is realized
87-
class_setSuperclass([__SwiftNativeNSEnumeratorBase class], bridgingState->NSEnumeratorClass);
90+
if (state->NSEnumeratorClass) {
91+
[state->NSEnumeratorClass class]; //make sure the class is realized
92+
class_setSuperclass([__SwiftNativeNSEnumeratorBase class], state->NSEnumeratorClass);
8893
}
8994
#pragma clang diagnostic pop
9095
}
9196

9297
static inline bool initializeBridgingFunctions() {
9398
swift::once(initializeBridgingStateOnce, [](){
94-
assert(!bridgingState);
99+
assert(!getBridgingState());
95100
auto getStringTypeID = (CFTypeID(*)(void))dlsym(RTLD_DEFAULT, "CFStringGetTypeID");
96101
if (!getStringTypeID) {
97102
return; //CF not loaded
@@ -109,21 +114,21 @@ static inline bool initializeBridgingFunctions() {
109114
state->NSSetClass = objc_lookUpClass("NSSet");
110115
state->NSDictionaryClass = objc_lookUpClass("NSDictionary");
111116
state->NSEnumeratorClass = objc_lookUpClass("NSEnumerator");
112-
bridgingState = state;
117+
bridgingState.store(state);
113118
_reparentClasses();
114119
});
115-
return bridgingState && bridgingState->NSStringClass != nullptr;
120+
auto state = getBridgingState();
121+
return state && state->NSStringClass != nullptr;
116122
}
117123

118124
SWIFT_RUNTIME_EXPORT void swift_initializeCoreFoundationState(CFBridgingState const * const state) {
119125
//Consume the once token to make sure that the lazy version of this in initializeBridgingFunctions only runs if we didn't hit this
120126
swift::once(initializeBridgingStateOnce, [state](){
121-
bridgingState = state;
127+
bridgingState.store(state);
122128
});
123129
//It's fine if this runs more than once, it's a noop if it's been done before
124130
//and we want to make sure it still happens if CF loads late after it failed initially
125-
bridgingState = state;
126-
std::atomic_thread_fence(std::memory_order_seq_cst); //This is probably unnecessary, but thinking through why it's unnecessary has given multiple people headaches now, and since this only runs once it's not a big deal to just have the barrier.
131+
bridgingState.store(state);
127132
_reparentClasses();
128133
}
129134

@@ -133,7 +138,7 @@ SWIFT_RUNTIME_EXPORT void swift_initializeCoreFoundationState(CFBridgingState co
133138

134139
Class swift::getNSErrorClass() {
135140
if (initializeBridgingFunctions()) {
136-
return bridgingState->NSErrorClass;
141+
return getBridgingState()->NSErrorClass;
137142
}
138143
return nullptr;
139144
}
@@ -147,20 +152,21 @@ SWIFT_RUNTIME_EXPORT void swift_initializeCoreFoundationState(CFBridgingState co
147152
__swift_uint8_t
148153
_swift_stdlib_isNSString(id obj) {
149154
assert(initializeBridgingFunctions());
150-
return bridgingState->_CFGetTypeID((CFTypeRef)obj) == bridgingState->_CFStringTypeID ? 1 : 0;
155+
auto state = getBridgingState();
156+
return state->_CFGetTypeID((CFTypeRef)obj) == state->_CFStringTypeID ? 1 : 0;
151157
}
152158

153159
_swift_shims_CFHashCode
154160
_swift_stdlib_CFStringHashNSString(id _Nonnull obj) {
155161
assert(initializeBridgingFunctions());
156-
return bridgingState->_CFStringHashNSString(obj);
162+
return getBridgingState()->_CFStringHashNSString(obj);
157163
}
158164

159165
_swift_shims_CFHashCode
160166
_swift_stdlib_CFStringHashCString(const _swift_shims_UInt8 * _Nonnull bytes,
161167
_swift_shims_CFIndex length) {
162168
assert(initializeBridgingFunctions());
163-
return bridgingState->_CFStringHashCString(bytes, length);
169+
return getBridgingState()->_CFStringHashCString(bytes, length);
164170
}
165171

166172
const __swift_uint8_t *

0 commit comments

Comments
 (0)