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);
|
||