parent
073bea6606
commit
bc179ccc3f
5 changed files with 111 additions and 9 deletions
|
|
@ -1319,9 +1319,9 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||||
genProc(m, theProc)
|
genProc(m, theProc)
|
||||||
result = theProc.loc.r
|
result = theProc.loc.r
|
||||||
else:
|
else:
|
||||||
if op == attachedTrace and m.config.selectedGC == gcOrc and
|
when false:
|
||||||
containsGarbageCollectedRef(t):
|
if op == attachedTrace and m.config.selectedGC == gcOrc and
|
||||||
when false:
|
containsGarbageCollectedRef(t):
|
||||||
# unfortunately this check is wrong for an object type that only contains
|
# unfortunately this check is wrong for an object type that only contains
|
||||||
# .cursor fields like 'Node' inside 'cycleleak'.
|
# .cursor fields like 'Node' inside 'cycleleak'.
|
||||||
internalError(m.config, info, "no attached trace proc found")
|
internalError(m.config, info, "no attached trace proc found")
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
# follow all elements:
|
# follow all elements:
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
of attachedDispose:
|
of attachedDispose:
|
||||||
|
forallElements(c, t, body, x, y)
|
||||||
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||||
|
|
||||||
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
|
||||||
else:
|
else:
|
||||||
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
|
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
|
||||||
result.n = newNodeI(nkRecList, info)
|
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)
|
owner, info, owner.options)
|
||||||
incl s.flags, sfAnon
|
incl s.flags, sfAnon
|
||||||
s.typ = result
|
s.typ = result
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ template setColor(c, col) =
|
||||||
proc nimIncRefCyclic(p: pointer) {.compilerRtl, inl.} =
|
proc nimIncRefCyclic(p: pointer) {.compilerRtl, inl.} =
|
||||||
let h = head(p)
|
let h = head(p)
|
||||||
inc h.rc, rcIncrement
|
inc h.rc, rcIncrement
|
||||||
h.setColor colPurple # mark as potential cycle!
|
#h.setColor colPurple # mark as potential cycle!
|
||||||
|
|
||||||
const
|
const
|
||||||
useJumpStack = false # for thavlak the jump stack doesn't improve the performance at all
|
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:
|
if desc.disposeImpl != nil:
|
||||||
cast[DisposeProc](desc.disposeImpl)(p)
|
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)
|
nimRawDispose(p)
|
||||||
|
|
||||||
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
|
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)
|
#cprintf("[DESTROY] %p\n", p)
|
||||||
else:
|
else:
|
||||||
dec cell.rc, rcIncrement
|
dec cell.rc, rcIncrement
|
||||||
if cell.color == colPurple:
|
#if cell.color == colPurple:
|
||||||
rememberCycle(result, cell, cast[ptr PNimType](p)[])
|
rememberCycle(result, cell, cast[ptr PNimType](p)[])
|
||||||
|
|
||||||
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
|
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
|
||||||
if p != nil:
|
if p != nil:
|
||||||
|
|
@ -353,5 +366,5 @@ proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl
|
||||||
#cprintf("[DESTROY] %p %s\n", p, desc.name)
|
#cprintf("[DESTROY] %p %s\n", p, desc.name)
|
||||||
else:
|
else:
|
||||||
dec cell.rc, rcIncrement
|
dec cell.rc, rcIncrement
|
||||||
if cell.color == colPurple:
|
#if cell.color == colPurple:
|
||||||
rememberCycle(result, cell, desc)
|
rememberCycle(result, cell, desc)
|
||||||
|
|
|
||||||
88
tests/arc/tasyncleak2.nim
Normal file
88
tests/arc/tasyncleak2.nim
Normal 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"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue