I've been snooping around the standard library implementations of
ContiguousArray<Element>. So far I gather that:
struct Array<Element>wraps a
var _buffer: _ContiguousArrayBuffer<Element>(assuming no ObjC bridging)
struct _ContiguousArrayBuffer<Element>wraps a
var _storage: __ContiguousArrayStorageBase.
From the way it's allocated, it looks to me like
__ContiguousArrayStorageBaseis a heap allocated object that starts off with a header and has tail allocated
- The header is allocated by a call to
_initStorageHeader(count:capacity:), which assigns a new
struct _ArrayBodylooks like a wrapper for
_SwiftArrayBodyStorageis a C++ struct that stores a count, capacity and a "elementTypeIsBridgedVerbatim"
Everything so far matches my expectations from the Swift Array design document:
This leaves me with a few questions:
- Where is
- Why does
_SwiftArrayBodyStorage? Why not use
- Why doesn't any of this use
ManagedBuffer? The bottom of the diagram above mentioned "Handled by
ManagedBufferPointer<_ArrayBody, T>, but that doesn't seem to be the case.
ManagedBufferseems to be the Swift primitive for "A heap object with some fixed layout (a header), followed by tail allocated elements". I would have expected it to be used profusely by all of these data structures, yet it doesn't seem to be. What gives?
- Why do we use up a word per buffer just to store the capacity, when it could be implemented as a computed property that derives the value from
_swift_stdlib_malloc_size(just like how the initializer already does it)? Is
_swift_stdlib_malloc_sizeslow enough that this "caching" is required?