From c2231df8644d276638120571066bb51490741944 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 21 Feb 2026 09:20:34 +0100 Subject: [PATCH] progress --- compiler/semmagic.nim | 2 ++ lib/pure/typetraits.nim | 3 +++ lib/system/seqs_v2.nim | 27 ++++++++++++++++++++------- lib/system/seqs_v2_reimpl.nim | 2 +- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 8a91d820f0..87e085d4fd 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -236,6 +236,8 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) let complexObj = containsGarbageCollectedRef(t) or hasDestructor(t) result = newIntNodeT(toInt128(ord(not complexObj)), traitCall, c.idgen, c.graph) + of "canFormCycles": + result = newIntNodeT(toInt128(ord(types.canFormAcycle(c.graph, operand))), traitCall, c.idgen, c.graph) of "hasDefaultValue": result = newIntNodeT(toInt128(ord(not operand.requiresInit)), traitCall, c.idgen, c.graph) of "isNamedTuple": diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 508181316e..3043754f03 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -96,6 +96,9 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".} ## ## Other languages name a type like these `blob`:idx:. +proc canFormCycles*(t: typedesc): bool {.magic: "TypeTrait".} + ## Returns true if `t` can form cycles. + proc hasDefaultValue*(t: typedesc): bool {.magic: "TypeTrait".} = ## Returns true if `t` has a valid default value. runnableExamples: diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index 5a3e437012..f81ac57d59 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -35,7 +35,18 @@ when defined(gcYrc): lockState = HasNoLock releaseRead gYrcGlobalLock - template yrcMutatorLock*(body: untyped) = + template yrcMutatorLock*(t: typedesc; body: untyped) = + {.noSideEffect.}: + when canFormCycles(t): + acquireMutatorLock() + try: + body + finally: + {.noSideEffect.}: + when canFormCycles(t): + releaseMutatorLock() + + template yrcMutatorLockUntyped(body: untyped) = {.noSideEffect.}: acquireMutatorLock() try: @@ -60,9 +71,11 @@ when defined(gcYrc): lockState = prevState else: - template yrcMutatorLock*(body: untyped) = + template yrcMutatorLock*(t: typedesc; body: untyped) = body + template yrcMutatorLockUntyped(body: untyped) = + body # Some optimizations here may be not to empty-seq-initialize some symbols, then StrictNotNil complains. {.push warning[StrictNotNil]: off.} # See https://github.com/nim-lang/Nim/issues/21401 @@ -174,7 +187,7 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [], noSideEf setLen(x, newLen) else: #sysAssert newLen <= x.len, "invalid newLen parameter for 'shrink'" - yrcMutatorLock: + yrcMutatorLock(T): when not supportsCopyMem(T): for i in countdown(x.len - 1, newLen): reset x[i] @@ -186,7 +199,7 @@ proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} = let oldLen = x.len #sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'" if newLen <= oldLen: return - yrcMutatorLock: + yrcMutatorLock(T): var xu = cast[ptr NimSeqV2[T]](addr x) if xu.p == nil or (xu.p.cap and not strlitFlag) < newLen: xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T))) @@ -206,7 +219,7 @@ proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, n ## Generic code becomes much easier to write if the Nim naming scheme is ## respected. {.cast(noSideEffect).}: - yrcMutatorLock: + yrcMutatorLock(T): let oldLen = x.len var xu = cast[ptr NimSeqV2[T]](addr x) if xu.p == nil or (xu.p.cap and not strlitFlag) < oldLen+1: @@ -223,7 +236,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} = if newlen < s.len: shrink(s, newlen) else: - yrcMutatorLock: + yrcMutatorLock(T): let oldLen = s.len if newlen <= oldLen: return var xu = cast[ptr NimSeqV2[T]](addr s) @@ -270,7 +283,7 @@ func setLenUninit[T](s: var seq[T], newlen: Natural) {.nodestroy.} = if newlen < s.len: shrink(s, newlen) else: - yrcMutatorLock: + yrcMutatorLock(T): let oldLen = s.len if newlen <= oldLen: return var xu = cast[ptr NimSeqV2[T]](addr s) diff --git a/lib/system/seqs_v2_reimpl.nim b/lib/system/seqs_v2_reimpl.nim index 8dc62f3aad..8e1d4383db 100644 --- a/lib/system/seqs_v2_reimpl.nim +++ b/lib/system/seqs_v2_reimpl.nim @@ -18,7 +18,7 @@ type template frees(s: NimSeqV2Reimpl) = if s.p != nil and (s.p.cap and strlitFlag) != strlitFlag: - yrcMutatorLock: + yrcMutatorLockUntyped: when compileOption("threads"): deallocShared(s.p) else: