mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-15 15:21:03 -08:00
bytevm: faster closure creation and less consing
OP_FLET previously had to first create functions referencing the env "before" and then add these functions to the env "after". This is because we were addressing from the stack top: env: bottom[0:var]top fn1: ref(top-1) fn2: ref(top-1) env: bottom[0:var, 1:fn1, 2:f2n]top Otherwise fn2 referencing top-1 would point to fn1 instead of var. Now that locals are addressed from the stack bottom we can add functions eagerly to locals without consing intermediate sequence of functions: env: bottom[0:var]top fn1: ref(bottom+0) env: bottom[0:var, 1:fn1]top fn2: ref(bottom+0) env: bottom[0:var, 1:fn1, 2:f2n]top That saves us one loop (nfun iterations). A similar observation applies to LABELS, although we still need the closure fixup because earlier function may reference a function defined later, so we still need a second loop. That said we don't have to cons a separate sequence of functions, because we may iterate over locals vector instead. Both changes save us from an operator that adds a collection to the lcl_env, so we remove tack_lcl macro and its expansion function foot_lcl.
This commit is contained in:
parent
0bf83ad30c
commit
fdf7c77909
1 changed files with 8 additions and 26 deletions
|
|
@ -122,7 +122,6 @@ VEclose_around_arg_type()
|
|||
*/
|
||||
|
||||
#define bind_lcl(env, entry) push_lcl(env, entry)
|
||||
#define tack_lcl(env, entries, n) foot_lcl(env, entries, n)
|
||||
|
||||
#define bind_var(env, var, val) bind_lcl(env, CONS(var, val))
|
||||
#define bind_function(env, fun) bind_lcl(env, fun)
|
||||
|
|
@ -138,19 +137,6 @@ push_lcl(cl_object stack, cl_object new)
|
|||
*(stack->frame.sp++) = new;
|
||||
}
|
||||
|
||||
static void
|
||||
foot_lcl(cl_object stack, cl_object list, cl_index n)
|
||||
{
|
||||
cl_object entry;
|
||||
cl_index idx = n;
|
||||
loop_for_on_unsafe(list) {
|
||||
entry = ECL_CONS_CAR(list);
|
||||
idx--;
|
||||
*(stack->frame.sp+idx) = entry;
|
||||
} end_loop_for_on_unsafe(list);
|
||||
stack->frame.sp += n;
|
||||
}
|
||||
|
||||
static void
|
||||
drop_lcl(cl_object stack, cl_fixnum n)
|
||||
{
|
||||
|
|
@ -724,16 +710,14 @@ ecl_interpret(cl_object frame, cl_object closure, cl_object bytecodes)
|
|||
*/
|
||||
CASE(OP_FLET); {
|
||||
int idx, nfun;
|
||||
cl_object fun_env=ECL_NIL, fun;
|
||||
cl_object fun;
|
||||
GET_OPARG(nfun, vector);
|
||||
/* Create closures. */
|
||||
for(idx = 0; idx<nfun; idx++) {
|
||||
GET_DATA(fun, vector, data);
|
||||
fun = ecl_close_around(fun, lcl_env, lex_env);
|
||||
fun_env = CONS(fun, fun_env);
|
||||
push_lcl(lcl_env, fun);
|
||||
}
|
||||
/* Update the environment with new functions. */
|
||||
tack_lcl(lcl_env, fun_env, nfun);
|
||||
THREAD_NEXT;
|
||||
}
|
||||
/* OP_LABELS nfun{arg}
|
||||
|
|
@ -748,21 +732,19 @@ ecl_interpret(cl_object frame, cl_object closure, cl_object bytecodes)
|
|||
*/
|
||||
CASE(OP_LABELS); {
|
||||
cl_index idx, nfun;
|
||||
cl_object fun_env=ECL_NIL, fun;
|
||||
cl_object fun;
|
||||
cl_object *sp = lcl_env->frame.sp;
|
||||
GET_OPARG(nfun, vector);
|
||||
/* Create closures. */
|
||||
for(idx = 0; idx<nfun; idx++) {
|
||||
GET_DATA(fun, vector, data);
|
||||
fun = close_around_self(fun);
|
||||
fun_env = CONS(fun, fun_env);
|
||||
push_lcl(lcl_env, fun);
|
||||
}
|
||||
/* Update the environment with new functions. */
|
||||
tack_lcl(lcl_env, fun_env, nfun);
|
||||
/* Update the closures so that all functions can call each other */
|
||||
loop_for_on_unsafe(fun_env) {
|
||||
fun = ECL_CONS_CAR(fun_env);
|
||||
for(idx = 0; idx<nfun; idx++) {
|
||||
fun = *sp++;
|
||||
close_around_self_fixup(fun, lcl_env, lex_env);
|
||||
} end_loop_for_on_unsafe(fun_env);
|
||||
}
|
||||
THREAD_NEXT;
|
||||
}
|
||||
/* OP_LFUNCTION index{fixnum} ; local
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue