diff options
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 45 |
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 |