зеркало из https://github.com/github/ruby.git
Add rb_block_call2, a flexible variant of rb_block_call
This function accepts flags: RB_NO_KEYWORDS, RB_PASS_KEYWORDS, RB_PASS_CALLED_KEYWORDS: Works as the same as rb_block_call_kw. RB_BLOCK_NO_USE_PACKED_ARGS: The given block ("bl_proc") does not use "yielded_arg" of rb_block_call_func_t. Instead, the block accesses the yielded arguments via "argc" and "argv". This flag allows the called method to yield arguments without allocating an Array.
This commit is contained in:
Родитель
77b12a8aaf
Коммит
114e32b357
|
@ -75,7 +75,7 @@
|
|||
* Pass keywords if current method is called with keywords, useful for argument
|
||||
* delegation
|
||||
*/
|
||||
#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p()
|
||||
#define RB_PASS_CALLED_KEYWORDS !!rb_keyword_given_p()
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ struct vm_ifunc {
|
|||
const void *data;
|
||||
struct vm_ifunc_argc argc;
|
||||
};
|
||||
#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
|
||||
|
||||
struct rb_imemo_tmpbuf_struct {
|
||||
VALUE flags;
|
||||
|
|
|
@ -77,6 +77,8 @@ VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
|||
rb_block_call_func_t bl_proc, int min_argc, int max_argc,
|
||||
VALUE data2);
|
||||
void rb_check_stack_overflow(void);
|
||||
#define RB_BLOCK_NO_USE_PACKED_ARGS 2
|
||||
VALUE rb_block_call2(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t bl_proc, VALUE data2, long flags);
|
||||
|
||||
#if USE_YJIT
|
||||
/* vm_exec.c */
|
||||
|
|
6
proc.c
6
proc.c
|
@ -1159,6 +1159,12 @@ rb_block_pair_yield_optimizable(void)
|
|||
return min > 1;
|
||||
}
|
||||
|
||||
case block_handler_type_ifunc:
|
||||
{
|
||||
const struct vm_ifunc *ifunc = block.as.captured.code.ifunc;
|
||||
if (ifunc->flags & IFUNC_YIELD_OPTIMIZABLE) return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
return min > 1;
|
||||
}
|
||||
|
|
31
vm_eval.c
31
vm_eval.c
|
@ -1558,6 +1558,37 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
|
|||
return rb_iterate_internal(iterate_method, (VALUE)&arg, bl_proc, data2);
|
||||
}
|
||||
|
||||
/*
|
||||
* A flexible variant of rb_block_call and rb_block_call_kw.
|
||||
* This function accepts flags:
|
||||
*
|
||||
* RB_NO_KEYWORDS, RB_PASS_KEYWORDS, RB_PASS_CALLED_KEYWORDS:
|
||||
* Works as the same as rb_block_call_kw.
|
||||
*
|
||||
* RB_BLOCK_NO_USE_PACKED_ARGS:
|
||||
* The given block ("bl_proc") does not use "yielded_arg" of rb_block_call_func_t.
|
||||
* Instead, the block accesses the yielded arguments via "argc" and "argv".
|
||||
* This flag allows the called method to yield arguments without allocating an Array.
|
||||
*/
|
||||
VALUE
|
||||
rb_block_call2(VALUE obj, ID mid, int argc, const VALUE *argv,
|
||||
rb_block_call_func_t bl_proc, VALUE data2, long flags)
|
||||
{
|
||||
struct iter_method_arg arg;
|
||||
|
||||
arg.obj = obj;
|
||||
arg.mid = mid;
|
||||
arg.argc = argc;
|
||||
arg.argv = argv;
|
||||
arg.kw_splat = flags & 1;
|
||||
|
||||
struct vm_ifunc *ifunc = rb_vm_ifunc_proc_new(bl_proc, (void *)data2);
|
||||
if (flags & RB_BLOCK_NO_USE_PACKED_ARGS)
|
||||
ifunc->flags |= IFUNC_YIELD_OPTIMIZABLE;
|
||||
|
||||
return rb_iterate0(iterate_method, (VALUE)&arg, ifunc, GET_EC());
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
||||
rb_block_call_func_t bl_proc, int min_argc, int max_argc,
|
||||
|
|
Загрузка…
Ссылка в новой задаче