Skip to content

Commit fbb5ac5

Browse files
AmjadHDringabout
andauthored
Remove some unnecessary initialization in seq operations (#22677)
* `PrepareSeqAdd` * `add` * `setLen` * `grow` Merge after #21842. --------- Co-authored-by: ringabout <[email protected]>
1 parent f8f6a3c commit fbb5ac5

File tree

1 file changed

+35
-7
lines changed

1 file changed

+35
-7
lines changed

lib/system/seqs_v2.nim

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,42 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin
7979
var p = cast[ptr NimSeqPayloadBase](p)
8080
let oldCap = p.cap and not strlitFlag
8181
let newCap = max(resize(oldCap), len+addlen)
82+
var q: ptr NimSeqPayloadBase
8283
if (p.cap and strlitFlag) == strlitFlag:
83-
var q = cast[ptr NimSeqPayloadBase](alignedAlloc0(headerSize + elemSize * newCap, elemAlign))
84+
q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
85+
copyMem(q +! headerSize, p +! headerSize, len * elemSize)
86+
else:
87+
let oldSize = headerSize + elemSize * oldCap
88+
let newSize = headerSize + elemSize * newCap
89+
q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
90+
91+
zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize)
92+
q.cap = newCap
93+
result = q
94+
95+
proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
96+
noSideEffect, tags: [], raises: [], compilerRtl.} =
97+
{.noSideEffect.}:
98+
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
99+
if addlen <= 0:
100+
result = p
101+
elif p == nil:
102+
result = newSeqPayloadUninit(len+addlen, elemSize, elemAlign)
103+
else:
104+
# Note: this means we cannot support things that have internal pointers as
105+
# they get reallocated here. This needs to be documented clearly.
106+
var p = cast[ptr NimSeqPayloadBase](p)
107+
let oldCap = p.cap and not strlitFlag
108+
let newCap = max(resize(oldCap), len+addlen)
109+
if (p.cap and strlitFlag) == strlitFlag:
110+
var q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
84111
copyMem(q +! headerSize, p +! headerSize, len * elemSize)
85112
q.cap = newCap
86113
result = q
87114
else:
88115
let oldSize = headerSize + elemSize * oldCap
89116
let newSize = headerSize + elemSize * newCap
90-
var q = cast[ptr NimSeqPayloadBase](alignedRealloc0(p, oldSize, newSize, elemAlign))
117+
var q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
91118
q.cap = newCap
92119
result = q
93120
@@ -104,16 +131,17 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} =
104131
{.noSideEffect.}:
105132
cast[ptr NimSeqV2[T]](addr x).len = newLen
106133
107-
proc grow*[T](x: var seq[T]; newLen: Natural; value: T) =
134+
proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} =
108135
let oldLen = x.len
109136
#sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'"
110137
if newLen <= oldLen: return
111138
var xu = cast[ptr NimSeqV2[T]](addr x)
112139
if xu.p == nil or (xu.p.cap and not strlitFlag) < newLen:
113-
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
140+
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
114141
xu.len = newLen
115142
for i in oldLen .. newLen-1:
116-
xu.p.data[i] = value
143+
wasMoved(xu.p.data[i])
144+
`=copy`(xu.p.data[i], value)
117145

118146
proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
119147
## 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
126154
let oldLen = x.len
127155
var xu = cast[ptr NimSeqV2[T]](addr x)
128156
if xu.p == nil or (xu.p.cap and not strlitFlag) < oldLen+1:
129-
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
157+
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, 1, sizeof(T), alignof(T)))
130158
xu.len = oldLen+1
131159
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
132160
# copyMem(). This is fine as know by construction that
@@ -143,7 +171,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
143171
if newlen <= oldLen: return
144172
var xu = cast[ptr NimSeqV2[T]](addr s)
145173
if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen:
146-
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
174+
xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
147175
xu.len = newlen
148176
for i in oldLen..<newlen:
149177
xu.p.data[i] = default(T)

0 commit comments

Comments
 (0)