Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

core.internal.gc.blockmeta

Functions to manipulate metadata in-block.
functionality was moved from rt.lifetime
pure nothrow bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength = size_t.max);
Set the allocated length of the array block. This is called any time an array is appended to or its length is set.
The allocated block looks like this for blocks < PAGESIZE:
|elem0|elem1|elem2|...|elemN-1|emptyspace|N*elemsize|
The size of the allocated length at the end depends on the block size:
a block of 16 to 256 bytes has an 8-bit length.
a block with 512 to pagesize/2 bytes has a 16-bit length.
For blocks >= pagesize, the length is a size_t and is at the beginning of the block. The reason we have to do this is because the block can extend into more pages, so we cannot trust the block length if it sits at the end of the block, because it might have just been extended. If we can prove in the future that the block is unshared, we may be able to change this, but I'm not sure it's important.
In order to do put the length at the front, we have to provide 16 bytes buffer space in case the block has to be aligned properly. In x86, certain SSE instructions will only work if the data is 16-byte aligned. In addition, we need the sentinel byte to prevent accidental pointers to the next block. Because of the extra overhead, we only do this for page size and above, where the overhead is minimal compared to the block size.
So for those blocks, it looks like:
|N*elemsize|padding|elem0|elem1|...|elemN-1|emptyspace|sentinelbyte|
where elem0 starts 16 bytes after the first byte.
pure nothrow void __setBlockFinalizerInfo(ref BlkInfo info, const TypeInfo ti);
The block finalizer info is set separately from the array length, as that is only needed on the initial setup of the block. No shared is needed, since this should only happen when the block is new. If the STRUCTFINAL bit is not set, no finalizer is stored (but if needed the slot is zeroed)
pure nothrow const(TypeInfo) __getBlockFinalizerInfo(ref BlkInfo info);

pure nothrow const(TypeInfo) __getBlockFinalizerInfo(void* base, size_t size, uint attr);
Get the finalizer info from the block (typeinfo). If called on a block, without STRUCTFINAL set, returns null.
pure nothrow size_t __arrayAllocLength(ref BlkInfo info);
get the used size of the array for the given block
pure nothrow size_t __arrayAllocLengthAtomic(ref BlkInfo info);
Atomically get the used size of the array for the given block
pure nothrow size_t __arrayAllocCapacity(ref BlkInfo info);
Get the maximum bytes that can be stored in the given block.
pure nothrow @trusted size_t __arrayPad(size_t size, const TypeInfo tinext);
get the padding required to allocate size bytes. Note that the padding is NOT included in the passed in size. Therefore, do NOT call this function with the size of an allocated block.
pure nothrow @trusted size_t __allocPad(size_t size, uint bits);
get the padding required to allocate size bytes, use the bits to determine which metadata must be stored.
pure nothrow void* __arrayStart()(return scope BlkInfo info);

pure nothrow void* __arrayStart()(return scope void* base, size_t size);
Get the start of the array for the given block.
Parameters:
BlkInfo info array metadata
void* base pointer to base of memory block
size_t size size of memory block.
Returns:
pointer to the start of the array
pure nothrow @nogc void __trimExtents(ref scope void* base, ref size_t blockSize, uint attr);
Trim a block's extents to the known valid data that is not metadata. This takes into account the finalizer and array metadata.