summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/seqs.nim87
-rw-r--r--lib/system.nim13
-rw-r--r--lib/system/excpt.nim64
3 files changed, 65 insertions, 99 deletions
diff --git a/lib/core/seqs.nim b/lib/core/seqs.nim
index 914ca438c..b7f9fb153 100644
--- a/lib/core/seqs.nim
+++ b/lib/core/seqs.nim
@@ -30,60 +30,6 @@ template payloadSize(cap): int = cap * sizeof(T) + sizeof(int) + sizeof(Allocato
 
 # XXX make code memory safe for overflows in '*'
 
-when false:
-  # this is currently not part of Nim's type bound operators and so it's
-  # built into the tracing proc generation just like before.
-  proc `=trace`[T](s: NimSeqV2[T]) =
-    for i in 0 ..< s.len: `=trace`(s.data[i])
-
-#[
-Keep in mind that C optimizers are bad at detecting the connection
-between ``s.p != nil`` and ``s.len != 0`` and that these are intermingled
-with user-level code that accesses ``s.len`` only, never ``s.p`` directly.
-This means the check for whether ``s.p`` needs to be freed should
-be ``s.len == 0`` even though that feels slightly more awkward.
-]#
-
-when not defined(nimV2):
-  proc `=destroy`[T](s: var seq[T]) =
-    var x = cast[ptr NimSeqV2[T]](addr s)
-    var p = x.p
-    if p != nil:
-      mixin `=destroy`
-      when not supportsCopyMem(T):
-        for i in 0..<x.len: `=destroy`(p.data[i])
-      if p.allocator != nil:
-        p.allocator.dealloc(p.allocator, p, payloadSize(p.cap))
-      x.p = nil
-      x.len = 0
-
-  proc `=`[T](x: var seq[T]; y: seq[T]) =
-    mixin `=destroy`
-    var a = cast[ptr NimSeqV2[T]](addr x)
-    var b = cast[ptr NimSeqV2[T]](unsafeAddr y)
-
-    if a.p == b.p: return
-    `=destroy`(x)
-    a.len = b.len
-    if b.p != nil:
-      a.p = cast[type(a.p)](alloc(payloadSize(a.len)))
-      when supportsCopyMem(T):
-        if a.len > 0:
-          copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], a.len * sizeof(T))
-      else:
-        for i in 0..<a.len:
-          a.p.data[i] = b.p.data[i]
-
-  proc `=sink`[T](x: var seq[T]; y: seq[T]) =
-    mixin `=destroy`
-    var a = cast[ptr NimSeqV2[T]](addr x)
-    var b = cast[ptr NimSeqV2[T]](unsafeAddr y)
-    if a.p != nil and a.p != b.p:
-      `=destroy`(x)
-    a.len = b.len
-    a.p = b.p
-
-
 type
   PayloadBase = object
     cap: int
@@ -181,36 +127,3 @@ proc setLen[T](s: var seq[T], newlen: Natural) =
       if xu.p == nil or xu.p.cap < newlen:
         xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T)))
       xu.len = newlen
-
-when false:
-  proc resize[T](s: var NimSeqV2[T]) =
-    let old = s.cap
-    if old == 0: s.cap = 8
-    else: s.cap = (s.cap * 3) shr 1
-    s.data = cast[type(s.data)](realloc(s.data, old * sizeof(T), s.cap * sizeof(T)))
-
-  proc reserveSlot[T](x: var NimSeqV2[T]): ptr T =
-    if x.len >= x.cap: resize(x)
-    result = addr(x.data[x.len])
-    inc x.len
-
-  template add*[T](x: var NimSeqV2[T]; y: T) =
-    reserveSlot(x)[] = y
-
-  template `[]`*[T](x: NimSeqV2[T]; i: Natural): T =
-    assert i < x.len
-    x.data[i]
-
-  template `[]=`*[T](x: NimSeqV2[T]; i: Natural; y: T) =
-    assert i < x.len
-    x.data[i] = y
-
-  proc `@`*[T](elems: sink openArray[T]): NimSeqV2[T] =
-    result.cap = elems.len
-    result.len = elems.len
-    result.data = cast[type(result.data)](alloc(result.cap * sizeof(T)))
-    when supportsCopyMem(T):
-      copyMem(result.data, unsafeAddr(elems[0]), result.cap * sizeof(T))
-    else:
-      for i in 0..<result.len:
-        result.data[i] = elems[i]
diff --git a/lib/system.nim b/lib/system.nim
index cb211e6a9..81d308073 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -3218,6 +3218,9 @@ proc `<`*[T: tuple](x, y: T): bool =
 const
   usesDestructors = defined(gcDestructors) or defined(gcHooks)
 
+when not usesDestructors:
+  {.pragma: nodestroy.}
+
 when not defined(nimscript) and hasAlloc:
   type
     GC_Strategy* = enum  ## The strategy the GC should use for the application.
@@ -3671,8 +3674,6 @@ when not defined(JS): #and not defined(nimscript):
         prev: PSafePoint # points to next safe point ON THE STACK
         status: int
         context: C_JmpBuf
-        hasRaiseAction: bool
-        raiseAction: proc (e: ref Exception): bool {.closure.}
       SafePoint = TSafePoint
 
   when declared(initAllocator):
@@ -3776,11 +3777,15 @@ when not defined(JS): #and not defined(nimscript):
       ## Retrieves the current exception; if there is none, `nil` is returned.
       result = currException
 
+    proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, benign, 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.} =
       ## Retrieves the error message that was attached to the current
       ## exception; if there is none, `""` is returned.
-      var e = getCurrentException()
-      return if e == nil: "" else: e.msg
+      return if currException == nil: "" else: currException.msg
 
     proc setCurrentException*(exc: ref Exception) {.inline, benign.} =
       ## Sets the current exception.
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index ef9a6deaf..6e06b10f8 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -103,19 +103,20 @@ proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} =
   gcFramePtr = s
 
 proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
-  s.hasRaiseAction = false
   s.prev = excHandler
   excHandler = s
 
 proc popSafePoint {.compilerRtl, inl.} =
   excHandler = excHandler.prev
 
-proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
+proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inl.} =
   e.up = currException
   currException = e
+  #showErrorMessage "A"
 
 proc popCurrentException {.compilerRtl, inl.} =
   currException = currException.up
+  #showErrorMessage "B"
 
 proc popCurrentExceptionEx(id: uint) {.compilerRtl.} =
   # in cpp backend exceptions can pop-up in the different order they were raised, example #5628
@@ -332,7 +333,53 @@ template unhandled(buf, body) =
   else:
     body
 
-proc raiseExceptionAux(e: ref Exception) =
+proc nimLeaveFinally() {.compilerRtl.} =
+  when defined(cpp) and not defined(noCppExceptions):
+    {.emit: "throw;".}
+  else:
+    template e: untyped = currException
+    if excHandler != nil:
+      c_longjmp(excHandler.context, 1)
+    else:
+      when hasSomeStackTrace:
+        var buf = newStringOfCap(2000)
+        if e.trace.len == 0: rawWriteStackTrace(buf)
+        else: add(buf, $e.trace)
+        add(buf, "Error: unhandled exception: ")
+        add(buf, e.msg)
+        add(buf, " [")
+        add(buf, $e.name)
+        add(buf, "]\n")
+        unhandled(buf):
+          showErrorMessage(buf)
+          quitOrDebug()
+        `=destroy`(buf)
+      else:
+        # ugly, but avoids heap allocations :-)
+        template xadd(buf, s, slen) =
+          if L + slen < high(buf):
+            copyMem(addr(buf[L]), cstring(s), slen)
+            inc L, slen
+        template add(buf, s) =
+          xadd(buf, s, s.len)
+        var buf: array[0..2000, char]
+        var L = 0
+        if e.trace.len != 0:
+          add(buf, $e.trace) # gc allocation
+        add(buf, "Error: unhandled exception: ")
+        add(buf, e.msg)
+        add(buf, " [")
+        xadd(buf, e.name, e.name.len)
+        add(buf, "]\n")
+        when defined(nimNoArrayToCstringConversion):
+          template tbuf(): untyped = addr buf
+        else:
+          template tbuf(): untyped = buf
+        unhandled(tbuf()):
+          showErrorMessage(tbuf())
+          quitOrDebug()
+
+proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
   if localRaiseHook != nil:
     if not localRaiseHook(e): return
   if globalRaiseHook != nil:
@@ -351,9 +398,8 @@ proc raiseExceptionAux(e: ref Exception) =
     pushCurrentException(e)
   else:
     if excHandler != nil:
-      if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
-        pushCurrentException(e)
-        c_longjmp(excHandler.context, 1)
+      pushCurrentException(e)
+      c_longjmp(excHandler.context, 1)
     else:
       when hasSomeStackTrace:
         var buf = newStringOfCap(2000)
@@ -367,6 +413,7 @@ proc raiseExceptionAux(e: ref Exception) =
         unhandled(buf):
           showErrorMessage(buf)
           quitOrDebug()
+        `=destroy`(buf)
       else:
         # ugly, but avoids heap allocations :-)
         template xadd(buf, s, slen) =
@@ -392,7 +439,8 @@ proc raiseExceptionAux(e: ref Exception) =
           showErrorMessage(tbuf())
           quitOrDebug()
 
-proc raiseExceptionEx(e: ref Exception, ename, procname, filename: cstring, line: int) {.compilerRtl.} =
+proc raiseExceptionEx(e: sink(ref Exception), ename, procname, filename: cstring,
+                      line: int) {.compilerRtl, nodestroy.} =
   if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
     if e.trace.len == 0:
@@ -406,7 +454,7 @@ proc raiseExceptionEx(e: ref Exception, ename, procname, filename: cstring, line
       e.trace.add StackTraceEntry(procname: procname, filename: filename, line: line)
   raiseExceptionAux(e)
 
-proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
+proc raiseException(e: sink(ref Exception), ename: cstring) {.compilerRtl.} =
   raiseExceptionEx(e, ename, nil, nil, 0)
 
 proc reraiseException() {.compilerRtl.} =