GC attribute modifications use case?
Steven Schveighoffer
schveiguy at gmail.com
Sun Dec 22 04:05:50 UTC 2024
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:
```d
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
More information about the Digitalmars-d
mailing list