improve alignment for refc (#25525)

(cherry picked from commit 1e3caf457b)
This commit is contained in:
ringabout
2026-02-17 23:00:11 +08:00
committed by narimiran
parent 6947d96b5f
commit 74b30de1c6
2 changed files with 17 additions and 9 deletions

View File

@@ -851,12 +851,12 @@ when defined(heaptrack):
proc bigChunkAlignOffset(alignment: int): int {.inline.} =
## Compute the alignment offset for big chunk data.
if alignment <= MemAlign:
if alignment == 0:
result = 0
else:
result = align(sizeof(BigChunk) + sizeof(Cell), alignment) - sizeof(BigChunk) - sizeof(Cell)
proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign): pointer =
proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = 0): pointer =
when defined(nimTypeNames):
inc(a.allocCounter)
sysAssert(allocInv(a), "rawAlloc: begin")
@@ -868,7 +868,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign):
# For custom alignments > MemAlign, force big chunk allocation
# Small chunks cannot handle arbitrary alignments due to fixed cell boundaries
if size <= SmallChunkSize-smallChunkOverhead() and alignment <= MemAlign:
if size <= SmallChunkSize-smallChunkOverhead() and alignment == 0:
template fetchSharedCells(tc: PSmallChunk) =
# Consumes cells from (potentially) foreign threads from `a.sharedFreeLists[s]`
when defined(gcDestructors):
@@ -1364,4 +1364,4 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
#sharedMemStatsShared(sharedHeap.currMem - sharedHeap.freeMem)
{.pop.}
{.pop.}
{.pop.}

View File

@@ -459,11 +459,15 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
collectCT(gch)
# Use alignment from typ.base if available, otherwise use MemAlign
let alignment = if typ.kind == tyRef and typ.base != nil: max(typ.base.align, MemAlign) else: MemAlign
let alignment = if typ.kind == tyRef and typ.base != nil and
typ.base.align >= MemAlign: typ.base.align else: 0
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell), alignment))
#gcAssert typ.kind in {tyString, tySequence} or size >= typ.base.size, "size too small"
# Check that the user data (after the Cell header) is properly aligned
gcAssert((cast[int](cellToUsr(res)) and (alignment-1)) == 0, "newObj: 2")
if alignment == 0:
gcAssert((cast[int](res) and (MemAlign-1)) == 0, "newObj: 2.1")
else:
gcAssert((cast[int](cellToUsr(res)) and (alignment-1)) == 0, "newObj: 2.2")
# now it is buffered in the ZCT
res.typ = typ
setFrameInfo(res)
@@ -512,11 +516,15 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline, raise
sysAssert(allocInv(gch.region), "newObjRC1 after collectCT")
# Use alignment from typ.base if available, otherwise use MemAlign
let alignment = if typ.base != nil: max(typ.base.align, MemAlign) else: MemAlign
let alignment = if typ.kind == tyRef and typ.base != nil and
typ.base.align >= MemAlign: typ.base.align else: 0
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell), alignment))
sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc")
# Check that the user data (after the Cell header) is properly aligned
sysAssert((cast[int](cellToUsr(res)) and (alignment-1)) == 0, "newObj: 2")
if alignment == 0:
sysAssert((cast[int](res) and (MemAlign-1)) == 0, "newObj: 2.1")
else:
sysAssert((cast[int](cellToUsr(res)) and (alignment-1)) == 0, "newObj: 2.2")
# now it is buffered in the ZCT
res.typ = typ
setFrameInfo(res)
@@ -922,4 +930,4 @@ when not defined(useNimRtl):
result.add "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
{.pop.} # raises: []
{.pop.} # profiler: off, stackTrace: off
{.pop.} # profiler: off, stackTrace: off