зеркало из 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
|
* Pass keywords if current method is called with keywords, useful for argument
|
||||||
* delegation
|
* 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;
|
const void *data;
|
||||||
struct vm_ifunc_argc argc;
|
struct vm_ifunc_argc argc;
|
||||||
};
|
};
|
||||||
|
#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
|
||||||
|
|
||||||
struct rb_imemo_tmpbuf_struct {
|
struct rb_imemo_tmpbuf_struct {
|
||||||
VALUE flags;
|
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,
|
rb_block_call_func_t bl_proc, int min_argc, int max_argc,
|
||||||
VALUE data2);
|
VALUE data2);
|
||||||
void rb_check_stack_overflow(void);
|
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
|
#if USE_YJIT
|
||||||
/* vm_exec.c */
|
/* vm_exec.c */
|
||||||
|
|
6
proc.c
6
proc.c
|
@ -1159,6 +1159,12 @@ rb_block_pair_yield_optimizable(void)
|
||||||
return min > 1;
|
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:
|
default:
|
||||||
return min > 1;
|
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);
|
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
|
VALUE
|
||||||
rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
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,
|
rb_block_call_func_t bl_proc, int min_argc, int max_argc,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче