mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 18:32:11 +00:00
Remove some unnecessary initialization in seq operations (#22677)
* `PrepareSeqAdd` * `add` * `setLen` * `grow` Merge after #21842. --------- Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
f8f6a3c926
commit
fbb5ac512c
@@ -79,15 +79,42 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin
|
||||
var p = cast[ptr NimSeqPayloadBase](p)
|
||||
let oldCap = p.cap and not strlitFlag
|
||||
let newCap = max(resize(oldCap), len+addlen)
|
||||
var q: ptr NimSeqPayloadBase
|
||||
if (p.cap and strlitFlag) == strlitFlag:
|
||||
var q = cast[ptr NimSeqPayloadBase](alignedAlloc0(headerSize + elemSize * newCap, elemAlign))
|
||||
q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
|
||||
copyMem(q +! headerSize, p +! headerSize, len * elemSize)
|
||||
else:
|
||||
let oldSize = headerSize + elemSize * oldCap
|
||||
let newSize = headerSize + elemSize * newCap
|
||||
q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
|
||||
|
||||
zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize)
|
||||
q.cap = newCap
|
||||
result = q
|
||||
|
||||
proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
||||
noSideEffect, tags: [], raises: [], compilerRtl.} =
|
||||
{.noSideEffect.}:
|
||||
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
|
||||
if addlen <= 0:
|
||||
result = p
|
||||
elif p == nil:
|
||||
result = newSeqPayloadUninit(len+addlen, elemSize, elemAlign)
|
||||
else:
|
||||
# Note: this means we cannot support things that have internal pointers as
|
||||
# they get reallocated here. This needs to be documented clearly.
|
||||
var p = cast[ptr NimSeqPayloadBase](p)
|
||||
let oldCap = p.cap and not strlitFlag
|
||||
let newCap = max(resize(oldCap), len+addlen)
|
||||
if (p.cap and strlitFlag) == strlitFlag:
|
||||
var q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
|
||||
copyMem(q +! headerSize, p +! headerSize, len * elemSize)
|
||||
q.cap = newCap
|
||||
result = q
|
||||
else:
|
||||
let oldSize = headerSize + elemSize * oldCap
|
||||
let newSize = headerSize + elemSize * newCap
|
||||
var q = cast[ptr NimSeqPayloadBase](alignedRealloc0(p, oldSize, newSize, elemAlign))
|
||||
var q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
|
||||
q.cap = newCap
|
||||
result = q
|
||||
|
||||
@@ -104,16 +131,17 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} =
|
||||
{.noSideEffect.}:
|
||||
cast[ptr NimSeqV2[T]](addr x).len = newLen
|
||||
|
||||
proc grow*[T](x: var seq[T]; newLen: Natural; value: T) =
|
||||
proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} =
|
||||
let oldLen = x.len
|
||||
#sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'"
|
||||
if newLen <= oldLen: return
|
||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||
if xu.p == nil or (xu.p.cap and not strlitFlag) < newLen:
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
|
||||
xu.len = newLen
|
||||
for i in oldLen .. newLen-1:
|
||||
xu.p.data[i] = value
|
||||
wasMoved(xu.p.data[i])
|
||||
`=copy`(xu.p.data[i], value)
|
||||
|
||||
proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
|
||||
## Generic proc for adding a data item `y` to a container `x`.
|
||||
@@ -126,7 +154,7 @@ proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, n
|
||||
let oldLen = x.len
|
||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||
if xu.p == nil or (xu.p.cap and not strlitFlag) < oldLen+1:
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, 1, sizeof(T), alignof(T)))
|
||||
xu.len = oldLen+1
|
||||
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
||||
# copyMem(). This is fine as know by construction that
|
||||
@@ -143,7 +171,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
|
||||
if newlen <= oldLen: return
|
||||
var xu = cast[ptr NimSeqV2[T]](addr s)
|
||||
if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen:
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
|
||||
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
|
||||
xu.len = newlen
|
||||
for i in oldLen..<newlen:
|
||||
xu.p.data[i] = default(T)
|
||||
|
||||
Reference in New Issue
Block a user