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"
41 int argc,
const VALUE *argv,
int priv);
51ruby_vm_special_exception_copy(
VALUE exc)
54 rb_obj_copy_ivar(e, exc);
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);
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);
100callable_class_p(
VALUE klass)
102#if VM_CHECK_MODE >= 2
103 if (!klass)
return FALSE;
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;
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) {
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 ||
194 RUBY_VM_NORMAL_ISEQ_P(iseq)
198 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(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;
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");
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);
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);
439 if (VMDEBUG == 2) SDR();
441 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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;
461 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
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);
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));
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));
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);
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);
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;
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");
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);
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)) {
758 rb_bug(
"check_method_entry: svar should not be there:");
765env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
767 if (obj ==
Qfalse)
return NULL;
769 switch (imemo_type(obj)) {
786 const VALUE *ep = cfp->ep;
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);
800 const VALUE *ep = cfp->ep;
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);
814 switch (me->def->type) {
815 case VM_METHOD_TYPE_ISEQ:
816 return me->def->body.iseq.
iseqptr;
825 switch (me->def->type) {
826 case VM_METHOD_TYPE_ISEQ:
827 return me->def->body.iseq.
cref;
833#if VM_CHECK_MODE == 0
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)) {
856 rb_bug(
"check_method_entry: svar should not be there:");
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;
908 switch (imemo_type(v)) {
911 new_cref = vm_cref_dup(cref);
916 VM_FORCE_WRITE(vptr, (
VALUE)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)
964 rb_bug(
"vm_get_cref: unreachable");
969rb_vm_get_cref(
const VALUE *ep)
971 return vm_get_cref(ep);
982 return vm_get_cref(cfp->ep);
986vm_get_const_key_cref(
const VALUE *ep)
992 if (CREF_DYNAMIC(cref)) {
995 cref = CREF_NEXT(cref);
1008 prev_cref = vm_env_cref(ep);
1014 prev_cref = vm_env_cref(cfp->ep);
1018 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1022vm_get_cbase(
const VALUE *ep)
1024 const rb_cref_t *cref = vm_get_cref(ep);
1026 return CREF_CLASS_FOR_DEFINITION(cref);
1030vm_get_const_base(
const VALUE *ep)
1032 const rb_cref_t *cref = vm_get_cref(ep);
1035 if (!CREF_PUSHED_BY_EVAL(cref)) {
1036 return CREF_CLASS_FOR_DEFINITION(cref);
1038 cref = CREF_NEXT(cref);
1045vm_check_if_namespace(
VALUE klass)
1048 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1053vm_ensure_not_refinement_module(
VALUE self)
1056 rb_warn(
"not defined at the refinement, but at the outer class/module");
1072 if (
NIL_P(orig_klass) && allow_nil) {
1074 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1078 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1079 root_cref = CREF_NEXT(root_cref);
1082 while (cref && CREF_NEXT(cref)) {
1083 if (CREF_PUSHED_BY_EVAL(cref)) {
1087 klass = CREF_CLASS(cref);
1089 cref = CREF_NEXT(cref);
1091 if (!
NIL_P(klass)) {
1095 if ((ce = rb_const_lookup(klass,
id))) {
1096 rb_const_warn_if_deprecated(ce, klass,
id);
1099 if (am == klass)
break;
1101 if (is_defined)
return 1;
1102 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1104 goto search_continue;
1111 if (UNLIKELY(!rb_ractor_main_p())) {
1113 rb_raise(rb_eRactorIsolationError,
1114 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" by non-main ractor.",
rb_class_path(klass), rb_id2str(
id));
1125 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1126 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1140 vm_check_if_namespace(orig_klass);
1142 return rb_public_const_defined_from(orig_klass,
id);
1145 return rb_public_const_get_from(orig_klass,
id);
1153 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1161 int allow_nil = TRUE;
1162 if (segments[0] == idNULL) {
1167 while (segments[idx]) {
1168 ID id = segments[idx++];
1169 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1182 rb_bug(
"vm_get_cvar_base: no cref");
1185 while (CREF_NEXT(cref) &&
1186 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1187 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1188 cref = CREF_NEXT(cref);
1190 if (top_level_raise && !CREF_NEXT(cref)) {
1194 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1202#define ractor_incidental_shareable_p(cond, val) \
1203 (!(cond) || rb_ractor_shareable_p(val))
1204#define ractor_object_incidental_shareable_p(obj, val) \
1205 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1214 return default_value;
1224 if (UNLIKELY(!rb_ractor_main_p())) {
1232 if (default_value ==
Qundef) {
1240 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1244 fields_obj = rb_obj_fields(obj,
id);
1248 return default_value;
1253 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1254 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1256 rb_getivar_cache cache = rb_getivar_cache_unpack(vm_cache_attr_index_atomic_read(is_attr, ic, cc));
1258 if (LIKELY(cache.shape_offset == shape_id)) {
1259 if (cache.index == ATTR_INDEX_NOT_SET) {
1260 return default_value;
1263 val = ivar_list[cache.index];
1264#if USE_DEBUG_COUNTER
1265 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1268 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1274#if USE_DEBUG_COUNTER
1276 if (cache.shape_offset != INVALID_SHAPE_ID) {
1277 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1280 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1284 if (cache.shape_offset != INVALID_SHAPE_ID) {
1285 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1288 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1291 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1294 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1298 if (UNLIKELY(rb_shape_complex_p(shape_id))) {
1302 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1304 if (!st_lookup(table,
id, &val)) {
1305 val = default_value;
1309 shape_id_t previous_cached_offset = cache.shape_offset;
1310 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &cache.index, &cache.shape_offset)) {
1311 if (cache.shape_offset != previous_cached_offset) {
1312 RUBY_ASSERT(!rb_shape_complex_p(cache.shape_offset));
1313 RUBY_ASSERT(cache.shape_offset != INVALID_SHAPE_ID);
1315 uint64_t packed_cache = rb_getivar_cache_pack(cache.shape_offset, cache.index);
1316 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1319 if (cache.index == ATTR_INDEX_NOT_SET) {
1320 val = default_value;
1324 val = ivar_list[cache.index];
1329 vm_cache_attr_index_set(is_attr, ic, cc, rb_getivar_cache_pack(shape_id, ATTR_INDEX_NOT_SET));
1330 val = default_value;
1335 if (!UNDEF_P(default_value)) {
1343 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1346 return rb_attr_get(obj,
id);
1361 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1363 rb_check_frozen(obj);
1365 shape_id_t previous_shape_id = RBASIC_SHAPE_ID(obj);
1366 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1367 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1369 if (!rb_shape_complex_p(next_shape_id)) {
1370 uint64_t packed_cache = rb_setivar_cache_pack(RSHAPE_OFFSET(previous_shape_id), RSHAPE_OFFSET(next_shape_id), index);
1371 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1374 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1384 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1390 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1397 if (UNLIKELY(!rb_ractor_main_p())) {
1401 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1402 if (UNLIKELY(!fields_obj)) {
1406 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1407 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, cache);
1408 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1412 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1414 if (shape_id != dest_shape_id) {
1415 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1416 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1419 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1428 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1429 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, cache);
1430 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1434 VALUE fields_obj = rb_obj_fields(obj,
id);
1436 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1438 if (shape_id != dest_shape_id) {
1439 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1440 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1443 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1457 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1458 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, cache);
1459 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1464 if (shape_id != dest_shape_id) {
1465 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1468 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1469 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1475 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1487 VALUE defined_class = 0;
1491 defined_class =
RBASIC(defined_class)->klass;
1494 VALUE rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
1496 rb_bug(
"the cvc table should be set");
1500 if (!rb_marked_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
1501 rb_bug(
"should have cvar cache entry");
1506 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
1519 cref = vm_get_cref(GET_EP());
1521 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1522 RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
1524 VALUE v = rb_ivar_lookup(ic->entry->class_value,
id,
Qundef);
1530 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1532 return update_classvariable_cache(iseq, klass,
id, cref, ic);
1538 return vm_getclassvariable(iseq, cfp,
id, ic);
1545 cref = vm_get_cref(GET_EP());
1547 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1548 RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
1550 rb_class_ivar_set(ic->entry->class_value,
id, val);
1554 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1558 update_classvariable_cache(iseq, klass,
id, cref, ic);
1564 vm_setclassvariable(iseq, cfp,
id, val, ic);
1571 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1582 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_ic_atomic_cache_read(ic));
1583 if (UNLIKELY(UNDEF_P(vm_setivar(obj, val, cache)))) {
1589 if (!UNDEF_P(vm_setivar_class(obj, val, cache))) {
1594 if (!UNDEF_P(vm_setivar_default(obj,
id, val, cache))) {
1598 vm_setivar_slowpath_ivar(obj,
id, val, iseq, ic);
1605 vm_setinstancevariable(iseq, obj,
id, val, ic);
1611 return vm_getinstancevariable(iseq, obj,
id, ic);
1620 ec->tag->state = RUBY_TAG_FATAL;
1623 ec->tag->state = TAG_THROW;
1625 else if (THROW_DATA_P(err)) {
1626 ec->tag->state = THROW_DATA_STATE((
struct vm_throw_data *)err);
1629 ec->tag->state = TAG_RAISE;
1636 const int flag,
const VALUE throwobj)
1644 else if (state == TAG_BREAK) {
1646 const VALUE *ep = GET_EP();
1647 const rb_iseq_t *base_iseq = GET_ISEQ();
1648 escape_cfp = reg_cfp;
1650 while (ISEQ_BODY(base_iseq)->
type != ISEQ_TYPE_BLOCK) {
1651 if (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1652 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1653 ep = escape_cfp->ep;
1654 base_iseq = CFP_ISEQ(escape_cfp);
1657 ep = VM_ENV_PREV_EP(ep);
1658 base_iseq = ISEQ_BODY(base_iseq)->parent_iseq;
1659 escape_cfp = rb_vm_search_cf_from_ep(ec, escape_cfp, ep);
1660 VM_ASSERT(CFP_ISEQ(escape_cfp) == base_iseq);
1664 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1670 ep = VM_ENV_PREV_EP(ep);
1672 while (escape_cfp < eocfp) {
1673 if (escape_cfp->ep == ep) {
1674 const rb_iseq_t *
const iseq = CFP_ISEQ(escape_cfp);
1675 const VALUE epc = CFP_PC(escape_cfp) - ISEQ_BODY(iseq)->iseq_encoded;
1680 for (i=0; i < ct->size; i++) {
1682 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1684 if (entry->type == CATCH_TYPE_BREAK &&
1685 entry->iseq == base_iseq &&
1686 entry->start < epc && entry->end >= epc) {
1687 if (entry->cont == epc) {
1696 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1701 rb_vm_localjump_error(
"break from proc-closure", throwobj, TAG_BREAK);
1704 else if (state == TAG_RETRY) {
1705 const VALUE *ep = VM_ENV_PREV_EP(GET_EP());
1707 escape_cfp = rb_vm_search_cf_from_ep(ec, reg_cfp, ep);
1709 else if (state == TAG_RETURN) {
1710 const VALUE *current_ep = GET_EP();
1711 const VALUE *target_ep = NULL, *target_lep, *ep = current_ep;
1712 int in_class_frame = 0;
1714 escape_cfp = reg_cfp;
1717 while (!VM_ENV_LOCAL_P(ep)) {
1718 if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) {
1721 ep = VM_ENV_PREV_EP(ep);
1725 while (escape_cfp < eocfp) {
1726 const VALUE *lep = VM_CF_LEP(escape_cfp);
1732 if (lep == target_lep &&
1733 VM_FRAME_RUBYFRAME_P(escape_cfp) &&
1734 ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1739 if (lep == target_lep) {
1740 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1742 if (in_class_frame) {
1747 const VALUE *tep = current_ep;
1749 while (target_lep != tep) {
1750 if (escape_cfp->ep == tep) {
1752 if (tep == target_ep) {
1756 goto unexpected_return;
1759 tep = VM_ENV_PREV_EP(tep);
1763 else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
1764 switch (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type) {
1766 case ISEQ_TYPE_MAIN:
1768 if (in_class_frame)
goto unexpected_return;
1769 if (target_ep == NULL) {
1773 goto unexpected_return;
1777 case ISEQ_TYPE_EVAL: {
1778 const rb_iseq_t *is = CFP_ISEQ(escape_cfp);
1779 enum rb_iseq_type t = ISEQ_BODY(is)->type;
1780 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE || t == ISEQ_TYPE_EVAL) {
1781 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
1782 t = ISEQ_BODY(is)->type;
1784 toplevel = t == ISEQ_TYPE_TOP || t == ISEQ_TYPE_MAIN;
1787 case ISEQ_TYPE_CLASS:
1796 if (escape_cfp->ep == target_lep && ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_METHOD) {
1797 if (target_ep == NULL) {
1801 goto unexpected_return;
1805 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1808 rb_vm_localjump_error(
"unexpected return", throwobj, TAG_RETURN);
1814 rb_bug(
"isns(throw): unsupported throw type");
1817 ec->tag->state = state;
1818 return (
VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state);
1823 rb_num_t throw_state,
VALUE throwobj)
1825 const int state = (int)(throw_state & VM_THROW_STATE_MASK);
1826 const int flag = (int)(throw_state & VM_THROW_NO_ESCAPE_FLAG);
1829 return vm_throw_start(ec, reg_cfp, state, flag, throwobj);
1832 return vm_throw_continue(ec, throwobj);
1839 return vm_throw(ec, reg_cfp, throw_state, throwobj);
1845 int is_splat = flag & 0x01;
1848 const VALUE obj = ary;
1860 if (num + is_splat == 0) {
1863 else if (flag & 0x02) {
1868 for (i = 0; i < num -
len; i++) {
1873 for (j = 0; i < num; i++, j++) {
1895 for (; i < num -
len; i++) {
1899 for (rb_num_t j = 0; i < num; i++, j++) {
1900 *cfp->sp++ = ptr[
len - j - 1];
1904 for (rb_num_t j = 0; j < num; j++) {
1905 *cfp->sp++ = ptr[num - j - 1];
1920 int initial_capa = 2;
1922#if VM_CHECK_MODE > 0
1923 ccs->debug_sig = ~(
VALUE)ccs;
1925 ccs->capa = initial_capa;
1930 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
1938 if (! vm_cc_markable(cc)) {
1942 if (UNLIKELY(ccs->len == ccs->capa)) {
1945 ccs = ruby_xrealloc(ccs, vm_ccs_alloc_size(ccs->capa));
1946#if VM_CHECK_MODE > 0
1947 ccs->debug_sig = ~(
VALUE)ccs;
1950 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
1952 VM_ASSERT(ccs->len < ccs->capa);
1954 const int pos = ccs->len++;
1955 ccs->entries[pos].argc = vm_ci_argc(ci);
1956 ccs->entries[pos].flag = vm_ci_flag(ci);
1959 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
1965#if VM_CHECK_MODE > 0
1969 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
1970 for (
int i=0; i<ccs->len; i++) {
1971 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u\n",
1972 ccs->entries[i].flag,
1973 ccs->entries[i].argc);
1974 rp(ccs->entries[i].cc);
1981 VM_ASSERT(vm_ccs_p(ccs));
1982 VM_ASSERT(ccs->len <= ccs->capa);
1984 for (
int i=0; i<ccs->len; i++) {
1987 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
1988 VM_ASSERT(vm_cc_class_check(cc, klass));
1989 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
1990 VM_ASSERT(!vm_cc_super_p(cc));
1991 VM_ASSERT(!vm_cc_refinement_p(cc));
2002 ASSERT_vm_locking();
2004 if (rb_multi_ractor_p()) {
2005 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2012 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2015 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2020 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2021 rb_vm_cc_table_delete(new_table, mid);
2022 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2025 rb_vm_cc_table_delete(cc_tbl, mid);
2032 ASSERT_vm_locking();
2034 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2038 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2042 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2043 return &vm_empty_cc;
2046 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2047 const VALUE original_cc_table = cc_tbl;
2050 cc_tbl = rb_vm_cc_table_create(1);
2052 else if (rb_multi_ractor_p()) {
2053 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2056 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2065 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2070 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2074 cme = rb_check_overloaded_cme(cme, ci);
2076 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2077 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2079 VM_ASSERT(vm_cc_cme(cc) != NULL);
2080 VM_ASSERT(cme->called_id == mid);
2081 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2083 if (original_cc_table != cc_tbl) {
2084 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2096 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2104 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2106 const int ccs_len = ccs->len;
2108 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2110 vm_evict_cc(klass, cc_tbl, mid);
2115 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2120 unsigned int argc = vm_ci_argc(ci);
2121 unsigned int flag = vm_ci_flag(ci);
2123 for (
int i=0; i<ccs_len; i++) {
2124 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2125 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2126 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2128 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2130 if (ccs_ci_argc == argc && ccs_ci_flag == flag) {
2131 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2133 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2134 VM_ASSERT(ccs_cc->klass == klass);
2135 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2151 const ID mid = vm_ci_mid(ci);
2153 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2159 if (rb_multi_ractor_p()) {
2162 cc = vm_lookup_cc(klass, ci, mid);
2166 cc = vm_populate_cc(klass, ci, mid);
2180 cc = vm_search_cc(klass, ci);
2183 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2184 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2185 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2186 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2187 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2195#if USE_DEBUG_COUNTER
2199 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2201#if OPT_INLINE_METHOD_CACHE
2205 if (cd_owner && cc != empty_cc) {
2209#if USE_DEBUG_COUNTER
2210 if (!old_cc || old_cc == empty_cc) {
2212 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2214 else if (old_cc == cc) {
2215 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2217 else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) {
2218 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2220 else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) &&
2221 vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) {
2222 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2225 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2230 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2231 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2244#if OPT_INLINE_METHOD_CACHE
2245 if (LIKELY(vm_cc_class_check(cc, klass))) {
2246 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2247 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2248 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2249 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2250 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2251 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2255 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2258 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2262 return vm_search_method_slowpath0((
VALUE)CFP_ISEQ(reg_cfp), cd, klass);
2269 VM_ASSERT(klass !=
Qfalse);
2272 const struct rb_callcache *cc = vm_search_method_fastpath(reg_cfp, cd, klass);
2273 return vm_cc_cme(cc);
2282 const struct rb_callcache *cc = vm_search_method_slowpath0(cd_owner, cd, klass);
2283 return vm_cc_cme(cc);
2286#if __has_attribute(transparent_union)
2299 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2300 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2301 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2302 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2303 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2304 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2307# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2310# define make_cfunc_type(f) (cfunc_type)(f)
2320 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2321 VM_ASSERT(callable_method_entry_p(me));
2323 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2327#if __has_attribute(transparent_union)
2328 return me->def->body.cfunc.func == func.anyargs;
2330 return me->def->body.cfunc.func == func;
2339 return me && METHOD_ENTRY_BASIC(me);
2345 VM_ASSERT(reg_cfp != NULL);
2347 return check_cfunc(cme, func);
2353 return check_cfunc(me, func);
2362 const struct rb_callcache *cc = vm_search_method_slowpath0((
VALUE)iseq, cd, klass);
2364 return check_cfunc(cme, func);
2367#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2368#define vm_method_cfunc_is(reg_cfp, cd, recv, func) vm_method_cfunc_is(reg_cfp, cd, recv, make_cfunc_type(func))
2370#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
2402opt_equality_specialized(
VALUE recv,
VALUE obj)
2404 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2405 goto compare_by_identity;
2407 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2408 goto compare_by_identity;
2411 goto compare_by_identity;
2420 return RBOOL(a == b);
2427 return rb_str_eql_internal(obj, recv);
2432 compare_by_identity:
2433 return RBOOL(recv == obj);
2439 VM_ASSERT(reg_cfp != NULL);
2441 VALUE val = opt_equality_specialized(recv, obj);
2442 if (!UNDEF_P(val))
return val;
2444 if (!vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_equal)) {
2448 return RBOOL(recv == obj);
2452#undef EQ_UNREDEFINED_P
2455NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2458opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2460 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2462 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2463 return RBOOL(recv == obj);
2473 VALUE val = opt_equality_specialized(recv, obj);
2474 if (!UNDEF_P(val)) {
2478 return opt_equality_by_mid_slowpath(recv, obj, mid);
2485 return opt_equality_by_mid(obj1, obj2, idEq);
2491 return opt_equality_by_mid(obj1, obj2, idEqlP);
2501 case VM_CHECKMATCH_TYPE_WHEN:
2503 case VM_CHECKMATCH_TYPE_RESCUE:
2505 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2508 case VM_CHECKMATCH_TYPE_CASE: {
2509 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2512 rb_bug(
"check_match: unreachable");
2518double_cmp_lt(
double a,
double b)
2520 return RBOOL(a < b);
2524double_cmp_le(
double a,
double b)
2526 return RBOOL(a <= b);
2530double_cmp_gt(
double a,
double b)
2532 return RBOOL(a > b);
2536double_cmp_ge(
double a,
double b)
2538 return RBOOL(a >= b);
2542static inline VALUE *
2547 if (CFP_ISEQ(cfp) && VM_FRAME_RUBYFRAME_P(cfp)) {
2548 VALUE *bp = prev_cfp->sp + ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size + VM_ENV_DATA_SIZE;
2550 if (ISEQ_BODY(CFP_ISEQ(cfp))->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2551 int lts = ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size;
2552 int params = ISEQ_BODY(CFP_ISEQ(cfp))->param.size;
2555 bp += vm_ci_argc(ci);
2558 if (ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2562#if VM_DEBUG_BP_CHECK
2563 if (bp != cfp->bp_check) {
2564 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2565 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2566 (
long)(bp - GET_EC()->vm_stack));
2567 rb_bug(
"vm_base_ptr: unreachable");
2580 return vm_base_ptr(cfp);
2595static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2600 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2602 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2608 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2611 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2612 int param = ISEQ_BODY(iseq)->param.size;
2613 int local = ISEQ_BODY(iseq)->local_table_size;
2614 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2620 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2621 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2622 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2623 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2624 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2625 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2626 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2627 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2628 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2632rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2634 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2635 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2636 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2637 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2638 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2639 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2640 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2641 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2642 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2646rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2648 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2649 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2650 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2651 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2652 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2653 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2654 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2655 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2658#define ALLOW_HEAP_ARGV (-2)
2659#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2664 vm_check_canary(GET_EC(), cfp->sp);
2670 int argc = calling->argc;
2672 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2676 VALUE *argv = cfp->sp - argc;
2680 cfp->sp -= argc - 1;
2681 cfp->sp[-1] = argv_ary;
2683 calling->heap_argv = argv_ary;
2689 if (max_args >= 0 &&
len + argc > max_args) {
2697 calling->argc +=
len - (max_args - argc + 1);
2698 len = max_args - argc + 1;
2707 calling->heap_argv = 0;
2709 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2711 for (i = 0; i <
len; i++) {
2712 *cfp->sp++ = ptr[i];
2724 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2725 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2726 const VALUE h = rb_hash_new_with_size(kw_len);
2727 VALUE *sp = cfp->sp;
2730 for (i=0; i<kw_len; i++) {
2731 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2735 cfp->sp -= kw_len - 1;
2736 calling->argc -= kw_len - 1;
2737 calling->kw_splat = 1;
2741vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2744 if (keyword_hash !=
Qnil) {
2746 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2749 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2755 keyword_hash = rb_hash_dup(keyword_hash);
2757 return keyword_hash;
2763 const struct rb_callinfo *restrict ci,
int max_args)
2765 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2766 if (IS_ARGS_KW_SPLAT(ci)) {
2768 VM_ASSERT(calling->kw_splat == 1);
2772 VALUE ary = cfp->sp[0];
2773 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2776 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2780 if (UNLIKELY(calling->heap_argv)) {
2782 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2783 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2784 calling->kw_splat = 0;
2792 VM_ASSERT(calling->kw_splat == 1);
2796 calling->kw_splat = 0;
2801 VM_ASSERT(calling->kw_splat == 0);
2805 VALUE ary = cfp->sp[0];
2807 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2812 VALUE last_hash, argv_ary;
2813 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2814 if (!IS_ARGS_KEYWORD(ci) &&
2817 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2822 calling->kw_splat = 1;
2828 if (!IS_ARGS_KEYWORD(ci) &&
2829 calling->argc > 0 &&
2831 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2838 cfp->sp[-1] = rb_hash_dup(last_hash);
2839 calling->kw_splat = 1;
2845 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2847 VM_ASSERT(calling->kw_splat == 1);
2848 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2853 calling->kw_splat = 0;
2859 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2861 VM_ASSERT(calling->kw_splat == 0);
2867 vm_caller_setup_arg_kw(cfp, calling, ci);
2871#define USE_OPT_HIST 0
2874#define OPT_HIST_MAX 64
2875static int opt_hist[OPT_HIST_MAX+1];
2879opt_hist_show_results_at_exit(
void)
2881 for (
int i=0; i<OPT_HIST_MAX; i++) {
2882 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
2892 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2893 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
2894 const int opt = calling->argc - lead_num;
2895 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
2896 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
2897 const int param = ISEQ_BODY(iseq)->param.size;
2898 const int local = ISEQ_BODY(iseq)->local_table_size;
2899 const int delta = opt_num - opt;
2901 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
2904 if (opt_pc < OPT_HIST_MAX) {
2908 opt_hist[OPT_HIST_MAX]++;
2912 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
2920 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2921 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
2922 const int opt = calling->argc - lead_num;
2923 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
2925 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
2928 if (opt_pc < OPT_HIST_MAX) {
2932 opt_hist[OPT_HIST_MAX]++;
2936 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
2941 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
2942 VALUE *
const locals);
2949 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2950 int param_size = ISEQ_BODY(iseq)->param.size;
2951 int local_size = ISEQ_BODY(iseq)->local_table_size;
2954 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
2956 local_size = local_size + vm_ci_argc(calling->cd->ci);
2957 param_size = param_size + vm_ci_argc(calling->cd->ci);
2959 cfp->sp[0] = (
VALUE)calling->cd->ci;
2961 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
2971 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
2972 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
2974 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2975 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
2977 const int ci_kw_len = kw_arg->keyword_len;
2978 const VALUE *
const ci_keywords = kw_arg->keywords;
2979 VALUE *argv = cfp->sp - calling->argc;
2980 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
2981 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
2983 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
2984 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
2986 int param = ISEQ_BODY(iseq)->param.size;
2987 int local = ISEQ_BODY(iseq)->local_table_size;
2988 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2995 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
2998 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
2999 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3001 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3002 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3003 VALUE *
const argv = cfp->sp - calling->argc;
3004 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3007 for (i=0; i<kw_param->num; i++) {
3008 klocals[i] = kw_param->default_values[i];
3015 int param = ISEQ_BODY(iseq)->param.size;
3016 int local = ISEQ_BODY(iseq)->local_table_size;
3017 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3027 cfp->sp -= (calling->argc + 1);
3028 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3029 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3038 set_table *dup_check_table = &vm->unused_block_warning_table;
3048 .v = (
VALUE)cme->def,
3052 if (!strict_unused_block) {
3053 key = (st_data_t)cme->def->original_id;
3055 if (set_table_lookup(dup_check_table, key)) {
3065 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3070 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3071 fprintf(stderr,
"key:%p\n", (
void *)key);
3075 if (set_insert(dup_check_table, key)) {
3080 VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label);
3082 if (!
NIL_P(m_loc)) {
3083 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3087 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3094 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3099 VM_ASSERT((vm_ci_argc(ci), 1));
3100 VM_ASSERT(vm_cc_cme(cc) != NULL);
3102 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3103 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3104 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3105 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)CFP_PC(ec->cfp));
3108 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3109 if (LIKELY(rb_simple_iseq_p(iseq))) {
3111 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3112 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3114 if (calling->argc != lead_num) {
3115 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3119 VM_ASSERT(cc == calling->cc);
3121 if (vm_call_iseq_optimizable_p(ci, cc)) {
3122 if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3123 VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF);
3124 vm_cc_bf_set(cc, (
void *)iseq->body->iseq_encoded[1]);
3125 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3128 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3133 else if (rb_iseq_only_optparam_p(iseq)) {
3136 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3137 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3139 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3140 const int argc = calling->argc;
3141 const int opt = argc - lead_num;
3143 if (opt < 0 || opt > opt_num) {
3144 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3147 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3148 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3149 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3150 vm_call_cacheable(ci, cc));
3153 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3154 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3155 vm_call_cacheable(ci, cc));
3159 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3160 for (
int i=argc; i<lead_num + opt_num; i++) {
3163 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3165 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3166 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3167 const int argc = calling->argc;
3168 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3170 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3173 if (argc - kw_arg->keyword_len == lead_num) {
3174 const int ci_kw_len = kw_arg->keyword_len;
3175 const VALUE *
const ci_keywords = kw_arg->keywords;
3177 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3179 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3180 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3182 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3183 vm_call_cacheable(ci, cc));
3188 else if (argc == lead_num) {
3190 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3191 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3193 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3195 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3196 vm_call_cacheable(ci, cc));
3222 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3223 bool can_fastpath =
true;
3225 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3227 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3228 ci = vm_ci_new_runtime(
3235 ci = forward_cd->caller_ci;
3237 can_fastpath =
false;
3241 if (!vm_ci_markable(ci)) {
3242 ci = vm_ci_new_runtime(
3247 can_fastpath =
false;
3249 argv[param_size - 1] = (
VALUE)ci;
3250 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3254 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3281 const VALUE * lep = VM_CF_LEP(cfp);
3287 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3292 iseq = CFP_ISEQ(rb_vm_search_cf_from_ep(ec, cfp, lep));
3296 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3298 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3299 VALUE * to = cfp->sp - 1;
3303 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3308 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3310 cfp->sp = to + argc;
3329 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3332 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3333 int param_size = ISEQ_BODY(iseq)->param.size;
3334 int local_size = ISEQ_BODY(iseq)->local_table_size;
3336 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3338 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3339 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3345 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3348 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3349 int param_size = ISEQ_BODY(iseq)->param.size;
3350 int local_size = ISEQ_BODY(iseq)->local_table_size;
3352 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3355 local_size = local_size + vm_ci_argc(calling->cd->ci);
3356 param_size = param_size + vm_ci_argc(calling->cd->ci);
3358 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3359 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3364 int opt_pc,
int param_size,
int local_size)
3369 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3370 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3373 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3379 int opt_pc,
int param_size,
int local_size)
3381 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3382 VALUE *argv = cfp->sp - calling->argc;
3383 VALUE *sp = argv + param_size;
3384 cfp->sp = argv - 1 ;
3386 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3387 calling->block_handler, (
VALUE)me,
3388 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3389 local_size - param_size,
3390 ISEQ_BODY(iseq)->stack_max);
3399 VALUE *argv = cfp->sp - calling->argc;
3401 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3402 VALUE *src_argv = argv;
3403 VALUE *sp_orig, *sp;
3404 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3406 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3407 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3408 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3409 dst_captured->code.val = src_captured->code.val;
3410 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3411 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3414 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3418 vm_pop_frame(ec, cfp, cfp->ep);
3421 sp_orig = sp = cfp->sp;
3424 sp[0] = calling->recv;
3428 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3429 *sp++ = src_argv[i];
3432 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3433 calling->recv, calling->block_handler, (
VALUE)me,
3434 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3435 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3436 ISEQ_BODY(iseq)->stack_max);
3444ractor_unsafe_check(
void)
3446 if (!rb_ractor_main_p()) {
3447 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3454 ractor_unsafe_check();
3462 ractor_unsafe_check();
3464 return (*f)(argc, argv, recv);
3470 ractor_unsafe_check();
3478 ractor_unsafe_check();
3480 return (*f)(recv, argv[0]);
3486 ractor_unsafe_check();
3488 return (*f)(recv, argv[0], argv[1]);
3494 ractor_unsafe_check();
3496 return (*f)(recv, argv[0], argv[1], argv[2]);
3502 ractor_unsafe_check();
3504 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3510 ractor_unsafe_check();
3511 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3512 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3518 ractor_unsafe_check();
3519 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3520 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3526 ractor_unsafe_check();
3527 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3528 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3534 ractor_unsafe_check();
3535 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3536 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3542 ractor_unsafe_check();
3543 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3544 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3550 ractor_unsafe_check();
3551 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;
3552 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3558 ractor_unsafe_check();
3559 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;
3560 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]);
3566 ractor_unsafe_check();
3567 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;
3568 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]);
3574 ractor_unsafe_check();
3575 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;
3576 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]);
3582 ractor_unsafe_check();
3583 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;
3584 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]);
3590 ractor_unsafe_check();
3591 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;
3592 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]);
3606 return (*f)(argc, argv, recv);
3620 return (*f)(recv, argv[0]);
3627 return (*f)(recv, argv[0], argv[1]);
3634 return (*f)(recv, argv[0], argv[1], argv[2]);
3641 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3647 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3648 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3654 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3655 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3661 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3662 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3668 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3669 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3675 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3676 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3682 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;
3683 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3689 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;
3690 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]);
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))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]);
3703 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;
3704 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]);
3710 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;
3711 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]);
3717 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;
3718 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]);
3724 const int ov_flags = RAISED_STACKOVERFLOW;
3725 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3726 if (rb_ec_raised_p(ec, ov_flags)) {
3727 rb_ec_raised_reset(ec, ov_flags);
3733#define CHECK_CFP_CONSISTENCY(func) \
3734 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3735 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3741#if VM_DEBUG_VERIFY_METHOD_CACHE
3742 switch (me->def->type) {
3743 case VM_METHOD_TYPE_CFUNC:
3744 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3746# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3748 METHOD_BUG(ATTRSET);
3750 METHOD_BUG(BMETHOD);
3753 METHOD_BUG(OPTIMIZED);
3754 METHOD_BUG(MISSING);
3755 METHOD_BUG(REFINED);
3759 rb_bug(
"wrong method type: %d", me->def->type);
3762 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3769 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3776 VALUE recv = calling->recv;
3777 VALUE block_handler = calling->block_handler;
3778 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3780 if (UNLIKELY(calling->kw_splat)) {
3781 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3784 VM_ASSERT(reg_cfp == ec->cfp);
3786 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3789 vm_push_frame(ec, NULL, frame_type, recv,
3790 block_handler, (
VALUE)me,
3791 0, ec->cfp->sp, 0, 0);
3793 int len = cfunc->argc;
3796 reg_cfp->sp = stack_bottom;
3797 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3799 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3801 rb_vm_pop_frame(ec);
3803 VM_ASSERT(ec->cfp->sp == stack_bottom);
3805 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3806 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3816 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3818 VALUE *sp = ec->cfp->sp;
3819 VALUE recv = *(sp - recv_idx - 1);
3820 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3821 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3822#if VM_CHECK_MODE > 0
3824 *(GET_EC()->cfp->sp) =
Qfalse;
3826 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3831rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3833 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3839 int argc = calling->argc;
3840 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3841 VALUE *argv = &stack_bottom[1];
3843 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3850 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3852 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3854 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3855 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3858 VALUE *stack_bottom = reg_cfp->sp - 2;
3860 VM_ASSERT(calling->argc == 1);
3864 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3867 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));
3869 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3876 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3879 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3880 return vm_call_cfunc_other(ec, reg_cfp, calling);
3884 calling->kw_splat = 0;
3886 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
3887 VALUE *sp = stack_bottom;
3888 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
3889 for(i = 0; i < argc; i++) {
3894 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
3900 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
3901 VALUE argv_ary = reg_cfp->sp[-1];
3905 int argc_offset = 0;
3907 if (UNLIKELY(argc > 0 &&
3909 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
3911 return vm_call_cfunc_other(ec, reg_cfp, calling);
3915 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
3921 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
3922 VALUE keyword_hash = reg_cfp->sp[-1];
3925 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
3928 return vm_call_cfunc_other(ec, reg_cfp, calling);
3935 RB_DEBUG_COUNTER_INC(ccf_cfunc);
3937 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3938 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
3940 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
3941 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
3943 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
3945 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
3946 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
3950 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
3951 return vm_call_cfunc_other(ec, reg_cfp, calling);
3958 RB_DEBUG_COUNTER_INC(ccf_ivar);
3960 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
3967 RB_DEBUG_COUNTER_INC(ccf_attrset);
3968 VALUE val = *(cfp->sp - 1);
3970 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_cc_atomic_cache_read(cc));
3971 ID id = vm_cc_cme(cc)->def->body.attr.id;
3972 rb_check_frozen(obj);
3973 VALUE res = vm_setivar(obj, val, cache);
3981 res = vm_setivar_class(obj, val, cache);
3982 if (!UNDEF_P(res)) {
3989 res = vm_setivar_default(obj,
id, val, cache);
3990 if (!UNDEF_P(res)) {
3995 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4003 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4013 VALUE procv = cme->def->body.bmethod.proc;
4016 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4017 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4021 GetProcPtr(procv, proc);
4022 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4032 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4036 VALUE procv = cme->def->body.bmethod.proc;
4039 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4040 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4044 GetProcPtr(procv, proc);
4045 const struct rb_block *block = &proc->block;
4047 while (vm_block_type(block) == block_type_proc) {
4048 block = vm_proc_block(block->as.proc);
4050 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4053 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4054 VALUE *
const argv = cfp->sp - calling->argc;
4055 const int arg_size = ISEQ_BODY(iseq)->param.size;
4058 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4059 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4062 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4067 vm_push_frame(ec, iseq,
4068 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4070 VM_GUARDED_PREV_EP(captured->ep),
4072 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4074 ISEQ_BODY(iseq)->local_table_size - arg_size,
4075 ISEQ_BODY(iseq)->stack_max);
4083 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4087 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4088 if (UNLIKELY(calling->heap_argv)) {
4093 argc = calling->argc;
4096 cfp->sp += - argc - 1;
4099 return vm_call_bmethod_body(ec, calling, argv);
4105 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4109 VALUE procv = cme->def->body.bmethod.proc;
4111 GetProcPtr(procv, proc);
4112 const struct rb_block *block = &proc->block;
4114 while (vm_block_type(block) == block_type_proc) {
4115 block = vm_proc_block(block->as.proc);
4117 if (vm_block_type(block) == block_type_iseq) {
4118 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4119 return vm_call_iseq_bmethod(ec, cfp, calling);
4122 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4123 return vm_call_noniseq_bmethod(ec, cfp, calling);
4127rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4129 VALUE klass = current_class;
4137 while (
RTEST(klass)) {
4139 if (owner == target_owner) {
4145 return current_class;
4154 if (orig_me->defined_class == 0) {
4155 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4156 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4157 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4159 if (me->def->reference_count == 1) {
4160 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4164 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4172 VM_ASSERT(callable_method_entry_p(cme));
4179 return aliased_callable_method_entry(me);
4185 calling->cc = &VM_CC_ON_STACK(
Qundef,
4188 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4190 return vm_call_method_each_type(ec, cfp, calling);
4193static enum method_missing_reason
4196 enum method_missing_reason stat = MISSING_NOENTRY;
4197 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4198 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4199 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4209 ASSUME(calling->argc >= 0);
4211 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4212 int argc = calling->argc;
4213 VALUE recv = calling->recv;
4216 flags |= VM_CALL_OPT_SEND;
4218 if (UNLIKELY(! mid)) {
4219 mid = idMethodMissing;
4220 missing_reason = ci_missing_reason(ci);
4221 ec->method_missing_reason = missing_reason;
4224 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4225 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4226 rb_ary_unshift(argv_ary, symbol);
4229 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4230 VALUE exc = rb_make_no_method_exception(
4252 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4255 argc = ++calling->argc;
4257 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4260 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4261 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4262 VALUE exc = rb_make_no_method_exception(
4275 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4281 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4282 calling->cd = &new_fcd.cd;
4286 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4287 new_fcd.caller_ci = caller_ci;
4290 calling->cc = &VM_CC_ON_STACK(klass,
4292 { .method_missing_reason = missing_reason },
4293 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4295 if (flags & VM_CALL_FCALL) {
4296 return vm_call_method(ec, reg_cfp, calling);
4300 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4302 if (vm_cc_cme(cc) != NULL) {
4303 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4304 case METHOD_VISI_PUBLIC:
4305 return vm_call_method_each_type(ec, reg_cfp, calling);
4306 case METHOD_VISI_PRIVATE:
4307 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4309 case METHOD_VISI_PROTECTED:
4310 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4313 VM_UNREACHABLE(vm_call_method);
4315 return vm_call_method_missing(ec, reg_cfp, calling);
4318 return vm_call_method_nome(ec, reg_cfp, calling);
4328 i = calling->argc - 1;
4330 if (calling->argc == 0) {
4331 rb_raise(rb_eArgError,
"no method name given");
4355 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4361 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4363 int flags = VM_CALL_FCALL;
4367 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4368 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4370 flags |= VM_CALL_ARGS_SPLAT;
4371 if (calling->kw_splat) {
4372 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4373 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4374 calling->kw_splat = 0;
4376 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4379 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4380 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4386 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4387 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4393 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4396 int flags = vm_ci_flag(ci);
4398 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4399 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4400 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4401 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4402 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4403 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4406 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4407 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4412 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4414 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4416 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4417 unsigned int argc, flag;
4419 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4420 argc = ++calling->argc;
4423 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4424 vm_check_canary(ec, reg_cfp->sp);
4428 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4431 ec->method_missing_reason = reason;
4435 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4441 if (!(flag & VM_CALL_FORWARDING)) {
4442 calling->cd = &new_fcd.cd;
4446 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4447 new_fcd.caller_ci = caller_ci;
4451 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4452 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4453 return vm_call_method(ec, reg_cfp, calling);
4459 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4470 return vm_call_method_nome(ec, cfp, calling);
4472 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4473 cme->def->body.refined.orig_me) {
4474 cme = refined_method_callable_without_refinement(cme);
4477 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4479 return vm_call_method_each_type(ec, cfp, calling);
4483find_refinement(
VALUE refinements,
VALUE klass)
4485 if (
NIL_P(refinements)) {
4488 return rb_hash_lookup(refinements, klass);
4497 if (CFP_ISEQ(cfp) && ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_BLOCK) {
4498 const rb_iseq_t *local_iseq = ISEQ_BODY(CFP_ISEQ(cfp))->local_iseq;
4501 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4502 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4506 }
while (CFP_ISEQ(cfp) != local_iseq);
4517 if (orig_me->defined_class == 0) {
4525 VM_ASSERT(callable_method_entry_p(cme));
4527 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4537 ID mid = vm_ci_mid(calling->cd->ci);
4538 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4542 for (; cref; cref = CREF_NEXT(cref)) {
4543 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4544 if (
NIL_P(refinement))
continue;
4547 rb_callable_method_entry(refinement, mid);
4550 if (vm_cc_call(cc) == vm_call_super_method) {
4553 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4558 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4559 cme->def != ref_me->def) {
4562 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4571 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4572 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4587 if (calling->cd->cc) {
4588 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);
4590 return vm_call_method(ec, cfp, calling);
4593 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4594 calling->cc= ref_cc;
4595 return vm_call_method(ec, cfp, calling);
4599 return vm_call_method_nome(ec, cfp, calling);
4605NOINLINE(
static VALUE
4613 int argc = calling->argc;
4616 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4619 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4625 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4628 VALUE procval = calling->recv;
4629 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4635 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4637 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4640 if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
4641 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4644 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4645 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4646 return vm_call_general(ec, reg_cfp, calling);
4653 VALUE recv = calling->recv;
4656 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4657 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4659 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4660 return RSTRUCT_GET_RAW(recv,
off);
4666 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4668 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4676 VALUE recv = calling->recv;
4679 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4680 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4682 rb_check_frozen(recv);
4684 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4685 RSTRUCT_SET_RAW(recv,
off, val);
4693 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4695 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4703#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4704 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4705 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4706 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4708 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4709 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4720 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4721 case OPTIMIZED_METHOD_TYPE_SEND:
4722 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4723 return vm_call_opt_send(ec, cfp, calling);
4724 case OPTIMIZED_METHOD_TYPE_CALL:
4725 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4726 return vm_call_opt_call(ec, cfp, calling);
4727 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4728 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4729 return vm_call_opt_block_call(ec, cfp, calling);
4730 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4731 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4735 VM_CALL_METHOD_ATTR(v,
4736 vm_call_opt_struct_aref(ec, cfp, calling),
4737 set_vm_cc_ivar(cc); \
4738 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4741 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4742 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4746 VM_CALL_METHOD_ATTR(v,
4747 vm_call_opt_struct_aset(ec, cfp, calling),
4748 set_vm_cc_ivar(cc); \
4749 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4753 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4765 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4767 switch (cme->def->type) {
4768 case VM_METHOD_TYPE_ISEQ:
4769 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4770 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4771 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4774 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4775 return vm_call_iseq_setup(ec, cfp, calling);
4778 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4779 case VM_METHOD_TYPE_CFUNC:
4780 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4781 return vm_call_cfunc(ec, cfp, calling);
4783 case VM_METHOD_TYPE_ATTRSET:
4784 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4788 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4790 if (vm_cc_markable(cc)) {
4791 vm_cc_attr_index_set(cc, IVAR_CACHE_INIT);
4792 VM_CALL_METHOD_ATTR(v,
4793 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4794 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4800 VM_CALLCACHE_UNMARKABLE |
4801 VM_CALLCACHE_ON_STACK,
4807 .value = IVAR_CACHE_INIT,
4812 VM_CALL_METHOD_ATTR(v,
4813 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4814 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4818 case VM_METHOD_TYPE_IVAR:
4819 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4821 vm_cc_attr_index_set(cc, rb_getivar_cache_pack(ROOT_SHAPE_ID, ATTR_INDEX_NOT_SET));
4822 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4823 VM_CALL_METHOD_ATTR(v,
4824 vm_call_ivar(ec, cfp, calling),
4825 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4828 case VM_METHOD_TYPE_MISSING:
4829 vm_cc_method_missing_reason_set(cc, 0);
4830 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4831 return vm_call_method_missing(ec, cfp, calling);
4833 case VM_METHOD_TYPE_BMETHOD:
4834 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4835 return vm_call_bmethod(ec, cfp, calling);
4837 case VM_METHOD_TYPE_ALIAS:
4838 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4839 return vm_call_alias(ec, cfp, calling);
4841 case VM_METHOD_TYPE_OPTIMIZED:
4842 return vm_call_optimized(ec, cfp, calling, ci, cc);
4844 case VM_METHOD_TYPE_UNDEF:
4847 case VM_METHOD_TYPE_ZSUPER:
4848 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4850 case VM_METHOD_TYPE_REFINED:
4853 return vm_call_refined(ec, cfp, calling);
4856 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4866 const int stat = ci_missing_reason(ci);
4868 if (vm_ci_mid(ci) == idMethodMissing) {
4869 if (UNLIKELY(calling->heap_argv)) {
4874 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4875 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4879 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
4891 VALUE defined_class = me->defined_class;
4892 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
4893 return NIL_P(refined_class) ? defined_class : refined_class;
4902 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4904 if (vm_cc_cme(cc) != NULL) {
4905 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4906 case METHOD_VISI_PUBLIC:
4907 return vm_call_method_each_type(ec, cfp, calling);
4909 case METHOD_VISI_PRIVATE:
4910 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
4911 enum method_missing_reason stat = MISSING_PRIVATE;
4912 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
4914 vm_cc_method_missing_reason_set(cc, stat);
4915 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4916 return vm_call_method_missing(ec, cfp, calling);
4918 return vm_call_method_each_type(ec, cfp, calling);
4920 case METHOD_VISI_PROTECTED:
4921 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
4922 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
4924 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4925 return vm_call_method_missing(ec, cfp, calling);
4929 VM_ASSERT(vm_cc_cme(cc) != NULL);
4932 calling->cc = &cc_on_stack;
4933 return vm_call_method_each_type(ec, cfp, calling);
4936 return vm_call_method_each_type(ec, cfp, calling);
4939 rb_bug(
"unreachable");
4943 return vm_call_method_nome(ec, cfp, calling);
4950 RB_DEBUG_COUNTER_INC(ccf_general);
4951 return vm_call_method(ec, reg_cfp, calling);
4957 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
4958 VM_ASSERT(cc != vm_cc_empty());
4960 *(vm_call_handler *)&cc->call_ = vm_call_general;
4966 RB_DEBUG_COUNTER_INC(ccf_super_method);
4971 if (ec == NULL) rb_bug(
"unreachable");
4974 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
4975 return vm_call_method(ec, reg_cfp, calling);
4981vm_search_normal_superclass(
VALUE klass)
4983 if (RICLASS_FOR_REFINEMENT_P(klass)) {
4984 klass =
RBASIC(klass)->klass;
4986 klass = RCLASS_ORIGIN(klass);
4990NORETURN(
static void vm_super_outside(
void));
4993vm_super_outside(
void)
4999empty_cc_for_super(
void)
5001 return &vm_empty_cc_for_super;
5007 VALUE current_defined_class;
5008 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
5015 current_defined_class = vm_defined_class_for_protected_call(me);
5018 iseq != method_entry_iseqptr(me) &&
5021 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5025 "self has wrong type to call super in this context: "
5026 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5031 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5033 "implicit argument passing of super from method defined"
5034 " by define_method() is not supported."
5035 " Specify all arguments explicitly.");
5038 ID mid = me->def->original_id;
5040 if (!vm_ci_markable(cd->ci)) {
5041 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5045 cd->ci = vm_ci_new_runtime(mid,
5048 vm_ci_kwarg(cd->ci));
5055 VALUE klass = vm_search_normal_superclass(me->defined_class);
5059 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5064 RCLASS_INCLUDER(me->defined_class) == 0) {
5066 "super in a method in a module that has been refined and that is called via super"
5067 " from a refinement method is not supported.");
5070 cc = vm_search_method_fastpath(reg_cfp, cd, klass);
5074 if (cached_cme == NULL) {
5076 cd->cc = empty_cc_for_super();
5078 else if (cached_cme->called_id != mid) {
5081 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5085 cd->cc = cc = empty_cc_for_super();
5089 switch (cached_cme->def->type) {
5091 case VM_METHOD_TYPE_REFINED:
5093 case VM_METHOD_TYPE_ATTRSET:
5094 case VM_METHOD_TYPE_IVAR:
5095 vm_cc_call_set(cc, vm_call_super_method);
5103 VM_ASSERT((vm_cc_cme(cc),
true));
5111block_proc_is_lambda(
const VALUE procval)
5116 GetProcPtr(procval, proc);
5117 return proc->is_lambda;
5127 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5130 int is_lambda = FALSE;
5131 VALUE val, arg, blockarg;
5133 const struct vm_ifunc *ifunc = captured->code.ifunc;
5138 else if (argc == 0) {
5145 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5147 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5149 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5152 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5155 VM_GUARDED_PREV_EP(captured->ep),
5157 0, ec->cfp->sp, 0, 0);
5158 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5159 rb_vm_pop_frame(ec);
5167 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5173 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
5182 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5184 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5192vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5194 VALUE ary, arg0 = argv[0];
5199 VM_ASSERT(argv[0] == arg0);
5207 if (rb_simple_iseq_p(iseq)) {
5211 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5213 if (arg_setup_type == arg_setup_block &&
5214 calling->argc == 1 &&
5215 ISEQ_BODY(iseq)->param.flags.has_lead &&
5216 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5217 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5218 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5221 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5222 if (arg_setup_type == arg_setup_block) {
5223 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5225 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5226 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5227 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5229 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5230 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5234 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5241 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5250 calling = &calling_entry;
5251 calling->argc = argc;
5252 calling->block_handler = block_handler;
5253 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5255 calling->heap_argv = 0;
5257 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5259 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5267 bool is_lambda,
VALUE block_handler)
5270 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5271 const int arg_size = ISEQ_BODY(iseq)->param.size;
5272 VALUE *
const rsp = GET_SP() - calling->argc;
5273 VALUE *
const argv = rsp;
5274 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5275 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5279 vm_push_frame(ec, iseq,
5282 VM_GUARDED_PREV_EP(captured->ep), 0,
5283 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5285 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5293 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5295 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5296 int flags = vm_ci_flag(ci);
5298 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5299 ((calling->argc == 0) ||
5300 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5301 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5302 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5303 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5305 if (UNLIKELY(calling->heap_argv)) {
5306#if VM_ARGC_STACK_MAX < 0
5308 rb_raise(rb_eArgError,
"no receiver given");
5314 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5315 reg_cfp->sp[-2] = calling->recv;
5316 flags |= VM_CALL_ARGS_SPLAT;
5319 if (calling->argc < 1) {
5320 rb_raise(rb_eArgError,
"no receiver given");
5322 calling->recv = TOPN(--calling->argc);
5324 if (calling->kw_splat) {
5325 flags |= VM_CALL_KW_SPLAT;
5329 if (calling->argc < 1) {
5330 rb_raise(rb_eArgError,
"no receiver given");
5332 calling->recv = TOPN(--calling->argc);
5335 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5341 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5346 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5347 argc = calling->argc;
5348 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);
5354vm_proc_to_block_handler(
VALUE procval)
5356 const struct rb_block *block = vm_proc_block(procval);
5358 switch (vm_block_type(block)) {
5359 case block_type_iseq:
5360 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5361 case block_type_ifunc:
5362 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5363 case block_type_symbol:
5364 return VM_BH_FROM_SYMBOL(block->as.symbol);
5365 case block_type_proc:
5366 return VM_BH_FROM_PROC(block->as.proc);
5368 VM_UNREACHABLE(vm_yield_with_proc);
5375 bool is_lambda,
VALUE block_handler)
5377 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5378 VALUE proc = VM_BH_TO_PROC(block_handler);
5379 is_lambda = block_proc_is_lambda(proc);
5380 block_handler = vm_proc_to_block_handler(proc);
5383 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5389 bool is_lambda,
VALUE block_handler)
5393 bool is_lambda,
VALUE block_handler);
5395 switch (vm_block_handler_type(block_handler)) {
5396 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5397 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5398 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5399 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5400 default: rb_bug(
"vm_invoke_block: unreachable");
5403 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5407vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5414 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5417 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5418 captured->code.iseq = blockiseq;
5420 return rb_vm_make_proc(ec, captured,
rb_cProc);
5424vm_once_exec(
VALUE iseq)
5431vm_once_clear(
VALUE data)
5434 is->once.running_thread = NULL;
5446 args[0] = obj; args[1] =
Qfalse;
5448 if (!UNDEF_P(r) &&
RTEST(r)) {
5460 enum defined_type
type = (
enum defined_type)op_type;
5467 return rb_gvar_defined(
SYM2ID(obj));
5469 case DEFINED_CVAR: {
5470 const rb_cref_t *cref = vm_get_cref(GET_EP());
5471 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5476 case DEFINED_CONST_FROM: {
5477 bool allow_nil =
type == DEFINED_CONST;
5479 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5484 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5486 case DEFINED_METHOD:{
5491 switch (METHOD_ENTRY_VISI(cme)) {
5492 case METHOD_VISI_PRIVATE:
5494 case METHOD_VISI_PROTECTED:
5498 case METHOD_VISI_PUBLIC:
5502 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(cme));
5506 return check_respond_to_missing(obj, v);
5511 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5515 case DEFINED_ZSUPER:
5520 VALUE klass = vm_search_normal_superclass(me->defined_class);
5521 if (!klass)
return false;
5523 ID id = me->def->original_id;
5530 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5532 rb_bug(
"unimplemented defined? type (VM)");
5542 return vm_defined(ec, reg_cfp, op_type, obj, v);
5546vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5549 const VALUE *ep = reg_ep;
5550 for (i = 0; i < lv; i++) {
5551 ep = GET_PREV_EP(ep);
5557vm_get_special_object(
const VALUE *
const reg_ep,
5558 enum vm_special_object_type
type)
5561 case VM_SPECIAL_OBJECT_VMCORE:
5562 return rb_mRubyVMFrozenCore;
5563 case VM_SPECIAL_OBJECT_CBASE:
5564 return vm_get_cbase(reg_ep);
5565 case VM_SPECIAL_OBJECT_CONST_BASE:
5566 return vm_get_const_base(reg_ep);
5568 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5575rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5577 return vm_get_special_object(reg_ep,
type);
5583 const VALUE ary2 = ary2st;
5584 VALUE tmp1 = rb_check_to_array(ary1);
5585 VALUE tmp2 = rb_check_to_array(ary2);
5606 const VALUE ary2 = ary2st;
5608 if (
NIL_P(ary2))
return ary1;
5610 VALUE tmp2 = rb_check_to_array(ary2);
5625 return vm_concat_array(ary1, ary2st);
5629rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5631 return vm_concat_to_array(ary1, ary2st);
5640 VALUE tmp = rb_check_to_array(ary);
5644 else if (
RTEST(flag)) {
5657 return vm_splat_array(flag, ary);
5663 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5665 if (flag & VM_CHECKMATCH_ARRAY) {
5669 for (i = 0; i < n; i++) {
5671 VALUE c = check_match(ec, v, target,
type);
5680 return check_match(ec, pattern, target,
type);
5687 return vm_check_match(ec, target, pattern, flag);
5691vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5693 const VALUE kw_bits = *(ep - bits);
5696 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5697 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5710 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5711 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5712 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5713 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5717 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5720 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5723 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5726 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5733vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5738 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5739 return rb_public_const_get_at(cbase,
id);
5747vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
5752 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
5757 "superclass mismatch for class %"PRIsVALUE
"",
5770vm_check_if_module(
ID id,
VALUE mod)
5789vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5792 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super :
rb_cObject;
5799vm_declare_module(
ID id,
VALUE cbase)
5805NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
5809 VALUE name = rb_id2str(
id);
5810 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
5812 VALUE location = rb_const_source_location_at(cbase,
id);
5813 if (!
NIL_P(location)) {
5814 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
5815 " previous definition of %"PRIsVALUE
" was here",
5822vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5826 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
5828 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
5832 vm_check_if_namespace(cbase);
5837 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
5838 if (!vm_check_if_class(
id, flags, super, klass))
5839 unmatched_redefinition(
"class", cbase,
id, klass);
5843 return vm_declare_class(
id, flags, cbase, super);
5848vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
5852 vm_check_if_namespace(cbase);
5853 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
5854 if (!vm_check_if_module(
id, mod))
5855 unmatched_redefinition(
"module", cbase,
id, mod);
5859 return vm_declare_module(
id, cbase);
5864vm_find_or_create_class_by_id(
ID id,
5869 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
5872 case VM_DEFINECLASS_TYPE_CLASS:
5874 return vm_define_class(
id, flags, cbase, super);
5876 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
5880 case VM_DEFINECLASS_TYPE_MODULE:
5882 return vm_define_module(
id, flags, cbase);
5885 rb_bug(
"unknown defineclass type: %d", (
int)
type);
5889static rb_method_visibility_t
5894 if (!vm_env_cref_by_cref(cfp->ep)) {
5895 return METHOD_VISI_PUBLIC;
5898 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
5907 if (!vm_env_cref_by_cref(cfp->ep)) {
5911 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
5919 rb_method_visibility_t visi;
5924 visi = METHOD_VISI_PUBLIC;
5927 klass = CREF_CLASS_FOR_DEFINITION(cref);
5928 visi = vm_scope_visibility_get(ec);
5935 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
5938 !RCLASS_SINGLETON_P(klass) && !RCLASS_EXPECT_NO_IVAR(klass) &&
5940 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
5943 if (!is_singleton && vm_scope_module_func_check(ec)) {
5945 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
5954rb_vm_untag_block_handler(
VALUE block_handler)
5956 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
5958 switch (vm_block_handler_type(block_handler)) {
5959 case block_handler_type_iseq:
5960 case block_handler_type_ifunc: {
5962 return captured->code.val;
5964 case block_handler_type_proc:
5965 case block_handler_type_symbol:
5966 return block_handler;
5968 rb_bug(
"rb_vm_untag_block_handler: unreachable");
5975 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
5984 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
5986 if (block_handler == VM_BLOCK_HANDLER_NONE) {
5987 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
5990 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
5994enum method_explorer_type {
5996 mexp_search_invokeblock,
6005 VALUE block_handler,
6006 enum method_explorer_type method_explorer
6011 int argc = vm_ci_argc(ci);
6012 VALUE recv = TOPN(argc);
6014 .block_handler = block_handler,
6015 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6021 switch (method_explorer) {
6022 case mexp_search_method:
6023 calling.cc = cc = vm_search_method_fastpath(reg_cfp, cd,
CLASS_OF(recv));
6024 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6026 case mexp_search_super:
6027 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6028 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6030 case mexp_search_invokeblock:
6031 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6041 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6042 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6056 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6058 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6060 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6061 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6072 VALUE bh = VM_BLOCK_HANDLER_NONE;
6073 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6083 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
true);
6084 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super);
6098 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6100 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6102 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6103 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6114 VALUE bh = VM_BLOCK_HANDLER_NONE;
6115 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6143 if (check_method_basic_definition(cme)) {
6152 if (check_cfunc(cme, rb_mod_to_s)) {
6158 val = rb_mod_to_s(recv);
6164 if (check_cfunc(cme, rb_nil_to_s)) {
6165 return rb_nil_to_s(recv);
6169 if (check_cfunc(cme, rb_true_to_s)) {
6170 return rb_true_to_s(recv);
6174 if (check_cfunc(cme, rb_false_to_s)) {
6175 return rb_false_to_s(recv);
6179 if (check_cfunc(cme, rb_int_to_s)) {
6180 return rb_fix_to_s(recv);
6192 return vm_objtostring(reg_cfp, recv, cd);
6196vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6198 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6207vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6209 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6218vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6220 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6234 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6238 VALUE args[1] = {target};
6241 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6244 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6251 return vm_opt_duparray_include_p(ec, ary, target);
6257 if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
6258 if (array_len == 0) {
6262 VALUE result = *ptr;
6263 rb_snum_t i = array_len - 1;
6265 const VALUE v = *++ptr;
6266 if (OPTIMIZED_CMP(v, result) > 0) {
6281 return vm_opt_newarray_max(ec, array_len, ptr);
6287 if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
6288 if (array_len == 0) {
6292 VALUE result = *ptr;
6293 rb_snum_t i = array_len - 1;
6295 const VALUE v = *++ptr;
6296 if (OPTIMIZED_CMP(v, result) < 0) {
6311 return vm_opt_newarray_min(ec, array_len, ptr);
6318 if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
6319 return rb_ary_hash_values(array_len, ptr);
6329 return vm_opt_newarray_hash(ec, array_len, ptr);
6338 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6339 struct RArray fake_ary = {RBASIC_INIT};
6340 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6344 VALUE args[1] = {target};
6352 return vm_opt_newarray_include_p(ec, array_len,
ptr, target);
6358 if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) {
6359 struct RArray fake_ary = {RBASIC_INIT};
6360 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6361 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6371 if (!UNDEF_P(buffer)) {
6372 args[1] = rb_hash_new_with_size(1);
6373 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6378 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len,
ptr), idPack, argc, args, kw_splat);
6385 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt, buffer);
6391 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt,
Qundef);
6397vm_track_constant_cache(
ID id,
void *ic)
6400 struct rb_id_table *const_cache = &vm->constant_cache;
6401 VALUE lookup_result;
6404 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6408 ics = set_init_numtable();
6409 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6424 vm->inserting_constant_cache_id = id;
6426 set_insert(ics, (st_data_t)ic);
6428 vm->inserting_constant_cache_id = (
ID)0;
6435 for (
int i = 0; segments[i]; i++) {
6436 ID id = segments[i];
6437 if (
id == idNULL)
continue;
6438 vm_track_constant_cache(
id, ic);
6447 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6448 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6450 return (ic_cref == NULL ||
6451 ic_cref == vm_get_cref(reg_ep));
6459 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6460 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6465rb_vm_ic_hit_p(
IC ic,
const VALUE *reg_ep)
6467 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6473 if (ruby_vm_const_missing_count > 0) {
6474 ruby_vm_const_missing_count = 0;
6481 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6485 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6489 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6490 rb_yjit_constant_ic_update(iseq, ic, pos);
6500 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6503 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
6506 ruby_vm_constant_cache_misses++;
6507 val = vm_get_ev_const_chain(ec, segments);
6508 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6511 vm_ic_update(CFP_ISEQ(GET_CFP()), ic, val, GET_EP(), CFP_PC(GET_CFP()) - 2);
6523 if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
6524 return is->once.value;
6526 else if (is->once.running_thread == NULL) {
6528 is->once.running_thread = th;
6533 RB_OBJ_SET_SHAREABLE(val);
6539 is->once.running_thread = RUNNING_THREAD_ONCE_DONE;
6542 else if (is->once.running_thread == th) {
6544 return vm_once_exec((
VALUE)iseq);
6548 RUBY_VM_CHECK_INTS(ec);
6555vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6557 switch (OBJ_BUILTIN_TYPE(key)) {
6563 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6564 SYMBOL_REDEFINED_OP_FLAG |
6565 INTEGER_REDEFINED_OP_FLAG |
6566 FLOAT_REDEFINED_OP_FLAG |
6567 NIL_REDEFINED_OP_FLAG |
6568 TRUE_REDEFINED_OP_FLAG |
6569 FALSE_REDEFINED_OP_FLAG |
6570 STRING_REDEFINED_OP_FLAG)) {
6574 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6578 if (st_lookup(rb_imemo_cdhash_tbl(hash), key, &val)) {
6598 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6599 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6600 static const char stack_consistency_error[] =
6601 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6602#if defined RUBY_DEVEL
6603 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6608 rb_bug(stack_consistency_error, nsp, nbp);
6615 if (FIXNUM_2_P(recv, obj) &&
6616 BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
6617 return rb_fix_plus_fix(recv, obj);
6619 else if (FLONUM_2_P(recv, obj) &&
6620 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6628 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6633 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
6634 return rb_str_opt_plus(recv, obj);
6638 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
6649 if (FIXNUM_2_P(recv, obj) &&
6650 BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
6651 return rb_fix_minus_fix(recv, obj);
6653 else if (FLONUM_2_P(recv, obj) &&
6654 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6662 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6673 if (FIXNUM_2_P(recv, obj) &&
6674 BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
6675 return rb_fix_mul_fix(recv, obj);
6677 else if (FLONUM_2_P(recv, obj) &&
6678 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6686 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6697 if (FIXNUM_2_P(recv, obj) &&
6698 BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
6699 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6701 else if (FLONUM_2_P(recv, obj) &&
6702 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6703 return rb_flo_div_flo(recv, obj);
6710 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6711 return rb_flo_div_flo(recv, obj);
6721 if (FIXNUM_2_P(recv, obj) &&
6722 BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
6723 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
6725 else if (FLONUM_2_P(recv, obj) &&
6726 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6734 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6745 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not_equal)) {
6746 VALUE val = opt_equality(reg_cfp, recv, obj, cd_eq);
6748 if (!UNDEF_P(val)) {
6749 return RBOOL(!
RTEST(val));
6759 if (FIXNUM_2_P(recv, obj) &&
6760 BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
6763 else if (FLONUM_2_P(recv, obj) &&
6764 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6772 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6783 if (FIXNUM_2_P(recv, obj) &&
6784 BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
6787 else if (FLONUM_2_P(recv, obj) &&
6788 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6796 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6807 if (FIXNUM_2_P(recv, obj) &&
6808 BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
6811 else if (FLONUM_2_P(recv, obj) &&
6812 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6820 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6831 if (FIXNUM_2_P(recv, obj) &&
6832 BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
6835 else if (FLONUM_2_P(recv, obj) &&
6836 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6844 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6860 BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
6869 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
6887 BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
6898 if (FIXNUM_2_P(recv, obj) &&
6899 BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
6911 if (FIXNUM_2_P(recv, obj) &&
6912 BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
6913 return rb_fix_aref(recv, obj);
6918 BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG)) {
6920 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
6923 return rb_ary_aref1(recv, obj);
6927 BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
6928 return rb_hash_aref(recv, obj);
6942 BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
6948 BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
6949 rb_hash_aset(recv, obj, set);
6958vm_opt_length(
VALUE recv,
int bop)
6964 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6965 if (bop == BOP_EMPTY_P) {
6966 return LONG2NUM(RSTRING_LEN(recv));
6973 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6977 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6986vm_opt_empty_p(
VALUE recv)
6988 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7001 BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
7004 else if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_false)) {
7020 case RSHIFT(~0UL, 1):
7023 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7041vm_opt_succ(
VALUE recv)
7044 BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
7045 return fix_succ(recv);
7051 BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
7062 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not)) {
7063 return RBOOL(!
RTEST(recv));
7078 BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
7082 BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
7100 VALUE self = GET_SELF();
7102 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7104 if (local_hooks) local_hooks->running++;
7106 if (event & global_hooks->events) {
7109 vm_dtrace(event, ec);
7110 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7114 if (local_hooks) local_hooks->running--;
7115 if (local_hooks != NULL) {
7116 if (event & local_hooks->events) {
7119 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7125#define VM_TRACE_HOOK(target_event, val) do { \
7126 if ((pc_events & (target_event)) & enabled_flags) { \
7127 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7134 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7135 VM_ASSERT(ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_RESCUE);
7136 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7142 const VALUE *pc = reg_cfp->pc;
7144 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7147 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7151 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
7152 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7154 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7156 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7158 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7162 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7166 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7167 enabled_flags |= iseq_local_events;
7169 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7171 if (bmethod_frame) {
7173 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7174 unsigned int bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7175 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7177 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7180 if (bmethod_local_hooks) {
7181 bmethod_local_events = bmethod_local_hooks->events;
7186 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7190 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7198 else if (ec->trace_arg != NULL) {
7206 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7209 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %s:%d %s\n",
7212 RSTRING_PTR(rb_iseq_path(iseq)),
7213 (
int)rb_iseq_line_no(iseq, pos),
7214 RSTRING_PTR(rb_iseq_label(iseq)));
7216 VM_ASSERT(reg_cfp->pc == pc);
7217 VM_ASSERT(pc_events != 0);
7227 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7228 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7239#if VM_CHECK_MODE > 0
7240NORETURN( NOINLINE( COLDFUNC
7241void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7244Init_vm_stack_canary(
void)
7247 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7248 vm_stack_canary |= 0x01;
7250 vm_stack_canary_was_born =
true;
7255rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7259 const char *insn = rb_insns_name(i);
7263 rb_bug(
"dead canary found at %s: %s", insn, str);
7267void Init_vm_stack_canary(
void) { }
7299 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7306 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7313 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7320 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7327 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7334 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7341 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7348 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7355 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7361 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);
7362 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]);
7368 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);
7369 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]);
7375 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);
7376 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]);
7382 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);
7383 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]);
7389 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);
7390 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]);
7396 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);
7397 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]);
7403 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);
7404 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]);
7409static builtin_invoker
7410lookup_builtin_invoker(
int argc)
7412 static const builtin_invoker invokers[] = {
7431 return invokers[argc];
7437 const bool canary_p = ISEQ_BODY(CFP_ISEQ(reg_cfp))->builtin_attrs & BUILTIN_ATTR_LEAF;
7438 SETUP_CANARY(canary_p);
7439 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7440 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7441 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7448 return invoke_bf(ec, cfp, bf, argv);
7455 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7456 for (
int i=0; i<bf->argc; i++) {
7457 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(CFP_ISEQ(cfp))->local_table[i+start_index]));
7459 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7460 (
void *)(uintptr_t)bf->func_ptr);
7463 if (bf->argc == 0) {
7464 return invoke_bf(ec, cfp, bf, NULL);
7467 const VALUE *argv = cfp->ep - ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7468 return invoke_bf(ec, cfp, bf, argv);
7478 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.
static bool RB_FL_ABLE(VALUE obj)
Checks if the object is flaggable.
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 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.
@ 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_cObject
Object 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().
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
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.
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).
int off
Offset inside of ptr.
int len
Length of the buffer.
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#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.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#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.
static VALUE * ROBJECT_FIELDS(VALUE obj)
Queries the instance variables.
#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 must be a hash of keywords.
#define RB_NO_KEYWORDS
Do not pass keywords.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
#define ANYARGS
Functions declared using this macro take arbitrary arguments, including void.
const VALUE ary[1]
Embedded elements.
const VALUE * ptr
Pointer to the C array that holds the elements of the array.
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
Internal header for Class.
rb_cref_t * cref
class reference, should be marked
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
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.
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.