summaryrefslogtreecommitdiff
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
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
-rw-r--r--ChangeLog21
-rw-r--r--class.c6
-rw-r--r--method.h6
-rw-r--r--proc.c1
-rw-r--r--vm_insnhelper.c41
-rw-r--r--vm_method.c15
6 files changed, 82 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index fb73bac394..2fe1fe1419 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Tue Oct 16 06:15:44 2012 Koichi Sasada <ko1@atdot.net>
+
+ * 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.
+
Tue Oct 16 02:32:29 2012 Koichi Sasada <ko1@atdot.net>
* vm_insnhelper.h (CI_SET_FASTPATH): add new parameter `enabled'.
diff --git a/class.c b/class.c
index 8d9889ec3b..43bac4b70f 100644
--- a/class.c
+++ b/class.c
@@ -1254,6 +1254,12 @@ rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc
}
void
+rb_define_method_fast(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
+{
+ rb_add_method_cfunc_fast(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
+}
+
+void
rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
diff --git a/method.h b/method.h
index 3d8a0e44ce..2baf9c5291 100644
--- a/method.h
+++ b/method.h
@@ -41,7 +41,8 @@ typedef enum {
VM_METHOD_TYPE_UNDEF,
VM_METHOD_TYPE_NOTIMPLEMENTED,
VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
- VM_METHOD_TYPE_MISSING /* wrapper for method_missing(id) */
+ VM_METHOD_TYPE_MISSING, /* wrapper for method_missing(id) */
+ VM_METHOD_TYPE_CFUNC_FAST
} rb_method_type_t;
typedef struct rb_method_cfunc_struct {
@@ -66,7 +67,7 @@ typedef struct rb_method_definition_struct {
VALUE proc; /* should be mark */
enum method_optimized_type {
OPTIMIZED_METHOD_TYPE_SEND,
- OPTIMIZED_METHOD_TYPE_CALL
+ OPTIMIZED_METHOD_TYPE_CALL,
} optimize_type;
} body;
int alias_count;
@@ -88,6 +89,7 @@ struct unlinked_method_entry_list_entry {
#define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF)
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
+void rb_add_method_cfunc_fast(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
diff --git a/proc.c b/proc.c
index 300c6a0b70..26d95597e3 100644
--- a/proc.c
+++ b/proc.c
@@ -1656,6 +1656,7 @@ rb_method_entry_arity(const rb_method_entry_t *me)
const rb_method_definition_t *def = me->def;
if (!def) return 0;
switch (def->type) {
+ case VM_METHOD_TYPE_CFUNC_FAST:
case VM_METHOD_TYPE_CFUNC:
if (def->body.cfunc.argc < 0)
return -1;
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;
}
}
diff --git a/vm_method.c b/vm_method.c
index fb656b3e8b..303817ded8 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -96,6 +96,20 @@ rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_me
}
void
+rb_add_method_cfunc_fast(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
+{
+ if (func != rb_f_notimplement) {
+ rb_method_cfunc_t opt;
+ opt.func = func;
+ opt.argc = argc;
+ rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC_FAST, &opt, noex);
+ }
+ else {
+ rb_define_notimplement_method_id(klass, mid, noex);
+ }
+}
+
+void
rb_unlink_method_entry(rb_method_entry_t *me)
{
struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
@@ -304,6 +318,7 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
def->body.iseq = (rb_iseq_t *)opts;
break;
case VM_METHOD_TYPE_CFUNC:
+ case VM_METHOD_TYPE_CFUNC_FAST:
def->body.cfunc = *(rb_method_cfunc_t *)opts;
break;
case VM_METHOD_TYPE_ATTRSET: