summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-10-15 21:24:08 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-10-15 21:24:08 +0000
commit90a6dce0415f7dc5accc9929d497a8044d9e6067 (patch)
tree79a8cd99ca279fafc4dbf5f333137458d142e618 /vm_insnhelper.c
parent747487cda7b5a8c893ed8f6b0d7f7498aa434a02 (diff)
* method.h: introduce new method type VM_METHOD_TYPE_CFUNC_FAST.
This method is similar to VM_METHOD_TYPE_CFUNC methods, but called cfunc without building new frame (does not push new control frame). If error is occured in cfunc, the backtrace only shows caller frame and upper. This kind of methods can be added by rb_define_method_fast(). This feature is similar to specialized instructions (opt_plus, etc), but more flexible (but a bit slower). * class.c (rb_define_method_fast): added. Maybe it will be renamed soon. * vm_insnhelper.c (vm_call_method): support method type VM_METHOD_TYPE_CFUNC_FAST. * proc.c (rb_method_entry_arity): catch up new method type. * vm_method.c (rb_add_method_cfunc_fast): added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37198 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 38cf608aa1..78c6c85a26 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1462,6 +1462,21 @@ vm_call_opt_call(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
}
static VALUE
+vm_call_cfunc_fast_unary(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+ cfp->sp -= 1;
+ return (*ci->me->def->body.cfunc.func)(ci->recv);
+}
+
+static VALUE
+vm_call_cfunc_fast_binary(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+ VALUE obj = *cfp->sp;
+ cfp->sp -= 2;
+ return (*ci->me->def->body.cfunc.func)(ci->recv, obj);
+}
+
+static VALUE
vm_call_missing(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
{
VALUE *argv = ALLOCA_N(VALUE, ci->argc+1);
@@ -1544,24 +1559,38 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
}
case VM_METHOD_TYPE_OPTIMIZED:{
switch (ci->me->def->body.optimize_type) {
- case OPTIMIZED_METHOD_TYPE_SEND: {
+ case OPTIMIZED_METHOD_TYPE_SEND:
CI_SET_FASTPATH(ci, vm_call_opt_send, enable_fastpath);
val = vm_call_opt_send(th, cfp, ci);
break;
- }
- case OPTIMIZED_METHOD_TYPE_CALL: {
+ case OPTIMIZED_METHOD_TYPE_CALL:
CI_SET_FASTPATH(ci, vm_call_opt_call, enable_fastpath);
val = vm_call_opt_call(th, cfp, ci);
break;
- }
default:
- rb_bug("eval_invoke_method: unsupported optimized method type (%d)",
+ rb_bug("vm_call_method: unsupported optimized method type (%d)",
ci->me->def->body.optimize_type);
}
break;
}
+ case VM_METHOD_TYPE_CFUNC_FAST:
+ switch (ci->me->def->body.cfunc.argc) {
+ case 0:
+ rb_check_arity(ci->argc, 0, 0);
+ CI_SET_FASTPATH(ci, vm_call_cfunc_fast_unary, enable_fastpath);
+ val = vm_call_cfunc_fast_unary(th, cfp, ci);
+ break;
+ case 1:
+ rb_check_arity(ci->argc, 0, 1);
+ CI_SET_FASTPATH(ci, vm_call_cfunc_fast_binary, enable_fastpath);
+ val = vm_call_cfunc_fast_binary(th, cfp, ci);
+ break;
+ default:
+ rb_bug("vm_call_method: unsupported cfunc_fast argc (%d)", ci->me->def->body.cfunc.argc);
+ }
+ break;
default:{
- rb_bug("eval_invoke_method: unsupported method type (%d)", ci->me->def->type);
+ rb_bug("vm_call_method: unsupported method type (%d)", ci->me->def->type);
break;
}
}