Skip to content

Commit 9fd03e2

Browse files
committed
[Runtime] Avoid function pointer indirection in refcounting functions.
Functions like swift_retain call through a function pointer so that Instruments can interpose. This slows down the common case where there is no interposition. Instead, initialize the function pointers to NULL and call through directly to the real implementation when it's NULL. The compiler is smart enough to inline this call and the result is a single conditional branch rather than a function pointer call. rdar://problem/18307425
1 parent 6674043 commit 9fd03e2

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

stdlib/public/runtime/HeapObject.cpp

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,6 @@ static inline bool isValidPointerForNativeRetain(const void *p) {
7272
#endif
7373
}
7474

75-
HeapObject *swift::swift_allocObject(HeapMetadata const *metadata,
76-
size_t requiredSize,
77-
size_t requiredAlignmentMask) {
78-
return _swift_allocObject(metadata, requiredSize, requiredAlignmentMask);
79-
}
80-
8175
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
8276
size_t requiredSize,
8377
size_t requiredAlignmentMask) {
@@ -98,7 +92,18 @@ static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
9892
return object;
9993
}
10094

101-
auto swift::_swift_allocObject = _swift_allocObject_;
95+
HeapObject *swift::swift_allocObject(HeapMetadata const *metadata,
96+
size_t requiredSize,
97+
size_t requiredAlignmentMask) {
98+
if (SWIFT_UNLIKELY(_swift_allocObject))
99+
return _swift_allocObject(metadata, requiredSize, requiredAlignmentMask);
100+
else
101+
return _swift_allocObject_(metadata, requiredSize, requiredAlignmentMask);
102+
}
103+
104+
HeapObject *(*swift::_swift_allocObject)(HeapMetadata const *metadata,
105+
size_t requiredSize,
106+
size_t requiredAlignmentMask);
102107

103108
HeapObject *
104109
swift::swift_initStackObject(HeapMetadata const *metadata,
@@ -292,18 +297,21 @@ HeapObject *swift::swift_allocEmptyBox() {
292297
extern "C" LLVM_LIBRARY_VISIBILITY LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
293298
void _swift_release_dealloc(HeapObject *object);
294299

295-
HeapObject *swift::swift_retain(HeapObject *object) {
296-
return _swift_retain(object);
297-
}
298-
299300
static HeapObject *_swift_retain_(HeapObject *object) {
300301
SWIFT_RT_TRACK_INVOCATION(object, swift_retain);
301302
if (isValidPointerForNativeRetain(object))
302303
object->refCounts.increment(1);
303304
return object;
304305
}
305306

306-
auto swift::_swift_retain = _swift_retain_;
307+
HeapObject *swift::swift_retain(HeapObject *object) {
308+
if (SWIFT_UNLIKELY(_swift_retain))
309+
return _swift_retain(object);
310+
else
311+
return _swift_retain_(object);
312+
}
313+
314+
HeapObject *(*swift::_swift_retain)(HeapObject *object);
307315

308316
HeapObject *swift::swift_nonatomic_retain(HeapObject *object) {
309317
SWIFT_RT_TRACK_INVOCATION(object, swift_nonatomic_retain);
@@ -312,18 +320,21 @@ HeapObject *swift::swift_nonatomic_retain(HeapObject *object) {
312320
return object;
313321
}
314322

315-
HeapObject *swift::swift_retain_n(HeapObject *object, uint32_t n) {
316-
return _swift_retain_n(object, n);
317-
}
318-
319323
static HeapObject *_swift_retain_n_(HeapObject *object, uint32_t n) {
320324
SWIFT_RT_TRACK_INVOCATION(object, swift_retain_n);
321325
if (isValidPointerForNativeRetain(object))
322326
object->refCounts.increment(n);
323327
return object;
324328
}
325329

326-
auto swift::_swift_retain_n = _swift_retain_n_;
330+
HeapObject *swift::swift_retain_n(HeapObject *object, uint32_t n) {
331+
if (SWIFT_UNLIKELY(_swift_retain_n))
332+
return _swift_retain_n(object, n);
333+
else
334+
return _swift_retain_n_(object, n);
335+
}
336+
337+
HeapObject *(*swift::_swift_retain_n)(HeapObject *object, uint32_t n);
327338

328339
HeapObject *swift::swift_nonatomic_retain_n(HeapObject *object, uint32_t n) {
329340
SWIFT_RT_TRACK_INVOCATION(object, swift_nonatomic_retain_n);
@@ -332,35 +343,41 @@ HeapObject *swift::swift_nonatomic_retain_n(HeapObject *object, uint32_t n) {
332343
return object;
333344
}
334345

335-
void swift::swift_release(HeapObject *object) {
336-
_swift_release(object);
337-
}
338-
339346
static void _swift_release_(HeapObject *object) {
340347
SWIFT_RT_TRACK_INVOCATION(object, swift_release);
341348
if (isValidPointerForNativeRetain(object))
342349
object->refCounts.decrementAndMaybeDeinit(1);
343350
}
344351

345-
auto swift::_swift_release = _swift_release_;
352+
void swift::swift_release(HeapObject *object) {
353+
if (SWIFT_UNLIKELY(_swift_release))
354+
_swift_release(object);
355+
else
356+
_swift_release_(object);
357+
}
358+
359+
void (*swift::_swift_release)(HeapObject *object);
346360

347361
void swift::swift_nonatomic_release(HeapObject *object) {
348362
SWIFT_RT_TRACK_INVOCATION(object, swift_nonatomic_release);
349363
if (isValidPointerForNativeRetain(object))
350364
object->refCounts.decrementAndMaybeDeinitNonAtomic(1);
351365
}
352366

353-
void swift::swift_release_n(HeapObject *object, uint32_t n) {
354-
return _swift_release_n(object, n);
355-
}
356-
357367
static void _swift_release_n_(HeapObject *object, uint32_t n) {
358368
SWIFT_RT_TRACK_INVOCATION(object, swift_release_n);
359369
if (isValidPointerForNativeRetain(object))
360370
object->refCounts.decrementAndMaybeDeinit(n);
361371
}
362372

363-
auto swift::_swift_release_n = _swift_release_n_;
373+
void swift::swift_release_n(HeapObject *object, uint32_t n) {
374+
if (SWIFT_UNLIKELY(_swift_release_n))
375+
return _swift_release_n(object, n);
376+
else
377+
return _swift_release_n_(object, n);
378+
}
379+
380+
void (*swift::_swift_release_n)(HeapObject *object, uint32_t n);
364381

365382
void swift::swift_nonatomic_release_n(HeapObject *object, uint32_t n) {
366383
SWIFT_RT_TRACK_INVOCATION(object, swift_nonatomic_release_n);
@@ -484,10 +501,6 @@ void swift::swift_nonatomic_unownedRelease_n(HeapObject *object, int n) {
484501
}
485502
}
486503

487-
HeapObject *swift::swift_tryRetain(HeapObject *object) {
488-
return _swift_tryRetain(object);
489-
}
490-
491504
static HeapObject *_swift_tryRetain_(HeapObject *object) {
492505
SWIFT_RT_TRACK_INVOCATION(object, swift_tryRetain);
493506
if (!isValidPointerForNativeRetain(object))
@@ -497,7 +510,14 @@ static HeapObject *_swift_tryRetain_(HeapObject *object) {
497510
else return nullptr;
498511
}
499512

500-
auto swift::_swift_tryRetain = _swift_tryRetain_;
513+
HeapObject *swift::swift_tryRetain(HeapObject *object) {
514+
if (SWIFT_UNLIKELY(_swift_tryRetain))
515+
return _swift_tryRetain(object);
516+
else
517+
return _swift_tryRetain_(object);
518+
}
519+
520+
HeapObject *(*swift::_swift_tryRetain)(HeapObject *object);
501521

502522
bool swift::swift_isDeallocating(HeapObject *object) {
503523
if (!isValidPointerForNativeRetain(object))

0 commit comments

Comments
 (0)