diff --git a/interp.c b/interp.c index a6e7ee5..6aa7db1 100644 --- a/interp.c +++ b/interp.c @@ -90,22 +90,26 @@ value_t run_interpreter(value_t lambda, value_t argv) { /* Builtin functions replace the byte-code and tail-call * steps; they also do not require frame variables. */ + state.nframe = 0; _get_builtin_fn(state.lambda.value)(&state); } else { - /* Allocate frame variables, initially undefined */ - state.frame.value = make_vector(get_fixnum(_LAMBDA_SLOT(state.lambda.value, FRAME_VARS)), UNDEFINED); + state.nframe = get_fixnum(_LAMBDA_SLOT(state.lambda.value, FRAME_VARS)); + release_assert((0 <= state.nframe) && (state.nframe <= 120)); run_byte_code(&state); perform_tail_call(&state); } - /* Clear temporaries so they can be GC'd. */ - state.frame.value = UNDEFINED; - state.in1.value = UNDEFINED; - state.in2.value = UNDEFINED; - state.in3.value = UNDEFINED; + /* Clear (used) frame-variable slots so they can be GC'd. */ + for (fixnum_t i = 0; i < state.nframe; ++i) + _get_vector(state.frame.value)->elements[i] = UNDEFINED; + + /* Clear temporaries. */ + state.in1.value = UNDEFINED; + state.in2.value = UNDEFINED; + state.in3.value = UNDEFINED; if (run_finalizers) { @@ -504,7 +508,7 @@ static value_t get_input(const interp_state_t *state, fixnum_t var) vector_t *vec = _get_vector(state->frame.value); var -= 128; - release_assert(var < vec->size); + release_assert(var < state->nframe); return vec->elements[var]; } /* 248 ... 252 are reserved */ @@ -527,15 +531,15 @@ static void set_output(const interp_state_t *state, fixnum_t var, value_t val) release_assert((var >= 128) && (var <= 255)); var -= 128; - release_assert(var < vec->size); + release_assert(var < state->nframe); vec->elements[var] = val; } static void register_state(interp_state_t *state, value_t lambda, value_t argv) { register_gc_root(&state->lambda, lambda); - register_gc_root(&state->frame, UNDEFINED); register_gc_root(&state->argv, argv); + register_gc_root(&state->frame, make_vector(120, UNDEFINED)); register_gc_root(&state->k, FALSE_VALUE); register_gc_root(&state->ctx, FALSE_VALUE); register_gc_root(&state->in1, FALSE_VALUE); @@ -546,8 +550,8 @@ static void register_state(interp_state_t *state, value_t lambda, value_t argv) static void unregister_state(interp_state_t *state) { unregister_gc_root(&state->lambda); - unregister_gc_root(&state->frame); unregister_gc_root(&state->argv); + unregister_gc_root(&state->frame); unregister_gc_root(&state->k); unregister_gc_root(&state->ctx); unregister_gc_root(&state->in1); diff --git a/interp.h b/interp.h index 5cf6bd2..6f46889 100644 --- a/interp.h +++ b/interp.h @@ -1,9 +1,8 @@ -/* Need to ensure gc.h is included first, because it depends on interp.h. */ -#include "gc.h" - #ifndef INTERP_H_9c7eea5c5cd0f7a32b79a8ca0ab2969f #define INTERP_H_9c7eea5c5cd0f7a32b79a8ca0ab2969f +#include "gc.h" + typedef struct interp_state { gc_root_t lambda; @@ -14,6 +13,7 @@ typedef struct interp_state gc_root_t in1; gc_root_t in2; gc_root_t in3; + fixnum_t nframe; } interp_state_t; void interpreter_init(void);