arc allocation method aligned (#15588)

* progress

* fix typo
This commit is contained in:
cooldome 2020-10-19 13:50:06 +01:00 • committed by GitHub
commit 833035bacd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 41 deletions

View file

@ -2180,17 +2180,25 @@ proc genDestroy(p: BProc; n: PNode) =
of tyString: of tyString:
var a: TLoc var a: TLoc
initLocExpr(p, arg, a) initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" & if optThreads in p.config.globalOptions:
" #deallocShared($1.p);$n" & linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
"}$n", " #deallocShared($1.p);$n" &
[rdLoc(a)]) "}$n", [rdLoc(a)])
else:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #dealloc($1.p);$n" &
"}$n", [rdLoc(a)])
of tySequence: of tySequence:
var a: TLoc var a: TLoc
initLocExpr(p, arg, a) initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" & if optThreads in p.config.globalOptions:
" #deallocShared($1.p);$n" & linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
"}$n", " #deallocShared($1.p);$n" &
[rdLoc(a), getTypeDesc(p.module, t.lastSon)]) "}$n", [rdLoc(a)])
else:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #dealloc($1.p);$n" &
"}$n", [rdLoc(a)])
else: discard "nothing to do" else: discard "nothing to do"
else: else:
let t = n[1].typ.skipTypes(abstractVar) let t = n[1].typ.skipTypes(abstractVar)

View file

@ -79,10 +79,6 @@ proc nimNewObj(size: int): pointer {.compilerRtl.} =
let s = size + sizeof(RefHeader) let s = size + sizeof(RefHeader)
when defined(nimscript): when defined(nimscript):
discard discard
elif defined(useMalloc):
var orig = c_malloc(cuint s)
nimZeroMem(orig, s)
result = orig +! sizeof(RefHeader)
elif compileOption("threads"): elif compileOption("threads"):
result = allocShared0(s) +! sizeof(RefHeader) result = allocShared0(s) +! sizeof(RefHeader)
else: else:
@ -102,8 +98,6 @@ proc nimNewObjUninit(size: int): pointer {.compilerRtl.} =
let s = size + sizeof(RefHeader) let s = size + sizeof(RefHeader)
when defined(nimscript): when defined(nimscript):
discard discard
elif defined(useMalloc):
var orig = cast[ptr RefHeader](c_malloc(cuint s))
elif compileOption("threads"): elif compileOption("threads"):
var orig = cast[ptr RefHeader](allocShared(s)) var orig = cast[ptr RefHeader](allocShared(s))
else: else:
@ -171,8 +165,6 @@ proc nimRawDispose(p: pointer) {.compilerRtl.} =
# we do NOT really free the memory here in order to reliably detect use-after-frees # we do NOT really free the memory here in order to reliably detect use-after-frees
if freedCells.data == nil: init(freedCells) if freedCells.data == nil: init(freedCells)
freedCells.incl head(p) freedCells.incl head(p)
elif defined(useMalloc):
c_free(p -! sizeof(RefHeader))
elif compileOption("threads"): elif compileOption("threads"):
deallocShared(p -! sizeof(RefHeader)) deallocShared(p -! sizeof(RefHeader))
else: else:

View file

@ -248,9 +248,7 @@ proc genericReset(dest: pointer, mt: PNimType) =
unsureAsgnRef(cast[PPointer](dest), nil) unsureAsgnRef(cast[PPointer](dest), nil)
of tySequence: of tySequence:
when defined(nimSeqsV2): when defined(nimSeqsV2):
var s = cast[ptr NimSeqV2Reimpl](dest) frees(cast[ptr NimSeqV2Reimpl](dest)[])
if s.p != nil:
deallocShared(s.p)
zeroMem(dest, mt.size) zeroMem(dest, mt.size)
else: else:
unsureAsgnRef(cast[PPointer](dest), nil) unsureAsgnRef(cast[PPointer](dest), nil)

View file

@ -19,13 +19,13 @@ type
proc add(s: var CellSeq, c: PT; t: PNimTypeV2) {.inline.} = proc add(s: var CellSeq, c: PT; t: PNimTypeV2) {.inline.} =
if s.len >= s.cap: if s.len >= s.cap:
s.cap = s.cap * 3 div 2 s.cap = s.cap * 3 div 2
when defined(useMalloc): when compileOption("threads"):
var d = cast[CellArray](c_malloc(uint(s.cap * sizeof(CellTuple)))) var d = cast[CellArray](allocShared(uint(s.cap * sizeof(CellTuple))))
else: else:
var d = cast[CellArray](alloc(s.cap * sizeof(CellTuple))) var d = cast[CellArray](alloc(s.cap * sizeof(CellTuple)))
copyMem(d, s.d, s.len * sizeof(CellTuple)) copyMem(d, s.d, s.len * sizeof(CellTuple))
when defined(useMalloc): when compileOption("threads"):
c_free(s.d) deallocShared(s.d)
else: else:
dealloc(s.d) dealloc(s.d)
s.d = d s.d = d
@ -36,15 +36,15 @@ proc add(s: var CellSeq, c: PT; t: PNimTypeV2) {.inline.} =
proc init(s: var CellSeq, cap: int = 1024) = proc init(s: var CellSeq, cap: int = 1024) =
s.len = 0 s.len = 0
s.cap = cap s.cap = cap
when defined(useMalloc): when compileOption("threads"):
s.d = cast[CellArray](c_malloc(uint(s.cap * sizeof(CellTuple)))) s.d = cast[CellArray](allocShared(uint(s.cap * sizeof(CellTuple))))
else: else:
s.d = cast[CellArray](alloc(s.cap * sizeof(CellTuple))) s.d = cast[CellArray](alloc(s.cap * sizeof(CellTuple)))
proc deinit(s: var CellSeq) = proc deinit(s: var CellSeq) =
if s.d != nil: if s.d != nil:
when defined(useMalloc): when compileOption("threads"):
c_free(s.d) deallocShared(s.d)
else: else:
dealloc(s.d) dealloc(s.d)
s.d = nil s.d = nil

View file

@ -174,7 +174,7 @@ when hasAlloc and not defined(js):
## from a shared heap. ## from a shared heap.
cast[ptr T](realloc(p, T.sizeof * newSize)) cast[ptr T](realloc(p, T.sizeof * newSize))
template dealloc*(p: pointer) = proc dealloc*(p: pointer) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} =
## Frees the memory allocated with ``alloc``, ``alloc0`` or ## Frees the memory allocated with ``alloc``, ``alloc0`` or
## ``realloc``. ## ``realloc``.
## ##

View file

@ -35,7 +35,10 @@ proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises
# we have to use type erasure here as Nim does not support generic # we have to use type erasure here as Nim does not support generic
# compilerProcs. Oh well, this will all be inlined anyway. # compilerProcs. Oh well, this will all be inlined anyway.
if cap > 0: if cap > 0:
var p = cast[ptr NimSeqPayloadBase](allocShared0(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize)) when compileOption("threads"):
var p = cast[ptr NimSeqPayloadBase](allocShared0(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize))
else:
var p = cast[ptr NimSeqPayloadBase](alloc0(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize))
p.cap = cap p.cap = cap
result = p result = p
else: else:
@ -62,14 +65,20 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin
let oldCap = p.cap and not strlitFlag let oldCap = p.cap and not strlitFlag
let newCap = max(resize(oldCap), len+addlen) let newCap = max(resize(oldCap), len+addlen)
if (p.cap and strlitFlag) == strlitFlag: if (p.cap and strlitFlag) == strlitFlag:
var q = cast[ptr NimSeqPayloadBase](allocShared0(headerSize + elemSize * newCap)) when compileOption("threads"):
var q = cast[ptr NimSeqPayloadBase](allocShared0(headerSize + elemSize * newCap))
else:
var q = cast[ptr NimSeqPayloadBase](alloc0(headerSize + elemSize * newCap))
copyMem(q +! headerSize, p +! headerSize, len * elemSize) copyMem(q +! headerSize, p +! headerSize, len * elemSize)
q.cap = newCap q.cap = newCap
result = q result = q
else: else:
let oldSize = headerSize + elemSize * oldCap let oldSize = headerSize + elemSize * oldCap
let newSize = headerSize + elemSize * newCap let newSize = headerSize + elemSize * newCap
var q = cast[ptr NimSeqPayloadBase](reallocShared0(p, oldSize, newSize)) when compileOption("threads"):
var q = cast[ptr NimSeqPayloadBase](reallocShared0(p, oldSize, newSize))
else:
var q = cast[ptr NimSeqPayloadBase](realloc0(p, oldSize, newSize))
q.cap = newCap q.cap = newCap
result = q result = q

View file

@ -15,3 +15,10 @@ type
NimSeqV2Reimpl = object NimSeqV2Reimpl = object
len: int len: int
p: ptr NimSeqPayloadReimpl p: ptr NimSeqPayloadReimpl
template frees(s: NimSeqV2Reimpl) =
if s.p != nil and (s.p.cap and strlitFlag) != strlitFlag:
when compileOption("threads"):
deallocShared(s.p)
else:
dealloc(s.p)

View file

@ -29,7 +29,10 @@ template contentSize(cap): int = cap + 1 + sizeof(NimStrPayloadBase)
template frees(s) = template frees(s) =
if not isLiteral(s): if not isLiteral(s):
deallocShared(s.p) when compileOption("threads"):
deallocShared(s.p)
else:
dealloc(s.p)
proc resize(old: int): int {.inline.} = proc resize(old: int): int {.inline.} =
if old <= 0: result = 4 if old <= 0: result = 4
@ -40,7 +43,10 @@ proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
if isLiteral(s): if isLiteral(s):
let oldP = s.p let oldP = s.p
# can't mutate a literal, so we need a fresh copy here: # can't mutate a literal, so we need a fresh copy here:
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len + addlen))) when compileOption("threads"):
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len + addlen)))
else:
s.p = cast[ptr NimStrPayload](alloc0(contentSize(s.len + addlen)))
s.p.cap = s.len + addlen s.p.cap = s.len + addlen
if s.len > 0: if s.len > 0:
# we are about to append, so there is no need to copy the \0 terminator: # we are about to append, so there is no need to copy the \0 terminator:
@ -49,7 +55,10 @@ proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
let oldCap = s.p.cap and not strlitFlag let oldCap = s.p.cap and not strlitFlag
if s.len + addlen > oldCap: if s.len + addlen > oldCap:
let newCap = max(s.len + addlen, resize(oldCap)) let newCap = max(s.len + addlen, resize(oldCap))
s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(oldCap), contentSize(newCap))) when compileOption("threads"):
s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(oldCap), contentSize(newCap)))
else:
s.p = cast[ptr NimStrPayload](realloc0(s.p, contentSize(oldCap), contentSize(newCap)))
s.p.cap = newCap s.p.cap = newCap
proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl, inline.} = proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl, inline.} =
@ -63,7 +72,10 @@ proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerproc.} =
if len <= 0: if len <= 0:
result = NimStringV2(len: 0, p: nil) result = NimStringV2(len: 0, p: nil)
else: else:
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len))) when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
p.cap = len p.cap = len
if len > 0: if len > 0:
# we are about to append, so there is no need to copy the \0 terminator: # we are about to append, so there is no need to copy the \0 terminator:
@ -94,7 +106,10 @@ proc rawNewString(space: int): NimStringV2 {.compilerproc.} =
if space <= 0: if space <= 0:
result = NimStringV2(len: 0, p: nil) result = NimStringV2(len: 0, p: nil)
else: else:
var p = cast[ptr NimStrPayload](allocShared0(contentSize(space))) when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(space)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(space)))
p.cap = space p.cap = space
result = NimStringV2(len: 0, p: p) result = NimStringV2(len: 0, p: p)
@ -102,7 +117,10 @@ proc mnewString(len: int): NimStringV2 {.compilerproc.} =
if len <= 0: if len <= 0:
result = NimStringV2(len: 0, p: nil) result = NimStringV2(len: 0, p: nil)
else: else:
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len))) when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
p.cap = len p.cap = len
result = NimStringV2(len: len, p: p) result = NimStringV2(len: len, p: p)
@ -128,7 +146,10 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
# 'let y = newStringOfCap(); var x = y' # 'let y = newStringOfCap(); var x = y'
# on the other hand... These get turned into moves now. # on the other hand... These get turned into moves now.
frees(a) frees(a)
a.p = cast[ptr NimStrPayload](allocShared0(contentSize(b.len))) when compileOption("threads"):
a.p = cast[ptr NimStrPayload](allocShared0(contentSize(b.len)))
else:
a.p = cast[ptr NimStrPayload](alloc0(contentSize(b.len)))
a.p.cap = b.len a.p.cap = b.len
a.len = b.len a.len = b.len
copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1) copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
@ -136,7 +157,10 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
proc nimPrepareStrMutationImpl(s: var NimStringV2) = proc nimPrepareStrMutationImpl(s: var NimStringV2) =
let oldP = s.p let oldP = s.p
# can't mutate a literal, so we need a fresh copy here: # can't mutate a literal, so we need a fresh copy here:
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len))) when compileOption("threads"):
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len)))
else:
s.p = cast[ptr NimStrPayload](alloc0(contentSize(s.len)))
s.p.cap = s.len s.p.cap = s.len
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len+1) copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len+1)

View file

@ -27,7 +27,10 @@ when defined(nimv2):
proc `=destroy`(a: var WideCStringObj) = proc `=destroy`(a: var WideCStringObj) =
if a.data != nil: if a.data != nil:
deallocShared(a.data) when compileOption("threads"):
deallocShared(a.data)
else:
dealloc(a.data)
proc `=`(a: var WideCStringObj; b: WideCStringObj) {.error.} proc `=`(a: var WideCStringObj; b: WideCStringObj) {.error.}
@ -37,7 +40,10 @@ when defined(nimv2):
proc createWide(a: var WideCStringObj; bytes: int) = proc createWide(a: var WideCStringObj; bytes: int) =
a.bytes = bytes a.bytes = bytes
a.data = cast[typeof(a.data)](allocShared0(bytes)) when compileOption("threads"):
a.data = cast[typeof(a.data)](allocShared0(bytes))
else:
a.data = cast[typeof(a.data)](alloc0(bytes))
template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx] template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx]
template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val