ruby-changes:25176
From: ko1 <ko1@a...>
Date: Wed, 17 Oct 2012 02:07:34 +0900 (JST)
Subject: [ruby-changes:25176] ko1:r37228 (trunk): * vm_insnhelper.c (vm_getivar, vm_setivar): support index inline cache
ko1 2012-10-17 02:07:23 +0900 (Wed, 17 Oct 2012) New Revision: 37228 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37228 Log: * vm_insnhelper.c (vm_getivar, vm_setivar): support index inline cache with rb_call_info_t to speedup `attr' getter and setter. Cached index is stored in rb_call_info_t::aux::index. `index' == 0 means not cached. `index' > 0 means cached and cached index is `index - 1'. * insns.def ((get|set)instancevariable): use new wrapper functions vm_(get|set)instancevariable() defined in vm_insnhelper.c. * vm_core.h (rb_call_info_t::aux): introduce new union data because opt_pc can share with index. Modified files: trunk/ChangeLog trunk/insns.def trunk/vm_core.h trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 37227) +++ ChangeLog (revision 37228) @@ -1,3 +1,17 @@ +Wed Oct 17 01:53:47 2012 Koichi Sasada <ko1@a...> + + * vm_insnhelper.c (vm_getivar, vm_setivar): support index inline cache + with rb_call_info_t to speedup `attr' getter and setter. + Cached index is stored in rb_call_info_t::aux::index. + `index' == 0 means not cached. `index' > 0 means cached and cached + index is `index - 1'. + + * insns.def ((get|set)instancevariable): use new wrapper functions + vm_(get|set)instancevariable() defined in vm_insnhelper.c. + + * vm_core.h (rb_call_info_t::aux): introduce new union data because + opt_pc can share with index. + Tue Oct 16 22:24:44 2012 Koichi Sasada <ko1@a...> * benchmark/driver.rb (show_results): Show speedup ratio Index: insns.def =================================================================== --- insns.def (revision 37227) +++ insns.def (revision 37228) @@ -126,7 +126,7 @@ () (VALUE val) { - val = vm_getivar(GET_SELF(), id, ic); + val = vm_getinstancevariable(GET_SELF(), id, ic); } /** @@ -141,7 +141,7 @@ (VALUE val) () { - vm_setivar(GET_SELF(), id, val, ic); + vm_setinstancevariable(GET_SELF(), id, val, ic); } /** Index: vm_core.h =================================================================== --- vm_core.h (revision 37227) +++ vm_core.h (revision 37228) @@ -160,9 +160,12 @@ /* temporary values for method calling */ int argc; - int opt_pc; struct rb_block_struct *blockptr; VALUE recv; + union { + int opt_pc; /* used by iseq */ + long index; /* used by ivar */ + } aux; VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci); } rb_call_info_t; Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 37227) +++ vm_insnhelper.c (revision 37228) @@ -492,17 +492,17 @@ #define USE_IC_FOR_IVAR 1 #endif -static VALUE -vm_getivar(VALUE obj, ID id, IC ic) +static inline VALUE +vm_getivar(VALUE obj, ID id, IC ic, rb_call_info_t *ci, int is_attr) { #if USE_IC_FOR_IVAR if (RB_TYPE_P(obj, T_OBJECT)) { VALUE val = Qundef; VALUE klass = RBASIC(obj)->klass; - if (LIKELY(ic->ic_class == klass && - ic->ic_vmstat == GET_VM_STATE_VERSION())) { - long index = ic->ic_value.index; + if (LIKELY((!is_attr && (ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION())) || + (is_attr && ci->aux.index > 0))) { + long index = !is_attr ? ic->ic_value.index : ci->aux.opt_pc - 1; long len = ROBJECT_NUMIV(obj); VALUE *ptr = ROBJECT_IVPTR(obj); @@ -521,14 +521,20 @@ if ((long)index < len) { val = ptr[index]; } - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); + if (!is_attr) { + ic->ic_class = klass; + ic->ic_value.index = index; + ic->ic_vmstat = GET_VM_STATE_VERSION(); + } + else { /* call_info */ + ci->aux.opt_pc = index + 1; + } } } } + if (UNLIKELY(val == Qundef)) { - rb_warning("instance variable %s not initialized", rb_id2name(id)); + if (!is_attr) rb_warning("instance variable %s not initialized", rb_id2name(id)); val = Qnil; } return val; @@ -541,8 +547,8 @@ #endif } -static void -vm_setivar(VALUE obj, ID id, VALUE val, IC ic) +static inline void +vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr) { #if USE_IC_FOR_IVAR if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) { @@ -555,9 +561,10 @@ VALUE klass = RBASIC(obj)->klass; st_data_t index; - if (LIKELY(ic->ic_class == klass && - ic->ic_vmstat == GET_VM_STATE_VERSION())) { - long index = ic->ic_value.index; + if (LIKELY( + (!is_attr && ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION()) || + (is_attr && ci->aux.index > 0))) { + long index = !is_attr ? ic->ic_value.index : ci->aux.index-1; long len = ROBJECT_NUMIV(obj); VALUE *ptr = ROBJECT_IVPTR(obj); @@ -570,9 +577,14 @@ 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_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); + if (!is_attr) { + ic->ic_class = klass; + ic->ic_value.index = index; + ic->ic_vmstat = GET_VM_STATE_VERSION(); + } + else { + ci->aux.index = index + 1; + } } /* fall through */ } @@ -584,6 +596,18 @@ } static VALUE +vm_getinstancevariable(VALUE obj, ID id, IC ic) +{ + return vm_getivar(obj, id, ic, 0, 0); +} + +static void +vm_setinstancevariable(VALUE obj, ID id, VALUE val, IC ic) +{ + vm_setivar(obj, id, val, ic, 0, 0); +} + +static VALUE vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj) { @@ -1182,11 +1206,11 @@ if ((ci)->argc != (iseq)->argc) { \ argument_error((iseq), ((ci)->argc), (iseq)->argc, (iseq)->argc); \ } \ - (ci)->opt_pc = 0; \ + (ci)->aux.opt_pc = 0; \ CI_SET_FASTPATH((ci), vm_call_iseq_setup_2, !(is_lambda) && !((ci)->me->flag & NOEX_PROTECTED)); \ } \ else { \ - (ci)->opt_pc = vm_callee_setup_arg_complex((th), (ci), (iseq), (argv)); \ + (ci)->aux.opt_pc = vm_callee_setup_arg_complex((th), (ci), (iseq), (argv)); \ } static VALUE @@ -1216,7 +1240,7 @@ vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr), - iseq->iseq_encoded + ci->opt_pc, sp, 0, ci->me); + iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me); cfp->sp = argv - 1 /* recv */; } @@ -1244,7 +1268,7 @@ vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag, ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr), - iseq->iseq_encoded + ci->opt_pc, sp, 0, ci->me); + iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me); cfp->sp = sp_orig; } @@ -1366,7 +1390,7 @@ static VALUE vm_call_ivar(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) { - VALUE val = rb_attr_get(ci->recv, ci->me->def->body.attr.id); + VALUE val = vm_getivar(ci->recv, ci->me->def->body.attr.id, 0, ci, 1); cfp->sp -= 1; return val; } @@ -1374,9 +1398,9 @@ static VALUE vm_call_attrset(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) { - VALUE val = rb_ivar_set(ci->recv, ci->me->def->body.attr.id, *(cfp->sp - 1)); + vm_setivar(ci->recv, ci->me->def->body.attr.id, *(cfp->sp - 1), 0, ci, 1); cfp->sp -= 2; - return val; + return Qnil; } static VALUE @@ -1523,12 +1547,14 @@ } case VM_METHOD_TYPE_ATTRSET:{ rb_check_arity(ci->argc, 0, 1); + ci->aux.index = 0; CI_SET_FASTPATH(ci, vm_call_attrset, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT)); val = vm_call_attrset(th, cfp, ci); break; } case VM_METHOD_TYPE_IVAR:{ rb_check_arity(ci->argc, 0, 0); + ci->aux.index = 0; CI_SET_FASTPATH(ci, vm_call_ivar, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT)); val = vm_call_ivar(th, cfp, ci); break; @@ -1987,7 +2013,7 @@ ci_entry.argc = argc; ci_entry.blockptr = (rb_block_t *)blockptr; VM_CALLEE_SETUP_ARG(th, &ci_entry, iseq, argv, 1); - return ci_entry.opt_pc; + return ci_entry.aux.opt_pc; } else { return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/