proc.c (rb_proc_alloc): inline and move to vm.c

* proc.c (rb_proc_alloc): inline and move to vm.c
  (rb_proc_wrap): new wrapper function used by rb_proc_alloc
  (proc_dup): simplify alloc + copy + wrap operation
  [ruby-core:64994]

* vm.c (rb_proc_alloc): new inline function
  (rb_vm_make_proc): call rb_proc_alloc

* vm_core.h: remove rb_proc_alloc, add rb_proc_wrap

* benchmark/bm_vm2_newlambda.rb: short test to show difference

First we allocate and populate an rb_proc_t struct inline to avoid
unnecessary zeroing of the large struct.  Inlining speeds up callers as
this takes many parameters to ensure correctness.  We then call the new
rb_proc_wrap function to create the object.

rb_proc_wrap - wraps a rb_proc_t pointer as a Ruby object, but
we only use it inside rb_proc_alloc.  We must call this before
the compiler may clobber VALUE parameters passed to rb_proc_alloc.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47562 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2014-09-12 20:57:45 +00:00
Родитель afa512d9e1
Коммит ec475ab32d
5 изменённых файлов: 59 добавлений и 25 удалений

Просмотреть файл

@ -1,3 +1,17 @@
Sat Sep 13 05:52:15 2014 Eric Wong <e@80x24.org>
* proc.c (rb_proc_alloc): inline and move to vm.c
(rb_proc_wrap): new wrapper function used by rb_proc_alloc
(proc_dup): simplify alloc + copy + wrap operation
[ruby-core:64994]
* vm.c (rb_proc_alloc): new inline function
(rb_vm_make_proc): call rb_proc_alloc
* vm_core.h: remove rb_proc_alloc, add rb_proc_wrap
* benchmark/bm_vm2_newlambda.rb: short test to show difference
Sat Sep 13 04:40:04 2014 Eric Wong <e@80x24.org>
* process.c (Init_process): subclass Thread as Process::Waiter

Просмотреть файл

@ -0,0 +1,5 @@
i = 0
while i<6_000_000 # benchmark loop 2
i += 1
lambda {}
end

24
proc.c
Просмотреть файл

@ -84,10 +84,11 @@ static const rb_data_type_t proc_data_type = {
};
VALUE
rb_proc_alloc(VALUE klass)
rb_proc_wrap(VALUE klass, rb_proc_t *proc)
{
rb_proc_t *proc;
return TypedData_Make_Struct(klass, rb_proc_t, &proc_data_type, proc);
proc->block.proc = TypedData_Wrap_Struct(klass, &proc_data_type, proc);
return proc->block.proc;
}
VALUE
@ -105,17 +106,14 @@ rb_obj_is_proc(VALUE proc)
static VALUE
proc_dup(VALUE self)
{
VALUE procval = rb_proc_alloc(rb_cProc);
rb_proc_t *src, *dst;
GetProcPtr(self, src);
GetProcPtr(procval, dst);
VALUE procval;
rb_proc_t *src;
rb_proc_t *dst = ALLOC(rb_proc_t);
dst->block = src->block;
dst->block.proc = procval;
dst->blockprocval = src->blockprocval;
dst->envval = src->envval;
dst->safe_level = src->safe_level;
dst->is_lambda = src->is_lambda;
GetProcPtr(self, src);
*dst = *src;
procval = rb_proc_wrap(rb_cProc, dst);
RB_GC_GUARD(self); /* for: body = proc_dup(body) */
return procval;
}

39
vm.c
Просмотреть файл

@ -651,11 +651,35 @@ vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block)
return block->proc;
}
static inline VALUE
rb_proc_alloc(VALUE klass, const rb_block_t *block,
VALUE envval, VALUE blockprocval,
int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
{
VALUE procval;
rb_proc_t *proc = ALLOC(rb_proc_t);
proc->block = *block;
proc->safe_level = safe_level;
proc->is_from_method = is_from_method;
proc->is_lambda = is_lambda;
procval = rb_proc_wrap(klass, proc);
/*
* ensure VALUEs are markable here as rb_proc_wrap may trigger allocation
* and clobber envval + blockprocval
*/
proc->envval = envval;
proc->blockprocval = blockprocval;
return procval;
}
VALUE
rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
{
VALUE procval, envval, blockprocval = 0;
rb_proc_t *proc;
rb_control_frame_t *cfp = RUBY_VM_GET_CFP_FROM_BLOCK_PTR(block);
if (block->proc) {
@ -667,16 +691,9 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
if (PROCDEBUG) {
check_env_value(envval);
}
procval = rb_proc_alloc(klass);
GetProcPtr(procval, proc);
proc->blockprocval = blockprocval;
proc->block.self = block->self;
proc->block.klass = block->klass;
proc->block.ep = block->ep;
proc->block.iseq = block->iseq;
proc->block.proc = procval;
proc->envval = envval;
proc->safe_level = th->safe_level;
procval = rb_proc_alloc(klass, block, envval, blockprocval,
th->safe_level, 0, 0);
if (VMDEBUG) {
if (th->stack < block->ep && block->ep < th->stack + th->stack_size) {

Просмотреть файл

@ -884,7 +884,7 @@ rb_block_t *rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp);
/* VM related object allocate functions */
VALUE rb_thread_alloc(VALUE klass);
VALUE rb_proc_alloc(VALUE klass);
VALUE rb_proc_wrap(VALUE klass, rb_proc_t *); /* may use with rb_proc_alloc */
/* for debug */
extern void rb_vmdebug_stack_dump_raw(rb_thread_t *, rb_control_frame_t *);