ref: 8ce0725162119a6dc59e5d3be4700e8afcb4417e
parent: 05b59aa248ee0e5cf56696ff0e4334948d0583fd
author: Jan-Willem Maessen <jmaessen@fb.com>
date: Sun Jan 21 11:43:17 EST 2024
Turn eval into evali This is based on the observation that two things can happen in eval: * The stack is clear, in which case the value in n is a direct reference to the WHNF of the original argument * The stack is not clear, in which case the top of stack is an AP representing the argument without indirections. In either case there's no need to push / pop it again and go chasing after indirections. This represents a small time savings of about .2s on bootstrap, see https://docs.google.com/spreadsheets/d/1Tw6LLwTEU0VxdWcf_ZUF1_T9KlchpNEFXKNiAarxd4I which shows data from 10 interleaved after/before runs plus some statistically bootstrapped averages with histograms showing limited overlap.
--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -1897,21 +1897,8 @@
return n;
}
-void eval(NODEPTR n);
+NODEPTR evali(NODEPTR n);
-/* Evaluate and skip indirections. */
-static INLINE NODEPTR
-evali(NODEPTR n)
-{- /* Need to push and pop in case GC happens */
- PUSH(n);
- eval(n);
- n = POPTOP();
- while (GETTAG(n) == T_IND)
- n = INDIR(n);
- return n;
-}
-
/* Follow indirections */
static INLINE NODEPTR
indir(NODEPTR n)
@@ -2141,8 +2128,8 @@
void execio(NODEPTR *);
/* Evaluate a node, returns when the node is in WHNF. */
-void
-eval(NODEPTR an)
+NODEPTR
+evali(NODEPTR an)
{NODEPTR n = an;
stackptr_t stk = stack_ptr;
@@ -2158,7 +2145,7 @@
#endif
/* Reset stack pointer and return. */
-#define RET do { stack_ptr = stk; return; } while(0)+#define RET do { goto ret; } while(0)/* Check that there are at least n arguments, return if not. */
#define CHECK(n) do { if (stack_ptr - stk < (n)) RET; } while(0)@@ -2402,7 +2389,7 @@
ERR1("error: %s", msg);#endif /* WANT_STDIO */
}
- case T_SEQ: CHECK(2); eval(ARG(TOP(0))); POP(2); n = TOP(-1); y = ARG(n); GOIND(y); /* seq x y = eval(x); y */
+ case T_SEQ: CHECK(2); evali(ARG(TOP(0))); POP(2); n = TOP(-1); y = ARG(n); GOIND(y); /* seq x y = eval(x); y */
case T_EQUAL:
CHECK(2); r = compare(TOP(1)); POP(2); n = TOP(-1); GOIND(r==0 ? combTrue : combFalse);
@@ -2469,6 +2456,14 @@
ERR1("eval tag %d", GETTAG(n));}
}
+ ret:
+ if (stack_ptr != stk) {+ // In this case, n was an AP that got pushed and potentially
+ // updated.
+ stack_ptr = stk;
+ n = TOP(-1);
+ }
+ return n;
}
/* This is the interpreter for the IO monad operations.
--
⑨