From 9eba45a72a63674e35d0e9dec6ddf73088ed39e8 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 23 Oct 2012 04:22:31 +0000 Subject: * vm_core.h, vm_insnhelper.c, vm_eval.c (OPT_CALL_CFUNC_WITHOUT_FRAME): add a new otpimization and its macro `OPT_CALL_CFUNC_WITHOUT_FRAME'. This optimization makes all cfunc method calls `frameless', which is fster than ordinal cfunc method call. If `frame' is needed (for example, it calls another method with `rb_funcall()'), then build a frame. In other words, this optimization delays frame building. However, to delay the frame building, we need additional overheads: (1) Store the last call information. (2) Check the delayed frame buidling before the frame is needed. (3) Overhead to build a delayed frame. rb_thread_t::passed_ci is storage of delayed cfunc call information. (1) is lightweight because it is only 1 assignment to `passed_ci'. To achieve (2), we modify GET_THREAD() to check `passed_ci' every time. It causes 10% overhead on my envrionment. This optimization only works for cfunc methods which do not need their `frame'. After evaluation on my environment, this optimization does not effective every time. Because of this evaluation results, this optimization is disabled at default. * vm_insnhelper.c, vm.c: add VM_PROFILE* macros to measure behaviour of VM internals. I will extend this feature. * vm_method.c, method.h: change parameters of the `invoker' function. Receive `func' pointer as the first parameter. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37293 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm_core.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'vm_core.h') diff --git a/vm_core.h b/vm_core.h index 5e68b8e9ab..e2d18c1aab 100644 --- a/vm_core.h +++ b/vm_core.h @@ -166,7 +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 */ + 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); @@ -478,6 +478,9 @@ typedef struct rb_thread_struct { /* for bmethod */ const rb_method_entry_t *passed_me; + /* for cfunc */ + rb_call_info_t *passed_ci; + /* for load(true) */ VALUE top_self; VALUE top_wrapper; @@ -816,7 +819,24 @@ extern rb_vm_t *ruby_current_vm; extern rb_event_flag_t ruby_vm_event_flags; #define GET_VM() ruby_current_vm -#define GET_THREAD() ruby_current_thread + +#ifndef OPT_CALL_CFUNC_WITHOUT_FRAME +#define OPT_CALL_CFUNC_WITHOUT_FRAME 0 +#endif + +static inline rb_thread_t * +GET_THREAD(void) +{ + rb_thread_t *th = ruby_current_thread; +#if OPT_CALL_CFUNC_WITHOUT_FRAME + if (UNLIKELY(th->passed_ci != 0)) { + void vm_call_cfunc_push_frame(rb_thread_t *th); + vm_call_cfunc_push_frame(th); + } +#endif + return th; +} + #define rb_thread_set_current_raw(th) (void)(ruby_current_thread = (th)) #define rb_thread_set_current(th) do { \ if ((th)->vm->running_thread != (th)) { \ -- cgit v1.2.3