VM: allow overriding MaxLoopIterations without rebuilding nim (#13233)

This commit is contained in:
Timothee Cour 2020-01-23 01:53:30 -08:00 • committed by Andreas Rumpf
commit b462baed65
6 changed files with 13 additions and 10 deletions

View file

@ -678,6 +678,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
setTarget(conf.target, conf.target.targetOS, cpu) setTarget(conf.target, conf.target.targetOS, cpu)
of "run", "r": of "run", "r":
processOnOffSwitchG(conf, {optRun}, arg, pass, info) processOnOffSwitchG(conf, {optRun}, arg, pass, info)
of "maxloopiterationsvm":
expectArg(conf, switch, arg, pass, info)
conf.maxLoopIterationsVM = parseInt(arg)
of "errormax": of "errormax":
expectArg(conf, switch, arg, pass, info) expectArg(conf, switch, arg, pass, info)
# Note: `nim check` (etc) can overwrite this. # Note: `nim check` (etc) can overwrite this.

View file

@ -235,6 +235,7 @@ type
hintCounter*: int hintCounter*: int
warnCounter*: int warnCounter*: int
errorMax*: int errorMax*: int
maxLoopIterationsVM*: int ## VM: max iterations of all loops
configVars*: StringTableRef configVars*: StringTableRef
symbols*: StringTableRef ## We need to use a StringTableRef here as defined symbols*: StringTableRef ## We need to use a StringTableRef here as defined
## symbols are always guaranteed to be style ## symbols are always guaranteed to be style
@ -380,7 +381,8 @@ proc newConfigRef*(): ConfigRef =
ccompilerpath: "", ccompilerpath: "",
toCompile: @[], toCompile: @[],
arguments: "", arguments: "",
suggestMaxResults: 10_000 suggestMaxResults: 10_000,
maxLoopIterationsVM: 10_000_000,
) )
setTargetFromSystem(result.target) setTargetFromSystem(result.target)
# enable colors by default on terminals # enable colors by default on terminals

View file

@ -486,11 +486,11 @@ proc compile(c: PCtx, s: PSym): int =
template handleJmpBack() {.dirty.} = template handleJmpBack() {.dirty.} =
if c.loopIterations <= 0: if c.loopIterations <= 0:
if allowInfiniteLoops in c.features: if allowInfiniteLoops in c.features:
c.loopIterations = MaxLoopIterations c.loopIterations = c.config.maxLoopIterationsVM
else: else:
msgWriteln(c.config, "stack trace: (most recent call last)") msgWriteln(c.config, "stack trace: (most recent call last)")
stackTraceAux(c, tos, pc) stackTraceAux(c, tos, pc)
globalError(c.config, c.debug[pc], errTooManyIterations) globalError(c.config, c.debug[pc], errTooManyIterations % $c.config.maxLoopIterationsVM)
dec(c.loopIterations) dec(c.loopIterations)
proc recSetFlagIsRef(arg: PNode) = proc recSetFlagIsRef(arg: PNode) =
@ -513,8 +513,7 @@ const
errConstantDivisionByZero = "division by zero" errConstantDivisionByZero = "division by zero"
errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'" errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'"
errTooManyIterations = "interpretation requires too many iterations; " & errTooManyIterations = "interpretation requires too many iterations; " &
"if you are sure this is not a bug in your code edit " & "if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
"compiler/vmdef.MaxLoopIterations and rebuild the compiler"
errFieldXNotFound = "node lacks field: " errFieldXNotFound = "node lacks field: "
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =

View file

@ -23,8 +23,6 @@ const
byteExcess* = 128 # we use excess-K for immediates byteExcess* = 128 # we use excess-K for immediates
MaxLoopIterations* = 10_000_000 # max iterations of all loops
# Calculate register shifts, masks and ranges # Calculate register shifts, masks and ranges
const const
@ -259,14 +257,14 @@ type
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx = proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx =
PCtx(code: @[], debug: @[], PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], 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: "", comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "",
cache: cache, config: g.config, graph: g) cache: cache, config: g.config, graph: g)
proc refresh*(c: PCtx, module: PSym) = proc refresh*(c: PCtx, module: PSym) =
c.module = module c.module = module
c.prc = PProc(blocks: @[]) c.prc = PProc(blocks: @[])
c.loopIterations = MaxLoopIterations c.loopIterations = c.config.maxLoopIterationsVM
proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} =
result = c.callbacks.len result = c.callbacks.len

View file

@ -125,6 +125,7 @@ Advanced options:
--incremental:on|off only recompile the changed modules (experimental!) --incremental:on|off only recompile the changed modules (experimental!)
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
--errorMax:N stop compilation after N errors; 0 means unlimited --errorMax:N stop compilation after N errors; 0 means unlimited
--maxLoopIterationsVM:N set max iterations for all VM loops
--experimental:$1 --experimental:$1
enable experimental language feature enable experimental language feature
--legacy:$2 --legacy:$2

View file

@ -1,5 +1,5 @@
discard """ 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 # issue #9829