Skip to content

Commit eb812f6

Browse files
committed
[Runtime] Improve performance and memory footprint of compatibility overrides
rdar://143401725 Replacing the (non-inlined) call to `swift_once` with a relaxed atomic significantly improves the generated code and reduces the memory footprint. The mechanism itself now does not cause a stack frame to be generated and the expected case (no override) should be perfectly predicted and executed in straight line code. The override case should also be well predicted, with only two branches on the same value.
1 parent c424525 commit eb812f6

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

stdlib/public/CompatibilityOverride/CompatibilityOverride.h

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@
8282
#define COMPATIBILITY_OVERRIDE_H
8383

8484
#include "../runtime/Private.h"
85+
#include "swift/Runtime/CMakeConfig.h"
8586
#include "swift/Runtime/Concurrency.h"
8687
#include "swift/Runtime/Metadata.h"
87-
#include "swift/Runtime/Once.h"
88-
#include "swift/Runtime/CMakeConfig.h"
88+
#include <atomic>
8989
#include <type_traits>
9090

9191
namespace swift {
@@ -192,15 +192,38 @@ namespace swift {
192192
/// functionality must be available as swift_funcNameHereImpl.
193193
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
194194
typedArgs, namedArgs) \
195+
/* We are creating this separate function for the override case, */ \
196+
/* to prevent a stack frame from being created for the default case. */ \
197+
SWIFT_NOINLINE \
198+
static ret swift_##name##Slow(COMPATIBILITY_UNPAREN_WITH_COMMA(typedArgs) \
199+
std::atomic<uintptr_t> &Override, \
200+
uintptr_t fn, Original_##name defaultImpl) { \
201+
constexpr uintptr_t DEFAULT_IMPL_SENTINEL = 0x1; \
202+
if (SWIFT_UNLIKELY(fn == 0x0)) { \
203+
fn = (uintptr_t)getOverride_##name(); \
204+
if (fn == 0x0) { \
205+
Override.store(DEFAULT_IMPL_SENTINEL, \
206+
std::memory_order::memory_order_relaxed); \
207+
return defaultImpl COMPATIBILITY_PAREN(namedArgs); \
208+
} \
209+
Override.store(fn, std::memory_order::memory_order_relaxed); \
210+
} \
211+
return ((Override_##name)fn)(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
212+
defaultImpl); \
213+
} \
195214
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
196-
static Override_##name Override; \
197-
static swift_once_t Predicate; \
198-
swift_once( \
199-
&Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \
200-
if (Override != nullptr) \
201-
return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
202-
swift_##name##Impl); \
203-
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
215+
constexpr uintptr_t DEFAULT_IMPL_SENTINEL = 0x1; \
216+
static std::atomic<uintptr_t> Override; \
217+
uintptr_t fn = Override.load(std::memory_order::memory_order_relaxed); \
218+
if (SWIFT_LIKELY(fn == DEFAULT_IMPL_SENTINEL)) { \
219+
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
220+
} else if (SWIFT_UNLIKELY(fn == 0x0)) { \
221+
return swift_##name##Slow(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
222+
Override, \
223+
fn, &swift_##name##Impl); \
224+
} \
225+
return ((Override_##name)fn)(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) & \
226+
swift_##name##Impl); \
204227
}
205228

206229
#endif // #else SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT

0 commit comments

Comments
 (0)