Skip to content

Commit 26b2f7b

Browse files
authored
Re-land using associated objects to attach bridged Array buffers (#78452)
1 parent 74883b3 commit 26b2f7b

File tree

6 files changed

+136
-1
lines changed

6 files changed

+136
-1
lines changed

stdlib/public/SwiftShims/swift/shims/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(sources
99
LibcOverlayShims.h
1010
LibcShims.h
1111
MetadataSections.h
12+
ObjCShims.h
1213
Random.h
1314
RefCount.h
1415
Reflection.h
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===--- ObjCShims.h - Access to libobjc for the core stdlib ---------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Using the ObjectiveC module in the core stdlib would create a
14+
// circular dependency, so instead we import these declarations as
15+
// part of SwiftShims.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#ifndef SWIFT_STDLIB_SHIMS_OBJCSHIMS_H
20+
#define SWIFT_STDLIB_SHIMS_OBJCSHIMS_H
21+
22+
#include "SwiftStdint.h"
23+
#include "Visibility.h"
24+
25+
#ifdef __cplusplus
26+
extern "C" {
27+
#endif
28+
29+
#ifdef __OBJC2__
30+
31+
extern void objc_setAssociatedObject(void);
32+
extern void objc_getAssociatedObject(void);
33+
int objc_sync_enter(id _Nonnull object);
34+
int objc_sync_exit(id _Nonnull object);
35+
36+
static void * _Nonnull getSetAssociatedObjectPtr() {
37+
return (void *)&objc_setAssociatedObject;
38+
}
39+
40+
static void * _Nonnull getGetAssociatedObjectPtr() {
41+
return (void *)&objc_getAssociatedObject;
42+
}
43+
44+
#endif // __OBJC2__
45+
46+
#ifdef __cplusplus
47+
} // extern "C"
48+
#endif
49+
50+
#endif // SWIFT_STDLIB_SHIMS_COREFOUNDATIONSHIMS_H
51+

stdlib/public/SwiftShims/swift/shims/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module SwiftShims {
22
header "AssertionReporting.h"
33
header "CoreFoundationShims.h"
4+
header "ObjCShims.h"
45
header "EmbeddedShims.h"
56
header "FoundationShims.h"
67
header "GlobalObjects.h"

stdlib/public/core/ArrayBuffer.swift

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,84 @@ extension _ArrayBuffer {
567567
}
568568
}
569569

570+
@inlinable @_alwaysEmitIntoClient
571+
static var associationKey: UnsafeRawPointer {
572+
//We never dereference this, we just need an address to use as a unique key
573+
UnsafeRawPointer(Builtin.addressof(&_swiftEmptyArrayStorage))
574+
}
575+
576+
@inlinable @_alwaysEmitIntoClient
577+
internal func getAssociatedBuffer() -> _ContiguousArrayBuffer<Element>? {
578+
let getter = unsafeBitCast(
579+
getGetAssociatedObjectPtr(),
580+
to: (@convention(c)(
581+
AnyObject,
582+
UnsafeRawPointer
583+
) -> UnsafeRawPointer?).self
584+
)
585+
if let assocPtr = getter(
586+
_storage.objCInstance,
587+
_ArrayBuffer.associationKey
588+
) {
589+
let buffer = assocPtr.loadUnaligned(
590+
as: _ContiguousArrayStorage<Element>.self
591+
)
592+
return _ContiguousArrayBuffer(buffer)
593+
}
594+
return nil
595+
}
596+
597+
@inlinable @_alwaysEmitIntoClient
598+
internal func setAssociatedBuffer(_ buffer: _ContiguousArrayBuffer<Element>) {
599+
let setter = unsafeBitCast(getSetAssociatedObjectPtr(), to: (@convention(c)(
600+
AnyObject,
601+
UnsafeRawPointer,
602+
AnyObject?,
603+
UInt
604+
) -> Void).self)
605+
setter(
606+
_storage.objCInstance,
607+
_ArrayBuffer.associationKey,
608+
buffer._storage,
609+
1 //OBJC_ASSOCIATION_RETAIN_NONATOMIC
610+
)
611+
}
612+
613+
@_alwaysEmitIntoClient @inline(never)
614+
internal func withUnsafeBufferPointer_nonNative<R, E>(
615+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
616+
) throws(E) -> R {
617+
let unwrapped: _ContiguousArrayBuffer<Element>
618+
// libobjc already provides the necessary memory barriers for
619+
// double checked locking to be safe, per comments on
620+
// https://github.com/swiftlang/swift/pull/75148
621+
if let associatedBuffer = getAssociatedBuffer() {
622+
unwrapped = associatedBuffer
623+
} else {
624+
let lock = _storage.objCInstance
625+
objc_sync_enter(lock)
626+
var associatedBuffer = getAssociatedBuffer()
627+
if let associatedBuffer {
628+
unwrapped = associatedBuffer
629+
} else {
630+
associatedBuffer = ContiguousArray(self)._buffer
631+
unwrapped = associatedBuffer.unsafelyUnwrapped
632+
setAssociatedBuffer(unwrapped)
633+
}
634+
defer { _fixLifetime(unwrapped) }
635+
objc_sync_exit(lock)
636+
}
637+
return try body(
638+
UnsafeBufferPointer(
639+
start: unwrapped.firstElementAddress,
640+
count: unwrapped.count
641+
)
642+
)
643+
}
644+
645+
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
646+
/// underlying contiguous storage. If no such storage exists, it is
647+
/// created on-demand.
570648
// Superseded by the typed-throws version of this function, but retained
571649
// for ABI reasons.
572650
@usableFromInline
@@ -594,7 +672,7 @@ extension _ArrayBuffer {
594672
return try body(
595673
UnsafeBufferPointer(start: firstElementAddress, count: count))
596674
}
597-
return try ContiguousArray(self).withUnsafeBufferPointer(body)
675+
return try withUnsafeBufferPointer_nonNative(body)
598676
}
599677

600678
// Superseded by the typed-throws version of this function, but retained

test/abi/macOS/arm64/stdlib.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,3 +807,5 @@ Added: _$ss13_SwiftifyInfoOMa
807807
Added: _$ss13_SwiftifyInfoOMn
808808
Added: _$ss13_SwiftifyInfoON
809809

810+
// Eager-lazy Array bridging
811+
Added: _$ss12_ArrayBufferV14associationKeySVvpZMV

test/abi/macOS/x86_64/stdlib.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,3 +808,5 @@ Added: _$ss13_SwiftifyInfoOMa
808808
Added: _$ss13_SwiftifyInfoOMn
809809
Added: _$ss13_SwiftifyInfoON
810810

811+
// Eager-lazy Array bridging
812+
Added: _$ss12_ArrayBufferV14associationKeySVvpZMV

0 commit comments

Comments
 (0)