summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorOle Friis Østergaard <olefriis@gmail.com>2023-02-28 13:44:57 +0100
committerJohn Hawthorn <john@hawthorn.email>2023-03-08 09:34:31 -0800
commit1a3f8e1c9f6ce4b1cd7236fdcdd17a8719654320 (patch)
tree1c98ce45d048e918923d7e5267062af5072538cf /vm_insnhelper.c
parentdc1e6573f2a1e3f85dd35c2acc26b647bd44e3b7 (diff)
downloadruby-1a3f8e1c9f6ce4b1cd7236fdcdd17a8719654320.tar.gz
Add defined_ivar instruction
This is a variation of the `defined` instruction, for use when we are checking for an instance variable. Splitting this out as a separate instruction lets us skip some checks, and it also allows us to use an instance variable cache, letting shape analysis speed up the operation further.
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 74181ac131..ff91c3c362 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1143,9 +1143,9 @@ fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, in
#define ATTR_INDEX_NOT_SET (attr_index_t)-1
-ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, const rb_iseq_t *, IVC, const struct rb_callcache *, int));
+ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, const rb_iseq_t *, IVC, const struct rb_callcache *, int, VALUE));
static inline VALUE
-vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
+vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, VALUE default_value)
{
#if OPT_IC_FOR_IVAR
VALUE val = Qundef;
@@ -1153,7 +1153,7 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
VALUE * ivar_list;
if (SPECIAL_CONST_P(obj)) {
- return Qnil;
+ return default_value;
}
#if SHAPE_IN_BASIC_FLAGS
@@ -1200,7 +1200,7 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
ivar_list = ivtbl->ivptr;
}
else {
- return Qnil;
+ return default_value;
}
}
@@ -1218,7 +1218,7 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
RUBY_ASSERT(cached_id != OBJ_TOO_COMPLEX_SHAPE_ID);
if (index == ATTR_INDEX_NOT_SET) {
- return Qnil;
+ return default_value;
}
val = ivar_list[index];
@@ -1260,7 +1260,7 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
if (shape_id == OBJ_TOO_COMPLEX_SHAPE_ID) {
if (!rb_id_table_lookup(ROBJECT_IV_HASH(obj), id, &val)) {
- val = Qnil;
+ val = default_value;
}
}
else {
@@ -1281,13 +1281,15 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
vm_ic_attr_index_initialize(ic, shape_id);
}
- val = Qnil;
+ val = default_value;
}
}
}
- RUBY_ASSERT(!UNDEF_P(val));
+ if (default_value != Qundef) {
+ RUBY_ASSERT(!UNDEF_P(val));
+ }
return val;
@@ -1572,7 +1574,7 @@ rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID
static inline VALUE
vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
{
- return vm_getivar(obj, id, iseq, ic, NULL, FALSE);
+ return vm_getivar(obj, id, iseq, ic, NULL, FALSE, Qnil);
}
static inline void
@@ -3459,7 +3461,7 @@ vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_call
const struct rb_callcache *cc = calling->cc;
RB_DEBUG_COUNTER_INC(ccf_ivar);
cfp->sp -= 1;
- VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE);
+ VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE, Qnil);
return ivar;
}