зеркало из https://github.com/github/ruby.git
* method.h (rb_method_cfunc_t::invoker): add new field (func ptr)
`invoker'. `invoker' function invoke cfunc body (rb_method_cfunc_t::func). `invoker' is set at method definition timing. With this change, the big `switch' (branch) in `call_cfunc()' is no longer needed. However, the performance benefit is only a bit. * vm_core.h (rb_call_info_t::aux::func): add a new field to store cfunc body function pointer. * vm_method.c (call_cfunc_invoker_func): add a new function which returns a suitable invoke function. * vm_method.c (setup_method_cfunc_struct): added. * vm_method.c (rb_add_method): fix to set `invoker'. * vm_eval.c (vm_call0_body): catch up above changes. * vm_insnhelper.c (call_cfunc): removed. * vm_insnhelper.c (vm_call_cfunc): fix to call cfunc body with `invoker' function. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37268 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
0fc7f4bb30
Коммит
f4dbc7a384
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
|||
Fri Oct 19 19:29:11 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* method.h (rb_method_cfunc_t::invoker): add new field (func ptr)
|
||||
`invoker'. `invoker' function invoke cfunc body
|
||||
(rb_method_cfunc_t::func).
|
||||
`invoker' is set at method definition timing.
|
||||
With this change, the big `switch' (branch) in `call_cfunc()'
|
||||
is no longer needed.
|
||||
However, the performance benefit is only a bit.
|
||||
|
||||
* vm_core.h (rb_call_info_t::aux::func): add a new field to store
|
||||
cfunc body function pointer.
|
||||
|
||||
* vm_method.c (call_cfunc_invoker_func): add a new function which
|
||||
returns a suitable invoke function.
|
||||
|
||||
* vm_method.c (setup_method_cfunc_struct): added.
|
||||
|
||||
* vm_method.c (rb_add_method): fix to set `invoker'.
|
||||
|
||||
* vm_eval.c (vm_call0_body): catch up above changes.
|
||||
|
||||
* vm_insnhelper.c (call_cfunc): removed.
|
||||
|
||||
* vm_insnhelper.c (vm_call_cfunc): fix to call cfunc body
|
||||
with `invoker' function.
|
||||
|
||||
Fri Oct 19 16:55:58 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* eval.c, vm_eval.c: use TH_PUSH_TAG() instead of PUSH_TAG().
|
||||
|
|
3
method.h
3
method.h
|
@ -45,8 +45,11 @@ typedef enum {
|
|||
VM_METHOD_TYPE_CFUNC_FRAMELESS
|
||||
} rb_method_type_t;
|
||||
|
||||
struct rb_call_info_struct;
|
||||
|
||||
typedef struct rb_method_cfunc_struct {
|
||||
VALUE (*func)(ANYARGS);
|
||||
VALUE (*invoker)(const struct rb_call_info_struct *ci, const VALUE *argv);
|
||||
int argc;
|
||||
} rb_method_cfunc_t;
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ typedef struct rb_call_info_struct {
|
|||
int opt_pc; /* used by iseq */
|
||||
long index; /* used by ivar */
|
||||
int missing_reason; /* used by method_missing */
|
||||
VALUE (*func)(ANYARGS); /* used by cfunc */
|
||||
} aux;
|
||||
|
||||
VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci);
|
||||
|
|
13
vm_eval.c
13
vm_eval.c
|
@ -93,8 +93,17 @@ vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
|
|||
0, reg_cfp->sp, 1, ci->me);
|
||||
|
||||
cfp->me = ci->me;
|
||||
val = call_cfunc(ci->me->def->body.cfunc.func, ci->recv,
|
||||
ci->me->def->body.cfunc.argc, ci->argc, argv);
|
||||
|
||||
{
|
||||
const rb_method_entry_t *me = ci->me;
|
||||
const rb_method_definition_t *def = me->def;
|
||||
int len = def->body.cfunc.argc;
|
||||
|
||||
if (len >= 0) rb_check_arity(ci->argc, len, len);
|
||||
|
||||
ci->aux.func = def->body.cfunc.func;
|
||||
val = (*def->body.cfunc.invoker)(ci, argv);
|
||||
}
|
||||
|
||||
if (reg_cfp != th->cfp + 1) {
|
||||
rb_bug("cfp consistency error - call0");
|
||||
|
|
197
vm_insnhelper.c
197
vm_insnhelper.c
|
@ -1293,88 +1293,119 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in
|
|||
return Qundef;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
call_cfunc(VALUE (*func)(), VALUE recv,
|
||||
int len, int argc, const VALUE *argv)
|
||||
static VALUE
|
||||
call_cfunc_m2(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
/* printf("len: %d, argc: %d\n", len, argc); */
|
||||
return (ci->aux.func)(ci->recv, rb_ary_new4(ci->argc, argv));
|
||||
}
|
||||
|
||||
if (len >= 0) rb_check_arity(argc, len, len);
|
||||
static VALUE
|
||||
call_cfunc_m1(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->argc, argv, ci->recv);
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case -2:
|
||||
return (*func) (recv, rb_ary_new4(argc, argv));
|
||||
break;
|
||||
case -1:
|
||||
return (*func) (argc, argv, recv);
|
||||
break;
|
||||
case 0:
|
||||
return (*func) (recv);
|
||||
break;
|
||||
case 1:
|
||||
return (*func) (recv, argv[0]);
|
||||
break;
|
||||
case 2:
|
||||
return (*func) (recv, argv[0], argv[1]);
|
||||
break;
|
||||
case 3:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2]);
|
||||
break;
|
||||
case 4:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3]);
|
||||
break;
|
||||
case 5:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
break;
|
||||
case 6:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5]);
|
||||
break;
|
||||
case 7:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6]);
|
||||
break;
|
||||
case 8:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7]);
|
||||
break;
|
||||
case 9:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8]);
|
||||
break;
|
||||
case 10:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9]);
|
||||
break;
|
||||
case 11:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||
argv[10]);
|
||||
break;
|
||||
case 12:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||
argv[10], argv[11]);
|
||||
break;
|
||||
case 13:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||
argv[11], argv[12]);
|
||||
break;
|
||||
case 14:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||
argv[11], argv[12], argv[13]);
|
||||
break;
|
||||
case 15:
|
||||
return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
|
||||
argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||
argv[11], argv[12], argv[13], argv[14]);
|
||||
break;
|
||||
default:
|
||||
rb_raise(rb_eArgError, "too many arguments(%d)", len);
|
||||
UNREACHABLE;
|
||||
}
|
||||
static VALUE
|
||||
call_cfunc_0(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_1(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_2(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_3(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_4(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_5(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_6(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_7(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_8(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_9(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_10(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_11(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_12(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_13(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_14(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
call_cfunc_15(const rb_call_info_t *ci, const VALUE *argv)
|
||||
{
|
||||
return (ci->aux.func)(ci->recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_call_cfunc_call(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
|
||||
{
|
||||
reg_cfp->sp -= ci->argc + 1;
|
||||
return (*ci->me->def->body.cfunc.invoker)(ci, reg_cfp->sp + 1);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1383,18 +1414,20 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
|
|||
volatile VALUE val = 0;
|
||||
const rb_method_entry_t *me = ci->me;
|
||||
const rb_method_definition_t *def = me->def;
|
||||
int len = def->body.cfunc.argc;
|
||||
|
||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, me->called_id, me->klass);
|
||||
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, ci->recv, ci->defined_class,
|
||||
VM_ENVVAL_BLOCK_PTR(ci->blockptr), 0, th->cfp->sp, 1, me);
|
||||
|
||||
reg_cfp->sp -= ci->argc + 1;
|
||||
if (len >= 0) rb_check_arity(ci->argc, len, len);
|
||||
|
||||
val = call_cfunc(def->body.cfunc.func, ci->recv, (int)def->body.cfunc.argc, ci->argc, reg_cfp->sp + 1);
|
||||
ci->aux.func = def->body.cfunc.func;
|
||||
val = vm_call_cfunc_call(th, reg_cfp, ci);
|
||||
|
||||
if (reg_cfp != th->cfp + 1) {
|
||||
rb_bug("cfp consistency error - send");
|
||||
rb_bug("vm_call_cfunc - cfp consistency error");
|
||||
}
|
||||
|
||||
vm_pop_frame(th);
|
||||
|
|
43
vm_method.c
43
vm_method.c
|
@ -303,6 +303,41 @@ method_added(VALUE klass, ID mid)
|
|||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
(*call_cfunc_invoker_func(int argc))(const rb_call_info_t *, const VALUE *)
|
||||
{
|
||||
switch (argc) {
|
||||
case -2: return call_cfunc_m2;
|
||||
case -1: return call_cfunc_m1;
|
||||
case 0: return call_cfunc_0;
|
||||
case 1: return call_cfunc_1;
|
||||
case 2: return call_cfunc_2;
|
||||
case 3: return call_cfunc_3;
|
||||
case 4: return call_cfunc_4;
|
||||
case 5: return call_cfunc_5;
|
||||
case 6: return call_cfunc_6;
|
||||
case 7: return call_cfunc_7;
|
||||
case 8: return call_cfunc_8;
|
||||
case 9: return call_cfunc_9;
|
||||
case 10: return call_cfunc_10;
|
||||
case 11: return call_cfunc_11;
|
||||
case 12: return call_cfunc_12;
|
||||
case 13: return call_cfunc_13;
|
||||
case 14: return call_cfunc_14;
|
||||
case 15: return call_cfunc_15;
|
||||
default:
|
||||
rb_bug("call_cfunc_func: unsupported length: %d", argc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
|
||||
{
|
||||
cfunc->func = func;
|
||||
cfunc->argc = argc;
|
||||
cfunc->invoker = call_cfunc_invoker_func(argc);
|
||||
}
|
||||
|
||||
rb_method_entry_t *
|
||||
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
|
||||
{
|
||||
|
@ -321,7 +356,10 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
|
|||
break;
|
||||
case VM_METHOD_TYPE_CFUNC:
|
||||
case VM_METHOD_TYPE_CFUNC_FRAMELESS:
|
||||
def->body.cfunc = *(rb_method_cfunc_t *)opts;
|
||||
{
|
||||
rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
|
||||
setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc);
|
||||
}
|
||||
break;
|
||||
case VM_METHOD_TYPE_ATTRSET:
|
||||
case VM_METHOD_TYPE_IVAR:
|
||||
|
@ -338,8 +376,7 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
|
|||
def->body.proc = (VALUE)opts;
|
||||
break;
|
||||
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
||||
def->body.cfunc.func = rb_f_notimplement;
|
||||
def->body.cfunc.argc = -1;
|
||||
setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1);
|
||||
break;
|
||||
case VM_METHOD_TYPE_OPTIMIZED:
|
||||
def->body.optimize_type = (enum method_optimized_type)opts;
|
||||
|
|
Загрузка…
Ссылка в новой задаче