Skip to content

Commit

Permalink
Add defined_ivar instruction
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
olefriis authored and jhawthorn committed Mar 8, 2023
1 parent dc1e657 commit 1a3f8e1
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 13 deletions.
5 changes: 2 additions & 3 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5460,9 +5460,8 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,

#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
case NODE_IVAR:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_IVAR),
ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_IVAR));
ADD_INSN3(ret, line_node, defined_ivar,
ID2SYM(node->nd_vid), get_ivar_ic_value(iseq,node->nd_vid), PUSH_VAL(DEFINED_IVAR));
return;

case NODE_GVAR:
Expand Down
14 changes: 14 additions & 0 deletions insns.def
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,20 @@ defined
}
}

/* defined?(@foo) */
DEFINE_INSN
defined_ivar
(ID id, IVC ic, VALUE pushval)
()
(VALUE val)
// attr bool leaf = false;
{
val = Qnil;
if (vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef) != Qundef) {
val = pushval;
}
}

/* check `target' matches `pattern'.
`flag & VM_CHECKMATCH_TYPE_MASK' describe how to check pattern.
VM_CHECKMATCH_TYPE_WHEN: ignore target and check pattern is truthy.
Expand Down
22 changes: 12 additions & 10 deletions vm_insnhelper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1143,17 +1143,17 @@ 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;
shape_id_t shape_id;
VALUE * ivar_list;

if (SPECIAL_CONST_P(obj)) {
return Qnil;
return default_value;
}

#if SHAPE_IN_BASIC_FLAGS
Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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];
Expand Down Expand Up @@ -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 {
Expand All @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 1a3f8e1

Please sign in to comment.