summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-04-04 09:06:29 +0200
committerAraq <rumpf_a@web.de>2014-04-04 09:06:29 +0200
commit033f2bbbf267cd4fe4f2567aca8aa7483201a737 (patch)
treef014be21c2329561b648094da3114d50d1a6bd64
parent6a055990f90ef943cb8f6f0ae73c2a011009f939 (diff)
downloadNim-033f2bbbf267cd4fe4f2567aca8aa7483201a737.tar.gz
new VM: fixes for exception handling
-rw-r--r--compiler/vm.nim25
1 files changed, 17 insertions, 8 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 7355e85fe..b365dba9a 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -222,13 +222,14 @@ proc pushSafePoint(f: PStackFrame; pc: int) =
 
 proc popSafePoint(f: PStackFrame) = discard f.safePoints.pop()
 
-proc cleanUpOnException(c: PCtx; tos: PStackFrame; regs: seq[TFullReg]): int =
+proc cleanUpOnException(c: PCtx; tos: PStackFrame): 
+                                              tuple[pc: int, f: PStackFrame] =
   let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
   var f = tos
   while true:
     while f.safePoints.isNil or f.safePoints.len == 0:
       f = f.next
-      if f.isNil: return -1
+      if f.isNil: return (-1, nil)
     var pc2 = f.safePoints[f.safePoints.high]
 
     var nextExceptOrFinally = -1
@@ -244,13 +245,13 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame; regs: seq[TFullReg]): int =
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
         # execute the corresponding handler:
-        return pc2
+        return (pc2, f)
       inc pc2
     if nextExceptOrFinally >= 0:
       pc2 = nextExceptOrFinally
     if c.code[pc2].opcode == opcFinally:
       # execute the corresponding handler, but don't quit walking the stack:
-      return pc2
+      return (pc2, f)
     # not the right one:
     discard f.safePoints.pop
 
@@ -869,19 +870,27 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcFinallyEnd:
       if c.currentExceptionA != nil:
         # we are in a cleanup run:
-        pc = cleanUpOnException(c, tos, regs)-1
-        if pc < 0: 
+        let (newPc, newTos) = cleanUpOnException(c, tos)
+        if newPc-1 < 0:
           bailOut(c, tos)
           return
+        pc = newPc-1
+        if tos != newTos:
+          tos = newTos
+          move(regs, tos.slots)
     of opcRaise:
       let raised = regs[ra].node
       c.currentExceptionA = raised
       c.exceptionInstr = pc
+      let (newPc, newTos) = cleanUpOnException(c, tos)
       # -1 because of the following 'inc'
-      pc = cleanUpOnException(c, tos, regs) - 1
-      if pc < 0:
+      if pc-1 < 0:
         bailOut(c, tos)
         return
+      pc = newPc -1
+      if tos != newTos:
+        tos = newTos
+        move(regs, tos.slots)
     of opcNew:
       ensureKind(rkNode)
       let typ = c.types[instr.regBx - wordExcess]