ARC now capable of custom extra alignment. Ref, closure and seq support. (#15697)
This commit is contained in:
parent
732ddc02da
commit
0956a99537
11 changed files with 273 additions and 77 deletions
|
|
@ -304,6 +304,87 @@ when hasAlloc and not defined(js):
|
|||
## or other memory may be corrupted.
|
||||
deallocShared(p)
|
||||
|
||||
include bitmasks
|
||||
|
||||
template `+!`(p: pointer, s: SomeInteger): pointer =
|
||||
cast[pointer](cast[int](p) +% int(s))
|
||||
|
||||
template `-!`(p: pointer, s: SomeInteger): pointer =
|
||||
cast[pointer](cast[int](p) -% int(s))
|
||||
|
||||
proc alignedAlloc(size, align: Natural): pointer =
|
||||
if align <= MemAlign:
|
||||
when compileOption("threads"):
|
||||
result = allocShared(size)
|
||||
else:
|
||||
result = alloc(size)
|
||||
else:
|
||||
# allocate (size + align - 1) necessary for alignment,
|
||||
# plus 2 bytes to store offset
|
||||
when compileOption("threads"):
|
||||
let base = allocShared(size + align - 1 + sizeof(uint16))
|
||||
else:
|
||||
let base = alloc(size + align - 1 + sizeof(uint16))
|
||||
# memory layout: padding + offset (2 bytes) + user_data
|
||||
# in order to deallocate: read offset at user_data - 2 bytes,
|
||||
# then deallocate user_data - offset
|
||||
let offset = align - (cast[int](base) and (align - 1))
|
||||
cast[ptr uint16](base +! (offset - sizeof(uint16)))[] = uint16(offset)
|
||||
result = base +! offset
|
||||
|
||||
proc alignedAlloc0(size, align: Natural): pointer =
|
||||
if align <= MemAlign:
|
||||
when compileOption("threads"):
|
||||
result = allocShared0(size)
|
||||
else:
|
||||
result = alloc0(size)
|
||||
else:
|
||||
# see comments for alignedAlloc
|
||||
when compileOption("threads"):
|
||||
let base = allocShared0(size + align - 1 + sizeof(uint16))
|
||||
else:
|
||||
let base = alloc0(size + align - 1 + sizeof(uint16))
|
||||
let offset = align - (cast[int](base) and (align - 1))
|
||||
cast[ptr uint16](base +! (offset - sizeof(uint16)))[] = uint16(offset)
|
||||
result = base +! offset
|
||||
|
||||
proc alignedDealloc(p: pointer, align: int) {.compilerproc.} =
|
||||
if align <= MemAlign:
|
||||
when compileOption("threads"):
|
||||
deallocShared(p)
|
||||
else:
|
||||
dealloc(p)
|
||||
else:
|
||||
# read offset at p - 2 bytes, then deallocate (p - offset) pointer
|
||||
let offset = cast[ptr uint16](p -! sizeof(uint16))[]
|
||||
when compileOption("threads"):
|
||||
deallocShared(p -! offset)
|
||||
else:
|
||||
dealloc(p -! offset)
|
||||
|
||||
proc alignedRealloc(p: pointer, oldSize, newSize, align: Natural): pointer =
|
||||
if align <= MemAlign:
|
||||
when compileOption("threads"):
|
||||
result = reallocShared(p, newSize)
|
||||
else:
|
||||
result = realloc(p, newSize)
|
||||
else:
|
||||
result = alignedAlloc(newSize, align)
|
||||
copyMem(result, p, oldSize)
|
||||
alignedDealloc(p, align)
|
||||
|
||||
proc alignedRealloc0(p: pointer, oldSize, newSize, align: Natural): pointer =
|
||||
if align <= MemAlign:
|
||||
when compileOption("threads"):
|
||||
result = reallocShared0(p, oldSize, newSize)
|
||||
else:
|
||||
result = realloc0(p, oldSize, newSize)
|
||||
else:
|
||||
result = alignedAlloc(newSize, align)
|
||||
copyMem(result, p, oldSize)
|
||||
zeroMem(result +! oldSize, newSize - oldSize)
|
||||
alignedDealloc(p, align)
|
||||
|
||||
{.pop.}
|
||||
|
||||
# GC interface:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue