* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37228 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
aedc460fed
commit
db1e99cdad
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
|||||||
|
Wed Oct 17 01:53:47 2012 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* 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@atdot.net>
|
Tue Oct 16 22:24:44 2012 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* benchmark/driver.rb (show_results): Show speedup ratio
|
* benchmark/driver.rb (show_results): Show speedup ratio
|
||||||
|
@ -126,7 +126,7 @@ getinstancevariable
|
|||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
val = vm_getivar(GET_SELF(), id, ic);
|
val = vm_getinstancevariable(GET_SELF(), id, ic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,7 +141,7 @@ setinstancevariable
|
|||||||
(VALUE val)
|
(VALUE val)
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
vm_setivar(GET_SELF(), id, val, ic);
|
vm_setinstancevariable(GET_SELF(), id, val, ic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,9 +160,12 @@ typedef struct rb_call_info_struct {
|
|||||||
|
|
||||||
/* temporary values for method calling */
|
/* temporary values for method calling */
|
||||||
int argc;
|
int argc;
|
||||||
int opt_pc;
|
|
||||||
struct rb_block_struct *blockptr;
|
struct rb_block_struct *blockptr;
|
||||||
VALUE recv;
|
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);
|
VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci);
|
||||||
} rb_call_info_t;
|
} rb_call_info_t;
|
||||||
|
@ -492,17 +492,17 @@ vm_search_const_defined_class(const VALUE cbase, ID id)
|
|||||||
#define USE_IC_FOR_IVAR 1
|
#define USE_IC_FOR_IVAR 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static VALUE
|
static inline VALUE
|
||||||
vm_getivar(VALUE obj, ID id, IC ic)
|
vm_getivar(VALUE obj, ID id, IC ic, rb_call_info_t *ci, int is_attr)
|
||||||
{
|
{
|
||||||
#if USE_IC_FOR_IVAR
|
#if USE_IC_FOR_IVAR
|
||||||
if (RB_TYPE_P(obj, T_OBJECT)) {
|
if (RB_TYPE_P(obj, T_OBJECT)) {
|
||||||
VALUE val = Qundef;
|
VALUE val = Qundef;
|
||||||
VALUE klass = RBASIC(obj)->klass;
|
VALUE klass = RBASIC(obj)->klass;
|
||||||
|
|
||||||
if (LIKELY(ic->ic_class == klass &&
|
if (LIKELY((!is_attr && (ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION())) ||
|
||||||
ic->ic_vmstat == GET_VM_STATE_VERSION())) {
|
(is_attr && ci->aux.index > 0))) {
|
||||||
long index = ic->ic_value.index;
|
long index = !is_attr ? ic->ic_value.index : ci->aux.opt_pc - 1;
|
||||||
long len = ROBJECT_NUMIV(obj);
|
long len = ROBJECT_NUMIV(obj);
|
||||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||||
|
|
||||||
@ -521,14 +521,20 @@ vm_getivar(VALUE obj, ID id, IC ic)
|
|||||||
if ((long)index < len) {
|
if ((long)index < len) {
|
||||||
val = ptr[index];
|
val = ptr[index];
|
||||||
}
|
}
|
||||||
ic->ic_class = klass;
|
if (!is_attr) {
|
||||||
ic->ic_value.index = index;
|
ic->ic_class = klass;
|
||||||
ic->ic_vmstat = GET_VM_STATE_VERSION();
|
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)) {
|
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;
|
val = Qnil;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -541,8 +547,8 @@ vm_getivar(VALUE obj, ID id, IC ic)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
|
vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr)
|
||||||
{
|
{
|
||||||
#if USE_IC_FOR_IVAR
|
#if USE_IC_FOR_IVAR
|
||||||
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) {
|
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) {
|
||||||
@ -555,9 +561,10 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
|
|||||||
VALUE klass = RBASIC(obj)->klass;
|
VALUE klass = RBASIC(obj)->klass;
|
||||||
st_data_t index;
|
st_data_t index;
|
||||||
|
|
||||||
if (LIKELY(ic->ic_class == klass &&
|
if (LIKELY(
|
||||||
ic->ic_vmstat == GET_VM_STATE_VERSION())) {
|
(!is_attr && ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION()) ||
|
||||||
long index = ic->ic_value.index;
|
(is_attr && ci->aux.index > 0))) {
|
||||||
|
long index = !is_attr ? ic->ic_value.index : ci->aux.index-1;
|
||||||
long len = ROBJECT_NUMIV(obj);
|
long len = ROBJECT_NUMIV(obj);
|
||||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||||
|
|
||||||
@ -570,9 +577,14 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
|
|||||||
struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
|
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)) {
|
if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
|
||||||
ic->ic_class = klass;
|
if (!is_attr) {
|
||||||
ic->ic_value.index = index;
|
ic->ic_class = klass;
|
||||||
ic->ic_vmstat = GET_VM_STATE_VERSION();
|
ic->ic_value.index = index;
|
||||||
|
ic->ic_vmstat = GET_VM_STATE_VERSION();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ci->aux.index = index + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
@ -583,6 +595,18 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static VALUE
|
||||||
vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
||||||
rb_num_t throw_state, VALUE throwobj)
|
rb_num_t throw_state, VALUE throwobj)
|
||||||
@ -1182,11 +1206,11 @@ static VALUE vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_c
|
|||||||
if ((ci)->argc != (iseq)->argc) { \
|
if ((ci)->argc != (iseq)->argc) { \
|
||||||
argument_error((iseq), ((ci)->argc), (iseq)->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)); \
|
CI_SET_FASTPATH((ci), vm_call_iseq_setup_2, !(is_lambda) && !((ci)->me->flag & NOEX_PROTECTED)); \
|
||||||
} \
|
} \
|
||||||
else { \
|
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
|
static VALUE
|
||||||
@ -1216,7 +1240,7 @@ vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *c
|
|||||||
|
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
|
||||||
VM_ENVVAL_BLOCK_PTR(ci->blockptr),
|
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 */;
|
cfp->sp = argv - 1 /* recv */;
|
||||||
}
|
}
|
||||||
@ -1244,7 +1268,7 @@ vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *c
|
|||||||
|
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
|
||||||
ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
|
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;
|
cfp->sp = sp_orig;
|
||||||
}
|
}
|
||||||
@ -1366,7 +1390,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
|
|||||||
static VALUE
|
static VALUE
|
||||||
vm_call_ivar(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
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;
|
cfp->sp -= 1;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -1374,9 +1398,9 @@ vm_call_ivar(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
|||||||
static VALUE
|
static VALUE
|
||||||
vm_call_attrset(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
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;
|
cfp->sp -= 2;
|
||||||
return val;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -1523,12 +1547,14 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
|||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_ATTRSET:{
|
case VM_METHOD_TYPE_ATTRSET:{
|
||||||
rb_check_arity(ci->argc, 0, 1);
|
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));
|
CI_SET_FASTPATH(ci, vm_call_attrset, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
|
||||||
val = vm_call_attrset(th, cfp, ci);
|
val = vm_call_attrset(th, cfp, ci);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_IVAR:{
|
case VM_METHOD_TYPE_IVAR:{
|
||||||
rb_check_arity(ci->argc, 0, 0);
|
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));
|
CI_SET_FASTPATH(ci, vm_call_ivar, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
|
||||||
val = vm_call_ivar(th, cfp, ci);
|
val = vm_call_ivar(th, cfp, ci);
|
||||||
break;
|
break;
|
||||||
@ -1987,7 +2013,7 @@ vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
|
|||||||
ci_entry.argc = argc;
|
ci_entry.argc = argc;
|
||||||
ci_entry.blockptr = (rb_block_t *)blockptr;
|
ci_entry.blockptr = (rb_block_t *)blockptr;
|
||||||
VM_CALLEE_SETUP_ARG(th, &ci_entry, iseq, argv, 1);
|
VM_CALLEE_SETUP_ARG(th, &ci_entry, iseq, argv, 1);
|
||||||
return ci_entry.opt_pc;
|
return ci_entry.aux.opt_pc;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr);
|
return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user