From 4990a325eaf7f138995e5697bdc88a1a76aa9f2b Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 23 Jul 2026 20:49:01 +0200 Subject: [PATCH] make it work with C++; documentation updated --- compiler/liftdestructors.nim | 14 ++++++++++++-- doc/mm.md | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 0529812c3a..aa8a20bc2a 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -94,11 +94,21 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genBuiltin(c, mWasMoved, "wasMoved", x) proc genAddr(c: var TLiftCtx; x: PNode): PNode = - if x.kind == nkHiddenDeref: + # These synthesized addresses are always passed to codegen procs that expect a + # genuine pointer (nimAsgnYrc, nimSinkYrc, destructors, ...). `addr(deref x)` + # collapses to `x` only when `x` is a real pointer; on the C++ backend a `var` + # parameter is a C++ reference, so we must keep the `nkHiddenAddr` to actually + # take its address (`&dest`) instead of passing the reference's value. Likewise + # `tfVarIsPtr` keeps the C++ backend from lowering the synthesized address back + # to a reference and dropping the `&` (e.g. a closure's `tyPointer` env). See + # #26026 CI (yrc + cpp). + if x.kind == nkHiddenDeref and c.g.config.backend != backendCpp: checkSonsLen(x, 1, c.g.config) result = x[0] else: - result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ, c.idgen)) + let addrTyp = makeVarType(x.typ.owner, x.typ, c.idgen) + addrTyp.incl tfVarIsPtr + result = newNodeIT(nkHiddenAddr, x.info, addrTyp) result.add x proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode = diff --git a/doc/mm.md b/doc/mm.md index 5e0d2f3b94..df3b5b17f0 100644 --- a/doc/mm.md +++ b/doc/mm.md @@ -50,9 +50,23 @@ cycle collector's overhead but `--mm:orc` also produces more machine code than `--mm:arc`, so if you're on a target where code size matters and you know that your code does not produce cycles, you can use `--mm:arc`. Notice that the default `async`:idx: implementation produces cycles -and leaks memory with `--mm:arc`, in other words, for `async` you need to use `--mm:orc`. +and leaks memory with `--mm:arc`, in other words, for `async` you need to use `--mm:orc` +or `--mm:yrc`. +Atomic ARC/YRC +-------------- + +ARC/ORC are not threadsafe if `ref` or other automatically managed types are +accessed across thread boundaries. +Moving isolated subgraphs between threads is supported for ARC/ORC and the language has support +for that in the form of `isolate`. The modes `mm:atomicArc` and `mm:yrc` do offer this thread safety -- at the cost of atomic instructions. Whether that cost is acceptable depends on your program, it hard to give general guidelines. On a modern CPU the potential speedups in the form of increased multi-threading capabilities should outweigh the costs of atomic instructions by far. On an embedded device the atomics would probably only hurt though. + +`mm:atomicArc` is a threadsafe variant of ARC: All the optimizations in the form of move semantics etc are still applied. `mm:yrc` is the threadsafe variant of ORC. + +YRC is a novel concurrent cycle collection algorithm -- these are beasts to verify +and to get correct so there are dragons lurking here, use at your own risk. + Other MM modes -------------- @@ -66,7 +80,7 @@ Other MM modes Heaps are thread-local. --mm:boehm Boehm based garbage collector, it offers a shared heap. --mm:go Go's garbage collector, useful for interoperability with Go. - Offers a shared heap. + Offers a shared heap. Note that `mm:go` has seen little real world use. Use at your own risk. --mm:none No memory management strategy nor a garbage collector. Allocated memory is simply never freed. You should use `--mm:arc` instead. @@ -76,6 +90,7 @@ Here is a comparison of the different memory management modes: ================== ======== ================= ============== ====== =================== =================== Memory Management Heap Reference Cycles Stop-The-World Atomic Valgrind compatible Command line switch ================== ======== ================= ============== ====== =================== =================== +YRC Shared Cycle Collector No Yes Yes `--mm:yrc` ORC Shared Cycle Collector No No Yes `--mm:orc` ARC Shared Leak No No Yes `--mm:arc` Atomic ARC Shared Leak No Yes Yes `--mm:atomicArc`