aboutsummaryrefslogtreecommitdiffhomepage
path: root/interp
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2022-08-04 15:26:44 -0700
committerRon Evans <[email protected]>2022-08-20 07:40:39 +0200
commit0b77e92c508bfd2a7d2cd871bc565ec63a679979 (patch)
tree8fb1a8c8e75b86885f01c56d8440afd9c80153ff /interp
parenta4ee98e0e1f7a8a30b066c97936b32e795d5733d (diff)
downloadtinygo-0b77e92c508bfd2a7d2cd871bc565ec63a679979.tar.gz
tinygo-0b77e92c508bfd2a7d2cd871bc565ec63a679979.zip
make interp timeout configurable from command line
Diffstat (limited to 'interp')
-rw-r--r--interp/interp.go12
-rw-r--r--interp/interp_test.go3
-rw-r--r--interp/interpreter.go9
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 {