Implement environment cache.
* mes.c (cache_save, cache_lookup, cache_invalidate, cache_invalidate_range): Implement cache for environment. (assq_ref_cache): New function, perform cached lookups. (builtin_eval,lookup_macro): Use it. (set_cdr_x): Invalidate cache. (set_x): Likewise. (apply_env): Likewise.
This commit is contained in:
parent
d1b8f0ff0c
commit
7885096526
137
mes.c
137
mes.c
|
@ -70,6 +70,7 @@ scm scm_nil = {SCM, "()"};
|
|||
scm scm_dot = {SCM, "."};
|
||||
scm scm_f = {SCM, "#f"};
|
||||
scm scm_t = {SCM, "#t"};
|
||||
scm scm_undefined = {SCM, "*undefined*"};
|
||||
scm scm_unspecified = {SCM, "*unspecified*"};
|
||||
scm scm_closure = {SCM, "*closure*"};
|
||||
scm scm_circular = {SCM, "*circular*"};
|
||||
|
@ -183,6 +184,7 @@ scm *
|
|||
set_cdr_x (scm *x, scm *e)
|
||||
{
|
||||
assert (x->type == PAIR);
|
||||
cache_invalidate (x->cdr);
|
||||
x->cdr = e;
|
||||
return &scm_unspecified;
|
||||
}
|
||||
|
@ -190,12 +192,7 @@ set_cdr_x (scm *x, scm *e)
|
|||
scm *
|
||||
set_x (scm *x, scm *e, scm *a)
|
||||
{
|
||||
return set_cdr_x (assq (x, a), e);
|
||||
}
|
||||
|
||||
scm *
|
||||
set_env_x (scm *x, scm *e, scm *a)
|
||||
{
|
||||
cache_invalidate (x);
|
||||
return set_cdr_x (assq (x, a), e);
|
||||
}
|
||||
|
||||
|
@ -286,18 +283,100 @@ pairlis (scm *x, scm *y, scm *a)
|
|||
scm *
|
||||
assq (scm *x, scm *a)
|
||||
{
|
||||
while (a != &scm_nil && EQ_P (x, a->car->car) == &scm_f) {
|
||||
a = a->cdr;
|
||||
}
|
||||
if (a == &scm_nil) {
|
||||
#if DEBUG
|
||||
printf ("alist miss: %s\n", x->name);
|
||||
#endif
|
||||
return &scm_f;
|
||||
}
|
||||
return a->car;
|
||||
while (a != &scm_nil && EQ_P (x, a->car->car) == &scm_f) a = a->cdr;
|
||||
return a != &scm_nil ? a->car : &scm_f;
|
||||
}
|
||||
|
||||
#define ENV_CACHE 1
|
||||
#if !ENV_CACHE
|
||||
scm *
|
||||
assq_ref_cache (scm *x, scm *a) //internal
|
||||
{
|
||||
x = assq (x, a);
|
||||
if (x == &scm_f) return &scm_f;
|
||||
return x->cdr;
|
||||
}
|
||||
scm*cache_invalidate (scm*x){}
|
||||
scm*cache_invalidate_range (scm*p,scm*a){}
|
||||
scm*cache_save (scm*p){}
|
||||
scm*cache_lookup (scm*x){}
|
||||
|
||||
#else // ENV_CACHE
|
||||
|
||||
#define CACHE_SIZE 20
|
||||
scm *env_cache_cars[CACHE_SIZE];
|
||||
scm *env_cache_cdrs[CACHE_SIZE];
|
||||
int cache_threshold = 0;
|
||||
scm *
|
||||
cache_save (scm *p)
|
||||
{
|
||||
int n = p->car->value;
|
||||
if (n < cache_threshold) return &scm_unspecified;
|
||||
int j = -1;
|
||||
for (int i=0; i < CACHE_SIZE; i++) {
|
||||
if (!env_cache_cars[i]) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
if (env_cache_cars[i] == p->car) return &scm_unspecified;
|
||||
if (n > env_cache_cars[i]->value) {
|
||||
n = env_cache_cars[i]->value;
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
if (j >= 0) {
|
||||
cache_threshold = p->car->value;
|
||||
env_cache_cars[j] = p->car;
|
||||
env_cache_cdrs[j] = p->cdr;
|
||||
}
|
||||
return &scm_unspecified;
|
||||
}
|
||||
|
||||
scm *
|
||||
cache_lookup (scm *x)
|
||||
{
|
||||
for (int i=0; i < CACHE_SIZE; i++) {
|
||||
if (!env_cache_cars[i]) break;
|
||||
if (env_cache_cars[i] == x) return env_cache_cdrs[i];
|
||||
}
|
||||
return &scm_undefined;
|
||||
}
|
||||
|
||||
scm *
|
||||
cache_invalidate (scm *x)
|
||||
{
|
||||
for (int i=0; i < CACHE_SIZE; i++) {
|
||||
if (env_cache_cars[i] == x) {
|
||||
env_cache_cars[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return &scm_unspecified;
|
||||
}
|
||||
|
||||
scm *
|
||||
cache_invalidate_range (scm *p, scm *a)
|
||||
{
|
||||
do {
|
||||
cache_invalidate (p->car->car);
|
||||
p = p->cdr;
|
||||
} while (p != a);
|
||||
return &scm_unspecified;
|
||||
}
|
||||
|
||||
scm *
|
||||
assq_ref_cache (scm *x, scm *a)
|
||||
{
|
||||
x->value++;
|
||||
scm *c = cache_lookup (x);
|
||||
if (c != &scm_undefined) return c;
|
||||
while (a != &scm_nil && x != a->car->car) a = a->cdr;
|
||||
if (a == &scm_nil) return &scm_undefined;
|
||||
cache_save (a->car);
|
||||
return a->car->cdr;
|
||||
}
|
||||
#endif // ENV_CACHE
|
||||
|
||||
scm *
|
||||
evlis (scm *m, scm *a)
|
||||
{
|
||||
|
@ -322,7 +401,10 @@ apply_env (scm *fn, scm *x, scm *a)
|
|||
}
|
||||
else if (fn->car == &scm_lambda) {
|
||||
scm *p = pairlis (cadr (fn), x, a);
|
||||
return builtin_eval (cons (&symbol_begin, cddr (fn)), cons (cons (&scm_closure, p), p));
|
||||
cache_invalidate_range (p, a->cdr);
|
||||
scm *r = builtin_eval (cons (&symbol_begin, cddr (fn)), cons (cons (&scm_closure, p), p));
|
||||
cache_invalidate_range (p, a->cdr);
|
||||
return r;
|
||||
}
|
||||
else if (fn->car == &scm_closure) {
|
||||
scm *args = caddr (fn);
|
||||
|
@ -330,7 +412,10 @@ apply_env (scm *fn, scm *x, scm *a)
|
|||
a = cdadr (fn);
|
||||
a = cdr (a);
|
||||
scm *p = pairlis (args, x, a);
|
||||
return builtin_eval (cons (&symbol_begin, body), cons (cons (&scm_closure, p), p));
|
||||
cache_invalidate_range (p, a->cdr);
|
||||
scm *r = builtin_eval (cons (&symbol_begin, body), cons (cons (&scm_closure, p), p));
|
||||
cache_invalidate_range (p, a->cdr);
|
||||
return r;
|
||||
}
|
||||
scm *efn = builtin_eval (fn, a);
|
||||
if (efn == &scm_f || efn == &scm_t) assert (!"apply bool");
|
||||
|
@ -348,12 +433,12 @@ builtin_eval (scm *e, scm *a)
|
|||
e = expand_macro_env (e, a);
|
||||
|
||||
if (e->type == SYMBOL) {
|
||||
scm *y = assq (e, a);
|
||||
if (y == &scm_f) {
|
||||
scm *y = assq_ref_cache (e, a);
|
||||
if (y == &scm_undefined) {
|
||||
fprintf (stderr, "eval: unbound variable: %s\n", e->name);
|
||||
assert (!"unbound variable");
|
||||
}
|
||||
return cdr (y);
|
||||
return y;
|
||||
}
|
||||
else if (e->type != PAIR)
|
||||
return e;
|
||||
|
@ -376,7 +461,7 @@ builtin_eval (scm *e, scm *a)
|
|||
if (e->car == &symbol_define_macro)
|
||||
return define (e, a);
|
||||
if (e->car == &symbol_set_x)
|
||||
return set_env_x (cadr (e), builtin_eval (caddr (e), a), a);
|
||||
return set_x (cadr (e), builtin_eval (caddr (e), a), a);
|
||||
#if BUILTIN_QUASIQUOTE
|
||||
if (e->car == &symbol_unquote)
|
||||
return builtin_eval (cadr (e), a);
|
||||
|
@ -616,6 +701,7 @@ internal_make_symbol (char const *s)
|
|||
scm *x = (scm*)malloc (sizeof (scm));
|
||||
x->type = SYMBOL;
|
||||
x->name = strdup (s);
|
||||
x->value = 0;
|
||||
symbols = cons (x, symbols);
|
||||
return x;
|
||||
}
|
||||
|
@ -1413,14 +1499,13 @@ scm *
|
|||
define_macro (scm *x, scm *a)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
scm *
|
||||
lookup_macro (scm *x, scm *a)
|
||||
{
|
||||
scm *m = assq (x, a);
|
||||
if (m != &scm_f && macro_p (cdr (m)) != &scm_f)
|
||||
return cdr (m)->macro;
|
||||
if (x->type != SYMBOL) return &scm_f;
|
||||
scm *m = assq_ref_cache (x, a);
|
||||
if (macro_p (m) == &scm_t) return m->macro;
|
||||
return &scm_f;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue