1 /**********************************************************************
3 vm_args.c - process method call arguments.
7 Copyright (C) 2014- Yukihiro Matsumoto
9 **********************************************************************/
11 NORETURN(static void raise_argument_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const VALUE exc
));
12 NORETURN(static void argument_arity_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const int miss_argc
, const int min_argc
, const int max_argc
));
13 NORETURN(static void argument_kw_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const char *error
, const VALUE keys
));
14 VALUE
rb_keyword_error_new(const char *error
, VALUE keys
); /* class.c */
15 static VALUE
method_missing(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int argc
, const VALUE
*argv
,
16 enum method_missing_reason call_status
, int kw_splat
);
17 #if !defined(_MSC_VER) || !defined(MJIT_HEADER)
20 const rb_callable_method_entry_t
*rb_resolve_refined_method_callable(VALUE refinements
, const rb_callable_method_entry_t
*me
);
27 /* additional args info */
30 const struct rb_callinfo_kwarg
*kw_arg
;
41 arg_rest_dup(struct args_info
*args
)
43 if (!args
->rest_dupped
) {
44 args
->rest
= rb_ary_dup(args
->rest
);
45 args
->rest_dupped
= TRUE
;
50 args_argc(struct args_info
*args
)
52 if (args
->rest
== Qfalse
) {
56 return args
->argc
+ RARRAY_LENINT(args
->rest
) - args
->rest_index
;
61 args_extend(struct args_info
*args
, const int min_argc
)
67 VM_ASSERT(args
->rest_index
== 0);
68 for (i
=args
->argc
+ RARRAY_LENINT(args
->rest
); i
<min_argc
; i
++) {
69 rb_ary_push(args
->rest
, Qnil
);
73 for (i
=args
->argc
; i
<min_argc
; i
++) {
74 args
->argv
[args
->argc
++] = Qnil
;
80 args_reduce(struct args_info
*args
, int over_argc
)
83 const long len
= RARRAY_LEN(args
->rest
);
85 if (len
> over_argc
) {
87 rb_ary_resize(args
->rest
, len
- over_argc
);
96 VM_ASSERT(args
->argc
>= over_argc
);
97 args
->argc
-= over_argc
;
101 args_check_block_arg0(struct args_info
*args
)
105 if (args
->rest
&& RARRAY_LEN(args
->rest
) == 1) {
106 VALUE arg0
= RARRAY_AREF(args
->rest
, 0);
107 ary
= rb_check_array_type(arg0
);
109 else if (args
->argc
== 1) {
110 VALUE arg0
= args
->argv
[0];
111 ary
= rb_check_array_type(arg0
);
112 args
->argv
[0] = arg0
; /* see: https://bugs.ruby-lang.org/issues/8484 */
117 args
->rest_index
= 0;
126 args_copy(struct args_info
*args
)
128 if (args
->rest
!= Qfalse
) {
129 int argc
= args
->argc
;
134 * argv: [m0, m1, m2, m3]
135 * rest: [a0, a1, a2, a3, a4, a5]
142 * rest: [m2, m3, a2, a3, a4, a5]
148 * argv: [] (argc == 0)
149 * rest: [m0, m1, m2, m3, a2, a3, a4, a5]
153 while (args
->rest_index
> 0 && argc
> 0) {
154 RARRAY_ASET(args
->rest
, --args
->rest_index
, args
->argv
[--argc
]);
157 rb_ary_unshift(args
->rest
, args
->argv
[--argc
]);
160 else if (args
->argc
> 0) {
161 args
->rest
= rb_ary_new_from_values(args
->argc
, args
->argv
);
162 args
->rest_index
= 0;
163 args
->rest_dupped
= TRUE
;
168 static inline const VALUE
*
169 args_rest_argv(struct args_info
*args
)
171 return RARRAY_CONST_PTR_TRANSIENT(args
->rest
) + args
->rest_index
;
175 args_rest_array(struct args_info
*args
)
180 ary
= rb_ary_behead(args
->rest
, args
->rest_index
);
181 args
->rest_index
= 0;
191 args_kw_argv_to_hash(struct args_info
*args
)
193 const struct rb_callinfo_kwarg
*kw_arg
= args
->kw_arg
;
194 const VALUE
*const passed_keywords
= kw_arg
->keywords
;
195 const int kw_len
= kw_arg
->keyword_len
;
196 VALUE h
= rb_hash_new_with_size(kw_len
);
197 const int kw_start
= args
->argc
- kw_len
;
198 const VALUE
* const kw_argv
= args
->argv
+ kw_start
;
201 args
->argc
= kw_start
+ 1;
202 for (i
=0; i
<kw_len
; i
++) {
203 rb_hash_aset(h
, passed_keywords
[i
], kw_argv
[i
]);
206 args
->argv
[args
->argc
- 1] = h
;
212 args_setup_lead_parameters(struct args_info
*args
, int argc
, VALUE
*locals
)
214 if (args
->argc
>= argc
) {
221 const VALUE
*argv
= args_rest_argv(args
);
223 for (i
=args
->argc
, j
=0; i
<argc
; i
++, j
++) {
226 args
->rest_index
+= argc
- args
->argc
;
232 args_setup_post_parameters(struct args_info
*args
, int argc
, VALUE
*locals
)
235 len
= RARRAY_LEN(args
->rest
);
236 MEMCPY(locals
, RARRAY_CONST_PTR_TRANSIENT(args
->rest
) + len
- argc
, VALUE
, argc
);
237 rb_ary_resize(args
->rest
, len
- argc
);
241 args_setup_opt_parameters(struct args_info
*args
, int opt_max
, VALUE
*locals
)
245 if (args
->argc
>= opt_max
) {
246 args
->argc
-= opt_max
;
247 args
->argv
+= opt_max
;
256 int len
= RARRAY_LENINT(args
->rest
);
257 const VALUE
*argv
= RARRAY_CONST_PTR_TRANSIENT(args
->rest
);
259 for (; i
<opt_max
&& args
->rest_index
< len
; i
++, args
->rest_index
++) {
260 locals
[i
] = argv
[args
->rest_index
];
264 /* initialize by nil */
265 for (j
=i
; j
<opt_max
; j
++) {
274 args_setup_rest_parameter(struct args_info
*args
, VALUE
*locals
)
276 *locals
= args_rest_array(args
);
280 make_unknown_kw_hash(const VALUE
*passed_keywords
, int passed_keyword_len
, const VALUE
*kw_argv
)
283 VALUE obj
= rb_ary_tmp_new(1);
285 for (i
=0; i
<passed_keyword_len
; i
++) {
286 if (kw_argv
[i
] != Qundef
) {
287 rb_ary_push(obj
, passed_keywords
[i
]);
294 make_rest_kw_hash(const VALUE
*passed_keywords
, int passed_keyword_len
, const VALUE
*kw_argv
)
297 VALUE obj
= rb_hash_new_with_size(passed_keyword_len
);
299 for (i
=0; i
<passed_keyword_len
; i
++) {
300 if (kw_argv
[i
] != Qundef
) {
301 rb_hash_aset(obj
, passed_keywords
[i
], kw_argv
[i
]);
308 args_setup_kw_parameters_lookup(const ID key
, VALUE
*ptr
, const VALUE
*const passed_keywords
, VALUE
*passed_values
, const int passed_keyword_len
)
311 const VALUE keyname
= ID2SYM(key
);
313 for (i
=0; i
<passed_keyword_len
; i
++) {
314 if (keyname
== passed_keywords
[i
]) {
315 *ptr
= passed_values
[i
];
316 passed_values
[i
] = Qundef
;
324 #define KW_SPECIFIED_BITS_MAX (32-1) /* TODO: 32 -> Fixnum's max bits */
327 args_setup_kw_parameters(rb_execution_context_t
*const ec
, const rb_iseq_t
*const iseq
,
328 VALUE
*const passed_values
, const int passed_keyword_len
, const VALUE
*const passed_keywords
,
331 const ID
*acceptable_keywords
= iseq
->body
->param
.keyword
->table
;
332 const int req_key_num
= iseq
->body
->param
.keyword
->required_num
;
333 const int key_num
= iseq
->body
->param
.keyword
->num
;
334 const VALUE
* const default_values
= iseq
->body
->param
.keyword
->default_values
;
336 int i
, di
, found
= 0;
337 int unspecified_bits
= 0;
338 VALUE unspecified_bits_value
= Qnil
;
340 for (i
=0; i
<req_key_num
; i
++) {
341 ID key
= acceptable_keywords
[i
];
342 if (args_setup_kw_parameters_lookup(key
, &locals
[i
], passed_keywords
, passed_values
, passed_keyword_len
)) {
346 if (!missing
) missing
= rb_ary_tmp_new(1);
347 rb_ary_push(missing
, ID2SYM(key
));
351 if (missing
) argument_kw_error(ec
, iseq
, "missing", missing
);
353 for (di
=0; i
<key_num
; i
++, di
++) {
354 if (args_setup_kw_parameters_lookup(acceptable_keywords
[i
], &locals
[i
], passed_keywords
, passed_values
, passed_keyword_len
)) {
358 if (default_values
[di
] == Qundef
) {
361 if (LIKELY(i
< KW_SPECIFIED_BITS_MAX
)) {
362 unspecified_bits
|= 0x01 << di
;
365 if (NIL_P(unspecified_bits_value
)) {
368 unspecified_bits_value
= rb_hash_new();
370 for (j
=0; j
<KW_SPECIFIED_BITS_MAX
; j
++) {
371 if (unspecified_bits
& (0x01 << j
)) {
372 rb_hash_aset(unspecified_bits_value
, INT2FIX(j
), Qtrue
);
376 rb_hash_aset(unspecified_bits_value
, INT2FIX(di
), Qtrue
);
380 locals
[i
] = default_values
[di
];
385 if (iseq
->body
->param
.flags
.has_kwrest
) {
386 const int rest_hash_index
= key_num
+ 1;
387 locals
[rest_hash_index
] = make_rest_kw_hash(passed_keywords
, passed_keyword_len
, passed_values
);
390 if (found
!= passed_keyword_len
) {
391 VALUE keys
= make_unknown_kw_hash(passed_keywords
, passed_keyword_len
, passed_values
);
392 argument_kw_error(ec
, iseq
, "unknown", keys
);
396 if (NIL_P(unspecified_bits_value
)) {
397 unspecified_bits_value
= INT2FIX(unspecified_bits
);
399 locals
[key_num
] = unspecified_bits_value
;
403 args_setup_kw_rest_parameter(VALUE keyword_hash
, VALUE
*locals
, int kw_flag
)
405 if (NIL_P(keyword_hash
)) {
406 keyword_hash
= rb_hash_new();
408 else if (!(kw_flag
& VM_CALL_KW_SPLAT_MUT
)) {
409 keyword_hash
= rb_hash_dup(keyword_hash
);
411 locals
[0] = keyword_hash
;
415 args_setup_block_parameter(const rb_execution_context_t
*ec
, struct rb_calling_info
*calling
, VALUE
*locals
)
417 VALUE block_handler
= calling
->block_handler
;
418 *locals
= rb_vm_bh_to_procval(ec
, block_handler
);
421 struct fill_values_arg
{
428 fill_keys_values(st_data_t key
, st_data_t val
, st_data_t ptr
)
430 struct fill_values_arg
*arg
= (struct fill_values_arg
*)ptr
;
432 arg
->keys
[i
] = (VALUE
)key
;
433 arg
->vals
[i
] = (VALUE
)val
;
438 ignore_keyword_hash_p(VALUE keyword_hash
, const rb_iseq_t
* const iseq
, unsigned int * kw_flag
, VALUE
* converted_keyword_hash
)
440 if (!RB_TYPE_P(keyword_hash
, T_HASH
)) {
441 keyword_hash
= rb_to_hash_type(keyword_hash
);
443 if (!(*kw_flag
& VM_CALL_KW_SPLAT_MUT
) &&
444 (iseq
->body
->param
.flags
.has_kwrest
||
445 iseq
->body
->param
.flags
.ruby2_keywords
)) {
446 *kw_flag
|= VM_CALL_KW_SPLAT_MUT
;
447 keyword_hash
= rb_hash_dup(keyword_hash
);
449 *converted_keyword_hash
= keyword_hash
;
450 return !(iseq
->body
->param
.flags
.has_kw
) &&
451 !(iseq
->body
->param
.flags
.has_kwrest
) &&
452 RHASH_EMPTY_P(keyword_hash
);
456 setup_parameters_complex(rb_execution_context_t
* const ec
, const rb_iseq_t
* const iseq
,
457 struct rb_calling_info
*const calling
,
458 const struct rb_callinfo
*ci
,
459 VALUE
* const locals
, const enum arg_setup_type arg_setup_type
)
461 const int min_argc
= iseq
->body
->param
.lead_num
+ iseq
->body
->param
.post_num
;
462 const int max_argc
= (iseq
->body
->param
.flags
.has_rest
== FALSE
) ? min_argc
+ iseq
->body
->param
.opt_num
: UNLIMITED_ARGUMENTS
;
464 unsigned int kw_flag
= vm_ci_flag(ci
) & (VM_CALL_KWARG
| VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
465 int opt_pc
= 0, allow_autosplat
= !kw_flag
;
466 struct args_info args_body
, *args
;
467 VALUE keyword_hash
= Qnil
;
468 VALUE
* const orig_sp
= ec
->cfp
->sp
;
470 VALUE flag_keyword_hash
= 0;
471 VALUE converted_keyword_hash
= 0;
473 vm_check_canary(ec
, orig_sp
);
477 * [pushed values] [uninitialized values]
479 * <- iseq->body->param.size------------>
483 * [pushed values] [initialized values ]
485 * <- iseq->body->param.size------------>
488 for (i
=calling
->argc
; i
<iseq
->body
->param
.size
; i
++) {
491 ec
->cfp
->sp
= &locals
[i
];
495 given_argc
= args
->argc
= calling
->argc
;
497 args
->rest_dupped
= FALSE
;
499 if (kw_flag
& VM_CALL_KWARG
) {
500 args
->kw_arg
= vm_ci_kwarg(ci
);
502 if (iseq
->body
->param
.flags
.has_kw
) {
503 int kw_len
= args
->kw_arg
->keyword_len
;
505 args
->kw_argv
= ALLOCA_N(VALUE
, kw_len
);
506 args
->argc
-= kw_len
;
507 given_argc
-= kw_len
;
508 MEMCPY(args
->kw_argv
, locals
+ args
->argc
, VALUE
, kw_len
);
511 args
->kw_argv
= NULL
;
512 given_argc
= args_kw_argv_to_hash(args
);
513 kw_flag
|= VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
;
518 args
->kw_argv
= NULL
;
521 if (vm_ci_flag(ci
) & VM_CALL_ARGS_SPLAT
) {
524 args
->rest
= locals
[--args
->argc
];
525 args
->rest_index
= 0;
526 len
= RARRAY_LENINT(args
->rest
);
527 given_argc
+= len
- 1;
528 rest_last
= RARRAY_AREF(args
->rest
, len
- 1);
530 if (!kw_flag
&& len
> 0) {
531 if (RB_TYPE_P(rest_last
, T_HASH
) &&
532 (((struct RHash
*)rest_last
)->basic
.flags
& RHASH_PASS_AS_KEYWORDS
)) {
533 rest_last
= rb_hash_dup(rest_last
);
534 kw_flag
|= VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
;
541 if (kw_flag
& VM_CALL_KW_SPLAT
) {
542 if (ignore_keyword_hash_p(rest_last
, iseq
, &kw_flag
, &converted_keyword_hash
)) {
544 rb_ary_pop(args
->rest
);
546 kw_flag
&= ~(VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
549 if (rest_last
!= converted_keyword_hash
) {
550 rest_last
= converted_keyword_hash
;
552 RARRAY_ASET(args
->rest
, len
- 1, rest_last
);
555 if (iseq
->body
->param
.flags
.ruby2_keywords
&& rest_last
) {
556 flag_keyword_hash
= rest_last
;
558 else if (iseq
->body
->param
.flags
.has_kw
|| iseq
->body
->param
.flags
.has_kwrest
) {
560 rb_ary_pop(args
->rest
);
562 keyword_hash
= rest_last
;
568 if (kw_flag
& VM_CALL_KW_SPLAT
) {
569 VALUE last_arg
= args
->argv
[args
->argc
-1];
570 if (ignore_keyword_hash_p(last_arg
, iseq
, &kw_flag
, &converted_keyword_hash
)) {
573 kw_flag
&= ~(VM_CALL_KW_SPLAT
| VM_CALL_KW_SPLAT_MUT
);
576 if (last_arg
!= converted_keyword_hash
) {
577 last_arg
= converted_keyword_hash
;
578 args
->argv
[args
->argc
-1] = last_arg
;
581 if (iseq
->body
->param
.flags
.ruby2_keywords
) {
582 flag_keyword_hash
= last_arg
;
584 else if (iseq
->body
->param
.flags
.has_kw
|| iseq
->body
->param
.flags
.has_kwrest
) {
587 keyword_hash
= last_arg
;
594 if (flag_keyword_hash
&& RB_TYPE_P(flag_keyword_hash
, T_HASH
)) {
595 ((struct RHash
*)flag_keyword_hash
)->basic
.flags
|= RHASH_PASS_AS_KEYWORDS
;
598 if (kw_flag
&& iseq
->body
->param
.flags
.accepts_no_kwarg
) {
599 rb_raise(rb_eArgError
, "no keywords accepted");
603 switch (arg_setup_type
) {
604 case arg_setup_method
:
605 break; /* do nothing special */
606 case arg_setup_block
:
607 if (given_argc
== (NIL_P(keyword_hash
) ? 1 : 2) &&
609 (min_argc
> 0 || iseq
->body
->param
.opt_num
> 1) &&
610 !iseq
->body
->param
.flags
.ambiguous_param0
&&
611 args_check_block_arg0(args
)) {
612 given_argc
= RARRAY_LENINT(args
->rest
);
618 if (given_argc
< min_argc
) {
619 if (arg_setup_type
== arg_setup_block
) {
620 CHECK_VM_STACK_OVERFLOW(ec
->cfp
, min_argc
);
621 given_argc
= min_argc
;
622 args_extend(args
, min_argc
);
625 argument_arity_error(ec
, iseq
, given_argc
, min_argc
, max_argc
);
629 if (given_argc
> max_argc
&& max_argc
!= UNLIMITED_ARGUMENTS
) {
630 if (arg_setup_type
== arg_setup_block
) {
632 args_reduce(args
, given_argc
- max_argc
);
633 given_argc
= max_argc
;
636 argument_arity_error(ec
, iseq
, given_argc
, min_argc
, max_argc
);
640 if (iseq
->body
->param
.flags
.has_lead
) {
641 args_setup_lead_parameters(args
, iseq
->body
->param
.lead_num
, locals
+ 0);
644 if (iseq
->body
->param
.flags
.has_rest
|| iseq
->body
->param
.flags
.has_post
){
648 if (iseq
->body
->param
.flags
.has_post
) {
649 args_setup_post_parameters(args
, iseq
->body
->param
.post_num
, locals
+ iseq
->body
->param
.post_start
);
652 if (iseq
->body
->param
.flags
.has_opt
) {
653 int opt
= args_setup_opt_parameters(args
, iseq
->body
->param
.opt_num
, locals
+ iseq
->body
->param
.lead_num
);
654 opt_pc
= (int)iseq
->body
->param
.opt_table
[opt
];
657 if (iseq
->body
->param
.flags
.has_rest
) {
658 args_setup_rest_parameter(args
, locals
+ iseq
->body
->param
.rest_start
);
661 if (iseq
->body
->param
.flags
.has_kw
) {
662 VALUE
* const klocals
= locals
+ iseq
->body
->param
.keyword
->bits_start
- iseq
->body
->param
.keyword
->num
;
664 if (args
->kw_argv
!= NULL
) {
665 const struct rb_callinfo_kwarg
*kw_arg
= args
->kw_arg
;
666 args_setup_kw_parameters(ec
, iseq
, args
->kw_argv
, kw_arg
->keyword_len
, kw_arg
->keywords
, klocals
);
668 else if (!NIL_P(keyword_hash
)) {
669 int kw_len
= rb_long2int(RHASH_SIZE(keyword_hash
));
670 struct fill_values_arg arg
;
672 arg
.keys
= args
->kw_argv
= ALLOCA_N(VALUE
, kw_len
* 2);
673 arg
.vals
= arg
.keys
+ kw_len
;
675 rb_hash_foreach(keyword_hash
, fill_keys_values
, (VALUE
)&arg
);
676 VM_ASSERT(arg
.argc
== kw_len
);
677 args_setup_kw_parameters(ec
, iseq
, arg
.vals
, kw_len
, arg
.keys
, klocals
);
680 VM_ASSERT(args_argc(args
) == 0);
681 args_setup_kw_parameters(ec
, iseq
, NULL
, 0, NULL
, klocals
);
684 else if (iseq
->body
->param
.flags
.has_kwrest
) {
685 args_setup_kw_rest_parameter(keyword_hash
, locals
+ iseq
->body
->param
.keyword
->rest_start
, kw_flag
);
687 else if (!NIL_P(keyword_hash
) && RHASH_SIZE(keyword_hash
) > 0 && arg_setup_type
== arg_setup_method
) {
688 argument_kw_error(ec
, iseq
, "unknown", rb_hash_keys(keyword_hash
));
691 if (iseq
->body
->param
.flags
.has_block
) {
692 if (iseq
->body
->local_iseq
== iseq
) {
696 args_setup_block_parameter(ec
, calling
, locals
+ iseq
->body
->param
.block_start
);
703 for (i
=0; i
<iseq
->body
->param
.size
; i
++) {
704 ruby_debug_printf("local[%d] = %p\n", i
, (void *)locals
[i
]);
709 ec
->cfp
->sp
= orig_sp
;
714 raise_argument_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const VALUE exc
)
719 vm_push_frame(ec
, iseq
, VM_FRAME_MAGIC_DUMMY
| VM_ENV_FLAG_LOCAL
, Qnil
/* self */,
720 VM_BLOCK_HANDLER_NONE
/* specval*/, Qfalse
/* me or cref */,
721 iseq
->body
->iseq_encoded
,
722 ec
->cfp
->sp
, 0, 0 /* stack_max */);
723 at
= rb_ec_backtrace_object(ec
);
724 rb_backtrace_use_iseq_first_lineno_for_last_location(at
);
728 at
= rb_ec_backtrace_object(ec
);
731 rb_ivar_set(exc
, idBt_locations
, at
);
732 rb_exc_set_backtrace(exc
, at
);
737 argument_arity_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const int miss_argc
, const int min_argc
, const int max_argc
)
739 VALUE exc
= rb_arity_error_new(miss_argc
, min_argc
, max_argc
);
740 if (iseq
->body
->param
.flags
.has_kw
) {
741 const struct rb_iseq_param_keyword
*const kw
= iseq
->body
->param
.keyword
;
742 const ID
*keywords
= kw
->table
;
743 int req_key_num
= kw
->required_num
;
744 if (req_key_num
> 0) {
745 static const char required
[] = "; required keywords";
746 VALUE mesg
= rb_attr_get(exc
, idMesg
);
747 rb_str_resize(mesg
, RSTRING_LEN(mesg
)-1);
748 rb_str_cat(mesg
, required
, sizeof(required
) - 1 - (req_key_num
== 1));
749 rb_str_cat_cstr(mesg
, ":");
751 rb_str_cat_cstr(mesg
, " ");
752 rb_str_append(mesg
, rb_id2str(*keywords
++));
753 rb_str_cat_cstr(mesg
, ",");
754 } while (--req_key_num
);
755 RSTRING_PTR(mesg
)[RSTRING_LEN(mesg
)-1] = ')';
758 raise_argument_error(ec
, iseq
, exc
);
762 argument_kw_error(rb_execution_context_t
*ec
, const rb_iseq_t
*iseq
, const char *error
, const VALUE keys
)
764 raise_argument_error(ec
, iseq
, rb_keyword_error_new(error
, keys
));
768 vm_caller_setup_arg_splat(rb_control_frame_t
*cfp
, struct rb_calling_info
*calling
)
770 int argc
= calling
->argc
;
771 VALUE
*argv
= cfp
->sp
- argc
;
772 VALUE ary
= argv
[argc
-1];
774 vm_check_canary(GET_EC(), cfp
->sp
);
778 const VALUE
*ptr
= RARRAY_CONST_PTR_TRANSIENT(ary
);
779 long len
= RARRAY_LEN(ary
), i
;
781 CHECK_VM_STACK_OVERFLOW(cfp
, len
);
783 for (i
= 0; i
< len
; i
++) {
786 calling
->argc
+= i
- 1;
791 vm_caller_setup_arg_kw(rb_control_frame_t
*cfp
, struct rb_calling_info
*calling
, const struct rb_callinfo
*ci
)
793 const VALUE
*const passed_keywords
= vm_ci_kwarg(ci
)->keywords
;
794 const int kw_len
= vm_ci_kwarg(ci
)->keyword_len
;
795 const VALUE h
= rb_hash_new_with_size(kw_len
);
799 for (i
=0; i
<kw_len
; i
++) {
800 rb_hash_aset(h
, passed_keywords
[i
], (sp
- kw_len
)[i
]);
804 cfp
->sp
-= kw_len
- 1;
805 calling
->argc
-= kw_len
- 1;
806 calling
->kw_splat
= 1;
810 vm_to_proc(VALUE proc
)
812 if (UNLIKELY(!rb_obj_is_proc(proc
))) {
814 const rb_callable_method_entry_t
*me
=
815 rb_callable_method_entry_with_refinements(CLASS_OF(proc
), idTo_proc
, NULL
);
818 b
= rb_vm_call0(GET_EC(), proc
, idTo_proc
, 0, NULL
, me
, RB_NO_KEYWORDS
);
821 /* NOTE: calling method_missing */
822 b
= rb_check_convert_type_with_id(proc
, T_DATA
, "Proc", idTo_proc
);
825 if (NIL_P(b
) || !rb_obj_is_proc(b
)) {
826 rb_raise(rb_eTypeError
,
827 "wrong argument type %s (expected Proc)",
828 rb_obj_classname(proc
));
838 refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg
, callback_arg
))
842 const rb_callable_method_entry_t
*me
= 0; /* for hidden object case */
843 rb_execution_context_t
*ec
;
844 const VALUE symbol
= RARRAY_AREF(callback_arg
, 0);
845 const VALUE refinements
= RARRAY_AREF(callback_arg
, 1);
846 int kw_splat
= RB_PASS_CALLED_KEYWORDS
;
850 rb_raise(rb_eArgError
, "no receiver given");
854 mid
= SYM2ID(symbol
);
855 for (klass
= CLASS_OF(obj
); klass
; klass
= RCLASS_SUPER(klass
)) {
856 me
= rb_callable_method_entry(klass
, mid
);
858 me
= rb_resolve_refined_method_callable(refinements
, me
);
864 if (!NIL_P(blockarg
)) {
865 vm_passed_block_handler_set(ec
, blockarg
);
868 return method_missing(ec
, obj
, mid
, argc
, argv
, MISSING_NOENTRY
, kw_splat
);
870 return rb_vm_call0(ec
, obj
, mid
, argc
, argv
, me
, kw_splat
);
874 vm_caller_setup_arg_block(const rb_execution_context_t
*ec
, rb_control_frame_t
*reg_cfp
,
875 const struct rb_callinfo
*ci
, const rb_iseq_t
*blockiseq
, const int is_super
)
877 if (vm_ci_flag(ci
) & VM_CALL_ARGS_BLOCKARG
) {
878 VALUE block_code
= *(--reg_cfp
->sp
);
880 if (NIL_P(block_code
)) {
881 return VM_BLOCK_HANDLER_NONE
;
883 else if (block_code
== rb_block_param_proxy
) {
884 VM_ASSERT(!VM_CFP_IN_HEAP_P(GET_EC(), reg_cfp
));
885 VALUE handler
= VM_CF_BLOCK_HANDLER(reg_cfp
);
886 reg_cfp
->block_code
= (const void *) handler
;
889 else if (SYMBOL_P(block_code
) && rb_method_basic_definition_p(rb_cSymbol
, idTo_proc
)) {
890 const rb_cref_t
*cref
= vm_env_cref(reg_cfp
->ep
);
891 if (cref
&& !NIL_P(cref
->refinements
)) {
892 VALUE ref
= cref
->refinements
;
893 VALUE func
= rb_hash_lookup(ref
, block_code
);
895 /* TODO: limit cached funcs */
896 VALUE callback_arg
= rb_ary_tmp_new(2);
897 rb_ary_push(callback_arg
, block_code
);
898 rb_ary_push(callback_arg
, ref
);
899 OBJ_FREEZE_RAW(callback_arg
);
900 func
= rb_func_lambda_new(refine_sym_proc_call
, callback_arg
, 1, UNLIMITED_ARGUMENTS
);
901 rb_hash_aset(ref
, block_code
, func
);
908 return vm_to_proc(block_code
);
911 else if (blockiseq
!= NULL
) { /* likely */
912 struct rb_captured_block
*captured
= VM_CFP_TO_CAPTURED_BLOCK(reg_cfp
);
913 captured
->code
.iseq
= blockiseq
;
914 return VM_BH_FROM_ISEQ_BLOCK(captured
);
918 return GET_BLOCK_HANDLER();
921 return VM_BLOCK_HANDLER_NONE
;