diff options
author | Araq <rumpf_a@web.de> | 2014-04-04 09:06:29 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-04-04 09:06:29 +0200 |
commit | 033f2bbbf267cd4fe4f2567aca8aa7483201a737 (patch) | |
tree | f014be21c2329561b648094da3114d50d1a6bd64 /compiler/vm.nim | |
parent | 6a055990f90ef943cb8f6f0ae73c2a011009f939 (diff) | |
download | Nim-033f2bbbf267cd4fe4f2567aca8aa7483201a737.tar.gz |
new VM: fixes for exception handling
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r-- | compiler/vm.nim | 25 |
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] |