ARC now capable of custom extra alignment. Ref, closure and seq support. (#15697)

This commit is contained in:
cooldome 2020-10-28 13:00:49 +00:00 • committed by GitHub
commit 0956a99537
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 273 additions and 77 deletions

View file

@ -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: