@@ -79,15 +79,42 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin
79
79
var p = cast[ptr NimSeqPayloadBase](p)
80
80
let oldCap = p.cap and not strlitFlag
81
81
let newCap = max(resize(oldCap), len+addlen)
82
+ var q: ptr NimSeqPayloadBase
82
83
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))
84
111
copyMem(q +! headerSize, p +! headerSize, len * elemSize)
85
112
q.cap = newCap
86
113
result = q
87
114
else:
88
115
let oldSize = headerSize + elemSize * oldCap
89
116
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))
91
118
q.cap = newCap
92
119
result = q
93
120
@@ -104,16 +131,17 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} =
104
131
{.noSideEffect.}:
105
132
cast[ptr NimSeqV2[T]](addr x).len = newLen
106
133
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.} =
108
135
let oldLen = x.len
109
136
#sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'"
110
137
if newLen <= oldLen: return
111
138
var xu = cast[ptr NimSeqV2[T]](addr x)
112
139
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)))
114
141
xu.len = newLen
115
142
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)
117
145
118
146
proc add* [T](x: var seq [T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
119
147
## 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
126
154
let oldLen = x.len
127
155
var xu = cast[ptr NimSeqV2[T]](addr x)
128
156
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)))
130
158
xu.len = oldLen+ 1
131
159
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
132
160
# copyMem(). This is fine as know by construction that
@@ -143,7 +171,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
143
171
if newlen <= oldLen: return
144
172
var xu = cast[ptr NimSeqV2[T]](addr s)
145
173
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)))
147
175
xu.len = newlen
148
176
for i in oldLen..< newlen:
149
177
xu.p.data[i] = default(T)
0 commit comments