mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
vm.c: add constant lookup cache with generation counter
Cache OP_GETCONST results in a global direct-mapped cache (64 entries) keyed by (irep, sym). Invalidate all entries via a generation counter bumped on mrb_const_set(), mrb_const_remove(), and mrb_define_const_id(). ~10% faster on constant-heavy code; disabled with MRB_NO_CONST_CACHE. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -243,6 +243,24 @@ struct mrb_cache_entry {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MRB_CONST_CACHE_SIZE
|
||||
# undef MRB_NO_CONST_CACHE
|
||||
mrb_static_assert_powerof2(MRB_CONST_CACHE_SIZE);
|
||||
#else
|
||||
/* default constant cache size: 64 */
|
||||
/* cache size needs to be power of 2 */
|
||||
# define MRB_CONST_CACHE_SIZE (1<<6)
|
||||
#endif
|
||||
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
struct mrb_const_cache_entry {
|
||||
const struct mrb_irep *irep;
|
||||
mrb_sym sym;
|
||||
uint32_t generation;
|
||||
mrb_value value;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mrb_jmpbuf;
|
||||
|
||||
typedef void (*mrb_atexit_func)(mrb_state*);
|
||||
@@ -297,6 +315,11 @@ struct mrb_state {
|
||||
struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
|
||||
#endif
|
||||
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
uint32_t const_generation;
|
||||
struct mrb_const_cache_entry const_cache[MRB_CONST_CACHE_SIZE];
|
||||
#endif
|
||||
|
||||
mrb_sym symidx;
|
||||
const char **symtbl;
|
||||
size_t symcapa;
|
||||
|
||||
@@ -1431,6 +1431,9 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
|
||||
mrb_class_name_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(v), sym);
|
||||
}
|
||||
mrb_obj_iv_set(mrb, mrb_obj_ptr(mod), sym, v);
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
mrb->const_generation++;
|
||||
#endif
|
||||
|
||||
if (!mrb->bootstrapping) {
|
||||
mrb_value name = mrb_symbol_value(sym);
|
||||
@@ -1457,6 +1460,9 @@ mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym)
|
||||
{
|
||||
mod_const_check(mrb, mod);
|
||||
mrb_iv_remove(mrb, mod, sym);
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
mrb->const_generation++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1474,6 +1480,9 @@ MRB_API void
|
||||
mrb_define_const_id(mrb_state *mrb, struct RClass *mod, mrb_sym name, mrb_value v)
|
||||
{
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)mod, name, v);
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
mrb->const_generation++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2028,9 +2028,26 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_GETCONST, BB) {
|
||||
mrb_value v = mrb_vm_const_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = v;
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
mrb_sym sym = irep->syms[b];
|
||||
uint32_t h = mrb_int_hash_func(mrb, ((intptr_t)irep) ^ sym) & (MRB_CONST_CACHE_SIZE-1);
|
||||
struct mrb_const_cache_entry *cc = &mrb->const_cache[h];
|
||||
if (cc->irep == irep && cc->sym == sym && cc->generation == mrb->const_generation) {
|
||||
regs[a] = cc->value;
|
||||
NEXT;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
mrb_value v = mrb_vm_const_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = v;
|
||||
#ifndef MRB_NO_CONST_CACHE
|
||||
cc->irep = irep;
|
||||
cc->sym = sym;
|
||||
cc->generation = mrb->const_generation;
|
||||
cc->value = v;
|
||||
#endif
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user