forward type alignment information to seqs (#12430)

This commit is contained in:
Arne Döring 2020-04-19 07:52:01 +02:00 • committed by GitHub
commit 4005f0d0e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 152 additions and 114 deletions

View file

@ -245,7 +245,7 @@ proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
# ----------------- sequences ----------------------------------------------
proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
proc incrSeq(seq: PGenericSeq, elemSize, elemAlign: int): PGenericSeq {.compilerproc.} =
# increments the length by one:
# this is needed for supporting ``add``;
#
@ -255,18 +255,16 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
result = seq
if result.len >= result.space:
let r = resize(result.space)
result = cast[PGenericSeq](growObj(result, elemSize * r +
GenericSeqSize))
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
result.reserved = r
inc(result.len)
proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
proc incrSeqV2(seq: PGenericSeq, elemSize, elemAlign: int): PGenericSeq {.compilerproc.} =
# incrSeq version 2
result = seq
if result.len >= result.space:
let r = resize(result.space)
result = cast[PGenericSeq](growObj(result, elemSize * r +
GenericSeqSize))
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
result.reserved = r
template `+!`(p: pointer, s: int): pointer =
@ -283,21 +281,19 @@ proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} =
when defined(nimIncrSeqV3):
result = cast[PGenericSeq](newSeq(typ, r))
result.len = s.len
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * typ.base.size)
copyMem(result +! align(GenericSeqSize, typ.base.align), s +! align(GenericSeqSize, typ.base.align), s.len * typ.base.size)
# since we steal the content from 's', it's crucial to set s's len to 0.
s.len = 0
else:
result = cast[PGenericSeq](growObj(result, typ.base.size * r +
GenericSeqSize))
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, typ.base.align) + typ.base.size * r))
result.reserved = r
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
proc setLengthSeq(seq: PGenericSeq, elemSize, elemAlign, newLen: int): PGenericSeq {.
compilerRtl, inl.} =
result = seq
if result.space < newLen:
let r = max(resize(result.space), newLen)
result = cast[PGenericSeq](growObj(result, elemSize * r +
GenericSeqSize))
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
result.reserved = r
elif newLen < result.len:
# we need to decref here, otherwise the GC leaks!
@ -307,8 +303,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
when false: # compileOption("gc", "v2"):
for i in newLen..result.len-1:
let len0 = gch.tempStack.len
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
extGetCellType(result).base, waPush)
let len1 = gch.tempStack.len
for i in len0 ..< len1:
@ -318,7 +313,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
if ntfNoRefs notin extGetCellType(result).base.flags:
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# XXX: zeroing out the memory can still result in crashes if a wiped-out
@ -327,7 +322,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
# presence of user defined destructors, the user will expect the cell to be
# "destroyed" thus creating the same problem. We can destroy the cell in the
# finalizer of the sequence, but this makes destruction non-deterministic.
zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +%
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
result.len = newLen
@ -339,10 +334,11 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
else:
when defined(nimIncrSeqV3):
let elemSize = typ.base.size
let elemAlign = typ.base.align
if s.space < newLen:
let r = max(resize(s.space), newLen)
result = cast[PGenericSeq](newSeq(typ, r))
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * elemSize)
copyMem(result +! align(GenericSeqSize, elemAlign), s +! align(GenericSeqSize, elemAlign), s.len * elemSize)
# since we steal the content from 's', it's crucial to set s's len to 0.
s.len = 0
elif newLen < s.len:
@ -354,7 +350,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
if ntfNoRefs notin typ.base.flags:
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# XXX: zeroing out the memory can still result in crashes if a wiped-out
@ -363,7 +359,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
# presence of user defined destructors, the user will expect the cell to be
# "destroyed" thus creating the same problem. We can destroy the cell in the
# finalizer of the sequence, but this makes destruction non-deterministic.
zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +%
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
else:
result = s