This commit is contained in:
araq
2026-02-09 12:52:07 +01:00
parent 6aad72b257
commit 933076191c
2 changed files with 24 additions and 9 deletions

View File

@@ -748,12 +748,19 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# YRC uses dedicated runtime procs for the entire write barrier:
if c.g.config.selectedGC == gcYrc:
let desc =
if isFinal(elemType):
let ti = genBuiltin(c, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
ti.typ = getSysType(c.g, c.info, tyPointer)
ti
else:
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, x), y)
body.add callCodegenProc(c.g, "nimAsgnYrc", c.info, genAddr(c, x), y, desc)
return
of attachedSink:
body.add callCodegenProc(c.g, "nimSinkYrc", c.info, genAddr(c, x), y)
body.add callCodegenProc(c.g, "nimSinkYrc", c.info, genAddr(c, x), y, desc)
return
else: discard # fall through for destructor, trace, wasMoved
@@ -842,13 +849,15 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
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)
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)
body.add callCodegenProc(c.g, "nimSinkYrc", c.info, genAddr(c, xenv), y, nilDesc)
return
else: discard # fall through for destructor, trace, wasMoved

View File

@@ -390,7 +390,7 @@ proc GC_partialCollect*(limit: int) =
roots.len = limit
proc GC_fullCollect* =
collectCycles()
GC_runOrc()
proc GC_enableMarkAndSweep*() = GC_enableOrc()
proc GC_disableMarkAndSweep*() = GC_disableOrc()
@@ -448,7 +448,13 @@ proc unsureAsgnRef(dest: ptr pointer, src: pointer) {.inline.} =
dest[] = src
if src != nil: nimIncRefCyclic(src, true)
proc nimAsgnYrc(dest: ptr pointer; src: pointer) {.compilerRtl.} =
proc yrcDec(tmp: pointer; desc: PNimTypeV2) {.inline.} =
if desc != nil:
discard nimDecRefIsLastCyclicStatic(tmp, desc)
else:
discard nimDecRefIsLastCyclicDyn(tmp)
proc nimAsgnYrc(dest: ptr pointer; src: pointer; desc: PNimTypeV2) {.compilerRtl.} =
## YRC write barrier for ref copy assignment.
## Atomically stores src into dest, then buffers RC adjustments.
## Freeing is always done by the cycle collector, never inline.
@@ -457,15 +463,15 @@ proc nimAsgnYrc(dest: ptr pointer; src: pointer) {.compilerRtl.} =
if src != nil:
nimIncRefCyclic(src, true)
if tmp != nil:
discard nimDecRefIsLastCyclicDyn(tmp)
yrcDec(tmp, desc)
proc nimSinkYrc(dest: ptr pointer; src: pointer) {.compilerRtl.} =
proc nimSinkYrc(dest: ptr pointer; src: pointer; desc: PNimTypeV2) {.compilerRtl.} =
## YRC write barrier for ref sink (move). No incRef on source.
## Freeing is always done by the cycle collector, never inline.
let tmp = dest[]
atomicStoreN(dest, src, ATOMIC_RELEASE)
if tmp != nil:
discard nimDecRefIsLastCyclicDyn(tmp)
yrcDec(tmp, desc)
proc nimMarkCyclic(p: pointer) {.compilerRtl, inl.} =
when optimizedOrc: