TlSF Alloctor: use less memory for --gc:arc (#13280)
This commit is contained in:
parent
84e8477b90
commit
be795bbf1a
3 changed files with 103 additions and 80 deletions
|
|
@ -48,9 +48,12 @@ type
|
||||||
AlignType = BiggestFloat
|
AlignType = BiggestFloat
|
||||||
FreeCell {.final, pure.} = object
|
FreeCell {.final, pure.} = object
|
||||||
next: ptr FreeCell # next free cell in chunk (overlaid with refcount)
|
next: ptr FreeCell # next free cell in chunk (overlaid with refcount)
|
||||||
|
when not defined(gcDestructors):
|
||||||
zeroField: int # 0 means cell is not used (overlaid with typ field)
|
zeroField: int # 0 means cell is not used (overlaid with typ field)
|
||||||
# 1 means cell is manually managed pointer
|
# 1 means cell is manually managed pointer
|
||||||
# otherwise a PNimType is stored in there
|
# otherwise a PNimType is stored in there
|
||||||
|
else:
|
||||||
|
alignment: int
|
||||||
|
|
||||||
PChunk = ptr BaseChunk
|
PChunk = ptr BaseChunk
|
||||||
PBigChunk = ptr BigChunk
|
PBigChunk = ptr BigChunk
|
||||||
|
|
@ -396,6 +399,7 @@ iterator allObjects(m: var MemRegion): pointer {.inline.} =
|
||||||
proc iterToProc*(iter: typed, envType: typedesc; procName: untyped) {.
|
proc iterToProc*(iter: typed, envType: typedesc; procName: untyped) {.
|
||||||
magic: "Plugin", compileTime.}
|
magic: "Plugin", compileTime.}
|
||||||
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
proc isCell(p: pointer): bool {.inline.} =
|
proc isCell(p: pointer): bool {.inline.} =
|
||||||
result = cast[ptr FreeCell](p).zeroField >% 1
|
result = cast[ptr FreeCell](p).zeroField >% 1
|
||||||
|
|
||||||
|
|
@ -630,6 +634,7 @@ proc getSmallChunk(a: var MemRegion): PSmallChunk =
|
||||||
result = cast[PSmallChunk](res)
|
result = cast[PSmallChunk](res)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
when not defined(gcDestructors):
|
||||||
proc isAllocatedPtr(a: MemRegion, p: pointer): bool {.benign.}
|
proc isAllocatedPtr(a: MemRegion, p: pointer): bool {.benign.}
|
||||||
|
|
||||||
when true:
|
when true:
|
||||||
|
|
@ -773,6 +778,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
|
||||||
inc(c.acc, size)
|
inc(c.acc, size)
|
||||||
else:
|
else:
|
||||||
result = c.freeList
|
result = c.freeList
|
||||||
|
when not defined(gcDestructors):
|
||||||
sysAssert(c.freeList.zeroField == 0, "rawAlloc 8")
|
sysAssert(c.freeList.zeroField == 0, "rawAlloc 8")
|
||||||
c.freeList = c.freeList.next
|
c.freeList = c.freeList.next
|
||||||
dec(c.free, size)
|
dec(c.free, size)
|
||||||
|
|
@ -826,6 +832,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
|
||||||
sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
|
sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
|
||||||
s == 0, "rawDealloc 3")
|
s == 0, "rawDealloc 3")
|
||||||
var f = cast[ptr FreeCell](p)
|
var f = cast[ptr FreeCell](p)
|
||||||
|
when not defined(gcDestructors):
|
||||||
#echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
|
#echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
|
||||||
sysAssert(f.zeroField != 0, "rawDealloc 1")
|
sysAssert(f.zeroField != 0, "rawDealloc 1")
|
||||||
f.zeroField = 0
|
f.zeroField = 0
|
||||||
|
|
@ -863,6 +870,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
|
||||||
sysAssert(allocInv(a), "rawDealloc: end")
|
sysAssert(allocInv(a), "rawDealloc: end")
|
||||||
when logAlloc: cprintf("dealloc(pointer_%p)\n", p)
|
when logAlloc: cprintf("dealloc(pointer_%p)\n", p)
|
||||||
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
proc isAllocatedPtr(a: MemRegion, p: pointer): bool =
|
proc isAllocatedPtr(a: MemRegion, p: pointer): bool =
|
||||||
if isAccessible(a, p):
|
if isAccessible(a, p):
|
||||||
var c = pageAddr(p)
|
var c = pageAddr(p)
|
||||||
|
|
@ -918,25 +926,36 @@ proc interiorAllocatedPtr(a: MemRegion, p: pointer): pointer =
|
||||||
sysAssert isAllocatedPtr(a, result), " result wrong pointer!"
|
sysAssert isAllocatedPtr(a, result), " result wrong pointer!"
|
||||||
|
|
||||||
proc ptrSize(p: pointer): int =
|
proc ptrSize(p: pointer): int =
|
||||||
|
when not defined(gcDestructors):
|
||||||
var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
|
var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
|
||||||
var c = pageAddr(p)
|
var c = pageAddr(p)
|
||||||
sysAssert(not chunkUnused(c), "ptrSize")
|
sysAssert(not chunkUnused(c), "ptrSize")
|
||||||
result = c.size -% sizeof(FreeCell)
|
result = c.size -% sizeof(FreeCell)
|
||||||
if not isSmallChunk(c):
|
if not isSmallChunk(c):
|
||||||
dec result, bigChunkOverhead()
|
dec result, bigChunkOverhead()
|
||||||
|
else:
|
||||||
|
var c = pageAddr(p)
|
||||||
|
sysAssert(not chunkUnused(c), "ptrSize")
|
||||||
|
result = c.size
|
||||||
|
if not isSmallChunk(c):
|
||||||
|
dec result, bigChunkOverhead()
|
||||||
|
|
||||||
proc alloc(allocator: var MemRegion, size: Natural): pointer {.gcsafe.} =
|
proc alloc(allocator: var MemRegion, size: Natural): pointer {.gcsafe.} =
|
||||||
|
when not defined(gcDestructors):
|
||||||
result = rawAlloc(allocator, size+sizeof(FreeCell))
|
result = rawAlloc(allocator, size+sizeof(FreeCell))
|
||||||
cast[ptr FreeCell](result).zeroField = 1 # mark it as used
|
cast[ptr FreeCell](result).zeroField = 1 # mark it as used
|
||||||
sysAssert(not isAllocatedPtr(allocator, result), "alloc")
|
sysAssert(not isAllocatedPtr(allocator, result), "alloc")
|
||||||
result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
|
result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
|
||||||
track("alloc", result, size)
|
track("alloc", result, size)
|
||||||
|
else:
|
||||||
|
result = rawAlloc(allocator, size)
|
||||||
|
|
||||||
proc alloc0(allocator: var MemRegion, size: Natural): pointer =
|
proc alloc0(allocator: var MemRegion, size: Natural): pointer =
|
||||||
result = alloc(allocator, size)
|
result = alloc(allocator, size)
|
||||||
zeroMem(result, size)
|
zeroMem(result, size)
|
||||||
|
|
||||||
proc dealloc(allocator: var MemRegion, p: pointer) =
|
proc dealloc(allocator: var MemRegion, p: pointer) =
|
||||||
|
when not defined(gcDestructors):
|
||||||
sysAssert(p != nil, "dealloc: p is nil")
|
sysAssert(p != nil, "dealloc: p is nil")
|
||||||
var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
|
var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
|
||||||
sysAssert(x != nil, "dealloc: x is nil")
|
sysAssert(x != nil, "dealloc: x is nil")
|
||||||
|
|
@ -945,6 +964,8 @@ proc dealloc(allocator: var MemRegion, p: pointer) =
|
||||||
rawDealloc(allocator, x)
|
rawDealloc(allocator, x)
|
||||||
sysAssert(not isAllocatedPtr(allocator, x), "dealloc: object still accessible")
|
sysAssert(not isAllocatedPtr(allocator, x), "dealloc: object still accessible")
|
||||||
track("dealloc", p, 0)
|
track("dealloc", p, 0)
|
||||||
|
else:
|
||||||
|
rawDealloc(allocator, p)
|
||||||
|
|
||||||
proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
|
proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
|
||||||
if newsize > 0:
|
if newsize > 0:
|
||||||
|
|
@ -958,7 +979,7 @@ proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
|
||||||
proc realloc0(allocator: var MemRegion, p: pointer, oldsize, newsize: Natural): pointer =
|
proc realloc0(allocator: var MemRegion, p: pointer, oldsize, newsize: Natural): pointer =
|
||||||
result = realloc(allocator, p, newsize)
|
result = realloc(allocator, p, newsize)
|
||||||
if newsize > oldsize:
|
if newsize > oldsize:
|
||||||
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
|
zeroMem(cast[pointer](cast[uint](result) + uint(oldsize)), newsize - oldsize)
|
||||||
|
|
||||||
proc deallocOsPages(a: var MemRegion) =
|
proc deallocOsPages(a: var MemRegion) =
|
||||||
# we free every 'ordinarily' allocated page by iterating over the page bits:
|
# we free every 'ordinarily' allocated page by iterating over the page bits:
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,8 @@ proc main() =
|
||||||
var elapsed = epochTime() - t
|
var elapsed = epochTime() - t
|
||||||
printDiagnostics()
|
printDiagnostics()
|
||||||
echo("Completed in " & $elapsed & "s. Success!")
|
echo("Completed in " & $elapsed & "s. Success!")
|
||||||
|
when declared(getMaxMem):
|
||||||
|
echo "Max memory ", formatSize getMaxMem()
|
||||||
|
|
||||||
when defined(GC_setMaxPause):
|
when defined(GC_setMaxPause):
|
||||||
GC_setMaxPause 2_000
|
GC_setMaxPause 2_000
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue