diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index e5d3a39d09..d58039dc9a 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -848,19 +848,11 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = let xenv = genBuiltin(c, mAccessEnv, "accessEnv", x) xenv.typ = getSysType(c.g, c.info, tyPointer) - # YRC uses dedicated runtime procs for the write barrier on the env pointer: - # Closure envs are always polymorphic, so pass nil for desc (uses Dyn variant): - if c.g.config.selectedGC == gcYrc: - let nilDesc = newNodeIT(nkNilLit, c.info, getSysType(c.g, c.info, tyPointer)) - case c.kind - of attachedAsgn, attachedDup: - body.add callCodegenProc(c.g, "nimAsgnYrc", c.info, genAddr(c, xenv), y, nilDesc) - return - of attachedSink: - body.add callCodegenProc(c.g, "nimSinkYrc", c.info, genAddr(c, xenv), y, nilDesc) - return - else: discard # fall through for destructor, trace, wasMoved - + # Closures are (fnPtr, env) pairs -- nimAsgnYrc/nimSinkYrc operate on single + # pointers so they cannot handle a closure struct. Instead we fall through to + # the regular ORC cyclic path which copies the whole struct via newAsgnStmt + # and calls nimIncRefCyclic / nimDecRefIsLastCyclicDyn on the env pointer. + # Those procs are already YRC-aware (they buffer into striped queues). let isCyclic = c.g.config.selectedGC in {gcOrc, gcYrc} let tmp = if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}: diff --git a/lib/system/yrc.nim b/lib/system/yrc.nim index 867a508f00..5163a3b73b 100644 --- a/lib/system/yrc.nim +++ b/lib/system/yrc.nim @@ -122,7 +122,8 @@ include threadids type Stripe = object - lockInc: Lock + when not defined(yrcAtomics): + lockInc: Lock toIncLen: int toInc: array[QueueSize, Cell] lockDec: Lock @@ -143,33 +144,53 @@ proc nimIncRefCyclic(p: pointer; cyclic: bool) {.compilerRtl, inl.} = let h = head(p) when optimizedOrc: if cyclic: h.rc = h.rc or maybeCycle - let idx = getStripeIdx() - while true: - var overflow = false - withLock stripes[idx].lockInc: - if stripes[idx].toIncLen < QueueSize: - stripes[idx].toInc[stripes[idx].toIncLen] = h - stripes[idx].toIncLen += 1 - else: - overflow = true - if overflow: - withLock gYrcGlobalLock: - for i in 0..