11#include "ruby/internal/config.h"
15#ifdef HAVE_STDATOMIC_H
16 #include <stdatomic.h>
20#include "debug_counter.h"
22#include "internal/class.h"
23#include "internal/compar.h"
24#include "internal/hash.h"
25#include "internal/numeric.h"
26#include "internal/proc.h"
27#include "internal/random.h"
28#include "internal/variable.h"
29#include "internal/set_table.h"
30#include "internal/struct.h"
35#include "insns_info.inc"
37extern rb_method_definition_t *rb_method_definition_create(rb_method_type_t
type,
ID mid);
38extern void rb_method_definition_set(
const rb_method_entry_t *me, rb_method_definition_t *def,
void *opts);
39extern int rb_method_definition_eq(
const rb_method_definition_t *d1,
const rb_method_definition_t *d2);
41 int argc,
const VALUE *argv,
int priv);
48static rb_control_frame_t *vm_get_ruby_level_caller_cfp(
const rb_execution_context_t *ec,
const rb_control_frame_t *cfp);
51ruby_vm_special_exception_copy(
VALUE exc)
54 rb_obj_copy_ivar(e, exc);
58NORETURN(
static void ec_stack_overflow(rb_execution_context_t *ec,
int));
60ec_stack_overflow(rb_execution_context_t *ec,
int setup)
62 VALUE mesg = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_sysstack];
63 ec->raised_flag = RAISED_STACKOVERFLOW;
65 VALUE at = rb_ec_backtrace_object(ec);
66 mesg = ruby_vm_special_exception_copy(mesg);
71 EC_JUMP_TAG(ec, TAG_RAISE);
74NORETURN(
static void vm_stackoverflow(
void));
79 ec_stack_overflow(GET_EC(), TRUE);
83rb_ec_stack_overflow(rb_execution_context_t *ec, ruby_stack_overflow_critical_level crit)
86 rb_bug(
"system stack overflow during GC. Faulty native extension?");
88 if (crit >= rb_stack_overflow_fatal) {
89 ec->raised_flag = RAISED_STACKOVERFLOW;
90 ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
91 EC_JUMP_TAG(ec, TAG_RAISE);
93 ec_stack_overflow(ec, crit < rb_stack_overflow_signal);
96static inline void stack_check(rb_execution_context_t *ec);
100callable_class_p(
VALUE klass)
102#if VM_CHECK_MODE >= 2
103 if (!klass)
return FALSE;
104 switch (RB_BUILTIN_TYPE(klass)) {
125callable_method_entry_p(
const rb_callable_method_entry_t *cme)
131 VM_ASSERT(IMEMO_TYPE_P((
VALUE)cme, imemo_ment),
"imemo_type:%s", rb_imemo_name(imemo_type((
VALUE)cme)));
133 if (callable_class_p(cme->defined_class)) {
143vm_check_frame_detail(
VALUE type,
int req_block,
int req_me,
int req_cref,
VALUE specval,
VALUE cref_or_me,
int is_cframe,
const rb_iseq_t *iseq)
145 unsigned int magic = (
unsigned int)(
type & VM_FRAME_MAGIC_MASK);
146 enum imemo_type cref_or_me_type = imemo_env;
148 if (RB_TYPE_P(cref_or_me,
T_IMEMO)) {
149 cref_or_me_type = imemo_type(cref_or_me);
151 if (
type & VM_FRAME_FLAG_BMETHOD) {
155 if (req_block && (
type & VM_ENV_FLAG_LOCAL) == 0) {
156 rb_bug(
"vm_push_frame: specval (%p) should be a block_ptr on %x frame", (
void *)specval, magic);
158 if (!req_block && (
type & VM_ENV_FLAG_LOCAL) != 0) {
159 rb_bug(
"vm_push_frame: specval (%p) should not be a block_ptr on %x frame", (
void *)specval, magic);
163 if (cref_or_me_type != imemo_ment) {
164 rb_bug(
"vm_push_frame: (%s) should be method entry on %x frame", rb_obj_info(cref_or_me), magic);
168 if (req_cref && cref_or_me_type != imemo_cref) {
169 rb_bug(
"vm_push_frame: (%s) should be CREF on %x frame", rb_obj_info(cref_or_me), magic);
172 if (cref_or_me !=
Qfalse && cref_or_me_type != imemo_cref) {
173 if (((
type & VM_FRAME_FLAG_LAMBDA) || magic == VM_FRAME_MAGIC_IFUNC || magic == VM_FRAME_MAGIC_DUMMY) && (cref_or_me_type == imemo_ment)) {
177 rb_bug(
"vm_push_frame: (%s) should be false or cref on %x frame", rb_obj_info(cref_or_me), magic);
183 if (cref_or_me_type == imemo_ment) {
184 const rb_callable_method_entry_t *me = (
const rb_callable_method_entry_t *)cref_or_me;
186 if (!callable_method_entry_p(me)) {
187 rb_bug(
"vm_push_frame: ment (%s) should be callable on %x frame.", rb_obj_info(cref_or_me), magic);
191 if ((
type & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
192 VM_ASSERT(iseq == NULL ||
193 RBASIC_CLASS((
VALUE)iseq) == 0 ||
194 RUBY_VM_NORMAL_ISEQ_P(iseq)
198 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(iseq));
206 const rb_iseq_t *iseq)
208 VALUE given_magic =
type & VM_FRAME_MAGIC_MASK;
211#define CHECK(magic, req_block, req_me, req_cref, is_cframe) \
213 vm_check_frame_detail(type, req_block, req_me, req_cref, \
214 specval, cref_or_me, is_cframe, iseq); \
216 switch (given_magic) {
218 CHECK(VM_FRAME_MAGIC_METHOD, TRUE, TRUE, FALSE, FALSE);
219 CHECK(VM_FRAME_MAGIC_CLASS, TRUE, FALSE, TRUE, FALSE);
220 CHECK(VM_FRAME_MAGIC_TOP, TRUE, FALSE, TRUE, FALSE);
221 CHECK(VM_FRAME_MAGIC_CFUNC, TRUE, TRUE, FALSE, TRUE);
222 CHECK(VM_FRAME_MAGIC_BLOCK, FALSE, FALSE, FALSE, FALSE);
223 CHECK(VM_FRAME_MAGIC_IFUNC, FALSE, FALSE, FALSE, TRUE);
224 CHECK(VM_FRAME_MAGIC_EVAL, FALSE, FALSE, FALSE, FALSE);
225 CHECK(VM_FRAME_MAGIC_RESCUE, FALSE, FALSE, FALSE, FALSE);
226 CHECK(VM_FRAME_MAGIC_DUMMY, TRUE, FALSE, FALSE, FALSE);
228 rb_bug(
"vm_push_frame: unknown type (%x)", (
unsigned int)given_magic);
233static VALUE vm_stack_canary;
234static bool vm_stack_canary_was_born =
false;
239previous_insn_index(
const rb_iseq_t *iseq,
const VALUE *pc)
241 unsigned int pos = 0;
242 while (pos < ISEQ_BODY(iseq)->iseq_size) {
243 int opcode = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[pos]);
244 unsigned int next_pos = pos + insn_len(opcode);
245 if (ISEQ_BODY(iseq)->iseq_encoded + next_pos == pc) {
250 rb_bug(
"failed to find the previous insn");
254rb_vm_check_canary(
const rb_execution_context_t *ec,
VALUE *sp)
259 if (! LIKELY(vm_stack_canary_was_born)) {
262 else if ((
VALUE *)reg_cfp == ec->vm_stack + ec->vm_stack_size) {
266 else if (! (iseq = GET_ISEQ())) {
269 else if (LIKELY(sp[0] != vm_stack_canary)) {
278 const VALUE *orig = rb_iseq_original_iseq(iseq);
279 const VALUE iseqw = rb_iseqw_new(iseq);
281 const char *stri = rb_str_to_cstr(inspection);
282 const VALUE disasm = rb_iseq_disasm(iseq);
283 const char *strd = rb_str_to_cstr(disasm);
284 const ptrdiff_t pos = previous_insn_index(iseq, GET_PC());
285 const enum ruby_vminsn_type insn = (
enum ruby_vminsn_type)orig[pos];
286 const char *name = insn_name(insn);
292 "We are killing the stack canary set by %s, "
293 "at %s@pc=%"PRIdPTR
"\n"
294 "watch out the C stack trace.\n"
296 name, stri, pos, strd);
297 rb_bug(
"see above.");
299#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
302#define vm_check_canary(ec, sp)
303#define vm_check_frame(a, b, c, d)
308vm_push_frame_debug_counter_inc(
315 RB_DEBUG_COUNTER_INC(frame_push);
317 if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
318 const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
319 const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
322 RB_DEBUG_COUNTER_INC(frame_R2R);
325 RB_DEBUG_COUNTER_INC(frame_R2C);
330 RB_DEBUG_COUNTER_INC(frame_C2R);
333 RB_DEBUG_COUNTER_INC(frame_C2C);
338 switch (
type & VM_FRAME_MAGIC_MASK) {
339 case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method);
return;
340 case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block);
return;
341 case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class);
return;
342 case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top);
return;
343 case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc);
return;
344 case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc);
return;
345 case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval);
return;
346 case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue);
return;
347 case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy);
return;
350 rb_bug(
"unreachable");
353#define vm_push_frame_debug_counter_inc(ec, cfp, t)
358rb_vm_stack_canary(
void)
361 return vm_stack_canary;
367STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
368STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
369STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
372vm_push_frame(rb_execution_context_t *ec,
373 const rb_iseq_t *iseq,
383 rb_control_frame_t *
const cfp = RUBY_VM_NEXT_CONTROL_FRAME(ec->cfp);
385 vm_check_frame(
type, specval, cref_or_me, iseq);
386 VM_ASSERT(local_size >= 0);
389 CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
390 vm_check_canary(ec, sp);
395 for (
int i=0; i < local_size; i++) {
422 #if defined HAVE_DECL_ATOMIC_SIGNAL_FENCE && HAVE_DECL_ATOMIC_SIGNAL_FENCE
423 atomic_signal_fence(memory_order_seq_cst);
431 vm_push_frame_debug_counter_inc(ec, cfp,
type);
435rb_vm_pop_frame_no_int(rb_execution_context_t *ec)
437 rb_control_frame_t *cfp = ec->cfp;
439 if (VMDEBUG == 2) SDR();
441 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
446vm_pop_frame(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const VALUE *ep)
448 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
450 if (VMDEBUG == 2) SDR();
452 RUBY_VM_CHECK_INTS(ec);
453 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
455 return flags & VM_FRAME_FLAG_FINISH;
459rb_vm_pop_frame(rb_execution_context_t *ec)
461 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
466rb_vm_push_frame_fname(rb_execution_context_t *ec,
VALUE fname)
468 rb_iseq_t *rb_iseq_alloc_with_dummy_path(
VALUE fname);
469 rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
473 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
475 VM_BLOCK_HANDLER_NONE,
482 return (
VALUE)dmy_iseq;
487rb_arity_error_new(
int argc,
int min,
int max)
489 VALUE err_mess = rb_sprintf(
"wrong number of arguments (given %d, expected %d", argc, min);
497 rb_str_catf(err_mess,
"..%d", max);
504rb_error_arity(
int argc,
int min,
int max)
511NOINLINE(
static void vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v));
514vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v)
517 rb_gc_writebarrier_remember(VM_ENV_ENVVAL(ep));
518 VM_FORCE_WRITE(&ep[index], v);
519 VM_ENV_FLAGS_UNSET(ep, VM_ENV_FLAG_WB_REQUIRED);
520 RB_DEBUG_COUNTER_INC(lvar_set_slowpath);
525vm_env_write(
const VALUE *ep,
int index,
VALUE v)
527 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
528 if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
529 VM_STACK_ENV_WRITE(ep, index, v);
532 vm_env_write_slowpath(ep, index, v);
537rb_vm_env_write(
const VALUE *ep,
int index,
VALUE v)
539 vm_env_write(ep, index, v);
543rb_vm_bh_to_procval(
const rb_execution_context_t *ec,
VALUE block_handler)
545 if (block_handler == VM_BLOCK_HANDLER_NONE) {
549 switch (vm_block_handler_type(block_handler)) {
550 case block_handler_type_iseq:
551 case block_handler_type_ifunc:
552 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler),
rb_cProc);
553 case block_handler_type_symbol:
554 return rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
555 case block_handler_type_proc:
556 return VM_BH_TO_PROC(block_handler);
558 VM_UNREACHABLE(rb_vm_bh_to_procval);
567vm_svar_valid_p(
VALUE svar)
570 switch (imemo_type(svar)) {
579 rb_bug(
"vm_svar_valid_p: unknown type: %s", rb_obj_info(svar));
585lep_svar(
const rb_execution_context_t *ec,
const VALUE *lep)
589 if (lep && (ec == NULL || ec->root_lep != lep)) {
590 svar = lep[VM_ENV_DATA_INDEX_ME_CREF];
593 svar = ec->root_svar;
596 VM_ASSERT(svar ==
Qfalse || vm_svar_valid_p(svar));
602lep_svar_write(
const rb_execution_context_t *ec,
const VALUE *lep,
const struct vm_svar *svar)
604 VM_ASSERT(vm_svar_valid_p((
VALUE)svar));
606 if (lep && (ec == NULL || ec->root_lep != lep)) {
607 vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (
VALUE)svar);
610 RB_OBJ_WRITE(rb_ec_thread_ptr(ec)->self, &ec->root_svar, svar);
615lep_svar_get(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key)
617 const struct vm_svar *svar = lep_svar(ec, lep);
622 case VM_SVAR_LASTLINE:
623 return svar->lastline;
624 case VM_SVAR_BACKREF:
625 return svar->backref;
627 const VALUE ary = svar->others;
642 struct vm_svar *svar = IMEMO_NEW(
struct vm_svar, imemo_svar, obj);
651lep_svar_set(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key,
VALUE val)
653 struct vm_svar *svar = lep_svar(ec, lep);
656 lep_svar_write(ec, lep, svar = svar_new((
VALUE)svar));
660 case VM_SVAR_LASTLINE:
663 case VM_SVAR_BACKREF:
667 VALUE ary = svar->others;
678vm_getspecial(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key, rb_num_t
type)
683 val = lep_svar_get(ec, lep, key);
686 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
703 rb_bug(
"unexpected back-ref");
714vm_backref_defined(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t
type)
716 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
726 return rb_reg_last_defined(backref);
728 rb_bug(
"unexpected back-ref");
732 nth = (int)(
type >> 1);
737PUREFUNC(
static rb_callable_method_entry_t *check_method_entry(
VALUE obj,
int can_be_svar));
738static rb_callable_method_entry_t *
739check_method_entry(
VALUE obj,
int can_be_svar)
741 if (obj ==
Qfalse)
return NULL;
744 if (!RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_method_entry: unknown type: %s", rb_obj_info(obj));
747 switch (imemo_type(obj)) {
749 return (rb_callable_method_entry_t *)obj;
758 rb_bug(
"check_method_entry: svar should not be there:");
764static rb_callable_method_entry_t *
765env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
767 if (obj ==
Qfalse)
return NULL;
769 switch (imemo_type(obj)) {
771 return (rb_callable_method_entry_t *)obj;
783const rb_callable_method_entry_t *
784rb_vm_frame_method_entry(
const rb_control_frame_t *cfp)
786 const VALUE *ep = cfp->ep;
787 rb_callable_method_entry_t *me;
789 while (!VM_ENV_LOCAL_P(ep)) {
790 if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
791 ep = VM_ENV_PREV_EP(ep);
794 return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
797const rb_callable_method_entry_t *
798rb_vm_frame_method_entry_unchecked(
const rb_control_frame_t *cfp)
800 const VALUE *ep = cfp->ep;
801 rb_callable_method_entry_t *me;
803 while (!VM_ENV_LOCAL_P_UNCHECKED(ep)) {
804 if ((me = env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
805 ep = VM_ENV_PREV_EP_UNCHECKED(ep);
808 return env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
811static const rb_iseq_t *
812method_entry_iseqptr(
const rb_callable_method_entry_t *me)
814 switch (me->def->type) {
815 case VM_METHOD_TYPE_ISEQ:
816 return me->def->body.iseq.iseqptr;
823method_entry_cref(
const rb_callable_method_entry_t *me)
825 switch (me->def->type) {
826 case VM_METHOD_TYPE_ISEQ:
827 return me->def->body.iseq.cref;
833#if VM_CHECK_MODE == 0
834PUREFUNC(
static rb_cref_t *check_cref(
VALUE,
int));
837check_cref(
VALUE obj,
int can_be_svar)
839 if (obj ==
Qfalse)
return NULL;
842 if (!RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_cref: unknown type: %s", rb_obj_info(obj));
845 switch (imemo_type(obj)) {
847 return method_entry_cref((rb_callable_method_entry_t *)obj);
849 return (rb_cref_t *)obj;
856 rb_bug(
"check_method_entry: svar should not be there:");
862static inline rb_cref_t *
863vm_env_cref(
const VALUE *ep)
867 while (!VM_ENV_LOCAL_P(ep)) {
868 if ((cref = check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return cref;
869 ep = VM_ENV_PREV_EP(ep);
872 return check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
876is_cref(
const VALUE v,
int can_be_svar)
879 switch (imemo_type(v)) {
892vm_env_cref_by_cref(
const VALUE *ep)
894 while (!VM_ENV_LOCAL_P(ep)) {
895 if (is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE))
return TRUE;
896 ep = VM_ENV_PREV_EP(ep);
898 return is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
902cref_replace_with_duplicated_cref_each_frame(
const VALUE *vptr,
int can_be_svar,
VALUE parent)
904 const VALUE v = *vptr;
905 rb_cref_t *cref, *new_cref;
908 switch (imemo_type(v)) {
910 cref = (rb_cref_t *)v;
911 new_cref = vm_cref_dup(cref);
916 VM_FORCE_WRITE(vptr, (
VALUE)new_cref);
918 return (rb_cref_t *)new_cref;
921 return cref_replace_with_duplicated_cref_each_frame(&((
struct vm_svar *)v)->
cref_or_me, FALSE, v);
925 rb_bug(
"cref_replace_with_duplicated_cref_each_frame: unreachable");
934vm_cref_replace_with_duplicated_cref(
const VALUE *ep)
936 if (vm_env_cref_by_cref(ep)) {
940 while (!VM_ENV_LOCAL_P(ep)) {
941 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
942 if ((cref = cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE, envval)) != NULL) {
945 ep = VM_ENV_PREV_EP(ep);
947 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
948 return cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE, envval);
951 rb_bug(
"vm_cref_dup: unreachable");
956vm_get_cref(
const VALUE *ep)
958 rb_cref_t *cref = vm_env_cref(ep);
964 rb_bug(
"vm_get_cref: unreachable");
969rb_vm_get_cref(
const VALUE *ep)
971 return vm_get_cref(ep);
975vm_ec_cref(
const rb_execution_context_t *ec)
977 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
982 return vm_get_cref(cfp->ep);
985static const rb_cref_t *
986vm_get_const_key_cref(
const VALUE *ep)
988 const rb_cref_t *cref = vm_get_cref(ep);
989 const rb_cref_t *key_cref = cref;
992 if (RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
993 RCLASS_CLONED_P(CREF_CLASS(cref)) ) {
996 cref = CREF_NEXT(cref);
1004rb_vm_rewrite_cref(rb_cref_t *cref,
VALUE old_klass,
VALUE new_klass)
1006 rb_cref_t *new_cref_head = NULL;
1007 rb_cref_t *new_cref_tail = NULL;
1009 #define ADD_NEW_CREF(new_cref) \
1010 if (new_cref_tail) { \
1011 RB_OBJ_WRITE(new_cref_tail, &new_cref_tail->next, new_cref); \
1014 new_cref_head = new_cref; \
1016 new_cref_tail = new_cref;
1019 rb_cref_t *new_cref;
1020 if (CREF_CLASS(cref) == old_klass) {
1021 new_cref = vm_cref_new_use_prev(new_klass, METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1022 ADD_NEW_CREF(new_cref);
1023 return new_cref_head;
1025 new_cref = vm_cref_new_use_prev(CREF_CLASS(cref), METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1026 cref = CREF_NEXT(cref);
1027 ADD_NEW_CREF(new_cref);
1033 return new_cref_head;
1037vm_cref_push(
const rb_execution_context_t *ec,
VALUE klass,
const VALUE *ep,
int pushed_by_eval,
int singleton)
1039 rb_cref_t *prev_cref = NULL;
1042 prev_cref = vm_env_cref(ep);
1045 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, ec->cfp);
1048 prev_cref = vm_env_cref(cfp->ep);
1052 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1056vm_get_cbase(
const VALUE *ep)
1058 const rb_cref_t *cref = vm_get_cref(ep);
1060 return CREF_CLASS_FOR_DEFINITION(cref);
1064vm_get_const_base(
const VALUE *ep)
1066 const rb_cref_t *cref = vm_get_cref(ep);
1069 if (!CREF_PUSHED_BY_EVAL(cref)) {
1070 return CREF_CLASS_FOR_DEFINITION(cref);
1072 cref = CREF_NEXT(cref);
1079vm_check_if_namespace(
VALUE klass)
1082 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1087vm_ensure_not_refinement_module(
VALUE self)
1089 if (RB_TYPE_P(self,
T_MODULE) &&
FL_TEST(self, RMODULE_IS_REFINEMENT)) {
1090 rb_warn(
"not defined at the refinement, but at the outer class/module");
1095vm_get_iclass(
const rb_control_frame_t *cfp,
VALUE klass)
1101vm_get_ev_const(rb_execution_context_t *ec,
VALUE orig_klass,
ID id,
bool allow_nil,
int is_defined)
1103 void rb_const_warn_if_deprecated(
const rb_const_entry_t *ce,
VALUE klass,
ID id);
1106 if (
NIL_P(orig_klass) && allow_nil) {
1108 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1109 const rb_cref_t *cref;
1112 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1113 root_cref = CREF_NEXT(root_cref);
1116 while (cref && CREF_NEXT(cref)) {
1117 if (CREF_PUSHED_BY_EVAL(cref)) {
1121 klass = CREF_CLASS(cref);
1123 cref = CREF_NEXT(cref);
1125 if (!
NIL_P(klass)) {
1127 rb_const_entry_t *ce;
1129 if ((ce = rb_const_lookup(klass,
id))) {
1130 rb_const_warn_if_deprecated(ce, klass,
id);
1133 if (am == klass)
break;
1135 if (is_defined)
return 1;
1136 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1138 goto search_continue;
1145 if (UNLIKELY(!rb_ractor_main_p())) {
1146 if (!rb_ractor_shareable_p(val)) {
1147 rb_raise(rb_eRactorIsolationError,
1148 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" by non-main ractor.",
rb_class_path(klass), rb_id2str(
id));
1159 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1160 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1174 vm_check_if_namespace(orig_klass);
1176 return rb_public_const_defined_from(orig_klass,
id);
1179 return rb_public_const_get_from(orig_klass,
id);
1185rb_vm_get_ev_const(rb_execution_context_t *ec,
VALUE orig_klass,
ID id,
VALUE allow_nil)
1187 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1191vm_get_ev_const_chain(rb_execution_context_t *ec,
const ID *segments)
1195 int allow_nil = TRUE;
1196 if (segments[0] == idNULL) {
1201 while (segments[idx]) {
1202 ID id = segments[idx++];
1203 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1211vm_get_cvar_base(
const rb_cref_t *cref,
const rb_control_frame_t *cfp,
int top_level_raise)
1216 rb_bug(
"vm_get_cvar_base: no cref");
1219 while (CREF_NEXT(cref) &&
1220 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1221 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1222 cref = CREF_NEXT(cref);
1224 if (top_level_raise && !CREF_NEXT(cref)) {
1228 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1236ALWAYS_INLINE(
static void fill_ivar_cache(
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id));
1238fill_ivar_cache(
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id)
1241 vm_cc_attr_index_set(cc, index, shape_id);
1244 vm_ic_attr_index_set(iseq, ic, index, shape_id);
1248#define ractor_incidental_shareable_p(cond, val) \
1249 (!(cond) || rb_ractor_shareable_p(val))
1250#define ractor_object_incidental_shareable_p(obj, val) \
1251 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1255vm_getivar(
VALUE obj,
ID id,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr,
VALUE default_value)
1260 return default_value;
1270 if (UNLIKELY(!rb_ractor_main_p())) {
1278 if (default_value ==
Qundef) {
1286 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1290 fields_obj = rb_obj_fields(obj,
id);
1294 return default_value;
1299 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1300 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1302 shape_id_t cached_id;
1306 vm_cc_atomic_shape_and_index(cc, &cached_id, &index);
1309 vm_ic_atomic_shape_and_index(ic, &cached_id, &index);
1312 if (LIKELY(cached_id == shape_id)) {
1315 if (index == ATTR_INDEX_NOT_SET) {
1316 return default_value;
1319 val = ivar_list[index];
1320#if USE_DEBUG_COUNTER
1321 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1324 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1330#if USE_DEBUG_COUNTER
1332 if (cached_id != INVALID_SHAPE_ID) {
1333 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1336 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1340 if (cached_id != INVALID_SHAPE_ID) {
1341 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1344 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1347 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1350 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1354 if (UNLIKELY(rb_shape_too_complex_p(shape_id))) {
1355 st_table *table = (st_table *)ivar_list;
1358 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1360 if (!st_lookup(table,
id, &val)) {
1361 val = default_value;
1365 shape_id_t previous_cached_id = cached_id;
1366 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &index, &cached_id)) {
1369 if (cached_id != previous_cached_id) {
1370 fill_ivar_cache(iseq, ic, cc, is_attr, index, cached_id);
1373 if (index == ATTR_INDEX_NOT_SET) {
1374 val = default_value;
1378 val = ivar_list[index];
1384 vm_cc_attr_index_initialize(cc, shape_id);
1387 vm_ic_attr_index_initialize(ic, shape_id);
1390 val = default_value;
1395 if (!UNDEF_P(default_value)) {
1403 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1406 return rb_attr_get(obj,
id);
1414populate_cache(attr_index_t index, shape_id_t next_shape_id,
ID id,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
bool is_attr)
1416 RUBY_ASSERT(!rb_shape_too_complex_p(next_shape_id));
1420 vm_cc_attr_index_set(cc, index, next_shape_id);
1423 vm_ic_attr_index_set(iseq, ic, index, next_shape_id);
1427ALWAYS_INLINE(
static VALUE vm_setivar_slowpath(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr));
1428NOINLINE(
static VALUE vm_setivar_slowpath_ivar(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic));
1432vm_setivar_slowpath(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr)
1435 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1437 rb_check_frozen(obj);
1439 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1440 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1442 if (!rb_shape_too_complex_p(next_shape_id)) {
1443 populate_cache(index, next_shape_id,
id, iseq, ic, cc, is_attr);
1446 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1454vm_setivar_slowpath_ivar(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic)
1456 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1462 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1465NOINLINE(
static VALUE vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1467vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1469 if (UNLIKELY(!rb_ractor_main_p())) {
1473 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1474 if (UNLIKELY(!fields_obj)) {
1478 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1481 if (shape_id == dest_shape_id) {
1482 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1484 else if (dest_shape_id != INVALID_SHAPE_ID) {
1485 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1486 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1496 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1498 if (shape_id != dest_shape_id) {
1499 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1500 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1503 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1508NOINLINE(
static VALUE vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1510vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1512 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1515 if (shape_id == dest_shape_id) {
1516 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1518 else if (dest_shape_id != INVALID_SHAPE_ID) {
1519 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1520 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1530 VALUE fields_obj = rb_obj_fields(obj,
id);
1532 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1534 if (shape_id != dest_shape_id) {
1535 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1536 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1539 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1545vm_setivar(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1553 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1554 RUBY_ASSERT(dest_shape_id == INVALID_SHAPE_ID || !rb_shape_too_complex_p(dest_shape_id));
1556 if (LIKELY(shape_id == dest_shape_id)) {
1557 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1558 VM_ASSERT(!rb_ractor_shareable_p(obj));
1560 else if (dest_shape_id != INVALID_SHAPE_ID) {
1561 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1562 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1564 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1566 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1581 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1582 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1588 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1598update_classvariable_cache(
const rb_iseq_t *iseq,
VALUE klass,
ID id,
const rb_cref_t * cref, ICVARC ic)
1600 VALUE defined_class = 0;
1603 if (RB_TYPE_P(defined_class,
T_ICLASS)) {
1604 defined_class =
RBASIC(defined_class)->klass;
1607 VALUE rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
1609 rb_bug(
"the cvc table should be set");
1613 if (!rb_marked_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
1614 rb_bug(
"should have cvar cache entry");
1619 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
1629vm_getclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *reg_cfp,
ID id, ICVARC ic)
1631 const rb_cref_t *cref;
1632 cref = vm_get_cref(GET_EP());
1634 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1635 RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
1637 VALUE v = rb_ivar_lookup(ic->entry->class_value,
id,
Qundef);
1643 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1645 return update_classvariable_cache(iseq, klass,
id, cref, ic);
1649rb_vm_getclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *cfp,
ID id, ICVARC ic)
1651 return vm_getclassvariable(iseq, cfp,
id, ic);
1655vm_setclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *reg_cfp,
ID id,
VALUE val, ICVARC ic)
1657 const rb_cref_t *cref;
1658 cref = vm_get_cref(GET_EP());
1660 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1661 RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
1663 rb_class_ivar_set(ic->entry->class_value,
id, val);
1667 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1671 update_classvariable_cache(iseq, klass,
id, cref, ic);
1675rb_vm_setclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *cfp,
ID id,
VALUE val, ICVARC ic)
1677 vm_setclassvariable(iseq, cfp,
id, val, ic);
1680ALWAYS_INLINE(
static VALUE vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic));
1682vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic)
1684 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1688vm_setinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id,
VALUE val, IVC ic)
1690 if (RB_SPECIAL_CONST_P(obj)) {
1695 shape_id_t dest_shape_id;
1697 vm_ic_atomic_shape_and_index(ic, &dest_shape_id, &index);
1699 if (UNLIKELY(UNDEF_P(vm_setivar(obj,
id, val, dest_shape_id, index)))) {
1705 if (!UNDEF_P(vm_setivar_class(obj,
id, val, dest_shape_id, index))) {
1710 if (!UNDEF_P(vm_setivar_default(obj,
id, val, dest_shape_id, index))) {
1714 vm_setivar_slowpath_ivar(obj,
id, val, iseq, ic);
1719rb_vm_setinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id,
VALUE val, IVC ic)
1721 vm_setinstancevariable(iseq, obj,
id, val, ic);
1725rb_vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic)
1727 return vm_getinstancevariable(iseq, obj,
id, ic);
1731vm_throw_continue(
const rb_execution_context_t *ec,
VALUE err)
1736 ec->tag->state = RUBY_TAG_FATAL;
1739 ec->tag->state = TAG_THROW;
1741 else if (THROW_DATA_P(err)) {
1742 ec->tag->state = THROW_DATA_STATE((
struct vm_throw_data *)err);
1745 ec->tag->state = TAG_RAISE;
1751vm_throw_start(
const rb_execution_context_t *ec, rb_control_frame_t *
const reg_cfp,
enum ruby_tag_type state,
1752 const int flag,
const VALUE throwobj)
1754 const rb_control_frame_t *escape_cfp = NULL;
1755 const rb_control_frame_t *
const eocfp = RUBY_VM_END_CONTROL_FRAME(ec);
1760 else if (state == TAG_BREAK) {
1762 const VALUE *ep = GET_EP();
1763 const rb_iseq_t *base_iseq = GET_ISEQ();
1764 escape_cfp = reg_cfp;
1766 while (ISEQ_BODY(base_iseq)->
type != ISEQ_TYPE_BLOCK) {
1767 if (ISEQ_BODY(escape_cfp->iseq)->type == ISEQ_TYPE_CLASS) {
1768 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1769 ep = escape_cfp->ep;
1770 base_iseq = escape_cfp->iseq;
1773 ep = VM_ENV_PREV_EP(ep);
1774 base_iseq = ISEQ_BODY(base_iseq)->parent_iseq;
1775 escape_cfp = rb_vm_search_cf_from_ep(ec, escape_cfp, ep);
1776 VM_ASSERT(escape_cfp->iseq == base_iseq);
1780 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1786 ep = VM_ENV_PREV_EP(ep);
1788 while (escape_cfp < eocfp) {
1789 if (escape_cfp->ep == ep) {
1790 const rb_iseq_t *
const iseq = escape_cfp->iseq;
1791 const VALUE epc = escape_cfp->pc - ISEQ_BODY(iseq)->iseq_encoded;
1796 for (i=0; i < ct->size; i++) {
1798 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1800 if (entry->type == CATCH_TYPE_BREAK &&
1801 entry->iseq == base_iseq &&
1802 entry->start < epc && entry->end >= epc) {
1803 if (entry->cont == epc) {
1812 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1817 rb_vm_localjump_error(
"break from proc-closure", throwobj, TAG_BREAK);
1820 else if (state == TAG_RETRY) {
1821 const VALUE *ep = VM_ENV_PREV_EP(GET_EP());
1823 escape_cfp = rb_vm_search_cf_from_ep(ec, reg_cfp, ep);
1825 else if (state == TAG_RETURN) {
1826 const VALUE *current_ep = GET_EP();
1827 const VALUE *target_ep = NULL, *target_lep, *ep = current_ep;
1828 int in_class_frame = 0;
1830 escape_cfp = reg_cfp;
1833 while (!VM_ENV_LOCAL_P(ep)) {
1834 if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) {
1837 ep = VM_ENV_PREV_EP(ep);
1841 while (escape_cfp < eocfp) {
1842 const VALUE *lep = VM_CF_LEP(escape_cfp);
1848 if (lep == target_lep &&
1849 VM_FRAME_RUBYFRAME_P(escape_cfp) &&
1850 ISEQ_BODY(escape_cfp->iseq)->type == ISEQ_TYPE_CLASS) {
1855 if (lep == target_lep) {
1856 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1858 if (in_class_frame) {
1863 const VALUE *tep = current_ep;
1865 while (target_lep != tep) {
1866 if (escape_cfp->ep == tep) {
1868 if (tep == target_ep) {
1872 goto unexpected_return;
1875 tep = VM_ENV_PREV_EP(tep);
1879 else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
1880 switch (ISEQ_BODY(escape_cfp->iseq)->type) {
1882 case ISEQ_TYPE_MAIN:
1884 if (in_class_frame)
goto unexpected_return;
1885 if (target_ep == NULL) {
1889 goto unexpected_return;
1893 case ISEQ_TYPE_EVAL: {
1894 const rb_iseq_t *is = escape_cfp->iseq;
1895 enum rb_iseq_type t = ISEQ_BODY(is)->type;
1896 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE || t == ISEQ_TYPE_EVAL) {
1897 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
1898 t = ISEQ_BODY(is)->type;
1900 toplevel = t == ISEQ_TYPE_TOP || t == ISEQ_TYPE_MAIN;
1903 case ISEQ_TYPE_CLASS:
1912 if (escape_cfp->ep == target_lep && ISEQ_BODY(escape_cfp->iseq)->type == ISEQ_TYPE_METHOD) {
1913 if (target_ep == NULL) {
1917 goto unexpected_return;
1921 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1924 rb_vm_localjump_error(
"unexpected return", throwobj, TAG_RETURN);
1930 rb_bug(
"isns(throw): unsupported throw type");
1933 ec->tag->state = state;
1934 return (
VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state);
1938vm_throw(
const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
1939 rb_num_t throw_state,
VALUE throwobj)
1941 const int state = (int)(throw_state & VM_THROW_STATE_MASK);
1942 const int flag = (int)(throw_state & VM_THROW_NO_ESCAPE_FLAG);
1945 return vm_throw_start(ec, reg_cfp, state, flag, throwobj);
1948 return vm_throw_continue(ec, throwobj);
1953rb_vm_throw(
const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t throw_state,
VALUE throwobj)
1955 return vm_throw(ec, reg_cfp, throw_state, throwobj);
1961 int is_splat = flag & 0x01;
1964 const VALUE obj = ary;
1976 if (num + is_splat == 0) {
1979 else if (flag & 0x02) {
1984 for (i = 0; i < num -
len; i++) {
1989 for (j = 0; i < num; i++, j++) {
2011 for (; i < num -
len; i++) {
2015 for (rb_num_t j = 0; i < num; i++, j++) {
2016 *cfp->sp++ =
ptr[
len - j - 1];
2020 for (rb_num_t j = 0; j < num; j++) {
2021 *cfp->sp++ =
ptr[num - j - 1];
2029static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
2034vm_ccs_create(
VALUE klass,
VALUE cc_tbl,
ID mid,
const rb_callable_method_entry_t *cme)
2036 int initial_capa = 2;
2038#if VM_CHECK_MODE > 0
2039 ccs->debug_sig = ~(
VALUE)ccs;
2041 ccs->capa = initial_capa;
2044 METHOD_ENTRY_CACHED_SET((rb_callable_method_entry_t *)cme);
2046 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2054 if (! vm_cc_markable(cc)) {
2058 if (UNLIKELY(ccs->len == ccs->capa)) {
2061 ccs = ruby_xrealloc(ccs, vm_ccs_alloc_size(ccs->capa));
2062#if VM_CHECK_MODE > 0
2063 ccs->debug_sig = ~(
VALUE)ccs;
2066 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2068 VM_ASSERT(ccs->len < ccs->capa);
2071 const int pos = ccs->len++;
2072 ccs->entries[pos].argc = vm_ci_argc(ci);
2073 ccs->entries[pos].flag = (
unsigned short)vm_ci_flag(ci);
2074 ccs->entries[pos].kw_len = (
unsigned short)(kwarg ? kwarg->keyword_len : 0);
2077 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
2083#if VM_CHECK_MODE > 0
2087 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
2088 for (
int i=0; i<ccs->len; i++) {
2089 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u kw_len:%u\n",
2090 ccs->entries[i].flag,
2091 ccs->entries[i].argc,
2092 ccs->entries[i].kw_len);
2093 rp(ccs->entries[i].cc);
2100 VM_ASSERT(vm_ccs_p(ccs));
2101 VM_ASSERT(ccs->len <= ccs->capa);
2103 for (
int i=0; i<ccs->len; i++) {
2106 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2107 VM_ASSERT(vm_cc_class_check(cc, klass));
2108 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
2109 VM_ASSERT(!vm_cc_super_p(cc));
2110 VM_ASSERT(!vm_cc_refinement_p(cc));
2116const rb_callable_method_entry_t *rb_check_overloaded_cme(
const rb_callable_method_entry_t *cme,
const struct rb_callinfo *
const ci);
2121 ASSERT_vm_locking();
2123 if (rb_multi_ractor_p()) {
2124 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2131 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2134 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2139 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2140 rb_vm_cc_table_delete(new_table, mid);
2141 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2144 rb_vm_cc_table_delete(cc_tbl, mid);
2151 ASSERT_vm_locking();
2153 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2155 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
2157 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2161 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2162 return &vm_empty_cc;
2165 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2166 const VALUE original_cc_table = cc_tbl;
2169 cc_tbl = rb_vm_cc_table_create(1);
2171 else if (rb_multi_ractor_p()) {
2172 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2175 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2184 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2189 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2193 cme = rb_check_overloaded_cme(cme, ci);
2195 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2196 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2198 VM_ASSERT(vm_cc_cme(cc) != NULL);
2199 VM_ASSERT(cme->called_id == mid);
2200 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2202 if (original_cc_table != cc_tbl) {
2203 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2215 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2223 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2225 const int ccs_len = ccs->len;
2227 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2229 vm_evict_cc(klass, cc_tbl, mid);
2234 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2243 unsigned int argc = vm_ci_argc(ci);
2244 unsigned int flag = vm_ci_flag(ci);
2245 unsigned int kw_len = kwarg ? kwarg->keyword_len : 0;
2247 for (
int i=0; i<ccs_len; i++) {
2248 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2249 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2250 unsigned int ccs_ci_kw_len = ccs->entries[i].kw_len;
2251 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2253 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2255 if (ccs_ci_argc == argc && ccs_ci_flag == flag && ccs_ci_kw_len == kw_len) {
2256 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2258 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2259 VM_ASSERT(ccs_cc->klass == klass);
2260 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2276 const ID mid = vm_ci_mid(ci);
2278 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2284 if (rb_multi_ractor_p()) {
2287 cc = vm_lookup_cc(klass, ci, mid);
2291 cc = vm_populate_cc(klass, ci, mid);
2305 cc = vm_search_cc(klass, ci);
2308 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2309 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2310 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2311 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2312 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2320#if USE_DEBUG_COUNTER
2324 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2326#if OPT_INLINE_METHOD_CACHE
2330 if (cd_owner && cc != empty_cc) {
2334#if USE_DEBUG_COUNTER
2335 if (!old_cc || old_cc == empty_cc) {
2337 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2339 else if (old_cc == cc) {
2340 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2342 else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) {
2343 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2345 else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) &&
2346 vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) {
2347 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2350 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2355 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2356 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2369#if OPT_INLINE_METHOD_CACHE
2370 if (LIKELY(vm_cc_class_check(cc, klass))) {
2371 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2372 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2373 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2374 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2375 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2376 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2380 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2383 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2387 return vm_search_method_slowpath0(cd_owner, cd, klass);
2394 VM_ASSERT(klass !=
Qfalse);
2397 const struct rb_callcache *cc = vm_search_method_fastpath(cd_owner, cd, klass);
2398 return vm_cc_cme(cc);
2404 return vm_search_method(cd_owner, cd, recv);
2407#if __has_attribute(transparent_union)
2420 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2421 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2422 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2423 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2424 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2425 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2428# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2431# define make_cfunc_type(f) (cfunc_type)(f)
2435check_cfunc(
const rb_callable_method_entry_t *me, cfunc_type func)
2441 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2442 VM_ASSERT(callable_method_entry_p(me));
2444 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2448#if __has_attribute(transparent_union)
2449 return me->def->body.cfunc.func == func.anyargs;
2451 return me->def->body.cfunc.func == func;
2458check_method_basic_definition(
const rb_callable_method_entry_t *me)
2460 return me && METHOD_ENTRY_BASIC(me);
2464vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2466 VM_ASSERT(iseq != NULL);
2468 return check_cfunc(cme, func);
2472rb_zjit_cme_is_cfunc(
const rb_callable_method_entry_t *me,
const cfunc_type func)
2474 return check_cfunc(me, func);
2478rb_vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2480 return vm_method_cfunc_is(iseq, cd, recv, func);
2483#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2484#define vm_method_cfunc_is(iseq, cd, recv, func) vm_method_cfunc_is(iseq, cd, recv, make_cfunc_type(func))
2486#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
2518opt_equality_specialized(
VALUE recv,
VALUE obj)
2520 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2521 goto compare_by_identity;
2523 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2524 goto compare_by_identity;
2527 goto compare_by_identity;
2532 else if (RBASIC_CLASS(recv) ==
rb_cFloat && RB_FLOAT_TYPE_P(obj) && EQ_UNREDEFINED_P(FLOAT)) {
2536 return RBOOL(a == b);
2538 else if (RBASIC_CLASS(recv) ==
rb_cString && EQ_UNREDEFINED_P(STRING)) {
2542 else if (RB_TYPE_P(obj,
T_STRING)) {
2543 return rb_str_eql_internal(obj, recv);
2548 compare_by_identity:
2549 return RBOOL(recv == obj);
2553opt_equality(
const rb_iseq_t *cd_owner,
VALUE recv,
VALUE obj, CALL_DATA cd)
2555 VM_ASSERT(cd_owner != NULL);
2557 VALUE val = opt_equality_specialized(recv, obj);
2558 if (!UNDEF_P(val))
return val;
2560 if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) {
2564 return RBOOL(recv == obj);
2568#undef EQ_UNREDEFINED_P
2571NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2574opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2576 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2578 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2579 return RBOOL(recv == obj);
2589 VALUE val = opt_equality_specialized(recv, obj);
2590 if (!UNDEF_P(val)) {
2594 return opt_equality_by_mid_slowpath(recv, obj, mid);
2601 return opt_equality_by_mid(obj1, obj2, idEq);
2607 return opt_equality_by_mid(obj1, obj2, idEqlP);
2610extern VALUE rb_vm_call0(rb_execution_context_t *ec,
VALUE,
ID,
int,
const VALUE*,
const rb_callable_method_entry_t *,
int kw_splat);
2611extern VALUE rb_vm_call_with_refinements(rb_execution_context_t *,
VALUE,
ID,
int,
const VALUE *,
int);
2614check_match(rb_execution_context_t *ec,
VALUE pattern,
VALUE target,
enum vm_check_match_type
type)
2617 case VM_CHECKMATCH_TYPE_WHEN:
2619 case VM_CHECKMATCH_TYPE_RESCUE:
2621 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2624 case VM_CHECKMATCH_TYPE_CASE: {
2625 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2628 rb_bug(
"check_match: unreachable");
2634double_cmp_lt(
double a,
double b)
2636 return RBOOL(a < b);
2640double_cmp_le(
double a,
double b)
2642 return RBOOL(a <= b);
2646double_cmp_gt(
double a,
double b)
2648 return RBOOL(a > b);
2652double_cmp_ge(
double a,
double b)
2654 return RBOOL(a >= b);
2658static inline VALUE *
2659vm_base_ptr(
const rb_control_frame_t *cfp)
2661 const rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2663 if (cfp->iseq && VM_FRAME_RUBYFRAME_P(cfp)) {
2664 VALUE *bp = prev_cfp->sp + ISEQ_BODY(cfp->iseq)->local_table_size + VM_ENV_DATA_SIZE;
2666 if (ISEQ_BODY(cfp->iseq)->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2667 int lts = ISEQ_BODY(cfp->iseq)->local_table_size;
2668 int params = ISEQ_BODY(cfp->iseq)->param.size;
2670 CALL_INFO ci = (CALL_INFO)cfp->ep[-(VM_ENV_DATA_SIZE + (lts - params))];
2671 bp += vm_ci_argc(ci);
2674 if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2678#if VM_DEBUG_BP_CHECK
2679 if (bp != cfp->bp_check) {
2680 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2681 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2682 (
long)(bp - GET_EC()->vm_stack));
2683 rb_bug(
"vm_base_ptr: unreachable");
2694rb_vm_base_ptr(
const rb_control_frame_t *cfp)
2696 return vm_base_ptr(cfp);
2703static inline VALUE vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc,
int param_size,
int local_size);
2704ALWAYS_INLINE(
static VALUE vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
const rb_callable_method_entry_t *me,
int opt_pc,
int param_size,
int local_size));
2705static inline VALUE vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc);
2706static VALUE vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
2707static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2708static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2709static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2711static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2714vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2716 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2718 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2722vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2724 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2727 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2728 int param = ISEQ_BODY(iseq)->param.size;
2729 int local = ISEQ_BODY(iseq)->local_table_size;
2730 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2734rb_simple_iseq_p(
const rb_iseq_t *iseq)
2736 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2737 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2738 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2739 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2740 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2741 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2742 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2743 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2747rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2749 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2750 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2751 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2752 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2753 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2754 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2755 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2756 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2760rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2762 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2763 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2764 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2765 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2766 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2767 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2768 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2771#define ALLOW_HEAP_ARGV (-2)
2772#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2775vm_caller_setup_arg_splat(rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE ary,
int max_args)
2777 vm_check_canary(GET_EC(), cfp->sp);
2783 int argc = calling->argc;
2785 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2789 VALUE *argv = cfp->sp - argc;
2793 cfp->sp -= argc - 1;
2794 cfp->sp[-1] = argv_ary;
2796 calling->heap_argv = argv_ary;
2802 if (max_args >= 0 &&
len + argc > max_args) {
2810 calling->argc +=
len - (max_args - argc + 1);
2811 len = max_args - argc + 1;
2820 calling->heap_argv = 0;
2822 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2824 for (i = 0; i <
len; i++) {
2825 *cfp->sp++ =
ptr[i];
2837 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2838 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2839 const VALUE h = rb_hash_new_with_size(kw_len);
2840 VALUE *sp = cfp->sp;
2843 for (i=0; i<kw_len; i++) {
2844 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2848 cfp->sp -= kw_len - 1;
2849 calling->argc -= kw_len - 1;
2850 calling->kw_splat = 1;
2854vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2856 if (UNLIKELY(!RB_TYPE_P(keyword_hash,
T_HASH))) {
2857 if (keyword_hash !=
Qnil) {
2859 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2862 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2868 keyword_hash = rb_hash_dup(keyword_hash);
2870 return keyword_hash;
2876 const struct rb_callinfo *restrict ci,
int max_args)
2878 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2879 if (IS_ARGS_KW_SPLAT(ci)) {
2881 VM_ASSERT(calling->kw_splat == 1);
2885 VALUE ary = cfp->sp[0];
2886 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2889 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2893 if (UNLIKELY(calling->heap_argv)) {
2895 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2896 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2897 calling->kw_splat = 0;
2905 VM_ASSERT(calling->kw_splat == 1);
2909 calling->kw_splat = 0;
2914 VM_ASSERT(calling->kw_splat == 0);
2918 VALUE ary = cfp->sp[0];
2920 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2925 VALUE last_hash, argv_ary;
2926 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2927 if (!IS_ARGS_KEYWORD(ci) &&
2929 RB_TYPE_P((last_hash = rb_ary_last(0, NULL, argv_ary)),
T_HASH) &&
2930 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2935 calling->kw_splat = 1;
2941 if (!IS_ARGS_KEYWORD(ci) &&
2942 calling->argc > 0 &&
2943 RB_TYPE_P((last_hash = cfp->sp[-1]),
T_HASH) &&
2944 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2951 cfp->sp[-1] = rb_hash_dup(last_hash);
2952 calling->kw_splat = 1;
2958 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2960 VM_ASSERT(calling->kw_splat == 1);
2961 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2966 calling->kw_splat = 0;
2972 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2974 VM_ASSERT(calling->kw_splat == 0);
2980 vm_caller_setup_arg_kw(cfp, calling, ci);
2984#define USE_OPT_HIST 0
2987#define OPT_HIST_MAX 64
2988static int opt_hist[OPT_HIST_MAX+1];
2992opt_hist_show_results_at_exit(
void)
2994 for (
int i=0; i<OPT_HIST_MAX; i++) {
2995 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
3001vm_call_iseq_setup_normal_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3005 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3006 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3007 const int opt = calling->argc - lead_num;
3008 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3009 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3010 const int param = ISEQ_BODY(iseq)->param.size;
3011 const int local = ISEQ_BODY(iseq)->local_table_size;
3012 const int delta = opt_num - opt;
3014 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3017 if (opt_pc < OPT_HIST_MAX) {
3021 opt_hist[OPT_HIST_MAX]++;
3025 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3029vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3033 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3034 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3035 const int opt = calling->argc - lead_num;
3036 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3038 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3041 if (opt_pc < OPT_HIST_MAX) {
3045 opt_hist[OPT_HIST_MAX]++;
3049 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3053args_setup_kw_parameters(rb_execution_context_t *
const ec,
const rb_iseq_t *
const iseq,
const rb_callable_method_entry_t *cme,
3054 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3055 VALUE *
const locals);
3058vm_call_iseq_forwardable(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3062 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3063 int param_size = ISEQ_BODY(iseq)->param.size;
3064 int local_size = ISEQ_BODY(iseq)->local_table_size;
3067 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3069 local_size = local_size + vm_ci_argc(calling->cd->ci);
3070 param_size = param_size + vm_ci_argc(calling->cd->ci);
3072 cfp->sp[0] = (
VALUE)calling->cd->ci;
3074 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3078vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3084 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3085 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3087 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3088 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3090 const int ci_kw_len = kw_arg->keyword_len;
3091 const VALUE *
const ci_keywords = kw_arg->keywords;
3092 VALUE *argv = cfp->sp - calling->argc;
3093 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3094 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3096 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3097 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3099 int param = ISEQ_BODY(iseq)->param.size;
3100 int local = ISEQ_BODY(iseq)->local_table_size;
3101 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3105vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3108 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3111 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3112 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3114 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3115 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3116 VALUE *
const argv = cfp->sp - calling->argc;
3117 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3120 for (i=0; i<kw_param->num; i++) {
3121 klocals[i] = kw_param->default_values[i];
3128 int param = ISEQ_BODY(iseq)->param.size;
3129 int local = ISEQ_BODY(iseq)->local_table_size;
3130 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3133static VALUE builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
3136vm_call_single_noarg_leaf_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3140 cfp->sp -= (calling->argc + 1);
3141 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3142 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3148warn_unused_block(
const rb_callable_method_entry_t *cme,
const rb_iseq_t *iseq,
void *pc)
3150 rb_vm_t *vm = GET_VM();
3151 set_table *dup_check_table = vm->unused_block_warning_table;
3161 .v = (
VALUE)cme->def,
3165 if (!strict_unused_block) {
3166 key = (st_data_t)cme->def->original_id;
3168 if (set_table_lookup(dup_check_table, key)) {
3178 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3183 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3184 fprintf(stderr,
"key:%p\n", (
void *)key);
3188 if (set_insert(dup_check_table, key)) {
3192 VALUE m_loc = rb_method_entry_location((
const rb_method_entry_t *)cme);
3193 VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label);
3195 if (!
NIL_P(m_loc)) {
3196 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3200 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3206vm_callee_setup_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
3207 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3212 VM_ASSERT((vm_ci_argc(ci), 1));
3213 VM_ASSERT(vm_cc_cme(cc) != NULL);
3215 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3216 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3217 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3218 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)ec->cfp->pc);
3221 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3222 if (LIKELY(rb_simple_iseq_p(iseq))) {
3223 rb_control_frame_t *cfp = ec->cfp;
3224 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3225 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3227 if (calling->argc != lead_num) {
3228 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3232 VM_ASSERT(cc == calling->cc);
3234 if (vm_call_iseq_optimizable_p(ci, cc)) {
3235 if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3236 VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF);
3237 vm_cc_bf_set(cc, (
void *)iseq->body->iseq_encoded[1]);
3238 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3241 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3246 else if (rb_iseq_only_optparam_p(iseq)) {
3247 rb_control_frame_t *cfp = ec->cfp;
3249 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3250 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3252 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3253 const int argc = calling->argc;
3254 const int opt = argc - lead_num;
3256 if (opt < 0 || opt > opt_num) {
3257 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3260 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3261 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3262 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3263 vm_call_cacheable(ci, cc));
3266 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3267 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3268 vm_call_cacheable(ci, cc));
3272 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3273 for (
int i=argc; i<lead_num + opt_num; i++) {
3276 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3278 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3279 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3280 const int argc = calling->argc;
3281 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3283 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3286 if (argc - kw_arg->keyword_len == lead_num) {
3287 const int ci_kw_len = kw_arg->keyword_len;
3288 const VALUE *
const ci_keywords = kw_arg->keywords;
3290 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3292 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3293 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3295 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3296 vm_call_cacheable(ci, cc));
3301 else if (argc == lead_num) {
3303 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3304 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3306 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3308 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3309 vm_call_cacheable(ci, cc));
3335 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3336 bool can_fastpath =
true;
3338 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3340 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3341 ci = vm_ci_new_runtime(
3348 ci = forward_cd->caller_ci;
3350 can_fastpath =
false;
3354 if (!vm_ci_markable(ci)) {
3355 ci = vm_ci_new_runtime(
3360 can_fastpath =
false;
3362 argv[param_size - 1] = (
VALUE)ci;
3363 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3367 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3394 const VALUE * lep = VM_CF_LEP(cfp);
3396 const rb_iseq_t *iseq;
3400 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3405 iseq = rb_vm_search_cf_from_ep(ec, cfp, lep)->iseq;
3409 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3411 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3412 VALUE * to = cfp->sp - 1;
3416 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3421 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3423 cfp->sp = to + argc;
3440vm_call_iseq_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3442 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3445 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3446 int param_size = ISEQ_BODY(iseq)->param.size;
3447 int local_size = ISEQ_BODY(iseq)->local_table_size;
3449 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3451 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3452 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3456vm_call_iseq_fwd_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3458 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3461 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3462 int param_size = ISEQ_BODY(iseq)->param.size;
3463 int local_size = ISEQ_BODY(iseq)->local_table_size;
3465 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3468 local_size = local_size + vm_ci_argc(calling->cd->ci);
3469 param_size = param_size + vm_ci_argc(calling->cd->ci);
3471 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3472 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3476vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
3477 int opt_pc,
int param_size,
int local_size)
3482 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3483 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3486 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3491vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
const rb_callable_method_entry_t *me,
3492 int opt_pc,
int param_size,
int local_size)
3494 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3495 VALUE *argv = cfp->sp - calling->argc;
3496 VALUE *sp = argv + param_size;
3497 cfp->sp = argv - 1 ;
3499 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3500 calling->block_handler, (
VALUE)me,
3501 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3502 local_size - param_size,
3503 ISEQ_BODY(iseq)->stack_max);
3508vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc)
3512 VALUE *argv = cfp->sp - calling->argc;
3513 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3514 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3515 VALUE *src_argv = argv;
3516 VALUE *sp_orig, *sp;
3517 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3519 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3520 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3521 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3522 dst_captured->code.val = src_captured->code.val;
3523 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3524 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3527 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3531 vm_pop_frame(ec, cfp, cfp->ep);
3534 sp_orig = sp = cfp->sp;
3537 sp[0] = calling->recv;
3541 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3542 *sp++ = src_argv[i];
3545 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3546 calling->recv, calling->block_handler, (
VALUE)me,
3547 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3548 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3549 ISEQ_BODY(iseq)->stack_max);
3557ractor_unsafe_check(
void)
3559 if (!rb_ractor_main_p()) {
3560 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3567 ractor_unsafe_check();
3575 ractor_unsafe_check();
3577 return (*f)(argc, argv, recv);
3583 ractor_unsafe_check();
3591 ractor_unsafe_check();
3593 return (*f)(recv, argv[0]);
3599 ractor_unsafe_check();
3601 return (*f)(recv, argv[0], argv[1]);
3607 ractor_unsafe_check();
3609 return (*f)(recv, argv[0], argv[1], argv[2]);
3615 ractor_unsafe_check();
3617 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3623 ractor_unsafe_check();
3624 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3625 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3631 ractor_unsafe_check();
3632 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3633 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3639 ractor_unsafe_check();
3640 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3641 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3647 ractor_unsafe_check();
3648 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3649 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3655 ractor_unsafe_check();
3656 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3657 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3663 ractor_unsafe_check();
3664 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3665 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3671 ractor_unsafe_check();
3672 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3673 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
3679 ractor_unsafe_check();
3680 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3681 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
3687 ractor_unsafe_check();
3688 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3689 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
3695 ractor_unsafe_check();
3696 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3697 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
3703 ractor_unsafe_check();
3704 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3705 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
3719 return (*f)(argc, argv, recv);
3733 return (*f)(recv, argv[0]);
3740 return (*f)(recv, argv[0], argv[1]);
3747 return (*f)(recv, argv[0], argv[1], argv[2]);
3754 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3760 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3761 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3767 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3768 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3774 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3775 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3781 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3782 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3788 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3789 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3795 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3796 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3802 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3803 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
3809 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3810 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
3816 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3817 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
3823 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3824 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
3830 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3831 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
3835vm_cfp_consistent_p(rb_execution_context_t *ec,
const rb_control_frame_t *reg_cfp)
3837 const int ov_flags = RAISED_STACKOVERFLOW;
3838 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3839 if (rb_ec_raised_p(ec, ov_flags)) {
3840 rb_ec_raised_reset(ec, ov_flags);
3846#define CHECK_CFP_CONSISTENCY(func) \
3847 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3848 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3851const rb_method_cfunc_t *
3852vm_method_cfunc_entry(
const rb_callable_method_entry_t *me)
3854#if VM_DEBUG_VERIFY_METHOD_CACHE
3855 switch (me->def->type) {
3856 case VM_METHOD_TYPE_CFUNC:
3857 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3859# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3861 METHOD_BUG(ATTRSET);
3863 METHOD_BUG(BMETHOD);
3866 METHOD_BUG(OPTIMIZED);
3867 METHOD_BUG(MISSING);
3868 METHOD_BUG(REFINED);
3872 rb_bug(
"wrong method type: %d", me->def->type);
3875 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3879vm_call_cfunc_with_frame_(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
3882 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3886 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3887 const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me);
3889 VALUE recv = calling->recv;
3890 VALUE block_handler = calling->block_handler;
3891 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3893 if (UNLIKELY(calling->kw_splat)) {
3894 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3897 VM_ASSERT(reg_cfp == ec->cfp);
3899 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3902 vm_push_frame(ec, NULL, frame_type, recv,
3903 block_handler, (
VALUE)me,
3904 0, ec->cfp->sp, 0, 0);
3906 int len = cfunc->argc;
3907 if (
len >= 0) rb_check_arity(argc,
len,
len);
3909 reg_cfp->sp = stack_bottom;
3910 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3912 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3914 rb_vm_pop_frame(ec);
3916 VM_ASSERT(ec->cfp->sp == stack_bottom);
3918 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3919 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3927rb_vm_push_cfunc_frame(
const rb_callable_method_entry_t *cme,
int recv_idx)
3929 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3930 rb_execution_context_t *ec = GET_EC();
3931 VALUE *sp = ec->cfp->sp;
3932 VALUE recv = *(sp - recv_idx - 1);
3933 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3934 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3935#if VM_CHECK_MODE > 0
3937 *(GET_EC()->cfp->sp) =
Qfalse;
3939 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3944rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3946 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3950vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3952 int argc = calling->argc;
3953 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3954 VALUE *argv = &stack_bottom[1];
3956 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3960vm_call_cfunc_other(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3963 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3965 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3967 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3968 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3969 int argc = RARRAY_LENINT(argv_ary);
3971 VALUE *stack_bottom = reg_cfp->sp - 2;
3973 VM_ASSERT(calling->argc == 1);
3974 VM_ASSERT(RB_TYPE_P(argv_ary,
T_ARRAY));
3975 VM_ASSERT(RBASIC_CLASS(argv_ary) == 0);
3977 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3980 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_with_frame, !rb_splat_or_kwargs_p(ci) && !calling->kw_splat && !(vm_ci_flag(ci) & VM_CALL_FORWARDING));
3982 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3987vm_call_cfunc_array_argv(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
int stack_offset,
int argc_offset)
3989 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3990 int argc = RARRAY_LENINT(argv_ary) - argc_offset;
3992 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3993 return vm_call_cfunc_other(ec, reg_cfp, calling);
3997 calling->kw_splat = 0;
3999 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
4000 VALUE *sp = stack_bottom;
4001 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
4002 for(i = 0; i < argc; i++) {
4007 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4011vm_call_cfunc_only_splat(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4013 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4014 VALUE argv_ary = reg_cfp->sp[-1];
4015 int argc = RARRAY_LENINT(argv_ary);
4018 int argc_offset = 0;
4020 if (UNLIKELY(argc > 0 &&
4021 RB_TYPE_P((last_hash = argv[argc-1]),
T_HASH) &&
4022 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4024 return vm_call_cfunc_other(ec, reg_cfp, calling);
4028 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4032vm_call_cfunc_only_splat_kw(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4034 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4035 VALUE keyword_hash = reg_cfp->sp[-1];
4038 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4041 return vm_call_cfunc_other(ec, reg_cfp, calling);
4045vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4048 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4050 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4051 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4053 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4054 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4056 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4058 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4059 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4063 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4064 return vm_call_cfunc_other(ec, reg_cfp, calling);
4068vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4071 RB_DEBUG_COUNTER_INC(ccf_ivar);
4073 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4078vm_call_attrset_direct(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_callcache *cc,
VALUE obj)
4080 RB_DEBUG_COUNTER_INC(ccf_attrset);
4081 VALUE val = *(cfp->sp - 1);
4084 shape_id_t dest_shape_id;
4085 vm_cc_atomic_shape_and_index(cc, &dest_shape_id, &index);
4086 ID id = vm_cc_cme(cc)->def->body.attr.id;
4087 rb_check_frozen(obj);
4088 VALUE res = vm_setivar(obj,
id, val, dest_shape_id, index);
4096 res = vm_setivar_class(obj,
id, val, dest_shape_id, index);
4097 if (!UNDEF_P(res)) {
4104 res = vm_setivar_default(obj,
id, val, dest_shape_id, index);
4105 if (!UNDEF_P(res)) {
4110 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4116vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4118 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4122vm_call_bmethod_body(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const VALUE *argv)
4127 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4128 VALUE procv = cme->def->body.bmethod.proc;
4131 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4132 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4136 GetProcPtr(procv, proc);
4137 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4142static int vm_callee_setup_block_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
const rb_iseq_t *iseq,
VALUE *argv,
const enum arg_setup_type arg_setup_type);
4145vm_call_iseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4147 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4150 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4151 VALUE procv = cme->def->body.bmethod.proc;
4154 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4155 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4159 GetProcPtr(procv, proc);
4160 const struct rb_block *block = &proc->block;
4162 while (vm_block_type(block) == block_type_proc) {
4163 block = vm_proc_block(block->as.proc);
4165 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4168 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4169 VALUE *
const argv = cfp->sp - calling->argc;
4170 const int arg_size = ISEQ_BODY(iseq)->param.size;
4173 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4174 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4177 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4182 vm_push_frame(ec, iseq,
4183 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4185 VM_GUARDED_PREV_EP(captured->ep),
4187 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4189 ISEQ_BODY(iseq)->local_table_size - arg_size,
4190 ISEQ_BODY(iseq)->stack_max);
4196vm_call_noniseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4198 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4202 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4203 if (UNLIKELY(calling->heap_argv)) {
4204 argv = RARRAY_PTR(calling->heap_argv);
4208 argc = calling->argc;
4211 cfp->sp += - argc - 1;
4214 return vm_call_bmethod_body(ec, calling, argv);
4218vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4220 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4223 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4224 VALUE procv = cme->def->body.bmethod.proc;
4226 GetProcPtr(procv, proc);
4227 const struct rb_block *block = &proc->block;
4229 while (vm_block_type(block) == block_type_proc) {
4230 block = vm_proc_block(block->as.proc);
4232 if (vm_block_type(block) == block_type_iseq) {
4233 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4234 return vm_call_iseq_bmethod(ec, cfp, calling);
4237 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4238 return vm_call_noniseq_bmethod(ec, cfp, calling);
4242rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4244 VALUE klass = current_class;
4247 if (RB_TYPE_P(klass,
T_ICLASS) && RICLASS_IS_ORIGIN_P(klass) &&
4248 RB_TYPE_P(RBASIC_CLASS(klass),
T_CLASS)) {
4249 klass = RBASIC_CLASS(klass);
4252 while (
RTEST(klass)) {
4253 VALUE owner = RB_TYPE_P(klass,
T_ICLASS) ? RBASIC_CLASS(klass) : klass;
4254 if (owner == target_owner) {
4260 return current_class;
4263static const rb_callable_method_entry_t *
4264aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4266 const rb_method_entry_t *orig_me = me->def->body.alias.original_me;
4267 const rb_callable_method_entry_t *cme;
4269 if (orig_me->defined_class == 0) {
4270 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4271 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4272 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4274 if (me->def->reference_count == 1) {
4275 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4278 rb_method_definition_t *def =
4279 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4280 rb_method_definition_set((rb_method_entry_t *)me, def, (
void *)cme);
4284 cme = (
const rb_callable_method_entry_t *)orig_me;
4287 VM_ASSERT(callable_method_entry_p(cme));
4291const rb_callable_method_entry_t *
4292rb_aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4294 return aliased_callable_method_entry(me);
4298vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4300 calling->cc = &VM_CC_ON_STACK(
Qundef,
4303 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4305 return vm_call_method_each_type(ec, cfp, calling);
4308static enum method_missing_reason
4311 enum method_missing_reason stat = MISSING_NOENTRY;
4312 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4313 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4314 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4318static VALUE vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
4321vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4324 ASSUME(calling->argc >= 0);
4326 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4327 int argc = calling->argc;
4328 VALUE recv = calling->recv;
4331 flags |= VM_CALL_OPT_SEND;
4333 if (UNLIKELY(! mid)) {
4334 mid = idMethodMissing;
4335 missing_reason = ci_missing_reason(ci);
4336 ec->method_missing_reason = missing_reason;
4339 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4340 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4341 rb_ary_unshift(argv_ary, symbol);
4344 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4345 VALUE exc = rb_make_no_method_exception(
4367 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4370 argc = ++calling->argc;
4372 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4375 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4376 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4377 VALUE exc = rb_make_no_method_exception(
4390 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4396 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4397 calling->cd = &new_fcd.cd;
4401 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4402 new_fcd.caller_ci = caller_ci;
4405 calling->cc = &VM_CC_ON_STACK(klass,
4407 { .method_missing_reason = missing_reason },
4408 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4410 if (flags & VM_CALL_FCALL) {
4411 return vm_call_method(ec, reg_cfp, calling);
4415 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4417 if (vm_cc_cme(cc) != NULL) {
4418 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4419 case METHOD_VISI_PUBLIC:
4420 return vm_call_method_each_type(ec, reg_cfp, calling);
4421 case METHOD_VISI_PRIVATE:
4422 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4424 case METHOD_VISI_PROTECTED:
4425 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4428 VM_UNREACHABLE(vm_call_method);
4430 return vm_call_method_missing(ec, reg_cfp, calling);
4433 return vm_call_method_nome(ec, reg_cfp, calling);
4437vm_call_opt_send0(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
int flags)
4443 i = calling->argc - 1;
4445 if (calling->argc == 0) {
4446 rb_raise(rb_eArgError,
"no method name given");
4470 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4474vm_call_opt_send_complex(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4476 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4478 int flags = VM_CALL_FCALL;
4482 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4483 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4485 flags |= VM_CALL_ARGS_SPLAT;
4486 if (calling->kw_splat) {
4487 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4488 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4489 calling->kw_splat = 0;
4491 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4494 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4495 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4499vm_call_opt_send_simple(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4501 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4502 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4506vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4508 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4511 int flags = vm_ci_flag(ci);
4513 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4514 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4515 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4516 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4517 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4518 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4521 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4522 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4526vm_call_method_missing_body(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
4527 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4529 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4531 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4532 unsigned int argc, flag;
4534 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4535 argc = ++calling->argc;
4538 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4539 vm_check_canary(ec, reg_cfp->sp);
4543 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4546 ec->method_missing_reason = reason;
4550 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4556 if (!(flag & VM_CALL_FORWARDING)) {
4557 calling->cd = &new_fcd.cd;
4561 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4562 new_fcd.caller_ci = caller_ci;
4566 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4567 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4568 return vm_call_method(ec, reg_cfp, calling);
4572vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4574 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4577static const rb_callable_method_entry_t *refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me);
4579vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE klass)
4583 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, vm_ci_mid(calling->cd->ci)) : NULL;
4585 return vm_call_method_nome(ec, cfp, calling);
4587 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4588 cme->def->body.refined.orig_me) {
4589 cme = refined_method_callable_without_refinement(cme);
4592 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4594 return vm_call_method_each_type(ec, cfp, calling);
4598find_refinement(
VALUE refinements,
VALUE klass)
4600 if (
NIL_P(refinements)) {
4603 return rb_hash_lookup(refinements, klass);
4606PUREFUNC(
static rb_control_frame_t * current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp));
4607static rb_control_frame_t *
4608current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp)
4610 rb_control_frame_t *top_cfp = cfp;
4612 if (cfp->iseq && ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_BLOCK) {
4613 const rb_iseq_t *local_iseq = ISEQ_BODY(cfp->iseq)->local_iseq;
4616 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4617 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4621 }
while (cfp->iseq != local_iseq);
4626static const rb_callable_method_entry_t *
4627refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me)
4629 const rb_method_entry_t *orig_me = me->def->body.refined.orig_me;
4630 const rb_callable_method_entry_t *cme;
4632 if (orig_me->defined_class == 0) {
4637 cme = (
const rb_callable_method_entry_t *)orig_me;
4640 VM_ASSERT(callable_method_entry_p(cme));
4642 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4649static const rb_callable_method_entry_t *
4650search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4652 ID mid = vm_ci_mid(calling->cd->ci);
4653 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4655 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4657 for (; cref; cref = CREF_NEXT(cref)) {
4658 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4659 if (
NIL_P(refinement))
continue;
4661 const rb_callable_method_entry_t *
const ref_me =
4662 rb_callable_method_entry(refinement, mid);
4665 if (vm_cc_call(cc) == vm_call_super_method) {
4666 const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp);
4667 const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp);
4668 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4673 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4674 cme->def != ref_me->def) {
4677 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4686 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4687 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4691 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, mid) : NULL;
4697vm_call_refined(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4699 const rb_callable_method_entry_t *ref_cme = search_refined_method(ec, cfp, calling);
4702 if (calling->cd->cc) {
4703 const struct rb_callcache *cc = calling->cc = vm_cc_new(vm_cc_cme(calling->cc)->defined_class, ref_cme, vm_call_general, cc_type_refinement);
4705 return vm_call_method(ec, cfp, calling);
4708 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4709 calling->cc= ref_cc;
4710 return vm_call_method(ec, cfp, calling);
4714 return vm_call_method_nome(ec, cfp, calling);
4718static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
bool is_lambda,
VALUE block_handler);
4720NOINLINE(
static VALUE
4721 vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4725vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4728 int argc = calling->argc;
4731 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4734 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4738vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4740 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4743 VALUE procval = calling->recv;
4744 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4748vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4750 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4752 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4755 if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
4756 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4759 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4760 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4761 return vm_call_general(ec, reg_cfp, calling);
4766vm_call_opt_struct_aref0(rb_execution_context_t *ec,
struct rb_calling_info *calling)
4768 VALUE recv = calling->recv;
4770 VM_ASSERT(RB_TYPE_P(recv,
T_STRUCT));
4771 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4772 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4774 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4775 return internal_RSTRUCT_GET(recv,
off);
4779vm_call_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4781 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4783 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4789vm_call_opt_struct_aset0(rb_execution_context_t *ec,
struct rb_calling_info *calling,
VALUE val)
4791 VALUE recv = calling->recv;
4793 VM_ASSERT(RB_TYPE_P(recv,
T_STRUCT));
4794 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4795 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4797 rb_check_frozen(recv);
4799 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4800 internal_RSTRUCT_SET(recv,
off, val);
4806vm_call_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4808 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4810 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4815NOINLINE(
static VALUE vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4818#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4819 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4820 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4821 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4823 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4824 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4832vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4835 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4836 case OPTIMIZED_METHOD_TYPE_SEND:
4837 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4838 return vm_call_opt_send(ec, cfp, calling);
4839 case OPTIMIZED_METHOD_TYPE_CALL:
4840 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4841 return vm_call_opt_call(ec, cfp, calling);
4842 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4843 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4844 return vm_call_opt_block_call(ec, cfp, calling);
4845 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4846 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4847 rb_check_arity(calling->argc, 0, 0);
4850 VM_CALL_METHOD_ATTR(v,
4851 vm_call_opt_struct_aref(ec, cfp, calling),
4852 set_vm_cc_ivar(cc); \
4853 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4856 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4857 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4858 rb_check_arity(calling->argc, 1, 1);
4861 VM_CALL_METHOD_ATTR(v,
4862 vm_call_opt_struct_aset(ec, cfp, calling),
4863 set_vm_cc_ivar(cc); \
4864 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4868 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4873vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4877 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4880 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4882 switch (cme->def->type) {
4883 case VM_METHOD_TYPE_ISEQ:
4884 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4885 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4886 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4889 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4890 return vm_call_iseq_setup(ec, cfp, calling);
4893 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4894 case VM_METHOD_TYPE_CFUNC:
4895 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4896 return vm_call_cfunc(ec, cfp, calling);
4898 case VM_METHOD_TYPE_ATTRSET:
4899 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4901 rb_check_arity(calling->argc, 1, 1);
4903 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4905 if (vm_cc_markable(cc)) {
4906 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4907 VM_CALL_METHOD_ATTR(v,
4908 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4909 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4915 VM_CALLCACHE_UNMARKABLE |
4916 VM_CALLCACHE_ON_STACK,
4922 .value = vm_pack_shape_and_index(INVALID_SHAPE_ID, ATTR_INDEX_NOT_SET),
4927 VM_CALL_METHOD_ATTR(v,
4928 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4929 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4933 case VM_METHOD_TYPE_IVAR:
4934 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4935 rb_check_arity(calling->argc, 0, 0);
4936 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4937 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4938 VM_CALL_METHOD_ATTR(v,
4939 vm_call_ivar(ec, cfp, calling),
4940 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4943 case VM_METHOD_TYPE_MISSING:
4944 vm_cc_method_missing_reason_set(cc, 0);
4945 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4946 return vm_call_method_missing(ec, cfp, calling);
4948 case VM_METHOD_TYPE_BMETHOD:
4949 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4950 return vm_call_bmethod(ec, cfp, calling);
4952 case VM_METHOD_TYPE_ALIAS:
4953 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4954 return vm_call_alias(ec, cfp, calling);
4956 case VM_METHOD_TYPE_OPTIMIZED:
4957 return vm_call_optimized(ec, cfp, calling, ci, cc);
4959 case VM_METHOD_TYPE_UNDEF:
4962 case VM_METHOD_TYPE_ZSUPER:
4963 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4965 case VM_METHOD_TYPE_REFINED:
4968 return vm_call_refined(ec, cfp, calling);
4971 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4974NORETURN(
static void vm_raise_method_missing(rb_execution_context_t *ec,
int argc,
const VALUE *argv,
VALUE obj,
int call_status));
4977vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4981 const int stat = ci_missing_reason(ci);
4983 if (vm_ci_mid(ci) == idMethodMissing) {
4984 if (UNLIKELY(calling->heap_argv)) {
4985 vm_raise_method_missing(ec, RARRAY_LENINT(calling->heap_argv),
RARRAY_CONST_PTR(calling->heap_argv), calling->recv, stat);
4988 rb_control_frame_t *reg_cfp = cfp;
4989 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4990 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4994 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
5004vm_defined_class_for_protected_call(
const rb_callable_method_entry_t *me)
5006 VALUE defined_class = me->defined_class;
5007 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
5008 return NIL_P(refined_class) ? defined_class : refined_class;
5012vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
5017 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5019 if (vm_cc_cme(cc) != NULL) {
5020 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5021 case METHOD_VISI_PUBLIC:
5022 return vm_call_method_each_type(ec, cfp, calling);
5024 case METHOD_VISI_PRIVATE:
5025 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5026 enum method_missing_reason stat = MISSING_PRIVATE;
5027 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5029 vm_cc_method_missing_reason_set(cc, stat);
5030 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5031 return vm_call_method_missing(ec, cfp, calling);
5033 return vm_call_method_each_type(ec, cfp, calling);
5035 case METHOD_VISI_PROTECTED:
5036 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5037 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5039 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5040 return vm_call_method_missing(ec, cfp, calling);
5044 VM_ASSERT(vm_cc_cme(cc) != NULL);
5047 calling->cc = &cc_on_stack;
5048 return vm_call_method_each_type(ec, cfp, calling);
5051 return vm_call_method_each_type(ec, cfp, calling);
5054 rb_bug(
"unreachable");
5058 return vm_call_method_nome(ec, cfp, calling);
5063vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5065 RB_DEBUG_COUNTER_INC(ccf_general);
5066 return vm_call_method(ec, reg_cfp, calling);
5072 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5073 VM_ASSERT(cc != vm_cc_empty());
5075 *(vm_call_handler *)&cc->call_ = vm_call_general;
5079vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5081 RB_DEBUG_COUNTER_INC(ccf_super_method);
5086 if (ec == NULL) rb_bug(
"unreachable");
5089 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5090 return vm_call_method(ec, reg_cfp, calling);
5096vm_search_normal_superclass(
VALUE klass)
5101 klass =
RBASIC(klass)->klass;
5103 klass = RCLASS_ORIGIN(klass);
5107NORETURN(
static void vm_super_outside(
void));
5110vm_super_outside(
void)
5116empty_cc_for_super(
void)
5118 return &vm_empty_cc_for_super;
5122vm_search_super_method(
const rb_control_frame_t *reg_cfp,
struct rb_call_data *cd,
VALUE recv)
5124 VALUE current_defined_class;
5125 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
5131 current_defined_class = vm_defined_class_for_protected_call(me);
5134 reg_cfp->iseq != method_entry_iseqptr(me) &&
5137 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5141 "self has wrong type to call super in this context: "
5142 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5147 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5149 "implicit argument passing of super from method defined"
5150 " by define_method() is not supported."
5151 " Specify all arguments explicitly.");
5154 ID mid = me->def->original_id;
5156 if (!vm_ci_markable(cd->ci)) {
5157 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5161 cd->ci = vm_ci_new_runtime(mid,
5164 vm_ci_kwarg(cd->ci));
5171 VALUE klass = vm_search_normal_superclass(me->defined_class);
5175 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5179 cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd, klass);
5180 const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc);
5183 if (cached_cme == NULL) {
5185 cd->cc = empty_cc_for_super();
5187 else if (cached_cme->called_id != mid) {
5188 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
5190 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5194 cd->cc = cc = empty_cc_for_super();
5198 switch (cached_cme->def->type) {
5200 case VM_METHOD_TYPE_REFINED:
5202 case VM_METHOD_TYPE_ATTRSET:
5203 case VM_METHOD_TYPE_IVAR:
5204 vm_cc_call_set(cc, vm_call_super_method);
5212 VM_ASSERT((vm_cc_cme(cc),
true));
5220block_proc_is_lambda(
const VALUE procval)
5225 GetProcPtr(procval, proc);
5226 return proc->is_lambda;
5234vm_yield_with_cfunc(rb_execution_context_t *ec,
5236 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5237 const rb_callable_method_entry_t *me)
5239 int is_lambda = FALSE;
5240 VALUE val, arg, blockarg;
5242 const struct vm_ifunc *ifunc = captured->code.ifunc;
5247 else if (argc == 0) {
5254 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5256 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5258 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5261 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5264 VM_GUARDED_PREV_EP(captured->ep),
5266 0, ec->cfp->sp, 0, 0);
5267 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5268 rb_vm_pop_frame(ec);
5274rb_vm_yield_with_cfunc(rb_execution_context_t *ec,
const struct rb_captured_block *captured,
int argc,
const VALUE *argv)
5276 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5280vm_yield_with_symbol(rb_execution_context_t *ec,
VALUE symbol,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler)
5282 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
5286vm_callee_setup_block_arg_arg0_splat(rb_control_frame_t *cfp,
const rb_iseq_t *iseq,
VALUE *argv,
VALUE ary)
5291 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5293 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5301vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5303 VALUE ary, arg0 = argv[0];
5308 VM_ASSERT(argv[0] == arg0);
5314vm_callee_setup_block_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
const rb_iseq_t *iseq,
VALUE *argv,
const enum arg_setup_type arg_setup_type)
5316 if (rb_simple_iseq_p(iseq)) {
5317 rb_control_frame_t *cfp = ec->cfp;
5320 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5322 if (arg_setup_type == arg_setup_block &&
5323 calling->argc == 1 &&
5324 ISEQ_BODY(iseq)->param.flags.has_lead &&
5325 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5326 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5327 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5330 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5331 if (arg_setup_type == arg_setup_block) {
5332 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5334 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5335 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5336 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5338 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5339 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5343 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5350 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5355vm_yield_setup_args(rb_execution_context_t *ec,
const rb_iseq_t *iseq,
const int argc,
VALUE *argv,
int flags,
VALUE block_handler,
enum arg_setup_type arg_setup_type)
5359 calling = &calling_entry;
5360 calling->argc = argc;
5361 calling->block_handler = block_handler;
5362 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5364 calling->heap_argv = 0;
5366 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5368 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5374vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5376 bool is_lambda,
VALUE block_handler)
5379 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5380 const int arg_size = ISEQ_BODY(iseq)->param.size;
5381 VALUE *
const rsp = GET_SP() - calling->argc;
5382 VALUE *
const argv = rsp;
5383 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5384 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5388 vm_push_frame(ec, iseq,
5391 VM_GUARDED_PREV_EP(captured->ep), 0,
5392 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5394 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5400vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5402 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5404 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5405 int flags = vm_ci_flag(ci);
5407 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5408 ((calling->argc == 0) ||
5409 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5410 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5411 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5412 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5414 if (UNLIKELY(calling->heap_argv)) {
5415#if VM_ARGC_STACK_MAX < 0
5417 rb_raise(rb_eArgError,
"no receiver given");
5423 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5424 reg_cfp->sp[-2] = calling->recv;
5425 flags |= VM_CALL_ARGS_SPLAT;
5428 if (calling->argc < 1) {
5429 rb_raise(rb_eArgError,
"no receiver given");
5431 calling->recv = TOPN(--calling->argc);
5433 if (calling->kw_splat) {
5434 flags |= VM_CALL_KW_SPLAT;
5438 if (calling->argc < 1) {
5439 rb_raise(rb_eArgError,
"no receiver given");
5441 calling->recv = TOPN(--calling->argc);
5444 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5448vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5450 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5455 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5456 argc = calling->argc;
5457 val = vm_yield_with_cfunc(ec, captured, captured->self, CALLING_ARGC(calling), calling->heap_argv ?
RARRAY_CONST_PTR(calling->heap_argv) : STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler, NULL);
5463vm_proc_to_block_handler(
VALUE procval)
5465 const struct rb_block *block = vm_proc_block(procval);
5467 switch (vm_block_type(block)) {
5468 case block_type_iseq:
5469 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5470 case block_type_ifunc:
5471 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5472 case block_type_symbol:
5473 return VM_BH_FROM_SYMBOL(block->as.symbol);
5474 case block_type_proc:
5475 return VM_BH_FROM_PROC(block->as.proc);
5477 VM_UNREACHABLE(vm_yield_with_proc);
5482vm_invoke_proc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5484 bool is_lambda,
VALUE block_handler)
5486 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5487 VALUE proc = VM_BH_TO_PROC(block_handler);
5488 is_lambda = block_proc_is_lambda(proc);
5489 block_handler = vm_proc_to_block_handler(proc);
5492 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5496vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5498 bool is_lambda,
VALUE block_handler)
5500 VALUE (*func)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5502 bool is_lambda,
VALUE block_handler);
5504 switch (vm_block_handler_type(block_handler)) {
5505 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5506 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5507 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5508 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5509 default: rb_bug(
"vm_invoke_block: unreachable");
5512 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5516vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5518 const rb_execution_context_t *ec = GET_EC();
5519 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
5523 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5526 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5527 captured->code.iseq = blockiseq;
5529 return rb_vm_make_proc(ec, captured,
rb_cProc);
5533vm_once_exec(
VALUE iseq)
5535 VALUE proc = vm_make_proc_with_iseq((rb_iseq_t *)iseq);
5540vm_once_clear(
VALUE data)
5543 is->once.running_thread = NULL;
5555 args[0] = obj; args[1] =
Qfalse;
5557 if (!UNDEF_P(r) &&
RTEST(r)) {
5566vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5569 enum defined_type
type = (
enum defined_type)op_type;
5576 return rb_gvar_defined(
SYM2ID(obj));
5578 case DEFINED_CVAR: {
5579 const rb_cref_t *cref = vm_get_cref(GET_EP());
5580 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5585 case DEFINED_CONST_FROM: {
5586 bool allow_nil =
type == DEFINED_CONST;
5588 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5593 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5595 case DEFINED_METHOD:{
5597 const rb_callable_method_entry_t *cme = rb_callable_method_entry_with_refinements(klass,
SYM2ID(obj), NULL);
5600 switch (METHOD_ENTRY_VISI(cme)) {
5601 case METHOD_VISI_PRIVATE:
5603 case METHOD_VISI_PROTECTED:
5607 case METHOD_VISI_PUBLIC:
5611 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(cme));
5615 return check_respond_to_missing(obj, v);
5620 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5624 case DEFINED_ZSUPER:
5626 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(GET_CFP());
5629 VALUE klass = vm_search_normal_superclass(me->defined_class);
5630 if (!klass)
return false;
5632 ID id = me->def->original_id;
5639 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5641 rb_bug(
"unimplemented defined? type (VM)");
5649rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5651 return vm_defined(ec, reg_cfp, op_type, obj, v);
5655vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5658 const VALUE *ep = reg_ep;
5659 for (i = 0; i < lv; i++) {
5660 ep = GET_PREV_EP(ep);
5666vm_get_special_object(
const VALUE *
const reg_ep,
5667 enum vm_special_object_type
type)
5670 case VM_SPECIAL_OBJECT_VMCORE:
5671 return rb_mRubyVMFrozenCore;
5672 case VM_SPECIAL_OBJECT_CBASE:
5673 return vm_get_cbase(reg_ep);
5674 case VM_SPECIAL_OBJECT_CONST_BASE:
5675 return vm_get_const_base(reg_ep);
5677 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5684rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5686 return vm_get_special_object(reg_ep,
type);
5692 const VALUE ary2 = ary2st;
5693 VALUE tmp1 = rb_check_to_array(ary1);
5694 VALUE tmp2 = rb_check_to_array(ary2);
5715 const VALUE ary2 = ary2st;
5717 if (
NIL_P(ary2))
return ary1;
5719 VALUE tmp2 = rb_check_to_array(ary2);
5734 return vm_concat_array(ary1, ary2st);
5738rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5740 return vm_concat_to_array(ary1, ary2st);
5749 VALUE tmp = rb_check_to_array(ary);
5753 else if (
RTEST(flag)) {
5766 return vm_splat_array(flag, ary);
5770vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5772 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5774 if (flag & VM_CHECKMATCH_ARRAY) {
5778 for (i = 0; i < n; i++) {
5780 VALUE c = check_match(ec, v, target,
type);
5789 return check_match(ec, pattern, target,
type);
5794rb_vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5796 return vm_check_match(ec, target, pattern, flag);
5800vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5802 const VALUE kw_bits = *(ep - bits);
5805 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5806 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5810 VM_ASSERT(RB_TYPE_P(kw_bits,
T_HASH));
5819 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5820 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5821 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5822 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5826 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5829 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5832 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5835 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5842vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5847 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5848 return rb_public_const_get_at(cbase,
id);
5856vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
5858 if (!RB_TYPE_P(klass,
T_CLASS)) {
5861 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
5866 "superclass mismatch for class %"PRIsVALUE
"",
5879vm_check_if_module(
ID id,
VALUE mod)
5898vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5901 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super : rb_cObject;
5909vm_declare_module(
ID id,
VALUE cbase)
5915NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
5919 VALUE name = rb_id2str(
id);
5920 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
5922 VALUE location = rb_const_source_location_at(cbase,
id);
5923 if (!
NIL_P(location)) {
5924 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
5925 " previous definition of %"PRIsVALUE
" was here",
5932vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5936 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !RB_TYPE_P(super,
T_CLASS)) {
5938 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
5942 vm_check_if_namespace(cbase);
5947 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
5948 if (!vm_check_if_class(
id, flags, super, klass))
5949 unmatched_redefinition(
"class", cbase,
id, klass);
5953 return vm_declare_class(
id, flags, cbase, super);
5958vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
5962 vm_check_if_namespace(cbase);
5963 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
5964 if (!vm_check_if_module(
id, mod))
5965 unmatched_redefinition(
"module", cbase,
id, mod);
5969 return vm_declare_module(
id, cbase);
5974vm_find_or_create_class_by_id(
ID id,
5979 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
5982 case VM_DEFINECLASS_TYPE_CLASS:
5984 return vm_define_class(
id, flags, cbase, super);
5986 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
5990 case VM_DEFINECLASS_TYPE_MODULE:
5992 return vm_define_module(
id, flags, cbase);
5995 rb_bug(
"unknown defineclass type: %d", (
int)
type);
5999static rb_method_visibility_t
6000vm_scope_visibility_get(
const rb_execution_context_t *ec)
6002 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
6004 if (!vm_env_cref_by_cref(cfp->ep)) {
6005 return METHOD_VISI_PUBLIC;
6008 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6013vm_scope_module_func_check(
const rb_execution_context_t *ec)
6015 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
6017 if (!vm_env_cref_by_cref(cfp->ep)) {
6021 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6026vm_define_method(
const rb_execution_context_t *ec,
VALUE obj,
ID id,
VALUE iseqval,
int is_singleton)
6029 rb_method_visibility_t visi;
6030 rb_cref_t *cref = vm_ec_cref(ec);
6034 visi = METHOD_VISI_PUBLIC;
6037 klass = CREF_CLASS_FOR_DEFINITION(cref);
6038 visi = vm_scope_visibility_get(ec);
6045 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6047 if (
id == idInitialize && klass != rb_cObject && RB_TYPE_P(klass,
T_CLASS) && (
rb_get_alloc_func(klass) == rb_class_allocate_instance)) {
6048 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6051 if (!is_singleton && vm_scope_module_func_check(ec)) {
6053 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6062rb_vm_untag_block_handler(
VALUE block_handler)
6064 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6066 switch (vm_block_handler_type(block_handler)) {
6067 case block_handler_type_iseq:
6068 case block_handler_type_ifunc: {
6070 return captured->code.val;
6072 case block_handler_type_proc:
6073 case block_handler_type_symbol:
6074 return block_handler;
6076 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6081rb_vm_get_untagged_block_handler(rb_control_frame_t *reg_cfp)
6083 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6092 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6094 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6095 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6098 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6102enum method_explorer_type {
6104 mexp_search_invokeblock,
6113 VALUE block_handler,
6114 enum method_explorer_type method_explorer
6119 int argc = vm_ci_argc(ci);
6120 VALUE recv = TOPN(argc);
6122 .block_handler = block_handler,
6123 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6129 switch (method_explorer) {
6130 case mexp_search_method:
6131 calling.cc = cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd,
CLASS_OF(recv));
6132 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6134 case mexp_search_super:
6135 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6136 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6138 case mexp_search_invokeblock:
6139 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6146rb_vm_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6149 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6150 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6156rb_vm_sendforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6163 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6165 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6167 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6176rb_vm_opt_send_without_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6179 VALUE bh = VM_BLOCK_HANDLER_NONE;
6180 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6186rb_vm_invokesuper(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6190 struct rb_callinfo adjusted_ci = VM_CI_ON_STACK(vm_ci_mid(cd->ci),
6193 vm_ci_kwarg(cd->ci));
6194 const struct rb_callcache *original_cc = rbimpl_atomic_ptr_load((
void **)&cd->cc, RBIMPL_ATOMIC_ACQUIRE);
6200 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), adjusted_cd.ci, blockiseq,
true);
6201 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd, bh, mexp_search_super);
6203 if (original_cc != adjusted_cd.cc && vm_cc_markable(adjusted_cd.cc)) {
6204 rbimpl_atomic_ptr_store((
volatile void **)&cd->cc, (
void *)adjusted_cd.cc, RBIMPL_ATOMIC_RELEASE);
6213rb_vm_invokesuperforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6219 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6221 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6223 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6232rb_vm_invokeblock(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6235 VALUE bh = VM_BLOCK_HANDLER_NONE;
6236 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6253vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6264 if (check_method_basic_definition(cme)) {
6273 if (check_cfunc(cme, rb_mod_to_s)) {
6279 val = rb_mod_to_s(recv);
6285 if (check_cfunc(cme, rb_nil_to_s)) {
6286 return rb_nil_to_s(recv);
6290 if (check_cfunc(cme, rb_true_to_s)) {
6291 return rb_true_to_s(recv);
6295 if (check_cfunc(cme, rb_false_to_s)) {
6296 return rb_false_to_s(recv);
6300 if (check_cfunc(cme, rb_int_to_s)) {
6301 return rb_fix_to_s(recv);
6311rb_vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6313 return vm_objtostring(iseq, recv, cd);
6317vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6319 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6328vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6330 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6339vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6341 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6353vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6355 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6359 VALUE args[1] = {target};
6362 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6365 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6370rb_vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6372 return vm_opt_duparray_include_p(ec, ary, target);
6376vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6378 if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
6379 if (array_len == 0) {
6384 rb_snum_t i = array_len - 1;
6387 if (OPTIMIZED_CMP(v, result) > 0) {
6400rb_vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6402 return vm_opt_newarray_max(ec, array_len,
ptr);
6406vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6408 if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
6409 if (array_len == 0) {
6414 rb_snum_t i = array_len - 1;
6417 if (OPTIMIZED_CMP(v, result) < 0) {
6430rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6432 return vm_opt_newarray_min(ec, array_len,
ptr);
6436vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6439 if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
6440 return rb_ary_hash_values(array_len,
ptr);
6448rb_vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr)
6450 return vm_opt_newarray_hash(ec, array_len,
ptr);
6457vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr,
VALUE target)
6459 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6460 struct RArray fake_ary = {RBASIC_INIT};
6461 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6465 VALUE args[1] = {target};
6471rb_vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr,
VALUE target)
6473 return vm_opt_newarray_include_p(ec, array_len,
ptr, target);
6477vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr,
VALUE fmt,
VALUE buffer)
6479 if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) {
6480 struct RArray fake_ary = {RBASIC_INIT};
6481 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6482 return rb_ec_pack_ary(ec, ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6492 if (!UNDEF_P(buffer)) {
6493 args[1] = rb_hash_new_with_size(1);
6494 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6499 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len,
ptr), idPack, argc, args, kw_splat);
6504rb_vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr,
VALUE fmt,
VALUE buffer)
6506 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt, buffer);
6510rb_vm_opt_newarray_pack(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *
ptr,
VALUE fmt)
6512 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt,
Qundef);
6518vm_track_constant_cache(
ID id,
void *ic)
6520 rb_vm_t *vm = GET_VM();
6521 struct rb_id_table *const_cache = vm->constant_cache;
6522 VALUE lookup_result;
6525 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6529 ics = set_init_numtable();
6530 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6545 vm->inserting_constant_cache_id = id;
6547 set_insert(ics, (st_data_t)ic);
6549 vm->inserting_constant_cache_id = (
ID)0;
6553vm_ic_track_const_chain(rb_control_frame_t *cfp, IC ic,
const ID *segments)
6556 for (
int i = 0; segments[i]; i++) {
6557 ID id = segments[i];
6558 if (
id == idNULL)
continue;
6559 vm_track_constant_cache(
id, ic);
6566vm_inlined_ic_hit_p(
VALUE flags,
VALUE value,
const rb_cref_t *ic_cref,
const VALUE *reg_ep)
6568 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6569 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6571 return (ic_cref == NULL ||
6572 ic_cref == vm_get_cref(reg_ep));
6580 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6581 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6586rb_vm_ic_hit_p(IC ic,
const VALUE *reg_ep)
6588 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6592vm_ic_update(
const rb_iseq_t *iseq, IC ic,
VALUE val,
const VALUE *reg_ep,
const VALUE *pc)
6594 if (ruby_vm_const_missing_count > 0) {
6595 ruby_vm_const_missing_count = 0;
6602 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6604 if (rb_ractor_shareable_p(val)) {
6606 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6610 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6611 rb_yjit_constant_ic_update(iseq, ic, pos);
6615rb_vm_opt_getconstant_path(rb_execution_context_t *ec, rb_control_frame_t *
const reg_cfp, IC ic)
6621 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6624 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
6627 ruby_vm_constant_cache_misses++;
6628 val = vm_get_ev_const_chain(ec, segments);
6629 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6632 vm_ic_update(GET_ISEQ(), ic, val, GET_EP(), GET_PC() - 2);
6638vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, ISE is)
6640 rb_thread_t *th = rb_ec_thread_ptr(ec);
6641 rb_thread_t *
const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1);
6644 if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
6645 return is->once.value;
6647 else if (is->once.running_thread == NULL) {
6649 is->once.running_thread = th;
6653 if (RB_FL_ABLE(val)) {
6654 RB_OBJ_SET_SHAREABLE(val);
6660 is->once.running_thread = RUNNING_THREAD_ONCE_DONE;
6663 else if (is->once.running_thread == th) {
6665 return vm_once_exec((
VALUE)iseq);
6669 RUBY_VM_CHECK_INTS(ec);
6676vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6678 switch (OBJ_BUILTIN_TYPE(key)) {
6684 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6685 SYMBOL_REDEFINED_OP_FLAG |
6686 INTEGER_REDEFINED_OP_FLAG |
6687 FLOAT_REDEFINED_OP_FLAG |
6688 NIL_REDEFINED_OP_FLAG |
6689 TRUE_REDEFINED_OP_FLAG |
6690 FALSE_REDEFINED_OP_FLAG |
6691 STRING_REDEFINED_OP_FLAG)) {
6693 if (RB_FLOAT_TYPE_P(key)) {
6695 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6699 if (rb_hash_stlike_lookup(hash, key, &val)) {
6711 vm_stack_consistency_error(
const rb_execution_context_t *ec,
6712 const rb_control_frame_t *,
6715vm_stack_consistency_error(
const rb_execution_context_t *ec,
6716 const rb_control_frame_t *cfp,
6719 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6720 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6721 static const char stack_consistency_error[] =
6722 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6723#if defined RUBY_DEVEL
6724 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6729 rb_bug(stack_consistency_error, nsp, nbp);
6736 if (FIXNUM_2_P(recv, obj) &&
6737 BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
6738 return rb_fix_plus_fix(recv, obj);
6740 else if (FLONUM_2_P(recv, obj) &&
6741 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6747 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6749 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6754 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
6755 return rb_str_opt_plus(recv, obj);
6757 else if (RBASIC_CLASS(recv) ==
rb_cArray &&
6759 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
6770 if (FIXNUM_2_P(recv, obj) &&
6771 BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
6772 return rb_fix_minus_fix(recv, obj);
6774 else if (FLONUM_2_P(recv, obj) &&
6775 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6781 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6783 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6794 if (FIXNUM_2_P(recv, obj) &&
6795 BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
6796 return rb_fix_mul_fix(recv, obj);
6798 else if (FLONUM_2_P(recv, obj) &&
6799 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6805 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6807 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6818 if (FIXNUM_2_P(recv, obj) &&
6819 BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
6820 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6822 else if (FLONUM_2_P(recv, obj) &&
6823 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6824 return rb_flo_div_flo(recv, obj);
6829 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6831 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6832 return rb_flo_div_flo(recv, obj);
6842 if (FIXNUM_2_P(recv, obj) &&
6843 BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
6844 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
6846 else if (FLONUM_2_P(recv, obj) &&
6847 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6853 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6855 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6864vm_opt_neq(
const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq,
VALUE recv,
VALUE obj)
6866 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not_equal)) {
6867 VALUE val = opt_equality(iseq, recv, obj, cd_eq);
6869 if (!UNDEF_P(val)) {
6870 return RBOOL(!
RTEST(val));
6880 if (FIXNUM_2_P(recv, obj) &&
6881 BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
6884 else if (FLONUM_2_P(recv, obj) &&
6885 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6891 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6893 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6904 if (FIXNUM_2_P(recv, obj) &&
6905 BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
6908 else if (FLONUM_2_P(recv, obj) &&
6909 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6915 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6917 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6928 if (FIXNUM_2_P(recv, obj) &&
6929 BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
6932 else if (FLONUM_2_P(recv, obj) &&
6933 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6939 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6941 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6952 if (FIXNUM_2_P(recv, obj) &&
6953 BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
6956 else if (FLONUM_2_P(recv, obj) &&
6957 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6963 else if (RBASIC_CLASS(recv) ==
rb_cFloat &&
6965 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6981 BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
6982 if (LIKELY(RB_TYPE_P(obj,
T_STRING))) {
6989 else if (RBASIC_CLASS(recv) ==
rb_cArray &&
6990 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
7008 BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
7019 if (FIXNUM_2_P(recv, obj) &&
7020 BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
7032 if (FIXNUM_2_P(recv, obj) &&
7033 BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
7034 return rb_fix_aref(recv, obj);
7038 else if (RBASIC_CLASS(recv) ==
rb_cArray &&
7039 BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG)) {
7041 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7044 return rb_ary_aref1(recv, obj);
7047 else if (RBASIC_CLASS(recv) ==
rb_cHash &&
7048 BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
7049 return rb_hash_aref(recv, obj);
7062 else if (RBASIC_CLASS(recv) ==
rb_cArray &&
7063 BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
7068 else if (RBASIC_CLASS(recv) ==
rb_cHash &&
7069 BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
7070 rb_hash_aset(recv, obj, set);
7079vm_opt_length(
VALUE recv,
int bop)
7085 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7086 if (bop == BOP_EMPTY_P) {
7087 return LONG2NUM(RSTRING_LEN(recv));
7093 else if (RBASIC_CLASS(recv) ==
rb_cArray &&
7094 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7097 else if (RBASIC_CLASS(recv) ==
rb_cHash &&
7098 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7107vm_opt_empty_p(
VALUE recv)
7109 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7119vm_opt_nil_p(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7122 BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
7125 else if (vm_method_cfunc_is(iseq, cd, recv, rb_false)) {
7141 case RSHIFT(~0UL, 1):
7144 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7162vm_opt_succ(
VALUE recv)
7165 BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
7166 return fix_succ(recv);
7172 BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
7181vm_opt_not(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7183 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not)) {
7184 return RBOOL(!
RTEST(recv));
7199 BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
7203 BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
7211rb_event_flag_t rb_iseq_event_flags(
const rb_iseq_t *iseq,
size_t pos);
7213NOINLINE(
static void vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp));
7216vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const VALUE *pc,
7218 rb_hook_list_t *global_hooks, rb_hook_list_t *local_hooks,
VALUE val)
7221 VALUE self = GET_SELF();
7223 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7225 if (local_hooks) local_hooks->running++;
7227 if (event & global_hooks->events) {
7230 vm_dtrace(event, ec);
7231 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7235 if (local_hooks) local_hooks->running--;
7236 if (local_hooks != NULL) {
7237 if (event & local_hooks->events) {
7240 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7250#define VM_TRACE_HOOK(target_event, val) do { \
7251 if ((pc_events & (target_event)) & enabled_flags) { \
7252 if (local_hooks_cnt > 0) local_hooks = rb_iseq_local_hooks(iseq, r, false); \
7253 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7258rescue_errinfo(rb_execution_context_t *ec, rb_control_frame_t *cfp)
7260 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7261 VM_ASSERT(ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE);
7262 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7266vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
7268 const VALUE *pc = reg_cfp->pc;
7269 rb_ractor_t *r = rb_ec_ractor_ptr(ec);
7270 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7273 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7277 const rb_iseq_t *iseq = reg_cfp->iseq;
7278 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7280 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7281 rb_hook_list_t *local_hooks = NULL;
7282 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7284 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7285 local_hooks = (rb_hook_list_t*)val;
7288 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7290 rb_hook_list_t *bmethod_local_hooks = NULL;
7292 unsigned int bmethod_hooks_cnt = 0;
7293 rb_method_definition_t *bmethod_def = NULL;
7294 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7295 enabled_flags |= iseq_local_events;
7297 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7299 if (bmethod_frame) {
7300 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
7301 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7302 bmethod_def = me->def;
7303 bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7304 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7306 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7307 bmethod_local_hooks = (rb_hook_list_t*)val;
7309 if (bmethod_local_hooks) {
7310 bmethod_local_events = bmethod_local_hooks->events;
7315 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7319 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7327 else if (ec->trace_arg != NULL) {
7332 rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(ec);
7335 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7338 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %s:%d %s\n",
7341 RSTRING_PTR(rb_iseq_path(iseq)),
7342 (
int)rb_iseq_line_no(iseq, pos),
7343 RSTRING_PTR(rb_iseq_label(iseq)));
7345 VM_ASSERT(reg_cfp->pc == pc);
7346 VM_ASSERT(pc_events != 0);
7356 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7357 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7363 if (bmethod_hooks_cnt > 0) bmethod_local_hooks = rb_method_def_local_hooks(bmethod_def, r,
false);
7371#if VM_CHECK_MODE > 0
7372NORETURN( NOINLINE( COLDFUNC
7373void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7376Init_vm_stack_canary(
void)
7379 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7380 vm_stack_canary |= 0x01;
7382 vm_stack_canary_was_born =
true;
7387rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7391 const char *insn = rb_insns_name(i);
7395 rb_bug(
"dead canary found at %s: %s", insn, str);
7399void Init_vm_stack_canary(
void) { }
7428builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7430 typedef VALUE (*rb_invoke_funcptr0_t)(rb_execution_context_t *ec,
VALUE self);
7431 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7435builtin_invoker1(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7437 typedef VALUE (*rb_invoke_funcptr1_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1);
7438 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7442builtin_invoker2(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7444 typedef VALUE (*rb_invoke_funcptr2_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2);
7445 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7449builtin_invoker3(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7452 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7456builtin_invoker4(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7459 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7463builtin_invoker5(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7466 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7470builtin_invoker6(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7473 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7477builtin_invoker7(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7480 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7484builtin_invoker8(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7487 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7491builtin_invoker9(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7493 typedef VALUE (*rb_invoke_funcptr9_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9);
7494 return (*(rb_invoke_funcptr9_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
7498builtin_invoker10(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7500 typedef VALUE (*rb_invoke_funcptr10_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10);
7501 return (*(rb_invoke_funcptr10_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
7505builtin_invoker11(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7507 typedef VALUE (*rb_invoke_funcptr11_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10,
VALUE v11);
7508 return (*(rb_invoke_funcptr11_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
7512builtin_invoker12(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7514 typedef VALUE (*rb_invoke_funcptr12_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10,
VALUE v11,
VALUE v12);
7515 return (*(rb_invoke_funcptr12_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
7519builtin_invoker13(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7521 typedef VALUE (*rb_invoke_funcptr13_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10,
VALUE v11,
VALUE v12,
VALUE v13);
7522 return (*(rb_invoke_funcptr13_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
7526builtin_invoker14(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7528 typedef VALUE (*rb_invoke_funcptr14_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10,
VALUE v11,
VALUE v12,
VALUE v13,
VALUE v14);
7529 return (*(rb_invoke_funcptr14_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
7533builtin_invoker15(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7535 typedef VALUE (*rb_invoke_funcptr15_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2,
VALUE v3,
VALUE v4,
VALUE v5,
VALUE v6,
VALUE v7,
VALUE v8,
VALUE v9,
VALUE v10,
VALUE v11,
VALUE v12,
VALUE v13,
VALUE v14,
VALUE v15);
7536 return (*(rb_invoke_funcptr15_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
7539typedef VALUE (*builtin_invoker)(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
7541static builtin_invoker
7542lookup_builtin_invoker(
int argc)
7544 static const builtin_invoker invokers[] = {
7563 return invokers[argc];
7567invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7569 const bool canary_p = ISEQ_BODY(reg_cfp->iseq)->builtin_attrs & BUILTIN_ATTR_LEAF;
7570 SETUP_CANARY(canary_p);
7571 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7572 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7573 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7578vm_invoke_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7580 return invoke_bf(ec, cfp, bf, argv);
7584vm_invoke_builtin_delegate(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function *bf,
unsigned int start_index)
7587 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7588 for (
int i=0; i<bf->argc; i++) {
7589 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(cfp->iseq)->local_table[i+start_index]));
7591 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7592 (
void *)(uintptr_t)bf->func_ptr);
7595 if (bf->argc == 0) {
7596 return invoke_bf(ec, cfp, bf, NULL);
7599 const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7600 return invoke_bf(ec, cfp, bf, argv);
7607rb_vm_lvar_exposed(rb_execution_context_t *ec,
int index)
7609 const rb_control_frame_t *cfp = ec->cfp;
7610 return cfp->ep[index];
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_EVENT_END
Encountered an end of a class clause.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_B_RETURN
Encountered a next statement.
#define RUBY_EVENT_CLASS
Encountered a new class.
#define RUBY_EVENT_LINE
Encountered a new line.
#define RUBY_EVENT_RETURN
Encountered a return statement.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
#define RUBY_EVENT_B_CALL
Encountered an yield statement.
uint32_t rb_event_flag_t
Represents event(s).
#define RUBY_EVENT_CALL
A method, written in Ruby, is called.
#define RUBY_EVENT_RESCUE
Encountered a rescue statement.
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
VALUE rb_module_new(void)
Creates a new, anonymous module.
VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
VALUE rb_define_class_id(ID id, VALUE super)
This is a very badly designed API that creates an anonymous class.
#define TYPE(_)
Old name of rb_type.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define T_NIL
Old name of RUBY_T_NIL.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define T_STRUCT
Old name of RUBY_T_STRUCT.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define SYM2ID
Old name of RB_SYM2ID.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define STATIC_SYM_P
Old name of RB_STATIC_SYM_P.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define T_TRUE
Old name of RUBY_T_TRUE.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define T_HASH
Old name of RUBY_T_HASH.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define T_FALSE
Old name of RUBY_T_FALSE.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define DBL2NUM
Old name of rb_float_new.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define FL_TEST
Old name of RB_FL_TEST.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
void rb_notimplement(void)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eFatal
fatal exception.
VALUE rb_eNoMethodError
NoMethodError exception.
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
void rb_error_frozen_object(VALUE frozen_obj)
Identical to rb_error_frozen(), except it takes arbitrary Ruby object instead of C's string.
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
@ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
Warning is for checking unused block strictly.
VALUE rb_cClass
Class class.
VALUE rb_cArray
Array class.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_cRegexp
Regexp class.
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
VALUE rb_cHash
Hash class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_cBasicObject
BasicObject class.
VALUE rb_cModule
Module class.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_cFloat
Float class.
VALUE rb_cProc
Proc class.
VALUE rb_cString
String class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_resurrect(VALUE ary)
I guess there is no use case of this function in extension libraries, but this is a routine identical...
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_includes(VALUE ary, VALUE elem)
Queries if the passed array has the passed entry.
VALUE rb_ary_plus(VALUE lhs, VALUE rhs)
Creates a new array, concatenating the former to the latter.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_pop(VALUE ary)
Destructively deletes an element from the end of the passed array and returns what was deleted.
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc)
Identical to rb_proc_call(), except you can additionally pass another proc object,...
VALUE rb_reg_last_match(VALUE md)
This just returns the argument, stringified.
VALUE rb_reg_match(VALUE re, VALUE str)
This is the match operator.
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
VALUE rb_reg_match_post(VALUE md)
The portion of the original string after the given match.
VALUE rb_reg_nth_defined(int n, VALUE md)
Identical to rb_reg_nth_match(), except it just returns Boolean.
VALUE rb_reg_match_pre(VALUE md)
The portion of the original string before the given match.
VALUE rb_reg_match_last(VALUE md)
The portion of the original string that captured at the very last.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_succ(VALUE orig)
Searches for the "successor" of a string.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_length(VALUE)
Identical to rb_str_strlen(), except it returns the value in rb_cInteger.
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
void rb_thread_schedule(void)
Tries to switch to another thread.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
void rb_cvar_set(VALUE klass, ID name, VALUE val)
Assigns a value to a class variable.
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front)
Identical to rb_cvar_get(), except it takes additional "front" pointer.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
void rb_const_set(VALUE space, ID name, VALUE val)
Names a constant.
VALUE rb_autoload_load(VALUE space, ID name)
Kicks the autoload procedure as if it was "touched".
VALUE rb_mod_name(VALUE mod)
Queries the name of a module.
VALUE rb_const_get_at(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name)
Identical to rb_set_class_path(), except it accepts the name as Ruby's string instead of C's.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
int rb_const_defined_at(VALUE space, ID name)
Identical to rb_const_defined(), except it doesn't look for parent classes.
VALUE rb_cvar_defined(VALUE klass, ID name)
Queries if the given class has the given class variable.
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
int rb_const_defined(VALUE space, ID name)
Queries if the constant is defined at the namespace.
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
rb_alloc_func_t rb_get_alloc_func(VALUE klass)
Queries the allocator function of a class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
int rb_method_boundp(VALUE klass, ID id, int ex)
Queries if the klass has this method.
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
int off
Offset inside of ptr.
int len
Length of the buffer.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define RBASIC(obj)
Convenient casting macro.
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
#define RHASH_SIZE(h)
Queries the size of the hash.
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RB_PASS_KEYWORDS
Pass keywords, final argument should be a hash of keywords.
#define RB_NO_KEYWORDS
Do not pass keywords.
#define RTEST
This is an old name of RB_TEST.
#define ANYARGS
Functions declared using this macro take arbitrary arguments, including void.
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
IFUNC (Internal FUNCtion).
const VALUE cref_or_me
class reference or rb_method_entry_t
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.