summaryrefslogtreecommitdiff
path: root/vm_insnhelper.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 /vm_insnhelper.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 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 0aeab30077..72c90a8a5c 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1286,7 +1286,7 @@ vm_getclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_contr
{
if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) {
VALUE v = Qundef;
- RB_DEBUG_COUNTER_INC(cvar_inline_hit);
+ RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
if (st_lookup(RCLASS_IV_TBL(ic->entry->class_value), (st_data_t)id, &v)) {
return v;
@@ -1298,6 +1298,10 @@ vm_getclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_contr
VALUE cvar_value = rb_cvar_find(klass, id, &defined_class);
+ if (RB_TYPE_P(defined_class, T_ICLASS)) {
+ defined_class = RBASIC(defined_class)->klass;
+ }
+
struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
if (!rb_cvc_tbl) {
@@ -1307,11 +1311,7 @@ vm_getclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_contr
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 = defined_class;
- 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);
+ rb_bug("should have cvar cache entry");
} else {
ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
}
@@ -1323,11 +1323,42 @@ vm_getclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_contr
}
static inline void
-vm_setclassvariable(const rb_cref_t *cref, const rb_control_frame_t *cfp, ID id, VALUE val)
+vm_setclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic)
{
+ if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) {
+ RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
+
+ rb_class_ivar_set(ic->entry->class_value, id, val);
+ return;
+ }
+
VALUE klass = vm_get_cvar_base(cref, cfp, 1);
rb_cvar_set(klass, id, val);
+
+ VALUE defined_class = 0;
+ rb_cvar_find(klass, id, &defined_class);
+
+ if (RB_TYPE_P(defined_class, T_ICLASS)) {
+ defined_class = RBASIC(defined_class)->klass;
+ }
+
+ struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
+
+ if (!rb_cvc_tbl) {
+ rb_bug("the cvc table should be set");
+ }
+
+ struct rb_cvar_class_tbl_entry *ent;
+
+ if (!rb_id_table_lookup(rb_cvc_tbl, id, (VALUE*)&ent)) {
+ rb_bug("should have cvar cache entry");
+ } else {
+ ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
+ }
+
+ ic->entry = ent;
+ RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value);
}
static inline VALUE