summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreileencodes <[email protected]>2021-04-23 13:59:16 -0400
committerAaron Patterson <[email protected]>2021-05-11 12:04:27 -0700
commit08de37f9fa3469365e6b5c964689ae2bae0eb9f3 ()
tree21b0b6cd2ae3e878bbf0a6dc3f51dce8415c5327
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: Merged: https://.com/ruby/ruby/pull/4340
-rw-r--r--class.c1
-rw-r--r--compile.c5
-rw-r--r--debug_counter.h3
-rw-r--r--insns.def4
-rw-r--r--variable.c19
-rw-r--r--vm_insnhelper.c45
6 files changed, 65 insertions, 12 deletions
@@ -960,6 +960,7 @@ rb_include_class_new(VALUE module, VALUE super)
RCLASS_CONST_TBL(module) = rb_id_table_create(0);
}
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
RCLASS_SET_SUPER(klass, super);
@@ -8044,8 +8044,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
if (!popped) {
ADD_INSN(ret, line_node, dup);
}
- ADD_INSN1(ret, line_node, setclassvariable,
- ID2SYM(node->nd_vid));
break;
}
case NODE_OP_ASGN1: {
@@ -24,7 +24,8 @@ RB_DEBUG_COUNTER(mc_inline_miss_same_cme) // IMC miss, but same CME
RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition
RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods
-RB_DEBUG_COUNTER(cvar_inline_hit) // cvar cache hit
RB_DEBUG_COUNTER(cvar_inline_miss) // miss inline cache
RB_DEBUG_COUNTER(cvar_class_invalidate) // invalidate cvar cache when define a cvar that's defined on a subclass
RB_DEBUG_COUNTER(cvar_include_invalidate) // invalidate cvar cache on module include or prepend
@@ -244,14 +244,14 @@ getclassvariable
/* Set value of class variable id of klass as val. */
DEFINE_INSN
setclassvariable
-(ID id)
(VALUE val)
()
/* "class variable access from toplevel" warning can be hooked. */
// attr bool leaf = false; /* has rb_warning() */
{
vm_ensure_not_refinement_module(GET_SELF());
- vm_setclassvariable(vm_get_cref(GET_EP()), GET_CFP(), id, val);
}
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
@@ -40,6 +40,7 @@
#include "vm_sync.h"
RUBY_EXTERN rb_serial_t 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);
// 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.
@@ -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);
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);
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);
} 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)
{
VALUE klass = vm_get_cvar_base(cref, cfp, 1);
rb_cvar_set(klass, id, val);
}
static inline VALUE