runtime (gc.blocks): move objHeader to the end#5455
Conversation
f2b97aa to
7408184
Compare
| // findHead returns the head (last block) of an object, assuming the block | ||
| // points to an allocated object. It returns the same block if this block | ||
| // already points to the head. | ||
| func (b gcBlock) findHead() gcBlock { |
There was a problem hiding this comment.
Seems like we should rename this findHeader
There was a problem hiding this comment.
This finds the head block. It returns the index of the block with the header, not the header itself.
|
|
||
| // Find the first block in the allocation. | ||
| firstBlock := lastBlock | ||
| for firstBlock > 0 && (firstBlock-1).state() == blockStateTail { |
There was a problem hiding this comment.
Same question as above: can we scan multiple blocks at once by checking the entire meta byte?
There was a problem hiding this comment.
I didn't think that was in the scope of this PR since we didn't do that before. It is also less important because this only happens once per allocation, as opposed to findHead which runs for every interior pointer to an allocation.
This moves the objHeader from before an object body to after it. On 32-bit systems with 16-byte alignment requirements (x86, ARM, RISC-V), we previously padded the header to a whole block. This wastes up to 12 bytes, as on -gc=conservative the header is a single pointer. With this change, no padding is required (beyond that from rounding the size up). The "head" block in the metadata was moved to the end of the range to match the header location. This changed the block loop directions throughout the GC logic. The bit hacks used by sweep no longer work because there is no equivalent of addition that carries downwards. However it is now possible to merge the sweep and free range list rebuild passes because their loop directions match. There are two other places where we rebuilt the free ranges list: when initializing or growing the heap. The former can be easily replaced with a single hardcoded range containing the entire heap. In the latter case, I opted to only add the new space to the existing list. These replacements allowed me to fully remove the buildFreeRanges function.
|
I'm going to run this across the test corpus and the it's probably fine to merge. |
|
Test corpus fails on vs where it exits cleanly after ~150s on my laptop. |
|
Passes with |
This moves the objHeader from before an object body to after it. On 32-bit systems with 16-byte alignment requirements (x86, ARM, RISC-V), we previously padded the header to a whole block. This wastes up to 12 bytes, as on -gc=conservative the header is a single pointer. With this change, no padding is required (beyond that from rounding the size up).
The "head" block in the metadata was moved to the end of the range to match the header location. This changed the block loop directions throughout the GC logic. The bit hacks used by sweep no longer work because there is no equivalent of addition that carries downwards. However it is now possible to merge the sweep and free range list rebuild passes because their loop directions match.
There are two other places where we rebuilt the free ranges list: when initializing or growing the heap. The former can be easily replaced with a single hardcoded range containing the entire heap. In the latter case, I opted to only add the new space to the existing list. These replacements allowed me to fully remove the buildFreeRanges function.