Skip to content

Commit 8aa4d49

Browse files
committed
Disable runtime cow verification for mutableSpan property
1 parent f40f5cb commit 8aa4d49

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

stdlib/public/core/Array.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,17 @@ extension Array {
355355
}
356356
}
357357

358+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
359+
@inlinable
360+
@_semantics("array.make_mutable")
361+
@_effects(notEscaping self.**)
362+
internal mutating func _makeMutableAndUniqueUnchecked() {
363+
if _slowPath(!_buffer.beginCOWMutationUnchecked()) {
364+
_buffer = _buffer._consumeAndCreateNew()
365+
}
366+
}
367+
#endif
368+
358369
/// Marks the end of an Array mutation.
359370
///
360371
/// After a call to `_endMutation` the buffer must not be mutated until a call
@@ -1737,8 +1748,15 @@ extension Array {
17371748
@lifetime(&self)
17381749
@_alwaysEmitIntoClient
17391750
mutating get {
1751+
// _makeMutableAndUnique*() inserts begin_cow_mutation.
1752+
// LifetimeDependence analysis inserts call to end_cow_mutation_addr since we cannot schedule it in the stdlib for mutableSpan property.
1753+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
1754+
// We have runtime verification to check if begin_cow_mutation/end_cow_mutation are properly nested in asserts build of stdlib,
1755+
// disable checking whenever it is turned on since the compiler generated `end_cow_mutation_addr` is conservative and cannot be verified.
1756+
_makeMutableAndUniqueUnchecked()
1757+
#else
17401758
_makeMutableAndUnique()
1741-
// LifetimeDependence analysis inserts call to Builtin.endCOWMutation.
1759+
#endif
17421760
let pointer = unsafe _buffer.firstElementAddress
17431761
let count = _buffer.mutableCount
17441762
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)

stdlib/public/core/ArrayBuffer.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,22 @@ extension _ArrayBuffer {
135135
#endif
136136
return isUnique
137137
}
138-
138+
139+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
140+
@_alwaysEmitIntoClient
141+
internal mutating func beginCOWMutationUnchecked() -> Bool {
142+
let isUnique: Bool
143+
if !_isClassOrObjCExistential(Element.self) {
144+
isUnique = _storage.beginCOWMutationUnflaggedNative()
145+
} else if !_storage.beginCOWMutationNative() {
146+
return false
147+
} else {
148+
isUnique = _isNative
149+
}
150+
return isUnique
151+
}
152+
#endif
153+
139154
/// Puts the buffer in an immutable state.
140155
///
141156
/// - Precondition: The buffer must be mutable or the empty array singleton.

stdlib/public/core/ArraySlice.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,10 +1305,16 @@ extension ArraySlice {
13051305
@lifetime(&self)
13061306
@_alwaysEmitIntoClient
13071307
mutating get {
1308+
// _makeMutableAndUnique*() inserts begin_cow_mutation.
1309+
// LifetimeDependence analysis inserts call to end_cow_mutation_addr since we cannot schedule it in the stdlib for mutableSpan property.
1310+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
1311+
// We have runtime verification to check if begin_cow_mutation/end_cow_mutation are properly nested in asserts build of stdlib,
1312+
// disable checking whenever it is turned on since the compiler generated `end_cow_mutation_addr` is conservative and cannot be verified.
1313+
_makeMutableAndUniqueUnchecked()
1314+
#else
13081315
_makeMutableAndUnique()
1309-
// NOTE: We don't have the ability to schedule a call to
1310-
// ContiguousArrayBuffer.endCOWMutation().
1311-
// rdar://146785284 (lifetime analysis for end of mutation)
1316+
#endif
1317+
// LifetimeDependence analysis inserts call to Builtin.endCOWMutation.
13121318
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
13131319
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
13141320
return unsafe _overrideLifetime(span, mutating: &self)

stdlib/public/core/ContiguousArray.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,10 +1247,15 @@ extension ContiguousArray {
12471247
@lifetime(&self)
12481248
@_alwaysEmitIntoClient
12491249
mutating get {
1250+
// _makeMutableAndUnique*() inserts begin_cow_mutation.
1251+
// LifetimeDependence analysis inserts call to end_cow_mutation_addr since we cannot schedule it in the stdlib for mutableSpan property.
1252+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
1253+
// We have runtime verification to check if begin_cow_mutation/end_cow_mutation are properly nested in asserts build of stdlib,
1254+
// disable checking whenever it is turned on since the compiler generated `end_cow_mutation_addr` is conservative and cannot be verified.
1255+
_makeMutableAndUniqueUnchecked()
1256+
#else
12501257
_makeMutableAndUnique()
1251-
// NOTE: We don't have the ability to schedule a call to
1252-
// ContiguousArrayBuffer.endCOWMutation().
1253-
// rdar://146785284 (lifetime analysis for end of mutation)
1258+
#endif
12541259
let pointer = unsafe _buffer.firstElementAddress
12551260
let count = _buffer.mutableCount
12561261
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)

stdlib/public/core/ContiguousArrayBuffer.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,16 @@ internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
818818
return false;
819819
}
820820

821+
#if INTERNAL_CHECKS_ENABLED && COW_CHECKS_ENABLED
822+
@_alwaysEmitIntoClient
823+
internal mutating func beginCOWMutationUnchecked() -> Bool {
824+
if Bool(Builtin.beginCOWMutation(&_storage)) {
825+
return true
826+
}
827+
return false;
828+
}
829+
#endif
830+
821831
/// Puts the buffer in an immutable state.
822832
///
823833
/// - Precondition: The buffer must be mutable or the empty array singleton.

0 commit comments

Comments
 (0)