This commit is contained in:
Andreas Rumpf
2020-09-15 12:40:23 +02:00
committed by GitHub
parent 073bea6606
commit bc179ccc3f
5 changed files with 111 additions and 9 deletions

View File

@@ -1319,9 +1319,9 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
genProc(m, theProc)
result = theProc.loc.r
else:
if op == attachedTrace and m.config.selectedGC == gcOrc and
containsGarbageCollectedRef(t):
when false:
when false:
if op == attachedTrace and m.config.selectedGC == gcOrc and
containsGarbageCollectedRef(t):
# unfortunately this check is wrong for an object type that only contains
# .cursor fields like 'Node' inside 'cycleleak'.
internalError(m.config, info, "no attached trace proc found")

View File

@@ -448,6 +448,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# follow all elements:
forallElements(c, t, body, x, y)
of attachedDispose:
forallElements(c, t, body, x, y)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =

View File

@@ -158,7 +158,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
else:
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
result.n = newNodeI(nkRecList, info)
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info)),
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
owner, info, owner.options)
incl s.flags, sfAnon
s.typ = result

View File

@@ -40,7 +40,7 @@ template setColor(c, col) =
proc nimIncRefCyclic(p: pointer) {.compilerRtl, inl.} =
let h = head(p)
inc h.rc, rcIncrement
h.setColor colPurple # mark as potential cycle!
#h.setColor colPurple # mark as potential cycle!
const
useJumpStack = false # for thavlak the jump stack doesn't improve the performance at all
@@ -74,6 +74,19 @@ proc free(s: Cell; desc: PNimType) {.inline.} =
if desc.disposeImpl != nil:
cast[DisposeProc](desc.disposeImpl)(p)
when false:
cstderr.rawWrite desc.name
cstderr.rawWrite " "
if desc.disposeImpl == nil:
cstderr.rawWrite "lacks dispose"
if desc.traceImpl != nil:
cstderr.rawWrite ", but has trace\n"
else:
cstderr.rawWrite ", and lacks trace\n"
else:
cstderr.rawWrite "has dispose!\n"
nimRawDispose(p)
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
@@ -342,8 +355,8 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
#cprintf("[DESTROY] %p\n", p)
else:
dec cell.rc, rcIncrement
if cell.color == colPurple:
rememberCycle(result, cell, cast[ptr PNimType](p)[])
#if cell.color == colPurple:
rememberCycle(result, cell, cast[ptr PNimType](p)[])
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
if p != nil:
@@ -353,5 +366,5 @@ proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl
#cprintf("[DESTROY] %p %s\n", p, desc.name)
else:
dec cell.rc, rcIncrement
if cell.color == colPurple:
rememberCycle(result, cell, desc)
#if cell.color == colPurple:
rememberCycle(result, cell, desc)

88
tests/arc/tasyncleak2.nim Normal file
View File

@@ -0,0 +1,88 @@
discard """
output: "success"
cmd: "nim c --gc:orc $file"
"""
# issue #15076
import deques, strutils, asyncdispatch
proc doNothing(): Future[void] =
#[
var
:env
:env_1
try:
`=destroy`(:env)
internalNew(:env)
`=sink`(:env.retFuture1, newFuture("doNothing"))
`=destroy_1`(:env_1)
internalNew(:env_1)
`=`(:env_1.:up, :env)
`=sink_1`(:env.nameIterVar2, (doNothingIter, :env_1))
(doNothingNimAsyncContinue, :env)()
return `=_1`(result, :env.retFuture1)
finally:
`=destroy`(:env)
]#
var retFuture = newFuture[void]("doNothing")
iterator doNothingIter(): FutureBase {.closure.} =
# inspected ARC code: looks correct!
block:
var qqq = initDeque[string]()
for i in 0 .. 1000:
qqq.addLast($i)
complete(retFuture) # env.up.retFuture1
var nameIterVar = doNothingIter # iter_Env -> retFuture ->
proc doNothingNimAsyncContinue() {.closure.} =
# inspected ARC code: looks correct
if not nameIterVar.finished:
var next_gensym0 = nameIterVar()
while (not next_gensym0.isNil) and next_gensym0.finished:
next_gensym0 = nameIterVar()
if nameIterVar.finished:
break
if next_gensym0 != nil:
{.gcsafe.}:
next_gensym0.addCallback cast[proc () {.closure, gcsafe.}](doNothingNimAsyncContinue)
doNothingNimAsyncContinue()
return retFuture
proc main(): Future[void] =
template await[T](f_gensym12: Future[T]): auto {.used.} =
var internalTmpFuture_gensym12: FutureBase = f_gensym12
yield internalTmpFuture_gensym12
(cast[type(f_gensym12)](internalTmpFuture_gensym12)).read()
var retFuture = newFuture[void]("main")
iterator mainIter(): FutureBase {.closure.} =
block:
for x in 0 .. 1000:
await doNothing()
complete(retFuture)
var nameIterVar_gensym11 = mainIter
proc mainNimAsyncContinue() {.closure.} =
if not nameIterVar_gensym11.finished:
var next_gensym11 = unown nameIterVar_gensym11()
while (not next_gensym11.isNil) and next_gensym11.finished:
next_gensym11 = unown nameIterVar_gensym11()
if nameIterVar_gensym11.finished:
break
if next_gensym11 != nil:
{.gcsafe.}:
next_gensym11.addCallback cast[proc () {.closure, gcsafe.}](mainNimAsyncContinue)
mainNimAsyncContinue()
return retFuture
for i in 0..9:
waitFor main()
GC_fullCollect()
assert getOccupiedMem() < 1024
echo "success"