summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2025-05-21 08:41:13 +0200
committerJean Boussier <[email protected]>2025-05-21 09:29:27 +0200
commit0964593e5d7cee2f6a72911813dc72a6152f4ec9 (patch)
tree3f565bb054d369a954b7817698ee6b0a51ccc404 /proc.c
parentc980cab1552e2319ef40020a06a09dd7a0582ed0 (diff)
Shrink `sym_proc_cache` by half
There is no need to store the symbol and the proc given the proc has a reference to the symbol. This makes the cache half as small, now fitting in an object slot, but also make it easier to allow that cache to be used by ractors, assuming we'd make `Symbol#to_proc` return a shareable proc.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13390
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/proc.c b/proc.c
index c6568fe1a6..3b8ccebb22 100644
--- a/proc.c
+++ b/proc.c
@@ -1515,6 +1515,7 @@ rb_hash_proc(st_index_t hash, VALUE prc)
return hash;
}
+static VALUE sym_proc_cache = Qfalse;
/*
* call-seq:
@@ -1533,32 +1534,32 @@ rb_hash_proc(st_index_t hash, VALUE prc)
VALUE
rb_sym_to_proc(VALUE sym)
{
- static VALUE sym_proc_cache = Qfalse;
enum {SYM_PROC_CACHE_SIZE = 67};
- VALUE proc;
- long index;
- ID id;
-
- id = SYM2ID(sym);
if (rb_ractor_main_p()) {
- index = (id % SYM_PROC_CACHE_SIZE) << 1;
if (!sym_proc_cache) {
- sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE * 2);
- rb_vm_register_global_object(sym_proc_cache);
- rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
- }
- if (RARRAY_AREF(sym_proc_cache, index) == sym) {
- return RARRAY_AREF(sym_proc_cache, index + 1);
+ sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE);
+ rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE - 1, Qnil);
}
- else {
- proc = sym_proc_new(rb_cProc, ID2SYM(id));
- RARRAY_ASET(sym_proc_cache, index, sym);
- RARRAY_ASET(sym_proc_cache, index + 1, proc);
- return proc;
+
+ ID id = SYM2ID(sym);
+ long index = (id % SYM_PROC_CACHE_SIZE);
+ VALUE procval = RARRAY_AREF(sym_proc_cache, index);
+ if (RTEST(procval)) {
+ rb_proc_t *proc;
+ GetProcPtr(procval, proc);
+
+ if (proc->block.as.symbol == sym) {
+ return procval;
+ }
}
+
+ procval = sym_proc_new(rb_cProc, sym);
+ RARRAY_ASET(sym_proc_cache, index, procval);
+
+ return RB_GC_GUARD(procval);
} else {
- return sym_proc_new(rb_cProc, ID2SYM(id));
+ return sym_proc_new(rb_cProc, sym);
}
}
@@ -4575,6 +4576,8 @@ Init_Proc(void)
void
Init_Binding(void)
{
+ rb_gc_register_address(&sym_proc_cache);
+
rb_cBinding = rb_define_class("Binding", rb_cObject);
rb_undef_alloc_func(rb_cBinding);
rb_undef_method(CLASS_OF(rb_cBinding), "new");