diff --git a/changelog.md b/changelog.md index aff858818561..a21b23b5d402 100644 --- a/changelog.md +++ b/changelog.md @@ -130,7 +130,7 @@ with other backends. see #9125. Use `-d:nimLegacyJsRound` for previous behavior. - Deprecated `any`. See https://github.com/nim-lang/RFCs/issues/281 -- Added `std/sysrand` module to get random numbers from a secure source +- Added `std/sysrand` module to get random numbers from a secure source provided by the operating system. - Added optional `options` argument to `copyFile`, `copyFileToDir`, and @@ -173,6 +173,12 @@ provided by the operating system. dumping (on select signals) and notifying the parent process about the cause of termination. +- Added `system.prepareStrMutation` for better support of low + level `moveMem`, `copyMem` operations for Orc's copy-on-write string + implementation. + +- `hashes.hash` now supports `object`, but can be overloaded. + - Added `std/strbasics` for high performance string operations. Added `strip`, `setSlice`, `add(a: var string, b: openArray[char])`. diff --git a/lib/std/strbasics.nim b/lib/std/strbasics.nim index 357e562084a8..0ea5a2817411 100644 --- a/lib/std/strbasics.nim +++ b/lib/std/strbasics.nim @@ -80,11 +80,13 @@ func setSlice*(s: var string, slice: Slice[int]) = when not declared(moveMem): impl() else: + when defined(nimSeqsV2): + prepareStrMutation(s) moveMem(addr s[0], addr s[first], last - first + 1) s.setLen(last - first + 1) func strip*(a: var string, leading = true, trailing = true, chars: set[char] = whitespaces) {.inline.} = - ## Inplace version of `strip`. Strips leading or + ## Inplace version of `strip`. Strips leading or ## trailing `chars` (default: whitespace characters). ## ## If `leading` is true (default), leading `chars` are stripped. diff --git a/lib/system.nim b/lib/system.nim index 4b182905b731..6b7549a481c7 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3127,3 +3127,9 @@ export io when not defined(createNimHcr) and not defined(nimscript): include nimhcr + +when notJSnotNims and not defined(nimSeqsV2): + proc prepareStrMutation*(s: var string) {.inline.} = + ## String literals (e.g. "abc", etc) in the ARC/ORC mode are "copy on write", + ## therefore you should call `prepareStrMutation` before modifying the strings. + discard diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim index fe117997bf0a..b20457d511c1 100644 --- a/lib/system/strs_v2.nim +++ b/lib/system/strs_v2.nim @@ -168,3 +168,10 @@ proc nimPrepareStrMutationImpl(s: var NimStringV2) = proc nimPrepareStrMutationV2(s: var NimStringV2) {.compilerRtl, inline.} = if s.p != nil and (s.p.cap and strlitFlag) == strlitFlag: nimPrepareStrMutationImpl(s) + +proc prepareStrMutation*(s: var string) {.inline.} = + # string literals are "copy on write", so you need to call + # `prepareStrMutation` before modifying the strings. + {.cast(noSideEffect).}: + let s = unsafeAddr s + nimPrepareStrMutationV2(cast[ptr NimStringV2](s)[]) diff --git a/tests/arc/t17173.nim b/tests/arc/t17173.nim new file mode 100644 index 000000000000..5d868d9d4c42 --- /dev/null +++ b/tests/arc/t17173.nim @@ -0,0 +1,10 @@ +discard """ + matrix: "--gc:refc; --gc:arc; --newruntime" +""" + +import std/strbasics + + +var a = " vhellov " +strip(a) +doAssert a == "vhellov"