From 50bc8c61368f84171842c1ead710a5bab6e603bd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Mar 2026 09:07:19 +0900 Subject: [PATCH] vm.c: replace constant cache generation counter with direct invalidation Remove the per-entry generation field and per-state generation counter. Invalidation now clears entries directly, removing one comparison from every OP_GETCONST hot path. Co-authored-by: Claude --- include/mruby.h | 7 +++++-- src/variable.c | 18 +++++++++++++++--- src/vm.c | 3 +-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index a6382e62f..ca879344b 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -256,7 +256,6 @@ mrb_static_assert_powerof2(MRB_CONST_CACHE_SIZE); struct mrb_const_cache_entry { const struct mrb_irep *irep; mrb_sym sym; - uint32_t generation; mrb_value value; }; #endif @@ -316,7 +315,6 @@ struct mrb_state { #endif #ifndef MRB_NO_CONST_CACHE - uint32_t const_generation; struct mrb_const_cache_entry const_cache[MRB_CONST_CACHE_SIZE]; #endif @@ -1307,6 +1305,11 @@ MRB_API void mrb_method_cache_clear(mrb_state *mrb); #else #define mrb_method_cache_clear(mrb) ((void)0) #endif +#ifndef MRB_NO_CONST_CACHE +void mrb_const_cache_clear(mrb_state *mrb); +#else +#define mrb_const_cache_clear(mrb) ((void)0) +#endif /** * Check if mrb_open() failed diff --git a/src/variable.c b/src/variable.c index 3fe20ed36..92c56f76b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1423,6 +1423,18 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) * Raises: * E_TYPE_ERROR: If `mod` is not a class or module. */ +#ifndef MRB_NO_CONST_CACHE +void +mrb_const_cache_clear(mrb_state *mrb) +{ + struct mrb_const_cache_entry *cc = mrb->const_cache; + + for (int i=0; iirep = NULL; + } +} +#endif + MRB_API void mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) { @@ -1432,7 +1444,7 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) } mrb_obj_iv_set(mrb, mrb_obj_ptr(mod), sym, v); #ifndef MRB_NO_CONST_CACHE - mrb->const_generation++; + mrb_const_cache_clear(mrb); #endif if (!mrb->bootstrapping) { @@ -1461,7 +1473,7 @@ 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++; + mrb_const_cache_clear(mrb); #endif } @@ -1481,7 +1493,7 @@ mrb_define_const_id(mrb_state *mrb, struct RClass *mod, mrb_sym name, mrb_value { mrb_obj_iv_set(mrb, (struct RObject*)mod, name, v); #ifndef MRB_NO_CONST_CACHE - mrb->const_generation++; + mrb_const_cache_clear(mrb); #endif } diff --git a/src/vm.c b/src/vm.c index 01da5ac2d..f4983d033 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2032,7 +2032,7 @@ RETRY_TRY_BLOCK: 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) { + if (cc->irep == irep && cc->sym == sym) { regs[a] = cc->value; NEXT; } @@ -2044,7 +2044,6 @@ RETRY_TRY_BLOCK: #ifndef MRB_NO_CONST_CACHE cc->irep = irep; cc->sym = sym; - cc->generation = mrb->const_generation; cc->value = v; #endif }