Skip to content

Commit

Permalink
Merge pull request #2672 from ahoppen/6.0/atomic-on-heap
Browse files Browse the repository at this point in the history
[6.0] Heap allocate our atomics
  • Loading branch information
ahoppen authored Jun 6, 2024
2 parents 74c759f + f5d5abb commit 4c6cc0a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 28 deletions.
3 changes: 3 additions & 0 deletions Sources/SwiftSyntax/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@ add_swift_syntax_library(SwiftSyntax
generated/syntaxNodes/SyntaxNodesQRS.swift
generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift
)

target_link_swift_syntax_libraries(SwiftSyntax PRIVATE
_SwiftSyntaxCShims)
32 changes: 12 additions & 20 deletions Sources/SwiftSyntax/SyntaxArena.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,10 @@
//
//===----------------------------------------------------------------------===//

#if SWIFT_SYNTAX_BUILD_USING_CMAKE
// The CMake bulid of swift-syntax does not build the _AtomicBool module because swift-syntax's CMake build is
// Swift-only. Fake an `AtomicBool` type that is not actually atomic. This should be acceptable for the following
// reasons:
// - `AtomicBool` is only used for the `hasParent` assertion, so release compilers don't rely on it
// - The compiler is single-threaded so it it is safe from race conditions on `AtomicBool`.
fileprivate struct AtomicBool {
var value: Bool

init(initialValue: Bool) {
self.value = initialValue
}
}
#if swift(>=6.0)
private import _SwiftSyntaxCShims
#else
import _SwiftSyntaxCShims
@_implementationOnly import _SwiftSyntaxCShims
#endif

/// A syntax arena owns the memory for all syntax nodes within it.
Expand Down Expand Up @@ -69,7 +58,7 @@ public class SyntaxArena {
///
/// - Important: This is only intended to be used for assertions to catch
/// retain cycles in syntax arenas.
fileprivate var hasParent: AtomicBool
fileprivate let hasParent: UnsafeMutablePointer<AtomicBool>
#endif

/// Construct a new ``SyntaxArena`` in which syntax nodes can be allocated.
Expand All @@ -81,14 +70,17 @@ public class SyntaxArena {
self.allocator = BumpPtrAllocator(initialSlabSize: slabSize)
self.childRefs = []
#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
self.hasParent = AtomicBool(initialValue: false)
self.hasParent = swiftsyntax_atomic_bool_create(false)
#endif
}

deinit {
for child in childRefs {
child.release()
}
#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
swiftsyntax_atomic_bool_destroy(self.hasParent)
#endif
}

/// Allocates a buffer of `RawSyntax?` with the given count, then returns the
Expand Down Expand Up @@ -158,7 +150,7 @@ public class SyntaxArena {

#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
precondition(
!self.hasParent.value,
!swiftsyntax_atomic_bool_get(self.hasParent),
"an arena can't have a new child once it's owned by other arenas"
)
#endif
Expand Down Expand Up @@ -300,14 +292,14 @@ struct SyntaxArenaRef: Hashable, @unchecked Sendable {
}

#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
/// Accessor for ther underlying's `SyntaxArena.hasParent`
/// Accessor for the underlying's `SyntaxArena.hasParent`
var hasParent: Bool {
value.hasParent.value
swiftsyntax_atomic_bool_get(value.hasParent)
}

/// Sets the `SyntaxArena.hasParent` on the referenced arena.
func setHasParent(_ newValue: Bool) {
value.hasParent.value = newValue
swiftsyntax_atomic_bool_set(value.hasParent, newValue)
}
#endif

Expand Down
18 changes: 10 additions & 8 deletions Sources/_SwiftSyntaxCShims/include/AtomicBool.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,28 @@
#define SWIFTSYNTAX_ATOMICBOOL_H

#include <stdbool.h>
#include <stdlib.h>

typedef struct {
_Atomic(bool) value;
} AtomicBool;

__attribute__((swift_name("AtomicBool.init(initialValue:)")))
static inline AtomicBool atomic_bool_create(bool initialValue) {
AtomicBool atomic;
atomic.value = initialValue;
static inline AtomicBool *_Nonnull swiftsyntax_atomic_bool_create(bool initialValue) {
AtomicBool *atomic = malloc(sizeof(AtomicBool));
atomic->value = initialValue;
return atomic;
}

__attribute__((swift_name("getter:AtomicBool.value(self:)")))
static inline bool atomic_bool_get(AtomicBool *atomic) {
static inline bool swiftsyntax_atomic_bool_get(AtomicBool *_Nonnull atomic) {
return atomic->value;
}

__attribute__((swift_name("setter:AtomicBool.value(self:_:)")))
static inline void atomic_bool_set(AtomicBool *atomic, bool newValue) {
static inline void swiftsyntax_atomic_bool_set(AtomicBool *_Nonnull atomic, bool newValue) {
atomic->value = newValue;
}

static inline void swiftsyntax_atomic_bool_destroy(AtomicBool *_Nonnull atomic) {
free(atomic);
}

#endif // SWIFTSYNTAX_ATOMICBOOL_H

0 comments on commit 4c6cc0a

Please sign in to comment.