1
- //===--- HeapStorage .swift - Replacement for HeapBuffer ---------------- ---===//
1
+ //===--- ManagedBuffer .swift - variable-sized buffer of aligned memory ---===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
9
9
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
10
//
11
11
//===----------------------------------------------------------------------===//
12
- //
13
- //
14
- //
15
- //===----------------------------------------------------------------------===//
16
- // RUN: %target-build-swift -parse-stdlib -Xfrontend -disable-access-control %s -o %t.out
17
- // RUN: %target-run %t.out
18
12
19
- import Swift
20
- import Darwin
21
13
import SwiftShims
22
- import StdlibUnittest
23
-
24
- typealias _HeapObject = SwiftShims . HeapObject
25
-
26
- // This is already in the standard library
27
- func _roundUpToAlignment( offset: Int , alignment: Int ) -> Int {
28
- _sanityCheck ( offset >= 0 )
29
- _sanityCheck ( alignment > 0 )
30
- // Note, given that offset is >= 0, and alignment > 0, we don't
31
- // need to underflow check the -1, as it can never underflow.
32
- let x = ( offset + alignment &- 1 )
33
- // Note, as alignment is a power of 2, we'll use masking to efficiently
34
- // get the aligned value
35
- return x & ~ ( alignment &- 1 )
36
- }
37
14
38
- @asmname ( " swift_bufferAllocate " )
39
- func _swift_bufferAllocate(
40
- bufferType: AnyClass , size: Int , alignMask: Int ) -> AnyObject
41
-
42
- /// A class containing a property of type `Value` and
43
- /// raw storage for an array of `Element` whose size is
44
- /// determined at create time.
15
+ /// A class whose instances contain a property of type `Value` and raw
16
+ /// storage for an array of `Element`, whose size is determined at
17
+ /// instance creation.
45
18
///
46
19
/// Note that the `Element` array is suitably-aligned **raw memory**.
47
20
/// You are expected to construct and---if necessary---destroy objects
@@ -50,23 +23,23 @@ func _swift_bufferAllocate(
50
23
/// any live elements in the `deinit` of a subclass. Note: subclasses
51
24
/// must not have any stored properties; any storage needed should be
52
25
/// included in `Value`.
53
- public class HeapStorage < Value , Element > {
26
+ public class ManagedBuffer < Value, Element> {
54
27
55
28
/// Create a new instance of the most-derived class, calling
56
29
/// `initialize` on the partially-constructed object to generate an
57
30
/// initial `Value`. Note, in particular, accessing `value` inside
58
31
/// the `initialize` function is undefined.
59
32
public final class func create(
60
- minimumCapacity: Int, initialize: ( HeapStorage ) - > Value
61
- ) - > HeapStorage {
33
+ minimumCapacity: Int , initialize: ( ManagedBuffer ) -> Value
34
+ ) -> ManagedBuffer {
62
35
_precondition (
63
36
minimumCapacity >= 0 ,
64
- " HeapStorage must have non-negative capacity" )
37
+ " ManagedBuffer must have non-negative capacity" )
65
38
66
- let totalSize = HeapStorage . _elementOffset
39
+ let totalSize = ManagedBuffer . _elementOffset
67
40
+ minimumCapacity * strideof( Element . self)
68
41
69
- let alignMask = HeapStorage . _alignmentMask
42
+ let alignMask = ManagedBuffer . _alignmentMask
70
43
71
44
let result = self . _allocate ( totalSize, alignMask: alignMask)
72
45
@@ -79,7 +52,7 @@ public class HeapStorage<Value, Element> {
79
52
// helper function for create, above
80
53
internal final class func _allocate(
81
54
totalSize: Int , alignMask: Int
82
- ) - > HeapStorage {
55
+ ) -> ManagedBuffer {
83
56
return unsafeDowncast (
84
57
_swift_bufferAllocate ( self , totalSize, alignMask)
85
58
)
@@ -119,9 +92,9 @@ public class HeapStorage<Value, Element> {
119
92
/// The actual number of elements allocated for this object. May be
120
93
/// nontrivial to compute; it may be a good idea to store this
121
94
/// information in the value area upon creation.
122
- internal final var _allocatedElementCount : Int {
95
+ public final var allocatedElementCount : Int {
123
96
return (
124
- _allocatedByteCount &- HeapStorage . _elementOffset &+ sizeof ( Element) &- 1
97
+ _allocatedByteCount &- ManagedBuffer . _elementOffset &+ sizeof ( Element) &- 1
125
98
) &/ sizeof ( Element)
126
99
}
127
100
@@ -159,8 +132,8 @@ public class HeapStorage<Value, Element> {
159
132
body: ( _: UnsafeMutablePointer < Value > , _: UnsafeMutablePointer < Element > ) -> R
160
133
) -> R {
161
134
let result = body (
162
- UnsafeMutablePointer ( _address + HeapStorage . _valueOffset) ,
163
- UnsafeMutablePointer ( _address + HeapStorage . _elementOffset)
135
+ UnsafeMutablePointer ( _address + ManagedBuffer . _valueOffset) ,
136
+ UnsafeMutablePointer ( _address + ManagedBuffer . _elementOffset)
164
137
)
165
138
_fixLifetime ( self )
166
139
return result
@@ -186,97 +159,6 @@ public class HeapStorage<Value, Element> {
186
159
/// allocated size. Probably completely unused per
187
160
/// <rdar://problem/18156440>
188
161
internal final func __getInstanceSizeAndAlignMask( ) -> ( Int , Int ) {
189
- return ( _allocatedByteCount, HeapStorage . _alignmentMask)
162
+ return ( _allocatedByteCount, ManagedBuffer . _alignmentMask)
190
163
}
191
164
}
192
-
193
- //===----------------------------------------------------------------------===//
194
- //===--- Testing code -----------------------------------------------------===//
195
- //===----------------------------------------------------------------------===//
196
-
197
- struct CountAndCapacity {
198
- var count : LifetimeTracked
199
- let capacity : Int = 0
200
- }
201
-
202
- // An example of HeapStorage, very similar to what Array will use.
203
- // However, only half of the element storage is actually used to store
204
- // elements, as a simple way of catching potential bugs.
205
- final class TestHeapStorage < T> : HeapStorage < CountAndCapacity , T > {
206
- class func create( capacity: Int ) -> TestHeapStorage {
207
- let r = self . create ( capacity) {
208
- CountAndCapacity (
209
- count: LifetimeTracked ( 0 ) , capacity: $0. _allocatedElementCount)
210
- }
211
- return r as TestHeapStorage
212
- }
213
-
214
- var count : Int {
215
- get {
216
- return value. count. value
217
- }
218
- set {
219
- value. count = LifetimeTracked ( newValue)
220
- }
221
- }
222
-
223
- var capacity : Int {
224
- return value. capacity
225
- }
226
-
227
- deinit {
228
- teardown ( )
229
- }
230
-
231
- // This doesn't seem to compile properly when embedded directly in
232
- // deinit.
233
- func teardown( ) {
234
- let count = self . count
235
-
236
- withUnsafeMutablePointerToElements {
237
- ( x: UnsafeMutablePointer < T > ) -> ( ) in
238
- for i in stride ( from: 0 , to: count, by: 2 ) {
239
- ( x + i) . destroy ( )
240
- }
241
- }
242
- }
243
-
244
- func append( x: T ) {
245
- let count = self . count
246
- precondition ( count + 2 <= capacity)
247
-
248
- withUnsafeMutablePointerToElements {
249
- ( p: UnsafeMutablePointer < T > ) -> ( ) in
250
- ( p + count) . initialize ( x)
251
- }
252
- self . count = count + 2
253
- }
254
- }
255
-
256
- var tests = TestSuite ( " HeapStorage " )
257
-
258
- tests. test ( " basic " ) {
259
- expectEqual ( 0 , LifetimeTracked . instances)
260
- if true {
261
- let s = TestHeapStorage< LifetimeTracked> . create( 0 )
262
- expectEqual ( 1 , LifetimeTracked . instances)
263
- }
264
-
265
- expectEqual ( 0 , LifetimeTracked . instances)
266
- if true {
267
- let s = TestHeapStorage< LifetimeTracked> . create( 10 )
268
- expectEqual ( 0 , s. count)
269
- expectLE ( 10 , s. capacity)
270
- expectGE ( 12 , s. capacity) // allow some over-allocation but not too much
271
-
272
- expectEqual ( 1 , LifetimeTracked . instances)
273
- for i in 1 ..< 6 {
274
- s. append ( LifetimeTracked ( i) )
275
- expectEqual ( i + 1 , LifetimeTracked . instances)
276
- expectEqual ( i * 2 , s. count)
277
- }
278
- }
279
- expectEqual ( 0 , LifetimeTracked . instances)
280
- }
281
-
282
- runAllTests ( )
0 commit comments