From 15c6249f2c541d3d8fe5dbcd7a655a1b424420fa Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:41:06 +0800 Subject: [PATCH] replace benign with gcsafe (#25527) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/core/macros.nim | 18 +++++----- lib/pure/random.nim | 12 +++---- lib/pure/times.nim | 44 ++++++++++++------------ lib/std/private/osdirs.nim | 6 ++-- lib/std/syncio.nim | 60 ++++++++++++++++----------------- lib/system.nim | 24 ++++++------- lib/system/alloc.nim | 2 +- lib/system/assign.nim | 12 +++---- lib/system/avltree.nim | 4 +-- lib/system/channels_builtin.nim | 4 +-- lib/system/cyclebreaker.nim | 4 +-- lib/system/deepcopy.nim | 4 +-- lib/system/excpt.nim | 12 +++---- lib/system/gc.nim | 18 +++++----- lib/system/gc_common.nim | 2 +- lib/system/gc_hooks.nim | 2 +- lib/system/gc_interface.nim | 26 +++++++------- lib/system/gc_ms.nim | 12 +++---- lib/system/gc_regions.nim | 4 +-- lib/system/hti.nim | 4 +-- lib/system/jssys.nim | 4 +-- lib/system/memalloc.nim | 38 ++++++++++----------- lib/system/orc.nim | 4 +-- lib/system/repr.nim | 6 ++-- lib/system/yrc.nim | 6 ++-- 25 files changed, 166 insertions(+), 166 deletions(-) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 605df443ec..793ae75a13 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -433,15 +433,15 @@ when defined(nimHasNoReturnError): else: {.pragma: errorNoReturn.} -proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign, errorNoReturn.} +proc error*(msg: string, n: NimNode = nil) {.magic: "NError", gcsafe, errorNoReturn.} ## Writes an error message at compile time. The optional `n: NimNode` ## parameter is used as the source for file and line number information in ## the compilation error message. -proc warning*(msg: string, n: NimNode = nil) {.magic: "NWarning", benign.} +proc warning*(msg: string, n: NimNode = nil) {.magic: "NWarning", gcsafe.} ## Writes a warning message at compile time. -proc hint*(msg: string, n: NimNode = nil) {.magic: "NHint", benign.} +proc hint*(msg: string, n: NimNode = nil) {.magic: "NHint", gcsafe.} ## Writes a hint message at compile time. proc newStrLitNode*(s: string): NimNode {.noSideEffect.} = @@ -511,7 +511,7 @@ proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {. ## Generates a fresh symbol that is guaranteed to be unique. The symbol ## needs to occur in a declaration context. -proc callsite*(): NimNode {.magic: "NCallSite", benign, deprecated: +proc callsite*(): NimNode {.magic: "NCallSite", gcsafe, deprecated: "Deprecated since v0.18.1; use `varargs[untyped]` in the macro prototype instead".} ## Returns the AST of the invocation expression that invoked this macro. # see https://github.com/nim-lang/RFCs/issues/387 as candidate replacement. @@ -933,7 +933,7 @@ proc eqIdent*(a: NimNode; b: NimNode): bool {.magic: "EqIdent", noSideEffect.} const collapseSymChoice = not defined(nimLegacyMacrosCollapseSymChoice) -proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indented = false) {.benign.} = +proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indented = false) {.gcsafe.} = if level > 0: if indented: res.add("\n") @@ -982,21 +982,21 @@ proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indent if isLisp: res.add(")") -proc treeRepr*(n: NimNode): string {.benign.} = +proc treeRepr*(n: NimNode): string {.gcsafe.} = ## Convert the AST `n` to a human-readable tree-like string. ## ## See also `repr`, `lispRepr`_, and `astGenRepr`_. result = "" n.treeTraverse(result, isLisp = false, indented = true) -proc lispRepr*(n: NimNode; indented = false): string {.benign.} = +proc lispRepr*(n: NimNode; indented = false): string {.gcsafe.} = ## Convert the AST `n` to a human-readable lisp-like string. ## ## See also `repr`, `treeRepr`_, and `astGenRepr`_. result = "" n.treeTraverse(result, isLisp = true, indented = indented) -proc astGenRepr*(n: NimNode): string {.benign.} = +proc astGenRepr*(n: NimNode): string {.gcsafe.} = ## Convert the AST `n` to the code required to generate that AST. ## ## See also `repr`_, `treeRepr`_, and `lispRepr`_. @@ -1005,7 +1005,7 @@ proc astGenRepr*(n: NimNode): string {.benign.} = NodeKinds = {nnkEmpty, nnkIdent, nnkSym, nnkNone, nnkCommentStmt} LitKinds = {nnkCharLit..nnkInt64Lit, nnkFloatLit..nnkFloat64Lit, nnkStrLit..nnkTripleStrLit} - proc traverse(res: var string, level: int, n: NimNode) {.benign.} = + proc traverse(res: var string, level: int, n: NimNode) {.gcsafe.} = for i in 0..level-1: res.add " " if n.kind in NodeKinds: res.add("new" & ($n.kind).substr(3) & "Node(") diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 21303fdb64..ec5fef9e4c 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -243,7 +243,7 @@ proc rand[T: uint | uint64](r: var Rand; max: T): T = else: inc iters -proc rand*(r: var Rand; max: Natural): int {.benign.} = +proc rand*(r: var Rand; max: Natural): int {.gcsafe.} = ## Returns a random integer in the range `0..max` using the given state. ## ## **See also:** @@ -260,7 +260,7 @@ proc rand*(r: var Rand; max: Natural): int {.benign.} = cast[int](rand(r, uint64(max))) # xxx toUnsigned pending https://github.com/nim-lang/Nim/pull/18445 -proc rand*(max: int): int {.benign.} = +proc rand*(max: int): int {.gcsafe.} = ## Returns a random integer in the range `0..max`. ## ## If `randomize <#randomize>`_ has not been called, the sequence of random @@ -281,7 +281,7 @@ proc rand*(max: int): int {.benign.} = rand(state, max) -proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} = +proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.gcsafe.} = ## Returns a random floating point number in the range `0.0..max` ## using the given state. ## @@ -308,7 +308,7 @@ proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} = let u = (0x3FFu64 shl 52u64) or (x shr 12u64) result = (cast[float](u) - 1.0) * max -proc rand*(max: float): float {.benign.} = +proc rand*(max: float): float {.gcsafe.} = ## Returns a random floating point number in the range `0.0..max`. ## ## If `randomize <#randomize>`_ has not been called, the sequence of random @@ -612,7 +612,7 @@ proc initRand*(seed: int64): Rand = skipRandomNumbers(result) discard next(result) -proc randomize*(seed: int64) {.benign.} = +proc randomize*(seed: int64) {.gcsafe.} = ## Initializes the default random number generator with the given seed. ## ## Providing a specific seed will produce the same results for that seed each time. @@ -736,7 +736,7 @@ when not defined(standalone): since (1, 5, 1): export initRand - proc randomize*() {.benign.} = + proc randomize*() {.gcsafe.} = ## Initializes the default random number generator with a seed based on ## random number source. ## diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 3cdd3903c9..2951ac6cdb 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -382,9 +382,9 @@ type ## timezones. The `times` module only supplies implementations for the ## system's local time and UTC. zonedTimeFromTimeImpl: proc (x: Time): ZonedTime - {.tags: [], raises: [], benign.} + {.tags: [], raises: [], gcsafe.} zonedTimeFromAdjTimeImpl: proc (x: Time): ZonedTime - {.tags: [], raises: [], benign.} + {.tags: [], raises: [], gcsafe.} name: string ZonedTime* = object ## Represents a point in time with an associated @@ -432,7 +432,7 @@ else: # Helper procs # -{.pragma: operator, rtl, noSideEffect, benign.} +{.pragma: operator, rtl, noSideEffect, gcsafe.} proc convert*[T: SomeInteger](unitFrom, unitTo: FixedTimeUnit, quantity: T): T {.inline.} = @@ -518,7 +518,7 @@ proc fromEpochDay(epochday: int64): return (d.MonthdayRange, m.Month, (y + ord(m <= 2)).int) proc getDayOfYear*(monthday: MonthdayRange, month: Month, year: int): - YeardayRange {.tags: [], raises: [], benign.} = + YeardayRange {.tags: [], raises: [], gcsafe.} = ## Returns the day of the year. ## Equivalent with `dateTime(year, month, monthday, 0, 0, 0, 0).yearday`. runnableExamples: @@ -538,7 +538,7 @@ proc getDayOfYear*(monthday: MonthdayRange, month: Month, year: int): result = daysUntilMonth[month] + monthday - 1 proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay - {.tags: [], raises: [], benign.} = + {.tags: [], raises: [], gcsafe.} = ## Returns the day of the week enum from day, month and year. ## Equivalent with `dateTime(year, month, monthday, 0, 0, 0, 0).weekday`. runnableExamples: @@ -922,21 +922,21 @@ proc nanosecond*(time: Time): NanosecondRange = time.nanosecond proc fromUnix*(unix: int64): Time - {.benign, tags: [], raises: [], noSideEffect.} = + {.gcsafe, tags: [], raises: [], noSideEffect.} = ## Convert a unix timestamp (seconds since `1970-01-01T00:00:00Z`) ## to a `Time`. runnableExamples: doAssert $fromUnix(0).utc == "1970-01-01T00:00:00Z" initTime(unix, 0) -proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} = +proc toUnix*(t: Time): int64 {.gcsafe, tags: [], raises: [], noSideEffect.} = ## Convert `t` to a unix timestamp (seconds since `1970-01-01T00:00:00Z`). ## See also `toUnixFloat` for subsecond resolution. runnableExamples: doAssert fromUnix(0).toUnix() == 0 t.seconds -proc fromUnixFloat(seconds: float): Time {.benign, tags: [], raises: [], noSideEffect.} = +proc fromUnixFloat(seconds: float): Time {.gcsafe, tags: [], raises: [], noSideEffect.} = ## Convert a unix timestamp in seconds to a `Time`; same as `fromUnix` ## but with subsecond resolution. runnableExamples: @@ -946,7 +946,7 @@ proc fromUnixFloat(seconds: float): Time {.benign, tags: [], raises: [], noSideE let nsecs = (seconds - secs) * 1e9 initTime(secs.int64, nsecs.NanosecondRange) -proc toUnixFloat(t: Time): float {.benign, tags: [], raises: [].} = +proc toUnixFloat(t: Time): float {.gcsafe, tags: [], raises: [].} = ## Same as `toUnix` but using subsecond resolution. runnableExamples: let t = getTime() @@ -975,7 +975,7 @@ proc toWinTime*(t: Time): int64 = proc getTimeImpl(typ: typedesc[Time]): Time = raiseAssert "implemented in the vm" -proc getTime*(): Time {.tags: [TimeEffect], benign.} = +proc getTime*(): Time {.tags: [TimeEffect], gcsafe.} = ## Gets the current time as a `Time` with up to nanosecond resolution. when nimvm: result = getTimeImpl(Time) @@ -1154,7 +1154,7 @@ proc isLeapDay*(dt: DateTime): bool {.since: (1, 1).} = assertDateTimeInitialized dt dt.year.isLeapYear and dt.month == mFeb and dt.monthday == 29 -proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} = +proc toTime*(dt: DateTime): Time {.tags: [], raises: [], gcsafe.} = ## Converts a `DateTime` to a `Time` representing the same point in time. assertDateTimeInitialized dt let epochDay = toEpochDay(dt.monthday, dt.month, dt.year) @@ -1197,9 +1197,9 @@ proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime = proc newTimezone*( name: string, zonedTimeFromTimeImpl: proc (time: Time): ZonedTime - {.tags: [], raises: [], benign.}, + {.tags: [], raises: [], gcsafe.}, zonedTimeFromAdjTimeImpl: proc (adjTime: Time): ZonedTime - {.tags: [], raises: [], benign.} + {.tags: [], raises: [], gcsafe.} ): owned Timezone = ## Create a new `Timezone`. ## @@ -1263,12 +1263,12 @@ proc `==`*(zone1, zone2: Timezone): bool = zone1.name == zone2.name proc inZone*(time: Time, zone: Timezone): DateTime - {.tags: [], raises: [], benign.} = + {.tags: [], raises: [], gcsafe.} = ## Convert `time` into a `DateTime` using `zone` as the timezone. result = initDateTime(zone.zonedTimeFromTime(time), zone) proc inZone*(dt: DateTime, zone: Timezone): DateTime - {.tags: [], raises: [], benign.} = + {.tags: [], raises: [], gcsafe.} = ## Returns a `DateTime` representing the same point in time as `dt` but ## using `zone` as the timezone. assertDateTimeInitialized dt @@ -1283,14 +1283,14 @@ proc toAdjTime(dt: DateTime): Time = result = initTime(seconds, dt.nanosecond) when defined(js): - proc localZonedTimeFromTime(time: Time): ZonedTime {.benign.} = + proc localZonedTimeFromTime(time: Time): ZonedTime {.gcsafe.} = let jsDate = newDate(time.seconds * 1000) let offset = jsDate.getTimezoneOffset() * secondsInMin result.time = time result.utcOffset = offset result.isDst = false - proc localZonedTimeFromAdjTime(adjTime: Time): ZonedTime {.benign.} = + proc localZonedTimeFromAdjTime(adjTime: Time): ZonedTime {.gcsafe.} = let utcDate = newDate(adjTime.seconds * 1000) let localDate = newDate(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate(), utcDate.getUTCHours(), utcDate.getUTCMinutes(), @@ -1337,11 +1337,11 @@ else: return ((a.int64 - tm.toAdjUnix).int, tm.tm_isdst > 0) return (0, false) - proc localZonedTimeFromTime(time: Time): ZonedTime {.benign.} = + proc localZonedTimeFromTime(time: Time): ZonedTime {.gcsafe.} = let (offset, dst) = getLocalOffsetAndDst(time.seconds) result = ZonedTime(time: time, utcOffset: offset, isDst: dst) - proc localZonedTimeFromAdjTime(adjTime: Time): ZonedTime {.benign.} = + proc localZonedTimeFromAdjTime(adjTime: Time): ZonedTime {.gcsafe.} = var adjUnix = adjTime.seconds let past = adjUnix - secondsInDay let (pastOffset, _) = getLocalOffsetAndDst(past) @@ -1408,7 +1408,7 @@ proc local*(t: Time): DateTime = ## Shorthand for `t.inZone(local())`. t.inZone(local()) -proc now*(): DateTime {.tags: [TimeEffect], benign.} = +proc now*(): DateTime {.tags: [TimeEffect], gcsafe.} = ## Get the current time as a `DateTime` in the local timezone. ## Shorthand for `getTime().local`. ## @@ -2327,7 +2327,7 @@ proc parseTime*(input: string, f: static[string], zone: Timezone): Time const f2 = initTimeFormat(f) result = input.parse(f2, zone).toTime() -proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} = +proc `$`*(dt: DateTime): string {.tags: [], raises: [], gcsafe.} = ## Converts a `DateTime` object to a string representation. ## It uses the format `yyyy-MM-dd'T'HH:mm:sszzz`. runnableExamples: @@ -2339,7 +2339,7 @@ proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} = else: result = format(dt, "yyyy-MM-dd'T'HH:mm:sszzz") -proc `$`*(time: Time): string {.tags: [], raises: [], benign.} = +proc `$`*(time: Time): string {.tags: [], raises: [], gcsafe.} = ## Converts a `Time` value to a string representation. It will use the local ## time zone and use the format `yyyy-MM-dd'T'HH:mm:sszzz`. runnableExamples: diff --git a/lib/std/private/osdirs.nim b/lib/std/private/osdirs.nim index 5c6aa3e4d9..5c8ca2f432 100644 --- a/lib/std/private/osdirs.nim +++ b/lib/std/private/osdirs.nim @@ -331,7 +331,7 @@ proc rawRemoveDir(dir: string) {.noWeirdTarget.} = if rmdir(dir) != 0'i32 and errno != ENOENT: raiseOSError(osLastError(), dir) proc removeDir*(dir: string, checkDir = false) {.rtl, extern: "nos$1", tags: [ - WriteDirEffect, ReadDirEffect], benign, noWeirdTarget.} = + WriteDirEffect, ReadDirEffect], gcsafe, noWeirdTarget.} = ## Removes the directory `dir` including all subdirectories and files ## in `dir` (recursively). ## @@ -441,7 +441,7 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", discard existsOrCreateDir(p) proc copyDir*(source, dest: string, skipSpecial = false) {.rtl, extern: "nos$1", - tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], benign, noWeirdTarget.} = + tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], gcsafe, noWeirdTarget.} = ## Copies a directory from `source` to `dest`. ## ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks @@ -482,7 +482,7 @@ proc copyDirWithPermissions*(source, dest: string, ignorePermissionErrors = true, skipSpecial = false) {.rtl, extern: "nos$1", tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], - benign, noWeirdTarget.} = + gcsafe, noWeirdTarget.} = ## Copies a directory from `source` to `dest` preserving file permissions. ## ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim index 2aafb40e93..164b35666a 100644 --- a/lib/std/syncio.nim +++ b/lib/std/syncio.nim @@ -182,7 +182,7 @@ proc checkErr(f: File) = {.push stackTrace: off, profiler: off.} proc readBuffer*(f: File, buffer: pointer, len: Natural): int {. - tags: [ReadIOEffect], benign.} = + tags: [ReadIOEffect], gcsafe.} = ## Reads `len` bytes into the buffer pointed to by `buffer`. Returns ## the actual number of bytes that have been read which may be less than ## `len` (if not as many bytes are remaining), but not greater. @@ -191,20 +191,20 @@ proc readBuffer*(f: File, buffer: pointer, len: Natural): int {. proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {. - tags: [ReadIOEffect], benign.} = + tags: [ReadIOEffect], gcsafe.} = ## Reads `len` bytes into the buffer `a` starting at `a[start]`. Returns ## the actual number of bytes that have been read which may be less than ## `len` (if not as many bytes are remaining), but not greater. result = readBuffer(f, addr(a[start]), len) -proc readChars*(f: File, a: var openArray[char]): int {.tags: [ReadIOEffect], benign.} = +proc readChars*(f: File, a: var openArray[char]): int {.tags: [ReadIOEffect], gcsafe.} = ## Reads up to `a.len` bytes into the buffer `a`. Returns ## the actual number of bytes that have been read which may be less than ## `a.len` (if not as many bytes are remaining), but not greater. result = readBuffer(f, addr(a[0]), a.len) proc readChars*(f: File, a: var openArray[char], start, len: Natural): int {. - tags: [ReadIOEffect], benign, deprecated: + tags: [ReadIOEffect], gcsafe, deprecated: "use other `readChars` overload, possibly via: readChars(toOpenArray(buf, start, len-1))".} = ## Reads `len` bytes into the buffer `a` starting at `a[start]`. Returns ## the actual number of bytes that have been read which may be less than @@ -213,13 +213,13 @@ proc readChars*(f: File, a: var openArray[char], start, len: Natural): int {. raiseEIO("buffer overflow: (start+len) > length of openarray buffer") result = readBuffer(f, addr(a[start]), len) -proc write*(f: File, c: cstring) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, c: cstring) {.tags: [WriteIOEffect], gcsafe.} = ## Writes a value to the file `f`. May throw an IO exception. discard c_fputs(c, f) checkErr(f) proc writeBuffer*(f: File, buffer: pointer, len: Natural): int {. - tags: [WriteIOEffect], benign.} = + tags: [WriteIOEffect], gcsafe.} = ## Writes the bytes of buffer pointed to by the parameter `buffer` to the ## file `f`. Returns the number of actual written bytes, which may be less ## than `len` in case of an error. @@ -227,7 +227,7 @@ proc writeBuffer*(f: File, buffer: pointer, len: Natural): int {. checkErr(f) proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: Natural): int {. - tags: [WriteIOEffect], benign.} = + tags: [WriteIOEffect], gcsafe.} = ## Writes the bytes of `a[start..start+len-1]` to the file `f`. Returns ## the number of actual written bytes, which may be less than `len` in case ## of an error. @@ -235,7 +235,7 @@ proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: Natural): int {. result = writeBuffer(f, addr(x[int(start)]), len) proc writeChars*(f: File, a: openArray[char], start, len: Natural): int {. - tags: [WriteIOEffect], benign.} = + tags: [WriteIOEffect], gcsafe.} = ## Writes the bytes of `a[start..start+len-1]` to the file `f`. Returns ## the number of actual written bytes, which may be less than `len` in case ## of an error. @@ -264,7 +264,7 @@ when defined(windows): break inc i, w -proc write*(f: File, s: string) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, s: string) {.tags: [WriteIOEffect], gcsafe.} = when defined(windows): writeWindows(f, s, doRaise = true) else: @@ -393,7 +393,7 @@ when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(w inheritable.WinDWORD) != 0 proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect], - benign.} = + gcsafe.} = ## Reads a line of text from the file `f` into `line`. May throw an IO ## exception. ## A line of text may be delimited by `LF` or `CRLF`. The newline @@ -519,43 +519,43 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect], sp = 128 # read in 128 bytes at a time line.setLen(pos+sp) -proc readLine*(f: File): string {.tags: [ReadIOEffect], benign.} = +proc readLine*(f: File): string {.tags: [ReadIOEffect], gcsafe.} = ## Reads a line of text from the file `f`. May throw an IO exception. ## A line of text may be delimited by `LF` or `CRLF`. The newline ## character(s) are not part of the returned string. result = newStringOfCap(80) if not readLine(f, result): raiseEOF() -proc write*(f: File, i: int) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, i: int) {.tags: [WriteIOEffect], gcsafe.} = when sizeof(int) == 8: if c_fprintf(f, "%lld", i) < 0: checkErr(f) else: if c_fprintf(f, "%ld", i) < 0: checkErr(f) -proc write*(f: File, i: BiggestInt) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, i: BiggestInt) {.tags: [WriteIOEffect], gcsafe.} = when sizeof(BiggestInt) == 8: if c_fprintf(f, "%lld", i) < 0: checkErr(f) else: if c_fprintf(f, "%ld", i) < 0: checkErr(f) -proc write*(f: File, b: bool) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, b: bool) {.tags: [WriteIOEffect], gcsafe.} = if b: write(f, "true") else: write(f, "false") -proc write*(f: File, r: float32) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, r: float32) {.tags: [WriteIOEffect], gcsafe.} = var buffer {.noinit.}: array[65, char] discard writeFloatToBuffer(buffer, r) if c_fprintf(f, "%s", buffer[0].addr) < 0: checkErr(f) -proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], gcsafe.} = var buffer {.noinit.}: array[65, char] discard writeFloatToBuffer(buffer, r) if c_fprintf(f, "%s", buffer[0].addr) < 0: checkErr(f) -proc write*(f: File, c: char) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, c: char) {.tags: [WriteIOEffect], gcsafe.} = discard c_putc(cint(c), f) -proc write*(f: File, a: varargs[string, `$`]) {.tags: [WriteIOEffect], benign.} = +proc write*(f: File, a: varargs[string, `$`]) {.tags: [WriteIOEffect], gcsafe.} = for x in items(a): write(f, x) proc readAllBuffer(file: File): string = @@ -579,7 +579,7 @@ proc rawFileSize(file: File): int64 = result = c_ftell(file) discard c_fseek(file, oldPos, 0) -proc endOfFile*(f: File): bool {.tags: [], benign.} = +proc endOfFile*(f: File): bool {.tags: [], gcsafe.} = ## Returns true if `f` is at the end. var c = c_fgetc(f) discard c_ungetc(c, f) @@ -603,7 +603,7 @@ proc readAllFile(file: File): string = var len = rawFileSize(file) result = readAllFile(file, len) -proc readAll*(file: File): string {.tags: [ReadIOEffect], benign.} = +proc readAll*(file: File): string {.tags: [ReadIOEffect], gcsafe.} = ## Reads all data from the stream `file`. ## ## Raises an IO exception in case of an error. It is an error if the @@ -621,7 +621,7 @@ proc readAll*(file: File): string {.tags: [ReadIOEffect], benign.} = result = readAllBuffer(file) proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, - tags: [WriteIOEffect], benign.} = + tags: [WriteIOEffect], gcsafe.} = ## Writes the values `x` to `f` and then writes "\\n". ## May throw an IO exception. for i in items(x): @@ -713,7 +713,7 @@ when defined(posix) and not defined(nimscript): proc open*(f: var File, filename: string, mode: FileMode = fmRead, - bufSize: int = -1): bool {.tags: [], raises: [], benign.} = + bufSize: int = -1): bool {.tags: [], raises: [], gcsafe.} = ## Opens a file named `filename` with given `mode`. ## ## Default mode is readonly. Returns true if the file could be opened. @@ -747,7 +747,7 @@ proc open*(f: var File, filename: string, result = false proc reopen*(f: File, filename: string, mode: FileMode = fmRead): bool {. - tags: [], benign.} = + tags: [], gcsafe.} = ## Reopens the file `f` with given `filename` and `mode`. This ## is often used to redirect the `stdin`, `stdout` or `stderr` ## file variables. @@ -766,7 +766,7 @@ proc reopen*(f: File, filename: string, mode: FileMode = fmRead): bool {. result = false proc open*(f: var File, filehandle: FileHandle, - mode: FileMode = fmRead): bool {.tags: [], raises: [], benign.} = + mode: FileMode = fmRead): bool {.tags: [], raises: [], gcsafe.} = ## Creates a `File` from a `filehandle` with given `mode`. ## ## Default mode is readonly. Returns true if the file could be opened. @@ -792,26 +792,26 @@ proc open*(filename: string, if not open(result, filename, mode, bufSize): raise newException(IOError, "cannot open: " & filename) -proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.benign, sideEffect.} = +proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.gcsafe, sideEffect.} = ## Sets the position of the file pointer that is used for read/write ## operations. The file's first byte has the index zero. if c_fseek(f, pos, cint(relativeTo)) != 0: raiseEIO("cannot set file position") -proc getFilePos*(f: File): int64 {.benign.} = +proc getFilePos*(f: File): int64 {.gcsafe.} = ## Retrieves the current position of the file pointer that is used to ## read from the file `f`. The file's first byte has the index zero. result = c_ftell(f) if result < 0: raiseEIO("cannot retrieve file position") -proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.} = +proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], gcsafe.} = ## Retrieves the file size (in bytes) of `f`. let oldPos = getFilePos(f) discard c_fseek(f, 0, 2) # seek the end of the file result = getFilePos(f) setFilePos(f, oldPos) -proc setStdIoUnbuffered*() {.tags: [], benign.} = +proc setStdIoUnbuffered*() {.tags: [], gcsafe.} = ## Configures `stdin`, `stdout` and `stderr` to be unbuffered. when declared(stdout): discard c_setvbuf(stdout, nil, IONBF, 0) @@ -865,7 +865,7 @@ when defined(windows) and appType == "console" and discard setConsoleCP(Utf8codepage) addExitProc(restoreConsoleCP) -proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.} = +proc readFile*(filename: string): string {.tags: [ReadIOEffect], gcsafe.} = ## Opens a file named `filename` for reading, calls `readAll ## <#readAll,File>`_ and closes the file afterwards. Returns the string. ## Raises an IO exception in case of an error. If you need to call @@ -880,7 +880,7 @@ proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.} = else: raise newException(IOError, "cannot open: " & filename) -proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} = +proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], gcsafe.} = ## Opens a file named `filename` for writing. Then writes the ## `content` completely to the file and closes the file afterwards. ## Raises an IO exception in case of an error. diff --git a/lib/system.nim b/lib/system.nim index 6104c1b928..27e7a04320 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1147,7 +1147,7 @@ template sysAssert(cond: bool, msg: string) = const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) when notJSnotNims and hasAlloc and not defined(nimSeqsV2): - proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.} + proc addChar(s: NimString, c: char): NimString {.compilerproc, gcsafe.} when defined(nimscript) or not defined(nimSeqsV2): proc add*[T](x: var seq[T], y: sink T) {.magic: "AppendSeqElem", noSideEffect.} @@ -1664,7 +1664,7 @@ when not defined(js) and hasThreadSupport and hostOS != "standalone": when not defined(js) and defined(nimV2): type - DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].} + DestructorProc = proc (p: pointer) {.nimcall, gcsafe, raises: [].} TNimTypeV2 {.compilerproc.} = object destructor: pointer size: int @@ -1776,7 +1776,7 @@ when not defined(nimscript): when not declared(sysFatal): include "system/fatal" -proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", benign, sideEffect.} +proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", gcsafe, sideEffect.} ## Writes and flushes the parameters to the standard output. ## ## Special built-in that takes a variable number of arguments. Each argument @@ -1883,7 +1883,7 @@ when notJSnotNims: ## lead to the `raise` statement. This only works for debug builds. var - globalRaiseHook*: proc (e: ref Exception): bool {.nimcall, benign.} + globalRaiseHook*: proc (e: ref Exception): bool {.nimcall, gcsafe.} ## With this hook you can influence exception handling on a global level. ## If not nil, every 'raise' statement ends up calling this hook. ## @@ -1892,7 +1892,7 @@ when notJSnotNims: ## If `globalRaiseHook` returns false, the exception is caught and does ## not propagate further through the call stack. - localRaiseHook* {.threadvar.}: proc (e: ref Exception): bool {.nimcall, benign.} + localRaiseHook* {.threadvar.}: proc (e: ref Exception): bool {.nimcall, gcsafe.} ## With this hook you can influence exception handling on a ## thread local level. ## If not nil, every 'raise' statement ends up calling this hook. @@ -1902,7 +1902,7 @@ when notJSnotNims: ## If `localRaiseHook` returns false, the exception ## is caught and does not propagate further through the call stack. - outOfMemHook*: proc () {.nimcall, tags: [], benign, raises: [].} + outOfMemHook*: proc () {.nimcall, tags: [], gcsafe, raises: [].} ## Set this variable to provide a procedure that should be called ## in case of an `out of memory`:idx: event. The standard handler ## writes an error message and terminates the program. @@ -1923,7 +1923,7 @@ when notJSnotNims: ## If the handler does not raise an exception, ordinary control flow ## continues and the program is terminated. - unhandledExceptionHook*: proc (e: ref Exception) {.nimcall, tags: [], benign, raises: [].} + unhandledExceptionHook*: proc (e: ref Exception) {.nimcall, tags: [], gcsafe, raises: [].} ## Set this variable to provide a procedure that should be called ## in case of an `unhandle exception` event. The standard handler ## writes an error message and terminates the program, except when @@ -2066,7 +2066,7 @@ when hostOS == "standalone" and defined(nogc): if s == nil or s.len == 0: result = cstring"" else: result = cast[cstring](addr s.data) -proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.} +proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe.} ## Get type information for `x`. ## ## Ordinary code should not use this, but the `typeinfo module @@ -2285,21 +2285,21 @@ when not defined(js) and declared(alloc0) and declared(dealloc): dealloc(a) when notJSnotNims and hostOS != "standalone": - proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} = + proc getCurrentException*(): ref Exception {.compilerRtl, inl, gcsafe.} = ## Retrieves the current exception; if there is none, `nil` is returned. result = currException - proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, benign, nodestroy.} = + proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, gcsafe, nodestroy.} = # .nodestroy here so that we do not produce a write barrier as the # C codegen only uses it in a borrowed way: result = currException - proc getCurrentExceptionMsg*(): string {.inline, benign.} = + proc getCurrentExceptionMsg*(): string {.inline, gcsafe.} = ## Retrieves the error message that was attached to the current ## exception; if there is none, `""` is returned. return if currException == nil: "" else: currException.msg - proc setCurrentException*(exc: ref Exception) {.inline, benign.} = + proc setCurrentException*(exc: ref Exception) {.inline, gcsafe.} = ## Sets the current exception. ## ## .. warning:: Only use this if you know what you are doing. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index a23702dc1f..1c2706120e 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -725,7 +725,7 @@ proc getSmallChunk(a: var MemRegion): PSmallChunk = # ----------------------------------------------------------------------------- when not defined(gcDestructors): - proc isAllocatedPtr(a: MemRegion, p: pointer): bool {.benign.} + proc isAllocatedPtr(a: MemRegion, p: pointer): bool {.gcsafe.} when true: template allocInv(a: MemRegion): bool = true diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 9f4cbc0feb..0955222ec1 100644 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -9,11 +9,11 @@ include seqs_v2_reimpl -proc genericResetAux(dest: pointer, n: ptr TNimNode) {.benign.} +proc genericResetAux(dest: pointer, n: ptr TNimNode) {.gcsafe.} -proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.benign.} +proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.gcsafe.} proc genericAssignAux(dest, src: pointer, n: ptr TNimNode, - shallow: bool) {.benign.} = + shallow: bool) {.gcsafe.} = var d = cast[int](dest) s = cast[int](src) @@ -187,8 +187,8 @@ proc genericAssignOpenArray(dest, src: pointer, len: int, genericAssign(cast[pointer](d +% i *% mt.base.size), cast[pointer](s +% i *% mt.base.size), mt.base) -proc objectInit(dest: pointer, typ: PNimType) {.compilerproc, benign.} -proc objectInitAux(dest: pointer, n: ptr TNimNode) {.benign.} = +proc objectInit(dest: pointer, typ: PNimType) {.compilerproc, gcsafe.} +proc objectInitAux(dest: pointer, n: ptr TNimNode) {.gcsafe.} = var d = cast[int](dest) case n.kind of nkNone: sysAssert(false, "objectInitAux") @@ -224,7 +224,7 @@ proc objectInit(dest: pointer, typ: PNimType) = # ---------------------- assign zero ----------------------------------------- -proc genericReset(dest: pointer, mt: PNimType) {.compilerproc, benign.} +proc genericReset(dest: pointer, mt: PNimType) {.compilerproc, gcsafe.} proc genericResetAux(dest: pointer, n: ptr TNimNode) = var d = cast[int](dest) case n.kind diff --git a/lib/system/avltree.nim b/lib/system/avltree.nim index 8d4b7e8974..b9020565a5 100644 --- a/lib/system/avltree.nim +++ b/lib/system/avltree.nim @@ -51,7 +51,7 @@ proc split(t: var PAvlNode) = t.link[0] = temp inc t.level -proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} = +proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.gcsafe.} = if t.isBottom: t = allocAvlNode(a, key, upperBound) else: @@ -70,7 +70,7 @@ proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} = skew(t) split(t) -proc del(a: var MemRegion, t: var PAvlNode, x: int) {.benign.} = +proc del(a: var MemRegion, t: var PAvlNode, x: int) {.gcsafe.} = if isBottom(t): return a.last = t if x <% t.key: diff --git a/lib/system/channels_builtin.nim b/lib/system/channels_builtin.nim index 2123707301..9534c9b45e 100644 --- a/lib/system/channels_builtin.nim +++ b/lib/system/channels_builtin.nim @@ -181,10 +181,10 @@ proc deinitRawChannel(p: pointer) = when not usesDestructors: proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, - mode: LoadStoreMode) {.benign.} + mode: LoadStoreMode) {.gcsafe.} proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel, - mode: LoadStoreMode) {.benign.} = + mode: LoadStoreMode) {.gcsafe.} = var d = cast[int](dest) s = cast[int](src) diff --git a/lib/system/cyclebreaker.nim b/lib/system/cyclebreaker.nim index d611322d96..9ee8a98305 100644 --- a/lib/system/cyclebreaker.nim +++ b/lib/system/cyclebreaker.nim @@ -62,8 +62,8 @@ const colorMask = 0b011 type - TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].} - DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].} + TraceProc = proc (p, env: pointer) {.nimcall, gcsafe, raises: [].} + DisposeProc = proc (p: pointer) {.nimcall, gcsafe, raises: [].} template color(c): untyped = c.rc and colorMask template setColor(c, col) = diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 0f7d0eaae2..fdf1499e5f 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -58,9 +58,9 @@ proc put(t: var PtrTable; key, val: pointer) = inc t.counter proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; - tab: var PtrTable) {.benign.} + tab: var PtrTable) {.gcsafe.} proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode; - tab: var PtrTable) {.benign.} = + tab: var PtrTable) {.gcsafe.} = var d = cast[int](dest) s = cast[int](src) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 12552515cc..0218190607 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -16,7 +16,7 @@ import stacktraces const noStacktraceAvailable = "No stack traceback available\n" var - errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign, + errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], gcsafe, nimcall, raises: [].}) ## Function that will be called ## instead of `stdmsg.write` when printing stacktrace. @@ -61,10 +61,10 @@ proc showErrorMessage2(data: string) {.inline.} = # TODO showErrorMessage will turn it back to a string when a hook is set (!) showErrorMessage(data.cstring, data.len) -proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.} -proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.} -proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.} -proc chckNil(p: pointer) {.noinline, compilerproc, benign.} +proc chckIndx(i, a, b: int): int {.inline, compilerproc, gcsafe.} +proc chckRange(i, a, b: int): int {.inline, compilerproc, gcsafe.} +proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.} +proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.} type GcFrame = ptr GcFrameHeader @@ -653,7 +653,7 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and rawQuit 1 when not defined(noSignalHandler) and not defined(useNimRtl): - type Sighandler = proc (a: cint) {.noconv, benign.} + type Sighandler = proc (a: cint) {.noconv, gcsafe.} # xxx factor with ansi_c.CSighandlerT, posix.Sighandler proc signalHandler(sign: cint) {.exportc: "signalHandler", noconv, raises: [].} = diff --git a/lib/system/gc.nim b/lib/system/gc.nim index bc199b8351..861e0704f5 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -76,7 +76,7 @@ const when withRealTime and not declared(getTicks): include "system/timers" when defined(memProfiler): - proc nimProfile(requestedSize: int) {.benign.} + proc nimProfile(requestedSize: int) {.gcsafe.} when hasThreadSupport: import std/sharedlist @@ -97,7 +97,7 @@ type waZctDecRef, waPush #, waDebug - Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.} + Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, gcsafe, raises: [].} # A ref type can have a finalizer that is called before the object's # storage is freed. @@ -222,11 +222,11 @@ template gcTrace(cell, state: untyped) = when traceGC: traceCell(cell, state) # forward declarations: -proc collectCT(gch: var GcHeap) {.benign, raises: [].} -proc isOnStack(p: pointer): bool {.noinline, benign, raises: [].} -proc forAllChildren(cell: PCell, op: WalkOp) {.benign, raises: [].} -proc doOperation(p: pointer, op: WalkOp) {.benign, raises: [].} -proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign, raises: [].} +proc collectCT(gch: var GcHeap) {.gcsafe, raises: [].} +proc isOnStack(p: pointer): bool {.noinline, gcsafe, raises: [].} +proc forAllChildren(cell: PCell, op: WalkOp) {.gcsafe, raises: [].} +proc doOperation(p: pointer, op: WalkOp) {.gcsafe, raises: [].} +proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.gcsafe, raises: [].} # we need the prototype here for debugging purposes proc incRef(c: PCell) {.inline.} = @@ -338,7 +338,7 @@ proc cellsetReset(s: var CellSet) = {.push stacktrace:off.} -proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} = +proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.gcsafe.} = var d = cast[int](dest) case n.kind of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op) @@ -687,7 +687,7 @@ proc doOperation(p: pointer, op: WalkOp) = proc nimGCvisit(d: pointer, op: int) {.compilerRtl, raises: [].} = doOperation(d, WalkOp(op)) -proc collectZCT(gch: var GcHeap): bool {.benign, raises: [].} +proc collectZCT(gch: var GcHeap): bool {.gcsafe, raises: [].} proc collectCycles(gch: var GcHeap) {.raises: [].} = when hasThreadSupport: diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index eb08845603..08e8798b08 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -457,7 +457,7 @@ proc deallocHeap*(runFinalizers = true; allowGcAfterwards = true) = initGC() type - GlobalMarkerProc = proc () {.nimcall, benign, raises: [].} + GlobalMarkerProc = proc () {.nimcall, gcsafe, raises: [].} var globalMarkersLen {.exportc.}: int globalMarkers {.exportc.}: array[0..3499, GlobalMarkerProc] diff --git a/lib/system/gc_hooks.nim b/lib/system/gc_hooks.nim index 936b31b20a..a8ecdd2f51 100644 --- a/lib/system/gc_hooks.nim +++ b/lib/system/gc_hooks.nim @@ -11,7 +11,7 @@ ## collectors etc. type - GlobalMarkerProc = proc () {.nimcall, benign, raises: [], tags: [].} + GlobalMarkerProc = proc () {.nimcall, gcsafe, raises: [], tags: [].} var globalMarkersLen: int globalMarkers: array[0..3499, GlobalMarkerProc] diff --git a/lib/system/gc_interface.nim b/lib/system/gc_interface.nim index b34ce4a566..256efbe547 100644 --- a/lib/system/gc_interface.nim +++ b/lib/system/gc_interface.nim @@ -12,7 +12,7 @@ when hasAlloc: gcOptimizeSpace ## optimize for memory footprint when hasAlloc and not defined(js) and not usesDestructors: - proc GC_disable*() {.rtl, inl, benign, raises: [].} + proc GC_disable*() {.rtl, inl, gcsafe, raises: [].} ## Disables the GC. If called `n` times, `n` calls to `GC_enable` ## are needed to reactivate the GC. ## @@ -20,39 +20,39 @@ when hasAlloc and not defined(js) and not usesDestructors: ## the mark and sweep phase with ## `GC_disableMarkAndSweep <#GC_disableMarkAndSweep>`_. - proc GC_enable*() {.rtl, inl, benign, raises: [].} + proc GC_enable*() {.rtl, inl, gcsafe, raises: [].} ## Enables the GC again. - proc GC_fullCollect*() {.rtl, benign, raises: [].} + proc GC_fullCollect*() {.rtl, gcsafe, raises: [].} ## Forces a full garbage collection pass. ## Ordinary code does not need to call this (and should not). - proc GC_enableMarkAndSweep*() {.rtl, benign, raises: [].} - proc GC_disableMarkAndSweep*() {.rtl, benign, raises: [].} + proc GC_enableMarkAndSweep*() {.rtl, gcsafe, raises: [].} + proc GC_disableMarkAndSweep*() {.rtl, gcsafe, raises: [].} ## The current implementation uses a reference counting garbage collector ## with a seldomly run mark and sweep phase to free cycles. The mark and ## sweep phase may take a long time and is not needed if the application ## does not create cycles. Thus the mark and sweep phase can be deactivated ## and activated separately from the rest of the GC. - proc GC_getStatistics*(): string {.rtl, benign, raises: [].} + proc GC_getStatistics*(): string {.rtl, gcsafe, raises: [].} ## Returns an informative string about the GC's activity. This may be useful ## for tweaking. - proc GC_ref*[T](x: ref T) {.magic: "GCref", benign, raises: [].} - proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign, raises: [].} - proc GC_ref*(x: string) {.magic: "GCref", benign, raises: [].} + proc GC_ref*[T](x: ref T) {.magic: "GCref", gcsafe, raises: [].} + proc GC_ref*[T](x: seq[T]) {.magic: "GCref", gcsafe, raises: [].} + proc GC_ref*(x: string) {.magic: "GCref", gcsafe, raises: [].} ## Marks the object `x` as referenced, so that it will not be freed until ## it is unmarked via `GC_unref`. ## If called n-times for the same object `x`, ## n calls to `GC_unref` are needed to unmark `x`. - proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign, raises: [].} - proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign, raises: [].} - proc GC_unref*(x: string) {.magic: "GCunref", benign, raises: [].} + proc GC_unref*[T](x: ref T) {.magic: "GCunref", gcsafe, raises: [].} + proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe, raises: [].} + proc GC_unref*(x: string) {.magic: "GCunref", gcsafe, raises: [].} ## See the documentation of `GC_ref <#GC_ref,string>`_. - proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign, raises: [].} + proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, gcsafe, raises: [].} ## Expands operating GC stack range to `theStackBottom`. Does nothing ## if current stack bottom is already lower than `theStackBottom`. diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 9efca9cbae..fcaae690ba 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -36,7 +36,7 @@ type # local waMarkPrecise # fast precise marking - Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.} + Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, gcsafe, raises: [].} # A ref type can have a finalizer that is called before the object's # storage is freed. @@ -115,10 +115,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0: {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".} # forward declarations: -proc collectCT(gch: var GcHeap; size: int) {.benign, raises: [].} -proc forAllChildren(cell: PCell, op: WalkOp) {.benign, raises: [].} -proc doOperation(p: pointer, op: WalkOp) {.benign, raises: [].} -proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign, raises: [].} +proc collectCT(gch: var GcHeap; size: int) {.gcsafe, raises: [].} +proc forAllChildren(cell: PCell, op: WalkOp) {.gcsafe, raises: [].} +proc doOperation(p: pointer, op: WalkOp) {.gcsafe, raises: [].} +proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.gcsafe, raises: [].} # we need the prototype here for debugging purposes when defined(nimGcRefLeak): @@ -216,7 +216,7 @@ proc initGC() = gch.gcThreadId = atomicInc(gHeapidGenerator) - 1 gcAssert(gch.gcThreadId >= 0, "invalid computed thread ID") -proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} = +proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.gcsafe.} = var d = cast[int](dest) case n.kind of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op) diff --git a/lib/system/gc_regions.nim b/lib/system/gc_regions.nim index 0385e2963d..c1bf61d283 100644 --- a/lib/system/gc_regions.nim +++ b/lib/system/gc_regions.nim @@ -12,7 +12,7 @@ import std/private/syslocks when defined(memProfiler): - proc nimProfile(requestedSize: int) {.benign.} + proc nimProfile(requestedSize: int) {.gcsafe.} when defined(useMalloc): proc roundup(x, v: int): int {.inline.} = @@ -41,7 +41,7 @@ else: # We also support 'finalizers'. type - Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.} + Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, gcsafe, raises: [].} # A ref type can have a finalizer that is called before the object's # storage is freed. diff --git a/lib/system/hti.nim b/lib/system/hti.nim index a26aff9822..4ae61753af 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -96,8 +96,8 @@ type base*: ptr TNimType node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum finalizer*: pointer # the finalizer for the type - marker*: proc (p: pointer, op: int) {.nimcall, benign, tags: [], raises: [].} # marker proc for GC - deepcopy: proc (p: pointer): pointer {.nimcall, benign, tags: [], raises: [].} + marker*: proc (p: pointer, op: int) {.nimcall, gcsafe, tags: [], raises: [].} # marker proc for GC + deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe, tags: [], raises: [].} when defined(nimSeqsV2): typeInfoV2*: pointer when defined(nimTypeNames): diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index b469c4695f..96f35c3c0c 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -51,7 +51,7 @@ proc nimCharToStr(x: char): string {.compilerproc.} = proc isNimException(): bool {.asmNoStackFrame.} = {.emit: "return `lastJSError` && `lastJSError`.m_type;".} -proc getCurrentException*(): ref Exception {.compilerRtl, benign.} = +proc getCurrentException*(): ref Exception {.compilerRtl, gcsafe.} = if isNimException(): result = cast[ref Exception](lastJSError) proc getCurrentExceptionMsg*(): string = @@ -72,7 +72,7 @@ proc getCurrentExceptionMsg*(): string = proc setCurrentException*(exc: ref Exception) = lastJSError = cast[PJSError](exc) -proc closureIterSetExc(e: ref Exception) {.compilerRtl, benign.} = +proc closureIterSetExc(e: ref Exception) {.compilerRtl, gcsafe.} = setCurrentException(e) proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inline.} = diff --git a/lib/system/memalloc.nim b/lib/system/memalloc.nim index b26f3af24d..ed0de06c19 100644 --- a/lib/system/memalloc.nim +++ b/lib/system/memalloc.nim @@ -6,7 +6,7 @@ when notJSnotNims: ## Exactly `size` bytes will be overwritten. Like any procedure ## dealing with raw memory this is **unsafe**. - proc copyMem*(dest, source: pointer, size: Natural) {.inline, benign, + proc copyMem*(dest, source: pointer, size: Natural) {.inline, gcsafe, tags: [], raises: [], enforceNoRaises.} ## Copies the contents from the memory at `source` to the memory ## at `dest`. @@ -14,7 +14,7 @@ when notJSnotNims: ## regions may not overlap. Like any procedure dealing with raw ## memory this is **unsafe**. - proc moveMem*(dest, source: pointer, size: Natural) {.inline, benign, + proc moveMem*(dest, source: pointer, size: Natural) {.inline, gcsafe, tags: [], raises: [], enforceNoRaises.} ## Copies the contents from the memory at `source` to the memory ## at `dest`. @@ -48,17 +48,17 @@ when notJSnotNims: when hasAlloc and not defined(js): - proc allocImpl*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} - proc alloc0Impl*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} - proc deallocImpl*(p: pointer) {.noconv, rtl, tags: [], benign, raises: [].} - proc reallocImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} - proc realloc0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} + proc allocImpl*(size: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} + proc alloc0Impl*(size: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} + proc deallocImpl*(p: pointer) {.noconv, rtl, tags: [], gcsafe, raises: [].} + proc reallocImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} + proc realloc0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} - proc allocSharedImpl*(size: Natural): pointer {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} - proc allocShared0Impl*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].} - proc deallocSharedImpl*(p: pointer) {.noconv, rtl, benign, raises: [], tags: [].} - proc reallocSharedImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} - proc reallocShared0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].} + proc allocSharedImpl*(size: Natural): pointer {.noconv, compilerproc, rtl, gcsafe, raises: [], tags: [].} + proc allocShared0Impl*(size: Natural): pointer {.noconv, rtl, gcsafe, raises: [], tags: [].} + proc deallocSharedImpl*(p: pointer) {.noconv, rtl, gcsafe, raises: [], tags: [].} + proc reallocSharedImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} + proc reallocShared0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], gcsafe, raises: [].} # Allocator statistics for memory leak tests @@ -103,7 +103,7 @@ when hasAlloc and not defined(js): incStat(allocCount) allocImpl(size) - proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} = + proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, gcsafe, raises: [].} = ## Allocates a new memory block with at least `T.sizeof * size` bytes. ## ## The block has to be freed with `resize(block, 0) <#resize,ptr.T,Natural>`_ @@ -131,7 +131,7 @@ when hasAlloc and not defined(js): incStat(allocCount) alloc0Impl(size) - proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} = + proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, gcsafe, raises: [].} = ## Allocates a new memory block with at least `T.sizeof * size` bytes. ## ## The block has to be freed with `resize(block, 0) <#resize,ptr.T,Natural>`_ @@ -174,7 +174,7 @@ when hasAlloc and not defined(js): ## from a shared heap. realloc0Impl(p, oldSize, newSize) - proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, benign, raises: [].} = + proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, gcsafe, raises: [].} = ## Grows or shrinks a given memory block. ## ## If `p` is **nil** then a new memory block is returned. @@ -187,7 +187,7 @@ when hasAlloc and not defined(js): ## from a shared heap. cast[ptr T](realloc(p, T.sizeof * newSize)) - proc dealloc*(p: pointer) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} = + proc dealloc*(p: pointer) {.noconv, compilerproc, rtl, gcsafe, raises: [], tags: [].} = ## Frees the memory allocated with `alloc`, `alloc0`, ## `realloc`, `create` or `createU`. ## @@ -218,7 +218,7 @@ when hasAlloc and not defined(js): allocSharedImpl(size) proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline, tags: [], - benign, raises: [].} = + gcsafe, raises: [].} = ## Allocates a new memory block on the shared heap with at ## least `T.sizeof * size` bytes. ## @@ -296,7 +296,7 @@ when hasAlloc and not defined(js): ## `freeShared <#freeShared,ptr.T>`_. cast[ptr T](reallocShared(p, T.sizeof * newSize)) - proc deallocShared*(p: pointer) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} = + proc deallocShared*(p: pointer) {.noconv, compilerproc, rtl, gcsafe, raises: [], tags: [].} = ## Frees the memory allocated with `allocShared`, `allocShared0` or ## `reallocShared`. ## @@ -307,7 +307,7 @@ when hasAlloc and not defined(js): incStat(deallocCount) deallocSharedImpl(p) - proc freeShared*[T](p: ptr T) {.inline, benign, raises: [].} = + proc freeShared*[T](p: ptr T) {.inline, gcsafe, raises: [].} = ## Frees the memory allocated with `createShared`, `createSharedU` or ## `resizeShared`. ## diff --git a/lib/system/orc.nim b/lib/system/orc.nim index 2b9ce22ec4..5be19fad93 100644 --- a/lib/system/orc.nim +++ b/lib/system/orc.nim @@ -29,8 +29,8 @@ const logOrc = defined(nimArcIds) type - TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].} - DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].} + TraceProc = proc (p, env: pointer) {.nimcall, gcsafe, raises: [].} + DisposeProc = proc (p: pointer) {.nimcall, gcsafe, raises: [].} template color(c): untyped = c.rc and colorMask template setColor(c, col) = diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 13118e40b2..e8ac1e41e5 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -77,7 +77,7 @@ include system/repr_impl type PByteArray = ptr UncheckedArray[byte] # array[0xffff, byte] -proc addSetElem(result: var string, elem: int, typ: PNimType) {.benign.} = +proc addSetElem(result: var string, elem: int, typ: PNimType) {.gcsafe.} = case typ.kind of tyEnum: add result, reprEnum(elem, typ) of tyBool: add result, reprBool(bool(elem)) @@ -147,7 +147,7 @@ when not defined(useNimRtl): for i in 0..cl.indent-1: add result, ' ' proc reprAux(result: var string, p: pointer, typ: PNimType, - cl: var ReprClosure) {.benign.} + cl: var ReprClosure) {.gcsafe.} proc reprArray(result: var string, p: pointer, typ: PNimType, cl: var ReprClosure) = @@ -188,7 +188,7 @@ when not defined(useNimRtl): add result, "]" proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode, - cl: var ReprClosure) {.benign.} = + cl: var ReprClosure) {.gcsafe.} = case n.kind of nkNone: sysAssert(false, "reprRecordAux") of nkSlot: diff --git a/lib/system/yrc.nim b/lib/system/yrc.nim index a681917de2..c682c896e1 100644 --- a/lib/system/yrc.nim +++ b/lib/system/yrc.nim @@ -90,8 +90,8 @@ const logOrc = defined(nimArcIds) type - TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].} - DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].} + TraceProc = proc (p, env: pointer) {.nimcall, gcsafe, raises: [].} + DisposeProc = proc (p: pointer) {.nimcall, gcsafe, raises: [].} template color(c): untyped = c.rc and colorMask template setColor(c, col) = @@ -131,7 +131,7 @@ type toDec: array[QueueSize, (Cell, PNimTypeV2)] type - PreventThreadFromCollectProc* = proc(): bool {.nimcall, benign, raises: [].} + PreventThreadFromCollectProc* = proc(): bool {.nimcall, gcsafe, raises: [].} ## Callback run before this thread runs the cycle collector. ## Return `true` to allow collection, `false` to skip (e.g. real-time thread). ## Invoked while holding the global lock; must not call back into YRC.