summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-01-23 01:53:30 -0800
committerAndreas Rumpf <rumpf_a@web.de>2020-01-23 10:53:30 +0100
commitb462baed65589365df85798f15223b3b38557f9c (patch)
tree741c3df296775cfa26fd1179b0f92748aeb5cd0e
parentf12bea16ad968f10ffe97591ac789ddc36984962 (diff)
downloadNim-b462baed65589365df85798f15223b3b38557f9c.tar.gz
VM: allow overriding MaxLoopIterations without rebuilding nim (#13233)
-rw-r--r--compiler/commands.nim3
-rw-r--r--compiler/options.nim4
-rw-r--r--compiler/vm.nim7
-rw-r--r--compiler/vmdef.nim6
-rw-r--r--doc/advopt.txt1
-rw-r--r--tests/vm/tmaxloopiterations.nim2
6 files changed, 13 insertions, 10 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 04c918672..f90d79d5b 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -678,6 +678,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
       setTarget(conf.target, conf.target.targetOS, cpu)
   of "run", "r":
     processOnOffSwitchG(conf, {optRun}, arg, pass, info)
+  of "maxloopiterationsvm":
+    expectArg(conf, switch, arg, pass, info)
+    conf.maxLoopIterationsVM = parseInt(arg)
   of "errormax":
     expectArg(conf, switch, arg, pass, info)
     # Note: `nim check` (etc) can overwrite this.
diff --git a/compiler/options.nim b/compiler/options.nim
index 3866f4b7f..2d56974c5 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -235,6 +235,7 @@ type
     hintCounter*: int
     warnCounter*: int
     errorMax*: int
+    maxLoopIterationsVM*: int ## VM: max iterations of all loops
     configVars*: StringTableRef
     symbols*: StringTableRef ## We need to use a StringTableRef here as defined
                              ## symbols are always guaranteed to be style
@@ -380,7 +381,8 @@ proc newConfigRef*(): ConfigRef =
     ccompilerpath: "",
     toCompile: @[],
     arguments: "",
-    suggestMaxResults: 10_000
+    suggestMaxResults: 10_000,
+    maxLoopIterationsVM: 10_000_000,
   )
   setTargetFromSystem(result.target)
   # enable colors by default on terminals
diff --git a/compiler/vm.nim b/compiler/vm.nim
index d190c4645..8a08de36d 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -486,11 +486,11 @@ proc compile(c: PCtx, s: PSym): int =
 template handleJmpBack() {.dirty.} =
   if c.loopIterations <= 0:
     if allowInfiniteLoops in c.features:
-      c.loopIterations = MaxLoopIterations
+      c.loopIterations = c.config.maxLoopIterationsVM
     else:
       msgWriteln(c.config, "stack trace: (most recent call last)")
       stackTraceAux(c, tos, pc)
-      globalError(c.config, c.debug[pc], errTooManyIterations)
+      globalError(c.config, c.debug[pc], errTooManyIterations % $c.config.maxLoopIterationsVM)
   dec(c.loopIterations)
 
 proc recSetFlagIsRef(arg: PNode) =
@@ -513,8 +513,7 @@ const
   errConstantDivisionByZero = "division by zero"
   errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'"
   errTooManyIterations = "interpretation requires too many iterations; " &
-    "if you are sure this is not a bug in your code edit " &
-    "compiler/vmdef.MaxLoopIterations and rebuild the compiler"
+    "if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
   errFieldXNotFound = "node lacks field: "
 
 proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 6c359c9b1..a9ff7f2d0 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -23,8 +23,6 @@ const
 
   byteExcess* = 128 # we use excess-K for immediates
 
-  MaxLoopIterations* = 10_000_000 # max iterations of all loops
-
 # Calculate register shifts, masks and ranges
 
 const
@@ -259,14 +257,14 @@ type
 proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx =
   PCtx(code: @[], debug: @[],
     globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
-    prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
+    prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
     comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "",
     cache: cache, config: g.config, graph: g)
 
 proc refresh*(c: PCtx, module: PSym) =
   c.module = module
   c.prc = PProc(blocks: @[])
-  c.loopIterations = MaxLoopIterations
+  c.loopIterations = c.config.maxLoopIterationsVM
 
 proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} =
   result = c.callbacks.len
diff --git a/doc/advopt.txt b/doc/advopt.txt
index d53acc111..9dd59333c 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -125,6 +125,7 @@ Advanced options:
   --incremental:on|off      only recompile the changed modules (experimental!)
   --verbosity:0|1|2|3       set Nim's verbosity level (1 is default)
   --errorMax:N              stop compilation after N errors; 0 means unlimited
+  --maxLoopIterationsVM:N   set max iterations for all VM loops
   --experimental:$1
                             enable experimental language feature
   --legacy:$2
diff --git a/tests/vm/tmaxloopiterations.nim b/tests/vm/tmaxloopiterations.nim
index 6334d1e6d..c256df518 100644
--- a/tests/vm/tmaxloopiterations.nim
+++ b/tests/vm/tmaxloopiterations.nim
@@ -1,5 +1,5 @@
 discard """
-errormsg: "interpretation requires too many iterations; if you are sure this is not a bug in your code edit compiler/vmdef.MaxLoopIterations and rebuild the compiler"
+errormsg: "interpretation requires too many iterations; if you are sure this is not a bug in your code"
 """
 
 # issue #9829