diff --git a/compiler/btrees.nim b/compiler/btrees.nim index 5f78c07fe4..d5e7e8099c 100644 --- a/compiler/btrees.nim +++ b/compiler/btrees.nim @@ -16,7 +16,7 @@ const Mhalf = M div 2 type - Node[Key, Val] = ref object + Node[Key, Val] {.acyclic.} = ref object entries: int keys: array[M, Key] case isInternal: bool diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index eb22d79e0d..2fd8156154 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1327,6 +1327,10 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope = genProc(m, theProc) result = theProc.loc.r + + when false: + if not canFormAcycle(t) and op == attachedTrace: + echo "ayclic but has this =trace ", t, " ", theProc.ast else: when false: if op == attachedTrace and m.config.selectedGC == gcOrc and @@ -1352,9 +1356,12 @@ proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineIn let traceImpl = genHook(m, t, info, attachedTrace) let disposeImpl = genHook(m, t, info, attachedDispose) - addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6;", [ + var flags = 0 + if not canFormAcycle(t): flags = flags or 1 + + addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6; $1.flags = $7;", [ name, destroyImpl, getTypeDesc(m, t), typeName, - traceImpl, disposeImpl]) + traceImpl, disposeImpl, rope(flags)]) if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions: discard genTypeInfoV1(m, t, info) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 2948271d9d..c3eee3cfe6 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -468,8 +468,9 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = forallElements(c, t, body, x, y) body.add genBuiltin(c.g, mDestroy, "destroy", x) of attachedTrace: - # follow all elements: - forallElements(c, t, body, x, y) + if canFormAcycle(t.elemType): + # 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) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 13deace0d0..a31c890ec7 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -25,8 +25,8 @@ type POptionEntry* = ref TOptionEntry PProcCon* = ref TProcCon - TProcCon* = object # procedure context; also used for top-level - # statements + TProcCon* {.acyclic.} = object # procedure context; also used for top-level + # statements owner*: PSym # the symbol this context belongs to resultSym*: PSym # the result symbol (if we are in a proc) selfSym*: PSym # the 'self' symbol (if available) diff --git a/compiler/types.nim b/compiler/types.nim index de9953e6de..83313550e0 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -365,13 +365,13 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool = if tfAcyclic in t.flags: return case t.kind of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs: - if not containsOrIncl(marker, t.id): + if t.id == startId: + result = true + elif not containsOrIncl(marker, t.id): for i in 0..", importc.} + proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl, inline.} = let p = cast[ptr pointer](q) if p[] != nil: + + orcAssert strstr(desc.name, "TType") == nil, "following a TType but it's acyclic!" + var j = cast[ptr GcEnv](env) j.traceStack.add(head p[], desc) @@ -102,12 +114,6 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl, inline.} = var j = cast[ptr GcEnv](env) j.traceStack.add(head p[], cast[ptr PNimTypeV2](p[])[]) -template orcAssert(cond, msg) = - when logOrc: - if not cond: - cfprintf(cstderr, "[Bug!] %s\n", msg) - quit 1 - var roots {.threadvar.}: CellSeq @@ -349,6 +355,8 @@ proc registerCycle(s: Cell; desc: PNimTypeV2) = collectCycles() #writeCell("[added root]", s) + orcAssert strstr(desc.name, "TType") == nil, "added a TType as a root!" + proc GC_runOrc* = ## Forces a cycle collection pass. collectCycles()