A general request for information here.
The D GC is in the unfortunate state of having internal attributes modifiable at any time by user code.
For example, you can set or clear the NO_SCAN
bit. Or add a FINALIZE
bit. But not properly store the correct data for finalization.
In the new GC, we have some restrictions on this. For example, we put all scannable memory in a completely separate area from non-scannable allocations. This means we can save some time by checking only if allocations in the scannable region are allocated, instead of having to check all memory to see if it's scannable.
But obviously, this means setting the bit is not feasible -- it would require reallocating.
I question completely the utility of this mechanism -- setting attributes after the fact.
There is in fact one bit which does need to be modified, and that's when you add a finalizer to a block (or at least, add the bit to say finalize the block). But I think this is better left to a dedicated function. Oh, and the new GC already supports this mechanism.
So does anyone have any good use cases for setting arbitrary GC attributes after allocation?
For reference, here are the list of attributes:
enum BlkAttr : uint
{
NONE = 0b0000_0000, /// No attributes set.
FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect.
NO_MOVE = 0b0000_0100, /// Do not move this memory block on collect.
/**
This block contains the info to allow appending.
This can be used to manually allocate arrays. Initial slice size is 0.
Note: The slice's usable size will not match the block size. Use
$(REF1 capacity, object) to retrieve actual usable capacity.
Example:
----
// Allocate the underlying array.
int* pToArray = cast(int*)GC.malloc(10 * int.sizeof, GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE);
// Bind a slice. Check the slice has capacity information.
int[] slice = pToArray[0 .. 0];
assert(capacity(slice) > 0);
// Appending to the slice will not relocate it.
slice.length = 5;
slice ~= 1;
assert(slice.ptr == p);
----
*/
APPENDABLE = 0b0000_1000,
/**
This block is guaranteed to have a pointer to its base while it is
alive. Interior pointers can be safely ignored. This attribute is
useful for eliminating false pointers in very large data structures
and is only implemented for data structures at least a page in size.
*/
NO_INTERIOR = 0b0001_0000,
STRUCTFINAL = 0b0010_0000, // the block has a finalizer for (an array of) structs
}
The reason I'm asking is that I am reorganizing the GC API a bit, and one unittest is explicitly testing that setting/clearing the NO_SCAN
bit is working. I want to disable/remove this unittest.
And of course, as a bit of irony, this unittest was added by me back in 2014. I am my own worst enemy...
-Steve