summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
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