File tree 5 files changed +62
-8
lines changed 5 files changed +62
-8
lines changed Original file line number Diff line number Diff line change @@ -355,6 +355,17 @@ extension Array {
355
355
}
356
356
}
357
357
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
+
358
369
/// Marks the end of an Array mutation.
359
370
///
360
371
/// After a call to `_endMutation` the buffer must not be mutated until a call
@@ -1737,8 +1748,15 @@ extension Array {
1737
1748
@lifetime ( & self )
1738
1749
@_alwaysEmitIntoClient
1739
1750
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
1740
1758
_makeMutableAndUnique ( )
1741
- // LifetimeDependence analysis inserts call to Builtin.endCOWMutation.
1759
+ #endif
1742
1760
let pointer = unsafe _buffer . firstElementAddress
1743
1761
let count = _buffer. mutableCount
1744
1762
let span = unsafe MutableSpan( _unsafeStart: pointer, count: count)
Original file line number Diff line number Diff line change @@ -135,7 +135,22 @@ extension _ArrayBuffer {
135
135
#endif
136
136
return isUnique
137
137
}
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
+
139
154
/// Puts the buffer in an immutable state.
140
155
///
141
156
/// - Precondition: The buffer must be mutable or the empty array singleton.
Original file line number Diff line number Diff line change @@ -1305,10 +1305,16 @@ extension ArraySlice {
1305
1305
@lifetime ( & self )
1306
1306
@_alwaysEmitIntoClient
1307
1307
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
1308
1315
_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.
1312
1318
let ( pointer, count) = unsafe ( _buffer. firstElementAddress, _buffer. count)
1313
1319
let span = unsafe MutableSpan( _unsafeStart: pointer, count: count)
1314
1320
return unsafe _override Lifetime ( span, mutating: & self )
Original file line number Diff line number Diff line change @@ -1247,10 +1247,15 @@ extension ContiguousArray {
1247
1247
@lifetime ( & self )
1248
1248
@_alwaysEmitIntoClient
1249
1249
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
1250
1257
_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
1254
1259
let pointer = unsafe _buffer . firstElementAddress
1255
1260
let count = _buffer. mutableCount
1256
1261
let span = unsafe MutableSpan( _unsafeStart: pointer, count: count)
Original file line number Diff line number Diff line change @@ -818,6 +818,16 @@ internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
818
818
return false ;
819
819
}
820
820
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
+
821
831
/// Puts the buffer in an immutable state.
822
832
///
823
833
/// - Precondition: The buffer must be mutable or the empty array singleton.
You can’t perform that action at this time.
0 commit comments