diff --git a/ChangeLog b/ChangeLog index b8ea5b6d26..d980868eb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Sep 6 16:13:06 2009 Koichi Sasada + + * insns.def (setinstancevariable), vm_insnhelper.c (vm_setivar): + fix to use inline cache (trivial optimization). + Sun Sep 6 10:34:19 2009 Nobuyoshi Nakada * io.c: fixed rdoc, a patch from Nobuhiro IMAI at [ruby-core:25433]. diff --git a/insns.def b/insns.def index 1c2e9d5752..98febf89b8 100644 --- a/insns.def +++ b/insns.def @@ -165,11 +165,11 @@ getinstancevariable */ DEFINE_INSN setinstancevariable -(ID id) +(ID id, IC ic) (VALUE val) () { - rb_ivar_set(GET_SELF(), id, val); + vm_setivar(GET_SELF(), id, val, ic); } /** diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 117bf95790..8cec18d400 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1182,10 +1182,15 @@ vm_get_cvar_base(NODE *cref) return klass; } + +#ifndef ENABLE_IC_FOR_IVAR +#define ENABLE_IC_FOR_IVAR 1 +#endif + static VALUE vm_getivar(VALUE obj, ID id, IC ic) { -#if 1 +#if ENABLE_IC_FOR_IVAR if (TYPE(obj) == T_OBJECT) { VALUE val = Qundef; VALUE klass = RBASIC(obj)->klass; @@ -1210,7 +1215,7 @@ vm_getivar(VALUE obj, ID id, IC ic) if (index < len) { val = ptr[index]; } - ic->ic_class = RBASIC(obj)->klass; + ic->ic_class = klass; ic->ic_index = index; } } @@ -1229,6 +1234,47 @@ vm_getivar(VALUE obj, ID id, IC ic) #endif } +static void +vm_setivar(VALUE obj, ID id, VALUE val, IC ic) +{ +#if ENABLE_IC_FOR_IVAR + if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) { + rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); + } + if (OBJ_FROZEN(obj)) { + rb_error_frozen("object"); + } + + if (TYPE(obj) == T_OBJECT) { + VALUE klass = RBASIC(obj)->klass; + st_data_t index; + + if (ic->ic_class == klass) { + long index = ic->ic_index; + long len = ROBJECT_NUMIV(obj); + VALUE *ptr = ROBJECT_IVPTR(obj); + + if (index < len) { + ptr[index] = val; + return; /* inline cache hit */ + } + } + else { + struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + + if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { + ic->ic_class = klass; + ic->ic_index = index; + } + /* fall through */ + } + } + rb_ivar_set(obj, id, val); +#else + rb_ivar_set(obj, id, val); +#endif +} + static inline const rb_method_entry_t * vm_method_search(VALUE id, VALUE klass, IC ic) {