Project

General

Profile

Feature #10256 » 0001-rb_call_info_t-reduce-from-96-88-bytes-on-64-bit.patch

normalperson (Eric Wong), 09/18/2014 06:45 AM

View differences:

compile.c
{
rb_call_info_t *ci = (rb_call_info_t *)compile_data_alloc(iseq, sizeof(rb_call_info_t));
ci->mid = mid;
/* ci->fn = no default */
ci->flag = flag;
ci->orig_argc = argc;
ci->argc = argc;
......
ci->class_serial = 0;
ci->blockptr = 0;
ci->recv = Qundef;
ci->call = 0; /* TODO: should set default function? */
ci->aux.index = iseq->callinfo_size++;
vm_core.h
typedef struct rb_call_info_struct {
/* fixed at compile time */
ID mid;
unsigned int flag;
uint16_t fn; /* temporary for method calling */
uint16_t flag; /* only uses 9 bits */
int orig_argc;
rb_iseq_t *blockiseq;
......
int missing_reason; /* used by method_missing */
int inc_sp; /* used by cfunc */
} aux;
VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci);
} rb_call_info_t;
#if 1
vm_insnhelper.c
ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class);
ci->klass = klass;
ci->call = vm_call_general;
ci->fn = VM_CIFN_GENERAL;
#if OPT_INLINE_METHOD_CACHE
ci->method_state = GET_GLOBAL_METHOD_STATE();
ci->class_serial = RCLASS_SERIAL(klass);
......
ci->aux.opt_pc = 0;
CI_SET_FASTPATH(ci,
(UNLIKELY(ci->flag & VM_CALL_TAILCALL) ?
vm_call_iseq_setup_tailcall :
vm_call_iseq_setup_normal),
VM_CIFN_ISEQ_SETUP_TAILCALL :
VM_CIFN_ISEQ_SETUP_NORMAL),
(!is_lambda &&
!(ci->flag & VM_CALL_ARGS_SPLAT) && /* argc may differ for each calls */
!(ci->me->flag & NOEX_PROTECTED)));
......
if (!(ci->me->flag & NOEX_PROTECTED) &&
!(ci->flag & VM_CALL_ARGS_SPLAT)) {
CI_SET_FASTPATH(ci, vm_call_cfunc_latter, 1);
CI_SET_FASTPATH(ci, VM_CIFN_CFUNC_LATTER, 1);
}
val = vm_call_cfunc_latter(th, reg_cfp, ci);
......
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, ci->recv, ci->defined_class,
VM_ENVVAL_BLOCK_PTR(ci->blockptr), 0, th->cfp->sp + ci->aux.inc_sp, 1, me);
if (ci->call != vm_call_general) {
ci->call = vm_call_cfunc_with_frame;
if (ci->fn != VM_CIFN_GENERAL) {
ci->fn = VM_CIFN_CFUNC_WITH_FRAME;
}
}
#else /* OPT_CALL_CFUNC_WITHOUT_FRAME */
......
normal_method_dispatch:
switch (ci->me->def->type) {
case VM_METHOD_TYPE_ISEQ:{
CI_SET_FASTPATH(ci, vm_call_iseq_setup, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_ISEQ_SETUP, enable_fastpath);
return vm_call_iseq_setup(th, cfp, ci);
}
case VM_METHOD_TYPE_NOTIMPLEMENTED:
case VM_METHOD_TYPE_CFUNC:
CI_SET_FASTPATH(ci, vm_call_cfunc, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_CFUNC, enable_fastpath);
return vm_call_cfunc(th, cfp, ci);
case VM_METHOD_TYPE_ATTRSET:{
rb_check_arity(ci->argc, 1, 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_CIFN_CALL_ATTRSET,
enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
return vm_call_attrset(th, cfp, ci);
}
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));
CI_SET_FASTPATH(ci, VM_CIFN_IVAR,
enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
return vm_call_ivar(th, cfp, ci);
}
case VM_METHOD_TYPE_MISSING:{
ci->aux.missing_reason = 0;
CI_SET_FASTPATH(ci, vm_call_method_missing, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_METHOD_MISSING, enable_fastpath);
return vm_call_method_missing(th, cfp, ci);
}
case VM_METHOD_TYPE_BMETHOD:{
CI_SET_FASTPATH(ci, vm_call_bmethod, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_BMETHOD, enable_fastpath);
return vm_call_bmethod(th, cfp, ci);
}
case VM_METHOD_TYPE_ZSUPER:{
......
case VM_METHOD_TYPE_OPTIMIZED:{
switch (ci->me->def->body.optimize_type) {
case OPTIMIZED_METHOD_TYPE_SEND:
CI_SET_FASTPATH(ci, vm_call_opt_send, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_OPT_SEND, enable_fastpath);
return vm_call_opt_send(th, cfp, ci);
case OPTIMIZED_METHOD_TYPE_CALL:
CI_SET_FASTPATH(ci, vm_call_opt_call, enable_fastpath);
CI_SET_FASTPATH(ci, VM_CIFN_OPT_CALL, enable_fastpath);
return vm_call_opt_call(th, cfp, ci);
default:
rb_bug("vm_call_method: unsupported optimized method type (%d)",
......
}
me = rb_method_entry(refinement, ci->mid, &defined_class);
if (me) {
if (ci->call == vm_call_super_method) {
if (ci->fn == VM_CIFN_SUPER_METHOD) {
rb_control_frame_t *top_cfp = current_method_entry(th, cfp);
if (top_cfp->me &&
rb_method_definition_eq(me->def, top_cfp->me->def)) {
......
stat |= NOEX_VCALL;
}
ci->aux.missing_reason = stat;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
CI_SET_FASTPATH(ci, VM_CIFN_METHOD_MISSING, 1);
return vm_call_method_missing(th, cfp, ci);
}
else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->flag & NOEX_MASK) & NOEX_PROTECTED) {
......
}
else {
ci->aux.missing_reason = stat;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
CI_SET_FASTPATH(ci, VM_CIFN_METHOD_MISSING, 1);
return vm_call_method_missing(th, cfp, ci);
}
}
......
if (!ci->klass) {
/* bound instance method of module */
ci->aux.missing_reason = NOEX_SUPER;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
CI_SET_FASTPATH(ci, VM_CIFN_METHOD_MISSING, 1);
return;
}
/* TODO: use inline cache */
ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class);
ci->call = vm_call_super_method;
ci->fn = VM_CIFN_SUPER_METHOD;
while (iseq && !iseq->klass) {
iseq = iseq->parent_iseq;
......
is->once.running_thread = NULL;
return Qnil;
}
/* test w/o C99 support so we may ensure it works on non-C99 compilers: */
#if 0 && (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
# define map_(en,fn) [en] = fn
#else
# define map_(en,fn) fn
#endif
static inline vm_cifn
cifn_lookup(const rb_call_info_t *ci)
{
static const vm_cifn fn_map[] = {
map_(VM_CIFN_GENERAL, vm_call_general),
map_(VM_CIFN_SUPER_METHOD, vm_call_super_method),
map_(VM_CIFN_CFUNC, vm_call_cfunc),
#if OPT_CALL_CFUNC_WITHOUT_FRAME
map_(VM_CIFN_CFUNC_LATTER, vm_call_cfunc_latter),
#endif
map_(VM_CIFN_CFUNC_WITH_FRAME, vm_call_cfunc_with_frame),
map_(VM_CIFN_ISEQ_SETUP, vm_call_iseq_setup),
map_(VM_CIFN_ISEQ_SETUP_NORMAL, vm_call_iseq_setup_normal),
map_(VM_CIFN_ISEQ_SETUP_TAILCALL, vm_call_iseq_setup_tailcall),
map_(VM_CIFN_CALL_ATTRSET, vm_call_attrset),
map_(VM_CIFN_IVAR, vm_call_ivar),
map_(VM_CIFN_BMETHOD, vm_call_bmethod),
map_(VM_CIFN_OPT_SEND, vm_call_opt_send),
map_(VM_CIFN_OPT_CALL, vm_call_opt_call),
map_(VM_CIFN_METHOD_MISSING, vm_call_method_missing)
};
return fn_map[ci->fn];
}
#undef map_
vm_insnhelper.h
} \
} while (0)
typedef VALUE (*vm_cifn)(rb_thread_t *, rb_control_frame_t *, rb_call_info_t *);
static inline vm_cifn cifn_lookup(const rb_call_info_t *);
enum vm_cifn_type {
VM_CIFN_GENERAL = 0,
VM_CIFN_SUPER_METHOD,
VM_CIFN_CFUNC,
#if OPT_CALL_CFUNC_WITHOUT_FRAME
VM_CIFN_CFUNC_LATTER,
#endif
VM_CIFN_CFUNC_WITH_FRAME,
VM_CIFN_ISEQ_SETUP,
VM_CIFN_ISEQ_SETUP_NORMAL,
VM_CIFN_ISEQ_SETUP_TAILCALL,
VM_CIFN_CALL_ATTRSET,
VM_CIFN_IVAR,
VM_CIFN_BMETHOD,
VM_CIFN_OPT_SEND,
VM_CIFN_OPT_CALL,
VM_CIFN_METHOD_MISSING
};
#define CALL_METHOD(ci) do { \
VALUE v = (*(ci)->call)(th, GET_CFP(), (ci)); \
VALUE v = (cifn_lookup((ci)))(th, GET_CFP(), (ci)); \
if (v == Qundef) { \
RESTORE_REGS(); \
NEXT_INSN(); \
......
#endif
#if OPT_CALL_FASTPATH
#define CI_SET_FASTPATH(ci, func, enabled) do { \
if (LIKELY(enabled)) ((ci)->call = (func)); \
#define CI_SET_FASTPATH(ci, func_idx, enabled) do { \
if (LIKELY(enabled)) ((ci)->fn = (func_idx)); \
} while (0)
#else
#define CI_SET_FASTPATH(ci, func, enabled) /* do nothing */
-
(1-1/2)