summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2021-04-23 13:59:16 -0400
committerAaron Patterson <aaron.patterson@gmail.com>2021-05-11 12:04:27 -0700
commit08de37f9fa3469365e6b5c964689ae2bae0eb9f3 (patch)
tree21b0b6cd2ae3e878bbf0a6dc3f51dce8415c5327 /variable.c
parente8ae922b62adb00a80d3d4c49f7d7b0e6026eaba (diff)
Filling cache values on cvar write
Instead of on read. Once it's in the inline cache we never have to make one again. We want to eventually put the value into the cache, and the best opportunity to do that is when you write the value.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4340
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/variable.c b/variable.c
index 82918037f9..8c29fbdf3b 100644
--- a/variable.c
+++ b/variable.c
@@ -40,6 +40,7 @@
#include "vm_sync.h"
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
+#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
typedef void rb_gvar_compact_t(void *var);
@@ -3399,6 +3400,24 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
int result = rb_class_ivar_set(target, id, val);
+ struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
+
+ if (!rb_cvc_tbl) {
+ rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
+ }
+
+ struct rb_cvar_class_tbl_entry *ent;
+
+ if (!rb_id_table_lookup(rb_cvc_tbl, id, (VALUE*)&ent)) {
+ ent = ALLOC(struct rb_cvar_class_tbl_entry);
+ ent->class_value = target;
+ ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
+ rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent);
+ RB_DEBUG_COUNTER_INC(cvar_inline_miss);
+ } else {
+ ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
+ }
+
// Break the cvar cache if this is a new class variable
// and target is a module or a subclass with the same
// cvar in this lookup.