From 9deee38dc8b419bf9401cc04ccc0aeca47052658 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Tue, 1 Jul 2014 22:40:40 -0500 Subject: [PATCH] Fix off-by-one in TCO Now we have the ability to define a generator in jq: def for(cond; update): def _for: if cond then ., (update | _for) else . end; _for; for(. < 10; . + 1) # generates numbers between `.` and 10 Running this by hand with --debug-dump-disasm (with a fix for that coming up next) we can see that the call to _for is optimized: _for:0: 0000 DUP 0001 CALL_JQ cond:0^1 0005 JUMP_F 0022 0007 POP 0008 FORK 0012 0010 JUMP 0020 0012 CALL_JQ update:1^1 0016 TAIL_CALL_JQ _for:0^1 0020 JUMP 0023 0022 POP 0023 RET And timing this with 1000, 10000, 100000 iterations shows that indeed we must be applying TCO; otherwise, without TCO, this gets very slow very quickly. --- execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execute.c b/execute.c index 974707f5..860e46b7 100644 --- a/execute.c +++ b/execute.c @@ -801,7 +801,7 @@ static int ret_follows(uint16_t *pc) { return 1; if (*pc++ != JUMP) return 0; - return ret_follows(pc + *pc); // FIXME, might be ironic + return ret_follows(pc + *pc + 1); // FIXME, might be ironic } /*