summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgtypes.nim6
-rw-r--r--compiler/liftdestructors.nim1
-rw-r--r--compiler/lowerings.nim2
-rw-r--r--lib/system/orc.nim23
-rw-r--r--tests/arc/tasyncleak2.nim88
5 files changed, 111 insertions, 9 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 5b5720934..aa92b8534 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -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")
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index b3300850e..3d0635761 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -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) =
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index f6ca98196..2d96f8a60 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -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
diff --git a/lib/system/orc.nim b/lib/system/orc.nim
index 7c4cf9d98..7500ba374 100644
--- a/lib/system/orc.nim
+++ b/lib/system/orc.nim
@@ -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)
diff --git a/tests/arc/tasyncleak2.nim b/tests/arc/tasyncleak2.nim
new file mode 100644
index 000000000..4d8486b3b
--- /dev/null
+++ b/tests/arc/tasyncleak2.nim
@@ -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"