Feature #13602 » 0001-Optimize-instance-variable-access-if-VERBOSE-is-not-.patch
compile.c | ||
---|---|---|
case NODE_IVAR:{
|
||
debugi("nd_vid", node->nd_vid);
|
||
if (!popped) {
|
||
ADD_INSN2(ret, line, getinstancevariable,
|
||
if (RTEST(ruby_verbose)) {
|
||
ADD_INSN2(ret, line, getinstancevariable,
|
||
ID2SYM(node->nd_vid),
|
||
get_ivar_ic_value(iseq,node->nd_vid));
|
||
} else {
|
||
ADD_INSN2(ret, line, getinstancevariablefast,
|
||
ID2SYM(node->nd_vid),
|
||
get_ivar_ic_value(iseq,node->nd_vid));
|
||
}
|
||
}
|
||
break;
|
||
}
|
insns.def | ||
---|---|---|
/**
|
||
@c variable
|
||
@e Get value of instance variable id of self (optimized version
|
||
used when $VERBOSE is not true).
|
||
*/
|
||
DEFINE_INSN
|
||
getinstancevariablefast
|
||
(ID id, IC ic)
|
||
()
|
||
(VALUE val)
|
||
{
|
||
val = vm_getinstancevariablefast(GET_SELF(), id, ic);
|
||
}
|
||
/**
|
||
@c variable
|
||
@e Set value of instance variable id of self to val.
|
||
If is_local is not 0, set value of class local variable.
|
||
@j self のインスタンス変数 id を val にする。
|
test/ruby/test_exception.rb | ||
---|---|---|
end
|
||
def test_warning_warn
|
||
warning = capture_warning_warn {@a}
|
||
warning = capture_warning_warn {eval '@a'}
|
||
assert_match(/instance variable @a not initialized/, warning[0])
|
||
assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"})
|
test/ruby/test_module.rb | ||
---|---|---|
attr_accessor :cattr
|
||
end
|
||
attr_accessor :iattr
|
||
def ivar
|
||
@ivar
|
||
end
|
||
end
|
||
def test_uninitialized_instance_variable
|
||
a = AttrTest.new
|
||
assert_warning(/instance variable @ivar not initialized/) do
|
||
eval 'def a.ivar; @ivar end'
|
||
assert_nil(a.ivar)
|
||
end
|
||
a.instance_variable_set(:@ivar, 42)
|
vm_insnhelper.c | ||
---|---|---|
}
|
||
static inline VALUE
|
||
vm_getinstancevariablefast(VALUE obj, ID id, IC ic)
|
||
{
|
||
#if USE_IC_FOR_IVAR
|
||
if (LIKELY(RB_TYPE_P(obj, T_OBJECT))) {
|
||
VALUE val = Qnil;
|
||
if (RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_serial,
|
||
ic->ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass))) {
|
||
st_index_t index = ic->ic_value.index;
|
||
if (LIKELY(index < ROBJECT_NUMIV(obj))) {
|
||
val = ROBJECT_IVPTR(obj)[index];
|
||
if (UNLIKELY(val == Qundef)) {
|
||
val = Qnil;
|
||
}
|
||
}
|
||
RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
|
||
return val;
|
||
}
|
||
else {
|
||
st_data_t index;
|
||
struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
||
if (iv_index_tbl) {
|
||
if (st_lookup(iv_index_tbl, id, &index)) {
|
||
if (index < ROBJECT_NUMIV(obj)) {
|
||
val = ROBJECT_IVPTR(obj)[index];
|
||
if (UNLIKELY(val == Qundef)) {
|
||
val = Qnil;
|
||
}
|
||
}
|
||
ic->ic_value.index = index;
|
||
ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass);
|
||
}
|
||
}
|
||
RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
|
||
return val;
|
||
}
|
||
}
|
||
else {
|
||
RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_noobject);
|
||
}
|
||
#endif
|
||
RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
|
||
return rb_attr_get(obj, id);
|
||
}
|
||
static inline VALUE
|
||
vm_getinstancevariable(VALUE obj, ID id, IC ic)
|
||
{
|
||
return vm_getivar(obj, id, ic, 0, 0);
|