diff options
author | Damian Gryski <[email protected]> | 2022-08-04 15:26:44 -0700 |
---|---|---|
committer | Ron Evans <[email protected]> | 2022-08-20 07:40:39 +0200 |
commit | 0b77e92c508bfd2a7d2cd871bc565ec63a679979 (patch) | |
tree | 8fb1a8c8e75b86885f01c56d8440afd9c80153ff /interp | |
parent | a4ee98e0e1f7a8a30b066c97936b32e795d5733d (diff) | |
download | tinygo-0b77e92c508bfd2a7d2cd871bc565ec63a679979.tar.gz tinygo-0b77e92c508bfd2a7d2cd871bc565ec63a679979.zip |
make interp timeout configurable from command line
Diffstat (limited to 'interp')
-rw-r--r-- | interp/interp.go | 12 | ||||
-rw-r--r-- | interp/interp_test.go | 3 | ||||
-rw-r--r-- | interp/interpreter.go | 9 |
3 files changed, 12 insertions, 12 deletions
diff --git a/interp/interp.go b/interp/interp.go index 87aadf37e..a1f5f507a 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -30,10 +30,11 @@ type runner struct { objects []object // slice of objects in memory globals map[llvm.Value]int // map from global to index in objects slice start time.Time + timeout time.Duration callsExecuted uint64 } -func newRunner(mod llvm.Module, debug bool) *runner { +func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner { r := runner{ mod: mod, targetData: llvm.NewTargetData(mod.DataLayout()), @@ -42,6 +43,7 @@ func newRunner(mod llvm.Module, debug bool) *runner { objects: []object{{}}, globals: make(map[llvm.Value]int), start: time.Now(), + timeout: timeout, } r.pointerSize = uint32(r.targetData.PointerSize()) r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0) @@ -58,8 +60,8 @@ func (r *runner) dispose() { // Run evaluates runtime.initAll function as much as possible at compile time. // Set debug to true if it should print output while running. -func Run(mod llvm.Module, debug bool) error { - r := newRunner(mod, debug) +func Run(mod llvm.Module, timeout time.Duration, debug bool) error { + r := newRunner(mod, timeout, debug) defer r.dispose() initAll := mod.NamedFunction("runtime.initAll") @@ -199,10 +201,10 @@ func Run(mod llvm.Module, debug bool) error { // RunFunc evaluates a single package initializer at compile time. // Set debug to true if it should print output while running. -func RunFunc(fn llvm.Value, debug bool) error { +func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error { // Create and initialize *runner object. mod := fn.GlobalParent() - r := newRunner(mod, debug) + r := newRunner(mod, timeout, debug) defer r.dispose() initName := fn.Name() if !strings.HasSuffix(initName, ".init") { diff --git a/interp/interp_test.go b/interp/interp_test.go index c42586533..55ad3eaef 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" "testing" + "time" "tinygo.org/x/go-llvm" ) @@ -52,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) { defer mod.Dispose() // Perform the transform. - err = Run(mod, false) + err = Run(mod, 10*time.Minute, false) if err != nil { if err, match := err.(*Error); match { println(err.Error()) diff --git a/interp/interpreter.go b/interp/interpreter.go index 317bc6c03..95c99c842 100644 --- a/interp/interpreter.go +++ b/interp/interpreter.go @@ -17,8 +17,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent locals := make([]value, len(fn.locals)) r.callsExecuted++ - t0 := time.Since(r.start) - // Parameters are considered a kind of local values. for i, param := range params { locals[i] = param @@ -143,11 +141,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent } switch inst.opcode { case llvm.Ret: - const maxInterpSeconds = 180 - if t0 > maxInterpSeconds*time.Second { - // Running for more than maxInterpSeconds seconds. This should never happen, but does. + if time.Since(r.start) > r.timeout { + // Running for more than the allowed timeout; This shouldn't happen, but it does. // See github.com/tinygo-org/tinygo/issues/2124 - return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %d seconds, timing out (executed calls: %d)", maxInterpSeconds, r.callsExecuted)) + return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %s, timing out (executed calls: %d)", r.timeout, r.callsExecuted)) } if len(operands) != 0 { |