mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-25 16:11:44 +00:00
also optimize memory consumption for mm:orc
This commit is contained in:
@@ -1265,6 +1265,17 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
|
||||
proc alloc0Impl(size: Natural): pointer =
|
||||
result = alloc0(allocator, size)
|
||||
|
||||
when defined(gcOrc) or defined(gcYrc):
|
||||
proc nimAlignedAlloc0(size: Natural, alignment: int): pointer =
|
||||
result = rawAlloc(allocator, size, alignment)
|
||||
zeroMem(result, size)
|
||||
|
||||
proc nimAlignedAlloc(size: Natural, alignment: int): pointer =
|
||||
result = rawAlloc(allocator, size, alignment)
|
||||
|
||||
proc nimAlignedDealloc(p: pointer) =
|
||||
rawDealloc(allocator, p)
|
||||
|
||||
proc deallocImpl(p: pointer) =
|
||||
dealloc(allocator, p)
|
||||
|
||||
|
||||
@@ -92,12 +92,23 @@ else:
|
||||
when not defined(nimHasQuirky):
|
||||
{.pragma: quirky.}
|
||||
|
||||
# Forward declarations for native allocator alignment (implemented in alloc.nim).
|
||||
# rawAlloc's contract: result + sizeof(FreeCell) is alignment-aligned.
|
||||
# For ORC/YRC, sizeof(FreeCell) == sizeof(RefHeader).
|
||||
when (defined(gcOrc) or defined(gcYrc)) and not defined(useMalloc) and not defined(nimscript):
|
||||
proc nimAlignedAlloc0(size: Natural, alignment: int): pointer {.gcsafe, raises: [].}
|
||||
proc nimAlignedAlloc(size: Natural, alignment: int): pointer {.gcsafe, raises: [].}
|
||||
proc nimAlignedDealloc(p: pointer) {.gcsafe, raises: [].}
|
||||
|
||||
proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size +% hdrSize
|
||||
when defined(nimscript):
|
||||
discard
|
||||
elif (defined(gcOrc) or defined(gcYrc)) and not defined(useMalloc):
|
||||
let s = size +% sizeof(RefHeader)
|
||||
result = nimAlignedAlloc0(s, alignment) +! sizeof(RefHeader)
|
||||
else:
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size +% hdrSize
|
||||
result = alignedAlloc0(s, alignment) +! hdrSize
|
||||
when defined(nimArcDebug) or defined(nimArcIds):
|
||||
head(result).refId = gRefId
|
||||
@@ -111,12 +122,14 @@ proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
|
||||
|
||||
proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} =
|
||||
# Same as 'newNewObj' but do not initialize the memory to zero.
|
||||
# The codegen proved for us that this is not necessary.
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size + hdrSize
|
||||
when defined(nimscript):
|
||||
discard
|
||||
elif (defined(gcOrc) or defined(gcYrc)) and not defined(useMalloc):
|
||||
let s = size + sizeof(RefHeader)
|
||||
result = cast[ptr RefHeader](nimAlignedAlloc(s, alignment) +! sizeof(RefHeader))
|
||||
else:
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size + hdrSize
|
||||
result = cast[ptr RefHeader](alignedAlloc(s, alignment) +! hdrSize)
|
||||
head(result).rc = 0
|
||||
when defined(gcOrc) or defined(gcYrc):
|
||||
@@ -189,8 +202,11 @@ proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} =
|
||||
if freedCells.data == nil: init(freedCells)
|
||||
freedCells.incl head(p)
|
||||
else:
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
alignedDealloc(p -! hdrSize, alignment)
|
||||
when (defined(gcOrc) or defined(gcYrc)) and not defined(useMalloc):
|
||||
nimAlignedDealloc(p -! sizeof(RefHeader))
|
||||
else:
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
alignedDealloc(p -! hdrSize, alignment)
|
||||
|
||||
template `=dispose`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
|
||||
#proc dispose*(x: pointer) = nimRawDispose(x)
|
||||
|
||||
23
tests/align/talign_heap.nim
Normal file
23
tests/align/talign_heap.nim
Normal file
@@ -0,0 +1,23 @@
|
||||
discard """
|
||||
matrix: "--mm:refc; --mm:orc; --mm:arc"
|
||||
targets: "c cpp"
|
||||
output: "ok"
|
||||
"""
|
||||
|
||||
# Test that heap-allocated objects with .align use small chunks,
|
||||
# not a big chunk per object (regression test for #25577).
|
||||
type U = object
|
||||
d {.align: 32.}: int8
|
||||
|
||||
var e: seq[ref U]
|
||||
for _ in 0 ..< 10000: e.add(new U)
|
||||
|
||||
# Without small-chunk alignment, each object gets its own page (~46 MB).
|
||||
# With the fix, 10000 objects fit in ~1-3 MB depending on the GC.
|
||||
doAssert getTotalMem() < 8 * 1024 * 1024, "align:32 heap objects use too much memory"
|
||||
|
||||
# Verify alignment is actually correct
|
||||
for i in 0 ..< e.len:
|
||||
doAssert (cast[int](addr e[i].d) and 31) == 0, "field not 32-byte aligned"
|
||||
|
||||
echo "ok"
|
||||
Reference in New Issue
Block a user