mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-21 06:10:56 +00:00
progress
This commit is contained in:
@@ -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}:
|
||||
|
||||
@@ -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..<NumStripes:
|
||||
withLock stripes[i].lockInc:
|
||||
for j in 0..<stripes[i].toIncLen:
|
||||
let x = stripes[i].toInc[j]
|
||||
x.rc = x.rc +% rcIncrement
|
||||
stripes[i].toIncLen = 0
|
||||
when defined(yrcAtomics):
|
||||
let s = getStripeIdx()
|
||||
let slot = atomicFetchAdd(addr stripes[s].toIncLen, 1, ATOMIC_ACQ_REL)
|
||||
if slot < QueueSize:
|
||||
atomicStoreN(addr stripes[s].toInc[slot], h, ATOMIC_RELEASE)
|
||||
else:
|
||||
break
|
||||
withLock gYrcGlobalLock:
|
||||
h.rc = h.rc +% rcIncrement
|
||||
for i in 0..<NumStripes:
|
||||
let len = atomicExchangeN(addr stripes[i].toIncLen, 0, ATOMIC_ACQUIRE)
|
||||
for j in 0..<min(len, QueueSize):
|
||||
let x = atomicLoadN(addr stripes[i].toInc[j], ATOMIC_ACQUIRE)
|
||||
x.rc = x.rc +% rcIncrement
|
||||
else:
|
||||
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..<NumStripes:
|
||||
withLock stripes[i].lockInc:
|
||||
for j in 0..<stripes[i].toIncLen:
|
||||
let x = stripes[i].toInc[j]
|
||||
x.rc = x.rc +% rcIncrement
|
||||
stripes[i].toIncLen = 0
|
||||
else:
|
||||
break
|
||||
|
||||
proc mergePendingRoots() =
|
||||
for i in 0..<NumStripes:
|
||||
withLock stripes[i].lockInc:
|
||||
for j in 0..<stripes[i].toIncLen:
|
||||
let x = stripes[i].toInc[j]
|
||||
when defined(yrcAtomics):
|
||||
let incLen = atomicExchangeN(addr stripes[i].toIncLen, 0, ATOMIC_ACQUIRE)
|
||||
for j in 0..<min(incLen, QueueSize):
|
||||
let x = atomicLoadN(addr stripes[i].toInc[j], ATOMIC_ACQUIRE)
|
||||
x.rc = x.rc +% rcIncrement
|
||||
stripes[i].toIncLen = 0
|
||||
else:
|
||||
withLock stripes[i].lockInc:
|
||||
for j in 0..<stripes[i].toIncLen:
|
||||
let x = stripes[i].toInc[j]
|
||||
x.rc = x.rc +% rcIncrement
|
||||
stripes[i].toIncLen = 0
|
||||
withLock stripes[i].lockDec:
|
||||
for j in 0..<stripes[i].toDecLen:
|
||||
let (c, desc) = stripes[i].toDec[j]
|
||||
@@ -483,7 +504,8 @@ proc nimMarkCyclic(p: pointer) {.compilerRtl, inl.} =
|
||||
# Initialize locks at module load
|
||||
initLock(gYrcGlobalLock)
|
||||
for i in 0..<NumStripes:
|
||||
initLock(stripes[i].lockInc)
|
||||
when not defined(yrcAtomics):
|
||||
initLock(stripes[i].lockInc)
|
||||
initLock(stripes[i].lockDec)
|
||||
|
||||
{.pop.}
|
||||
|
||||
Reference in New Issue
Block a user