summary refs log tree commit diff stats
path: root/compiler/vm.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r--compiler/vm.nim21
1 files changed, 20 insertions, 1 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 70eb6f828..f8b32bac1 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -68,7 +68,9 @@ proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
                 msg: TMsgKind, arg = "") =
   msgWriteln("stack trace: (most recent call last)")
   stackTraceAux(c, tos, pc)
-  localError(c.debug[pc], msg, arg)
+  # XXX test if we want 'globalError' for every mode
+  if c.mode == emRepl: globalError(c.debug[pc], msg, arg)
+  else: localError(c.debug[pc], msg, arg)
 
 proc bailOut(c: PCtx; tos: PStackFrame) =
   stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
@@ -333,6 +335,16 @@ proc compile(c: PCtx, s: PSym): int =
   when debugEchoCode: c.echoCode result
   #c.echoCode
 
+template handleJmpBack() {.dirty.} =
+  if c.loopIterations <= 0:
+    if allowInfiniteLoops in c.features:
+      c.loopIterations = MaxLoopIterations
+    else:
+      msgWriteln("stack trace: (most recent call last)")
+      stackTraceAux(c, tos, pc)
+      globalError(c.debug[pc], errTooManyIterations)
+  dec(c.loopIterations)
+
 proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
   var pc = start
   var tos = tos
@@ -735,6 +747,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
           globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
       elif prc.kind != skTemplate:
         let newPc = compile(c, prc)
+        # tricky: a recursion is also a jump back, so we use the same
+        # logic as for loops:
+        if newPc < pc: handleJmpBack()
         #echo "new pc ", newPc, " calling: ", prc.name.s
         var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
         newSeq(newFrame.slots, prc.offset)
@@ -778,6 +793,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       # jump Bx
       let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
       inc pc, rbx
+    of opcJmpBack:
+      let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
+      inc pc, rbx
+      handleJmpBack()
     of opcBranch:
       # we know the next instruction is a 'fjmp':
       let branch = c.constants[instr.regBx-wordExcess]