Skip to content

Commit 96d5ed2

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 59e07f1 commit 96d5ed2

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)