Allocate space for max. number of frame variables up front.
Allows us to avoid reallocating a new vector after every tail-call.
This commit is contained in:
parent
6a12d967ef
commit
bc10f59c6e
26
interp.c
26
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);
|
||||
|
|
|
|||
6
interp.h
6
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue