Skip to content

Commit d647927

Browse files
committed
fixes #24402; Memory leak under Arc/Orc on inline iterators with nested seq
1 parent b3c1fba commit d647927

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

compiler/transf.nim

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@ proc transformYield(c: PTransf, n: PNode): PNode =
400400
let lhs = c.transCon.forStmt[i]
401401
let rhs = transform(c, v)
402402
result.add(asgnTo(lhs, rhs))
403-
elif e.kind notin {nkAddr, nkHiddenAddr}: # no need to generate temp for address operation
403+
elif e.kind notin {nkAddr, nkHiddenAddr} and e.kind != nkSym:
404+
# no need to generate temp for address operation + nodes without sideeffects
404405
# TODO do not use temp for nodes which cannot have side-effects
405406
var tmp = newTemp(c, e.typ, e.info)
406407
let v = newNodeI(nkVarSection, e.info)
@@ -435,7 +436,8 @@ proc transformYield(c: PTransf, n: PNode): PNode =
435436
else:
436437
notLiteralTuple = true
437438

438-
if e.kind notin {nkAddr, nkHiddenAddr} and notLiteralTuple:
439+
if e.kind notin {nkAddr, nkHiddenAddr} and notLiteralTuple and e.kind != nkSym:
440+
# no need to generate temp for address operation + nodes without sideeffects
439441
# TODO do not use temp for nodes which cannot have side-effects
440442
var tmp = newTemp(c, e.typ, e.info)
441443
let v = newNodeI(nkVarSection, e.info)

tests/arc/t24402.nim

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
discard """
2+
joinable: false
3+
"""
4+
5+
# bug #24402
6+
7+
iterator myPairsInline*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.inline.} =
8+
for indexValuePair in twoDarray.pairs:
9+
yield indexValuePair
10+
11+
iterator myPairsClosure*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.closure.} =
12+
for indexValuePair in twoDarray.pairs:
13+
yield indexValuePair
14+
15+
template testTotalMem(iter: untyped): int =
16+
proc innerTestTotalMem(): int {.gensym.} =
17+
result = 0
18+
19+
# do the same operation 100 times, which should have similar mem footprint
20+
# as doing it once.
21+
for iterNum in 0..100:
22+
result = max(result, getTotalMem()) # record current mem footprint
23+
24+
# initialize nested sequence
25+
var my2dArray: seq[seq[int32]] = @[]
26+
27+
# fill with some data...
28+
for i in 0'i32..10_000:
29+
var z = @[i, i+1]
30+
my2dArray.add z
31+
32+
# use that data somehow...
33+
var otherContainer: seq[int32] = @[]
34+
var count = 0'i32
35+
for oneDindex, innerArray in my2dArray.iter:
36+
for value in innerArray:
37+
inc count
38+
if oneDindex > 50 and value < 200:
39+
otherContainer.add count
40+
41+
innerTestTotalMem()
42+
43+
proc main =
44+
let closureMem = testTotalMem(myPairsClosure) #1052672
45+
let inlineMem = testTotalMem(myPairsInline) #20328448
46+
47+
when defined(echoFootprint):
48+
echo "Closure memory footprint: " & $closureMem
49+
echo "Inline memory footprint: " & $inlineMem
50+
51+
# check that mem footprint is relatively similar b/t each method
52+
doAssert (closureMem - inlineMem).abs < (closureMem div 10)
53+
54+
main()

0 commit comments

Comments
 (0)