diff options
Diffstat (limited to 'lib/system')
-rw-r--r-- | lib/system/atomics.nim | 20 | ||||
-rw-r--r-- | lib/system/endb.nim | 2 | ||||
-rw-r--r-- | lib/system/excpt.nim | 85 | ||||
-rw-r--r-- | lib/system/gc2.nim | 2 | ||||
-rw-r--r-- | lib/system/sysspawn.nim | 4 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 61 |
6 files changed, 114 insertions, 60 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index 8c3801687..afc435638 100644 --- a/lib/system/atomics.nim +++ b/lib/system/atomics.nim @@ -213,12 +213,20 @@ proc atomicDec*(memLoc: var int, x: int = 1): int = result = memLoc when defined(vcc): - proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64 - {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".} - proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32 - {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".} - proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte - {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".} + when defined(cpp): + proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64 + {.importcpp: "_InterlockedCompareExchange64(static_cast<NI64 volatile *>(#), #, #)", header: "<intrin.h>".} + proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32 + {.importcpp: "_InterlockedCompareExchange(static_cast<NI volatile *>(#), #, #)", header: "<intrin.h>".} + proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte + {.importcpp: "_InterlockedCompareExchange8(static_cast<char volatile *>(#), #, #)", header: "<intrin.h>".} + else: + proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64 + {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".} + proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32 + {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".} + proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte + {.importc: "_InterlockedCompareExchange8", header: "<intrin.h>".} proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool = when sizeof(T) == 8: diff --git a/lib/system/endb.nim b/lib/system/endb.nim index 35d8f25c4..d51ae29df 100644 --- a/lib/system/endb.nim +++ b/lib/system/endb.nim @@ -370,7 +370,7 @@ proc commandPrompt() = if dbgUser.len == 0: dbgUser.len = oldLen # now look what we have to do: var i = scanWord(addr dbgUser.data, dbgTemp, 0) - template `?`(x: expr): expr = dbgTemp == cstring(x) + template `?`(x: untyped): untyped = dbgTemp == cstring(x) if ?"s" or ?"step": dbgState = dbStepInto again = false diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 9e02d6824..70c18ae21 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -155,6 +155,52 @@ when not hasThreadSupport: var tempFrames: array[0..127, PFrame] # should not be alloc'd on stack +const + reraisedFromBegin = -10 + reraisedFromEnd = -100 + +template reraisedFrom(z): untyped = + StackTraceEntry(procname: nil, line: z, filename: nil) + +proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) = + var + it = f + i = 0 + while it != nil: + inc(i) + it = it.prev + var last = i-1 + if s.isNil: + s = newSeq[StackTraceEntry](i) + else: + last = s.len + i - 1 + s.setLen(last+1) + it = f + while it != nil: + s[last] = StackTraceEntry(procname: it.procname, + line: it.line, + filename: it.filename) + it = it.prev + dec last + +template addFrameEntry(s, f: untyped) = + var oldLen = s.len + add(s, f.filename) + if f.line > 0: + add(s, '(') + add(s, $f.line) + add(s, ')') + for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ') + add(s, f.procname) + add(s, "\n") + +proc `$`(s: seq[StackTraceEntry]): string = + result = newStringOfCap(2000) + for i in 0 .. s.len-1: + if s[i].line == reraisedFromBegin: result.add "[[reraised from:\n" + elif s[i].line == reraisedFromEnd: result.add "]]\n" + else: addFrameEntry(result, s[i]) + proc auxWriteStackTrace(f: PFrame, s: var string) = when hasThreadSupport: var @@ -194,17 +240,9 @@ proc auxWriteStackTrace(f: PFrame, s: var string) = if tempFrames[j] == nil: add(s, "(") add(s, $skipped) - add(s, " calls omitted) ...") + add(s, " calls omitted) ...\n") else: - var oldLen = s.len - add(s, tempFrames[j].filename) - if tempFrames[j].line > 0: - add(s, '(') - add(s, $tempFrames[j].line) - add(s, ')') - for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ') - add(s, tempFrames[j].procname) - add(s, "\n") + addFrameEntry(s, tempFrames[j]) proc stackTraceAvailable*(): bool @@ -221,6 +259,13 @@ when hasSomeStackTrace: auxWriteStackTraceWithBacktrace(s) else: add(s, "No stack traceback available\n") + + proc rawWriteStackTrace(s: var seq[StackTraceEntry]) = + when NimStackTrace: + auxWriteStackTrace(framePtr, s) + else: + s = nil + proc stackTraceAvailable(): bool = when NimStackTrace: if framePtr == nil: @@ -240,12 +285,6 @@ proc quitOrDebug() {.inline.} = else: endbStep() # call the debugger -when false: - proc rawRaise*(e: ref Exception) = - ## undocumented. Do not use. - pushCurrentException(e) - c_longjmp(excHandler.context, 1) - var onUnhandledException*: (proc (errorMsg: string) {. nimcall.}) ## set this error \ ## handler to override the existing behaviour on an unhandled exception. @@ -282,7 +321,7 @@ proc raiseExceptionAux(e: ref Exception) = when hasSomeStackTrace: var buf = newStringOfCap(2000) if isNil(e.trace): rawWriteStackTrace(buf) - else: add(buf, e.trace) + else: add(buf, $e.trace) add(buf, "Error: unhandled exception: ") if not isNil(e.msg): add(buf, e.msg) add(buf, " [") @@ -318,12 +357,11 @@ proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} = if e.name.isNil: e.name = ename when hasSomeStackTrace: if e.trace.isNil: - e.trace = "" rawWriteStackTrace(e.trace) elif framePtr != nil: - e.trace.add "[[reraised from:\n" + e.trace.add reraisedFrom(reraisedFromBegin) auxWriteStackTrace(framePtr, e.trace) - e.trace.add "]]\n" + e.trace.add reraisedFrom(reraisedFromEnd) raiseExceptionAux(e) proc reraiseException() {.compilerRtl.} = @@ -349,10 +387,15 @@ proc getStackTrace(): string = proc getStackTrace(e: ref Exception): string = if not isNil(e) and not isNil(e.trace): - result = e.trace + result = $e.trace else: result = "" +proc getStackTraceEntries*(e: ref Exception): seq[StackTraceEntry] = + ## Returns the attached stack trace to the exception ``e`` as + ## a ``seq``. This is not yet available for the JS backend. + shallowCopy(result, e.trace) + when defined(nimRequiresNimFrame): proc stackOverflow() {.noinline.} = writeStackTrace() diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 70bed8740..4ecf3b226 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -173,7 +173,7 @@ proc internRefcount(p: pointer): int {.exportc: "getRefcount".} = when BitsPerPage mod (sizeof(int)*8) != 0: {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".} -template color(c): expr = c.refCount and colorMask +template color(c): untyped = c.refCount and colorMask template setColor(c, col) = c.refcount = c.refcount and not colorMask or col diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim index a0d10c446..dc2d13578 100644 --- a/lib/system/sysspawn.nim +++ b/lib/system/sysspawn.nim @@ -153,12 +153,12 @@ proc preferSpawn*(): bool = ## it is not necessary to call this directly; use 'spawnX' instead. result = gSomeReady.event -proc spawn*(call: stmt) {.magic: "Spawn".} +proc spawn*(call: typed) {.magic: "Spawn".} ## always spawns a new task, so that the 'call' is never executed on ## the calling thread. 'call' has to be proc call 'p(...)' where 'p' ## is gcsafe and has 'void' as the return type. -template spawnX*(call: stmt) = +template spawnX*(call: typed) = ## spawns a new task if a CPU core is ready, otherwise executes the ## call in the calling thread. Usually it is advised to ## use 'spawn' in order to not block the producer for an unknown diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index d9586b00d..3f8e0eff0 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -322,37 +322,40 @@ proc nimIntToStr(x: int): string {.compilerRtl.} = result.add x proc add*(result: var string; x: float) = - var buf: array[0..64, char] - when defined(nimNoArrayToCstringConversion): - var n: int = c_sprintf(addr buf, "%.16g", x) + when nimvm: + result.add $x else: - var n: int = c_sprintf(buf, "%.16g", x) - var hasDot = false - for i in 0..n-1: - if buf[i] == ',': - buf[i] = '.' - hasDot = true - elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: - hasDot = true - if not hasDot: - buf[n] = '.' - buf[n+1] = '0' - buf[n+2] = '\0' - # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' - # of '-1.#IND' are produced. - # We want to get rid of these here: - if buf[n-1] in {'n', 'N', 'D', 'd'}: - result.add "nan" - elif buf[n-1] == 'F': - if buf[0] == '-': - result.add "-inf" + var buf: array[0..64, char] + when defined(nimNoArrayToCstringConversion): + var n: int = c_sprintf(addr buf, "%.16g", x) else: - result.add "inf" - else: - var i = 0 - while buf[i] != '\0': - result.add buf[i] - inc i + var n: int = c_sprintf(buf, "%.16g", x) + var hasDot = false + for i in 0..n-1: + if buf[i] == ',': + buf[i] = '.' + hasDot = true + elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: + hasDot = true + if not hasDot: + buf[n] = '.' + buf[n+1] = '0' + buf[n+2] = '\0' + # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' + # of '-1.#IND' are produced. + # We want to get rid of these here: + if buf[n-1] in {'n', 'N', 'D', 'd'}: + result.add "nan" + elif buf[n-1] == 'F': + if buf[0] == '-': + result.add "-inf" + else: + result.add "inf" + else: + var i = 0 + while buf[i] != '\0': + result.add buf[i] + inc i proc nimFloatToStr(f: float): string {.compilerproc.} = result = newStringOfCap(8) |