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"
36#include "insns_info.inc"
42 int argc,
const VALUE *argv,
int priv);
52ruby_vm_special_exception_copy(
VALUE exc)
55 rb_obj_copy_ivar(e, exc);
63 VALUE mesg = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_sysstack];
64 ec->raised_flag = RAISED_STACKOVERFLOW;
66 VALUE at = rb_ec_backtrace_object(ec);
67 mesg = ruby_vm_special_exception_copy(mesg);
72 EC_JUMP_TAG(ec, TAG_RAISE);
75NORETURN(
static void vm_stackoverflow(
void));
80 ec_stack_overflow(GET_EC(), TRUE);
87 rb_bug(
"system stack overflow during GC. Faulty native extension?");
89 if (crit >= rb_stack_overflow_fatal) {
90 ec->raised_flag = RAISED_STACKOVERFLOW;
91 ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
92 EC_JUMP_TAG(ec, TAG_RAISE);
94 ec_stack_overflow(ec, crit < rb_stack_overflow_signal);
101callable_class_p(
VALUE klass)
103#if VM_CHECK_MODE >= 2
104 if (!klass)
return FALSE;
132 VM_ASSERT(IMEMO_TYPE_P((
VALUE)cme, imemo_ment),
"imemo_type:%s", rb_imemo_name(imemo_type((
VALUE)cme)));
134 if (callable_class_p(cme->defined_class)) {
144vm_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)
146 unsigned int magic = (
unsigned int)(
type & VM_FRAME_MAGIC_MASK);
147 enum imemo_type cref_or_me_type = imemo_env;
150 cref_or_me_type = imemo_type(cref_or_me);
152 if (
type & VM_FRAME_FLAG_BMETHOD) {
156 if (req_block && (
type & VM_ENV_FLAG_LOCAL) == 0) {
157 rb_bug(
"vm_push_frame: specval (%p) should be a block_ptr on %x frame", (
void *)specval, magic);
159 if (!req_block && (
type & VM_ENV_FLAG_LOCAL) != 0) {
160 rb_bug(
"vm_push_frame: specval (%p) should not be a block_ptr on %x frame", (
void *)specval, magic);
164 if (cref_or_me_type != imemo_ment) {
165 rb_bug(
"vm_push_frame: (%s) should be method entry on %x frame", rb_obj_info(cref_or_me), magic);
169 if (req_cref && cref_or_me_type != imemo_cref) {
170 rb_bug(
"vm_push_frame: (%s) should be CREF on %x frame", rb_obj_info(cref_or_me), magic);
173 if (cref_or_me !=
Qfalse && cref_or_me_type != imemo_cref) {
174 if (((
type & VM_FRAME_FLAG_LAMBDA) || magic == VM_FRAME_MAGIC_IFUNC || magic == VM_FRAME_MAGIC_DUMMY) && (cref_or_me_type == imemo_ment)) {
178 rb_bug(
"vm_push_frame: (%s) should be false or cref on %x frame", rb_obj_info(cref_or_me), magic);
184 if (cref_or_me_type == imemo_ment) {
187 if (!callable_method_entry_p(me)) {
188 rb_bug(
"vm_push_frame: ment (%s) should be callable on %x frame.", rb_obj_info(cref_or_me), magic);
192 if ((
type & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
193 VM_ASSERT(iseq == NULL ||
195 RUBY_VM_NORMAL_ISEQ_P(iseq)
199 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(iseq));
209 VALUE given_magic =
type & VM_FRAME_MAGIC_MASK;
212#define CHECK(magic, req_block, req_me, req_cref, is_cframe) \
214 vm_check_frame_detail(type, req_block, req_me, req_cref, \
215 specval, cref_or_me, is_cframe, iseq); \
217 switch (given_magic) {
219 CHECK(VM_FRAME_MAGIC_METHOD, TRUE, TRUE, FALSE, FALSE);
220 CHECK(VM_FRAME_MAGIC_CLASS, TRUE, FALSE, TRUE, FALSE);
221 CHECK(VM_FRAME_MAGIC_TOP, TRUE, FALSE, TRUE, FALSE);
222 CHECK(VM_FRAME_MAGIC_CFUNC, TRUE, TRUE, FALSE, TRUE);
223 CHECK(VM_FRAME_MAGIC_BLOCK, FALSE, FALSE, FALSE, FALSE);
224 CHECK(VM_FRAME_MAGIC_IFUNC, FALSE, FALSE, FALSE, TRUE);
225 CHECK(VM_FRAME_MAGIC_EVAL, FALSE, FALSE, FALSE, FALSE);
226 CHECK(VM_FRAME_MAGIC_RESCUE, FALSE, FALSE, FALSE, FALSE);
227 CHECK(VM_FRAME_MAGIC_DUMMY, TRUE, FALSE, FALSE, FALSE);
229 rb_bug(
"vm_push_frame: unknown type (%x)", (
unsigned int)given_magic);
234static VALUE vm_stack_canary;
235static bool vm_stack_canary_was_born =
false;
242 unsigned int pos = 0;
243 while (pos < ISEQ_BODY(iseq)->iseq_size) {
244 int opcode = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[pos]);
245 unsigned int next_pos = pos + insn_len(opcode);
246 if (ISEQ_BODY(iseq)->iseq_encoded + next_pos == pc) {
251 rb_bug(
"failed to find the previous insn");
260 if (! LIKELY(vm_stack_canary_was_born)) {
263 else if ((
VALUE *)reg_cfp == ec->vm_stack + ec->vm_stack_size) {
267 else if (! (iseq = GET_ISEQ())) {
270 else if (LIKELY(sp[0] != vm_stack_canary)) {
279 const VALUE *orig = rb_iseq_original_iseq(iseq);
280 const VALUE iseqw = rb_iseqw_new(iseq);
282 const char *stri = rb_str_to_cstr(inspection);
283 const VALUE disasm = rb_iseq_disasm(iseq);
284 const char *strd = rb_str_to_cstr(disasm);
285 const ptrdiff_t pos = previous_insn_index(iseq, GET_PC());
286 const enum ruby_vminsn_type insn = (
enum ruby_vminsn_type)orig[pos];
287 const char *name = insn_name(insn);
293 "We are killing the stack canary set by %s, "
294 "at %s@pc=%"PRIdPTR
"\n"
295 "watch out the C stack trace.\n"
297 name, stri, pos, strd);
298 rb_bug(
"see above.");
300#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
303#define vm_check_canary(ec, sp)
304#define vm_check_frame(a, b, c, d)
309vm_push_frame_debug_counter_inc(
316 RB_DEBUG_COUNTER_INC(frame_push);
318 if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
319 const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
320 const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
323 RB_DEBUG_COUNTER_INC(frame_R2R);
326 RB_DEBUG_COUNTER_INC(frame_R2C);
331 RB_DEBUG_COUNTER_INC(frame_C2R);
334 RB_DEBUG_COUNTER_INC(frame_C2C);
339 switch (
type & VM_FRAME_MAGIC_MASK) {
340 case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method);
return;
341 case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block);
return;
342 case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class);
return;
343 case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top);
return;
344 case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc);
return;
345 case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc);
return;
346 case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval);
return;
347 case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue);
return;
348 case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy);
return;
351 rb_bug(
"unreachable");
354#define vm_push_frame_debug_counter_inc(ec, cfp, t)
359rb_vm_stack_canary(
void)
362 return vm_stack_canary;
368STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
369STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
370STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
386 vm_check_frame(
type, specval, cref_or_me, iseq);
387 VM_ASSERT(local_size >= 0);
390 CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
391 vm_check_canary(ec, sp);
396 for (
int i=0; i < local_size; i++) {
423 #if defined HAVE_DECL_ATOMIC_SIGNAL_FENCE && HAVE_DECL_ATOMIC_SIGNAL_FENCE
424 atomic_signal_fence(memory_order_seq_cst);
432 vm_push_frame_debug_counter_inc(ec, cfp,
type);
440 if (VMDEBUG == 2) SDR();
442 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
449 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
451 if (VMDEBUG == 2) SDR();
453 RUBY_VM_CHECK_INTS(ec);
454 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
456 return flags & VM_FRAME_FLAG_FINISH;
462 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
470 rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
474 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
476 VM_BLOCK_HANDLER_NONE,
483 return (
VALUE)dmy_iseq;
488rb_arity_error_new(
int argc,
int min,
int max)
490 VALUE err_mess = rb_sprintf(
"wrong number of arguments (given %d, expected %d", argc, min);
498 rb_str_catf(err_mess,
"..%d", max);
505rb_error_arity(
int argc,
int min,
int max)
512NOINLINE(
static void vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v));
515vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v)
517 const VALUE envval = VM_ENV_ENVVAL(ep);
524 rb_gc_writebarrier(envval, v);
526 VM_FORCE_WRITE(&ep[index], v);
530 rb_gc_writebarrier_remember(envval);
531 VM_FORCE_WRITE(&ep[index], v);
532 VM_ENV_FLAGS_UNSET(ep, VM_ENV_FLAG_WB_REQUIRED);
534 RB_DEBUG_COUNTER_INC(lvar_set_slowpath);
539vm_env_write(
const VALUE *ep,
int index,
VALUE v)
541 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
542 if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
543 VM_STACK_ENV_WRITE(ep, index, v);
546 vm_env_write_slowpath(ep, index, v);
551rb_vm_env_write(
const VALUE *ep,
int index,
VALUE v)
553 vm_env_write(ep, index, v);
559 if (block_handler == VM_BLOCK_HANDLER_NONE) {
563 switch (vm_block_handler_type(block_handler)) {
564 case block_handler_type_iseq:
565 case block_handler_type_ifunc:
566 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler),
rb_cProc);
567 case block_handler_type_symbol:
568 return rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
569 case block_handler_type_proc:
570 return VM_BH_TO_PROC(block_handler);
572 VM_UNREACHABLE(rb_vm_bh_to_procval);
581vm_svar_valid_p(
VALUE svar)
584 switch (imemo_type(svar)) {
593 rb_bug(
"vm_svar_valid_p: unknown type: %s", rb_obj_info(svar));
604 if (!lep)
return false;
605 if (ec == NULL)
return true;
606 if (ec->root_lep == lep)
return false;
610 if (
FIXNUM_P(lep[VM_ENV_DATA_INDEX_FLAGS]) &&
611 VM_ENV_ESCAPED_P(lep) &&
623 if (lep_svar_in_env_p(ec, lep)) {
624 svar = lep[VM_ENV_DATA_INDEX_ME_CREF];
627 svar = ec->root_svar;
630 VM_ASSERT(svar ==
Qfalse || vm_svar_valid_p(svar));
638 VM_ASSERT(vm_svar_valid_p((
VALUE)svar));
640 if (lep_svar_in_env_p(ec, lep)) {
641 vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (
VALUE)svar);
644 RB_OBJ_WRITE(rb_ec_thread_ptr(ec)->self, &ec->root_svar, svar);
651 const struct vm_svar *svar = lep_svar(ec, lep);
656 case VM_SVAR_LASTLINE:
657 return svar->lastline;
658 case VM_SVAR_BACKREF:
659 return svar->backref;
661 const VALUE ary = svar->others;
676 struct vm_svar *svar = IMEMO_NEW(
struct vm_svar, imemo_svar, obj);
687 struct vm_svar *svar = lep_svar(ec, lep);
690 lep_svar_write(ec, lep, svar = svar_new((
VALUE)svar));
694 case VM_SVAR_LASTLINE:
697 case VM_SVAR_BACKREF:
701 VALUE ary = svar->others;
717 val = lep_svar_get(ec, lep, key);
720 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
737 rb_bug(
"unexpected back-ref");
750 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
760 return rb_reg_last_defined(backref);
762 rb_bug(
"unexpected back-ref");
766 nth = (int)(
type >> 1);
773check_method_entry(
VALUE obj,
int can_be_svar)
775 if (obj ==
Qfalse)
return NULL;
778 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_method_entry: unknown type: %s", rb_obj_info(obj));
781 switch (imemo_type(obj)) {
792 rb_bug(
"check_method_entry: svar should not be there:");
799env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
801 if (obj ==
Qfalse)
return NULL;
803 switch (imemo_type(obj)) {
820 const VALUE *ep = cfp->ep;
823 while (!VM_ENV_LOCAL_P(ep)) {
824 if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
825 ep = VM_ENV_PREV_EP(ep);
828 return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
834 const VALUE *ep = cfp->ep;
837 while (!VM_ENV_LOCAL_P_UNCHECKED(ep)) {
838 if ((me = env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
839 ep = VM_ENV_PREV_EP_UNCHECKED(ep);
842 return env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
848 switch (me->def->type) {
849 case VM_METHOD_TYPE_ISEQ:
850 return me->def->body.iseq.
iseqptr;
859 switch (me->def->type) {
860 case VM_METHOD_TYPE_ISEQ:
861 return me->def->body.iseq.
cref;
867#if VM_CHECK_MODE == 0
871check_cref(
VALUE obj,
int can_be_svar)
873 if (obj ==
Qfalse)
return NULL;
876 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_cref: unknown type: %s", rb_obj_info(obj));
879 switch (imemo_type(obj)) {
890 rb_bug(
"check_method_entry: svar should not be there:");
897vm_env_cref(
const VALUE *ep)
901 while (!VM_ENV_LOCAL_P(ep)) {
902 if ((cref = check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return cref;
903 ep = VM_ENV_PREV_EP(ep);
906 return check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
910is_cref(
const VALUE v,
int can_be_svar)
913 switch (imemo_type(v)) {
926vm_env_cref_by_cref(
const VALUE *ep)
928 while (!VM_ENV_LOCAL_P(ep)) {
929 if (is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE))
return TRUE;
930 ep = VM_ENV_PREV_EP(ep);
932 return is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
936cref_replace_with_duplicated_cref_each_frame(
const VALUE *vptr,
int can_be_svar,
VALUE parent)
938 const VALUE v = *vptr;
942 switch (imemo_type(v)) {
945 new_cref = rb_vm_cref_dup(cref);
950 VM_FORCE_WRITE(vptr, (
VALUE)new_cref);
955 return cref_replace_with_duplicated_cref_each_frame(&((
struct vm_svar *)v)->
cref_or_me, FALSE, v);
959 rb_bug(
"cref_replace_with_duplicated_cref_each_frame: unreachable");
968vm_cref_replace_with_duplicated_cref(
const VALUE *ep)
970 if (vm_env_cref_by_cref(ep)) {
974 while (!VM_ENV_LOCAL_P(ep)) {
975 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
976 if ((cref = cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE, envval)) != NULL) {
979 ep = VM_ENV_PREV_EP(ep);
981 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
982 return cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE, envval);
985 rb_bug(
"vm_cref_dup: unreachable");
990vm_get_cref(
const VALUE *ep)
998 rb_bug(
"vm_get_cref: unreachable");
1003rb_vm_get_cref(
const VALUE *ep)
1005 return vm_get_cref(ep);
1016 return vm_get_cref(cfp->ep);
1020vm_get_const_key_cref(
const VALUE *ep)
1022 const rb_cref_t *cref = vm_get_cref(ep);
1026 if (CREF_DYNAMIC(cref)) {
1029 cref = CREF_NEXT(cref);
1042 prev_cref = vm_env_cref(ep);
1048 prev_cref = vm_env_cref(cfp->ep);
1052 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1056vm_get_cbase(
const VALUE *ep)
1058 const rb_cref_t *cref = vm_get_cref(ep);
1060 return CREF_CLASS_FOR_DEFINITION(cref);
1064vm_get_const_base(
const VALUE *ep)
1066 const rb_cref_t *cref = vm_get_cref(ep);
1069 if (!CREF_PUSHED_BY_EVAL(cref)) {
1070 return CREF_CLASS_FOR_DEFINITION(cref);
1072 cref = CREF_NEXT(cref);
1079vm_check_if_namespace(
VALUE klass)
1082 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1087vm_ensure_not_refinement_module(
VALUE self)
1090 rb_warn(
"not defined at the refinement, but at the outer class/module");
1106 if (
NIL_P(orig_klass) && allow_nil) {
1108 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1112 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1113 root_cref = CREF_NEXT(root_cref);
1116 while (cref && CREF_NEXT(cref)) {
1117 if (CREF_PUSHED_BY_EVAL(cref)) {
1121 klass = CREF_CLASS(cref);
1123 cref = CREF_NEXT(cref);
1125 if (!
NIL_P(klass)) {
1129 if ((ce = rb_const_lookup(klass,
id))) {
1130 rb_const_warn_if_deprecated(ce, klass,
id);
1133 if (am == klass)
break;
1135 if (is_defined)
return 1;
1136 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1138 goto search_continue;
1145 if (UNLIKELY(!rb_ractor_main_p())) {
1147 rb_raise(rb_eRactorIsolationError,
1148 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" by non-main ractor.",
rb_class_path(klass), rb_id2str(
id));
1159 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1160 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1174 vm_check_if_namespace(orig_klass);
1176 return rb_public_const_defined_from(orig_klass,
id);
1179 return rb_public_const_get_from(orig_klass,
id);
1187 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1195 int allow_nil = TRUE;
1196 if (segments[0] == idNULL) {
1201 while (segments[idx]) {
1202 ID id = segments[idx++];
1203 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1216 rb_bug(
"vm_get_cvar_base: no cref");
1219 while (CREF_NEXT(cref) &&
1220 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1221 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1222 cref = CREF_NEXT(cref);
1224 if (top_level_raise && !CREF_NEXT(cref)) {
1228 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1236#define ractor_incidental_shareable_p(cond, val) \
1237 (!(cond) || rb_ractor_shareable_p(val))
1238#define ractor_object_incidental_shareable_p(obj, val) \
1239 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1248 return default_value;
1253 fields_obj = ROBJECT_FIELDS_OBJ(obj);
1258 if (UNLIKELY(!rb_ractor_main_p())) {
1266 if (default_value ==
Qundef) {
1274 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1278 fields_obj = rb_obj_fields(obj,
id);
1282 return default_value;
1287 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1288 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1290 rb_getivar_cache cache = rb_getivar_cache_unpack(vm_cache_attr_index_atomic_read(is_attr, ic, cc));
1292 if (LIKELY(cache.shape_offset == shape_id)) {
1293 if (cache.index == ATTR_INDEX_NOT_SET) {
1294 return default_value;
1297 val = ivar_list[cache.index];
1298#if USE_DEBUG_COUNTER
1299 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1302 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1308#if USE_DEBUG_COUNTER
1310 if (cache.shape_offset != INVALID_SHAPE_ID) {
1311 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1314 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1318 if (cache.shape_offset != INVALID_SHAPE_ID) {
1319 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1322 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1325 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1328 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1332 if (UNLIKELY(rb_shape_complex_p(shape_id))) {
1336 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1338 if (!st_lookup(table,
id, &val)) {
1339 val = default_value;
1343 shape_id_t previous_cached_offset = cache.shape_offset;
1344 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &cache.index, &cache.shape_offset)) {
1345 if (cache.shape_offset != previous_cached_offset) {
1346 RUBY_ASSERT(!rb_shape_complex_p(cache.shape_offset));
1347 RUBY_ASSERT(cache.shape_offset != INVALID_SHAPE_ID);
1349 uint64_t packed_cache = rb_getivar_cache_pack(cache.shape_offset, cache.index);
1350 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1353 if (cache.index == ATTR_INDEX_NOT_SET) {
1354 val = default_value;
1358 val = ivar_list[cache.index];
1363 vm_cache_attr_index_set(is_attr, ic, cc, rb_getivar_cache_pack(shape_id, ATTR_INDEX_NOT_SET));
1364 val = default_value;
1369 if (!UNDEF_P(default_value)) {
1377 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1380 return rb_attr_get(obj,
id);
1395 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1397 rb_check_frozen(obj);
1399 shape_id_t previous_shape_id = RBASIC_SHAPE_ID(obj);
1400 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1401 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1403 if (!rb_shape_complex_p(next_shape_id)) {
1404 uint64_t packed_cache = rb_setivar_cache_pack(RSHAPE_OFFSET(previous_shape_id), RSHAPE_OFFSET(next_shape_id), index);
1405 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1408 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1418 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1424 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1431 if (UNLIKELY(!rb_ractor_main_p())) {
1435 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1436 if (UNLIKELY(!fields_obj)) {
1440 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1441 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, RBASIC_SHAPE_ID(fields_obj), cache);
1442 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1446 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1448 if (shape_id != dest_shape_id) {
1449 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1450 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1453 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1462 VALUE fields_obj = rb_obj_fields(obj,
id);
1463 if (UNLIKELY(!fields_obj)) {
1467 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1468 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, RBASIC_SHAPE_ID(fields_obj), cache);
1469 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1473 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1475 if (shape_id != dest_shape_id) {
1476 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1477 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1480 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1494 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1495 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, shape_id, cache);
1496 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1500 VALUE fields_obj = ROBJECT_FIELDS_OBJ(obj);
1501 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1502 if (shape_id != dest_shape_id) {
1503 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1504 if (fields_obj != obj) {
1505 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1509 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1510 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1516 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1528 VALUE defined_class = 0;
1532 defined_class =
RBASIC(defined_class)->klass;
1535 VALUE rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
1537 rb_bug(
"the cvc table should be set");
1541 if (!rb_marked_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
1542 rb_bug(
"should have cvar cache entry");
1547 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
1560 cref = vm_get_cref(GET_EP());
1562 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1563 RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
1565 VALUE v = rb_ivar_lookup(ic->entry->class_value,
id,
Qundef);
1571 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1573 return update_classvariable_cache(iseq, klass,
id, cref, ic);
1579 return vm_getclassvariable(iseq, cfp,
id, ic);
1586 cref = vm_get_cref(GET_EP());
1588 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1589 RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
1591 rb_class_ivar_set(ic->entry->class_value,
id, val);
1595 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1599 update_classvariable_cache(iseq, klass,
id, cref, ic);
1605 vm_setclassvariable(iseq, cfp,
id, val, ic);
1612 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1623 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_ic_atomic_cache_read(ic));
1624 if (UNLIKELY(UNDEF_P(vm_setivar(obj, val, cache)))) {
1630 if (!UNDEF_P(vm_setivar_class(obj, val, cache))) {
1635 if (!UNDEF_P(vm_setivar_default(obj,
id, val, cache))) {
1639 vm_setivar_slowpath_ivar(obj,
id, val, iseq, ic);
1646 vm_setinstancevariable(iseq, obj,
id, val, ic);
1652 return vm_getinstancevariable(iseq, obj,
id, ic);
1661 ec->tag->state = RUBY_TAG_FATAL;
1664 ec->tag->state = TAG_THROW;
1666 else if (THROW_DATA_P(err)) {
1667 ec->tag->state = THROW_DATA_STATE((
struct vm_throw_data *)err);
1670 ec->tag->state = TAG_RAISE;
1677 const int flag,
const VALUE throwobj)
1685 else if (state == TAG_BREAK) {
1687 const VALUE *ep = GET_EP();
1688 const rb_iseq_t *base_iseq = GET_ISEQ();
1689 escape_cfp = reg_cfp;
1691 while (ISEQ_BODY(base_iseq)->
type != ISEQ_TYPE_BLOCK) {
1692 if (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1693 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1694 ep = escape_cfp->ep;
1695 base_iseq = CFP_ISEQ(escape_cfp);
1698 ep = VM_ENV_PREV_EP(ep);
1699 base_iseq = ISEQ_BODY(base_iseq)->parent_iseq;
1700 escape_cfp = rb_vm_search_cf_from_ep(ec, escape_cfp, ep);
1701 VM_ASSERT(CFP_ISEQ(escape_cfp) == base_iseq);
1705 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1711 ep = VM_ENV_PREV_EP(ep);
1713 while (escape_cfp < eocfp) {
1714 if (escape_cfp->ep == ep) {
1715 const rb_iseq_t *
const iseq = CFP_ISEQ(escape_cfp);
1716 const VALUE epc = CFP_PC(escape_cfp) - ISEQ_BODY(iseq)->iseq_encoded;
1721 for (i=0; i < ct->size; i++) {
1723 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1725 if (entry->type == CATCH_TYPE_BREAK &&
1726 entry->iseq == base_iseq &&
1727 entry->start < epc && entry->end >= epc) {
1728 if (entry->cont == epc) {
1737 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1742 rb_vm_localjump_error(
"break from proc-closure", throwobj, TAG_BREAK);
1745 else if (state == TAG_RETRY) {
1746 const VALUE *ep = VM_ENV_PREV_EP(GET_EP());
1748 escape_cfp = rb_vm_search_cf_from_ep(ec, reg_cfp, ep);
1750 else if (state == TAG_RETURN) {
1751 const VALUE *current_ep = GET_EP();
1752 const VALUE *target_ep = NULL, *target_lep, *ep = current_ep;
1753 int in_class_frame = 0;
1755 escape_cfp = reg_cfp;
1758 while (!VM_ENV_LOCAL_P(ep)) {
1759 if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) {
1762 ep = VM_ENV_PREV_EP(ep);
1766 while (escape_cfp < eocfp) {
1767 const VALUE *lep = VM_CF_LEP(escape_cfp);
1773 if (lep == target_lep &&
1774 VM_FRAME_RUBYFRAME_P(escape_cfp) &&
1775 ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1780 if (lep == target_lep) {
1781 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1783 if (in_class_frame) {
1788 const VALUE *tep = current_ep;
1790 while (target_lep != tep) {
1791 if (escape_cfp->ep == tep) {
1793 if (tep == target_ep) {
1797 goto unexpected_return;
1800 tep = VM_ENV_PREV_EP(tep);
1804 else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
1805 switch (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type) {
1807 case ISEQ_TYPE_MAIN:
1809 if (in_class_frame)
goto unexpected_return;
1810 if (target_ep == NULL) {
1814 goto unexpected_return;
1818 case ISEQ_TYPE_EVAL: {
1819 const rb_iseq_t *is = CFP_ISEQ(escape_cfp);
1820 enum rb_iseq_type t = ISEQ_BODY(is)->type;
1821 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE || t == ISEQ_TYPE_EVAL) {
1822 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
1823 t = ISEQ_BODY(is)->type;
1825 toplevel = t == ISEQ_TYPE_TOP || t == ISEQ_TYPE_MAIN;
1828 case ISEQ_TYPE_CLASS:
1837 if (escape_cfp->ep == target_lep && ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_METHOD) {
1838 if (target_ep == NULL) {
1842 goto unexpected_return;
1846 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1849 rb_vm_localjump_error(
"unexpected return", throwobj, TAG_RETURN);
1855 rb_bug(
"isns(throw): unsupported throw type");
1858 ec->tag->state = state;
1859 return (
VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state);
1864 rb_num_t throw_state,
VALUE throwobj)
1866 const int state = (int)(throw_state & VM_THROW_STATE_MASK);
1867 const int flag = (int)(throw_state & VM_THROW_NO_ESCAPE_FLAG);
1870 return vm_throw_start(ec, reg_cfp, state, flag, throwobj);
1873 return vm_throw_continue(ec, throwobj);
1881 return vm_throw(ec, reg_cfp, throw_state, throwobj);
1890 VALUE val = vm_throw(ec, reg_cfp, throw_state, throwobj);
1895 enum ruby_tag_type state = ec->tag->state;
1897 EC_JUMP_TAG(ec, state);
1905 int is_splat = flag & 0x01;
1908 const VALUE obj = ary;
1920 if (num + is_splat == 0) {
1923 else if (flag & 0x02) {
1928 for (i = 0; i < num -
len; i++) {
1933 for (j = 0; i < num; i++, j++) {
1955 for (; i < num -
len; i++) {
1959 for (rb_num_t j = 0; i < num; i++, j++) {
1960 *cfp->sp++ = ptr[
len - j - 1];
1964 for (rb_num_t j = 0; j < num; j++) {
1965 *cfp->sp++ = ptr[num - j - 1];
1980 int initial_capa = 2;
1982#if VM_CHECK_MODE > 0
1983 ccs->debug_sig = ~(
VALUE)ccs;
1985 ccs->capa = initial_capa;
1990 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
1998 if (! vm_cc_markable(cc)) {
2002 if (UNLIKELY(ccs->len == ccs->capa)) {
2005 ccs = ruby_xrealloc(ccs, vm_ccs_alloc_size(ccs->capa));
2006#if VM_CHECK_MODE > 0
2007 ccs->debug_sig = ~(
VALUE)ccs;
2010 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2012 VM_ASSERT(ccs->len < ccs->capa);
2015 const int pos = ccs->len++;
2016 ccs->entries[pos].argc = vm_ci_argc(ci);
2017 ccs->entries[pos].flag = (
unsigned short)vm_ci_flag(ci);
2018 ccs->entries[pos].kw_len = (
unsigned short)(kwarg ? kwarg->keyword_len : 0);
2021 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
2027#if VM_CHECK_MODE > 0
2031 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
2032 for (
int i=0; i<ccs->len; i++) {
2033 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u kw_len:%u\n",
2034 ccs->entries[i].flag,
2035 ccs->entries[i].argc,
2036 ccs->entries[i].kw_len);
2037 rp(ccs->entries[i].cc);
2044 VM_ASSERT(vm_ccs_p(ccs));
2045 VM_ASSERT(ccs->len <= ccs->capa);
2047 for (
int i=0; i<ccs->len; i++) {
2050 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2051 VM_ASSERT(vm_cc_class_check(cc, klass));
2052 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
2053 VM_ASSERT(!vm_cc_super_p(cc));
2054 VM_ASSERT(!vm_cc_refinement_p(cc));
2065 ASSERT_vm_locking();
2067 if (rb_multi_ractor_p()) {
2068 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2075 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2078 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2083 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2084 rb_vm_cc_table_delete(new_table, mid);
2085 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2088 rb_vm_cc_table_delete(cc_tbl, mid);
2095 ASSERT_vm_locking();
2097 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2101 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2105 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2106 return &vm_empty_cc;
2109 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2110 const VALUE original_cc_table = cc_tbl;
2113 cc_tbl = rb_vm_cc_table_create(1);
2115 else if (rb_multi_ractor_p()) {
2116 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2119 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2128 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2133 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2137 cme = rb_check_overloaded_cme(cme, ci);
2139 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2140 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2142 VM_ASSERT(vm_cc_cme(cc) != NULL);
2143 VM_ASSERT(cme->called_id == mid);
2144 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2146 if (original_cc_table != cc_tbl) {
2147 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2159 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2167 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2169 const int ccs_len = ccs->len;
2171 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2173 vm_evict_cc(klass, cc_tbl, mid);
2178 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2187 unsigned int argc = vm_ci_argc(ci);
2188 unsigned int flag = vm_ci_flag(ci);
2189 unsigned int kw_len = kwarg ? kwarg->keyword_len : 0;
2191 for (
int i=0; i<ccs_len; i++) {
2192 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2193 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2194 unsigned int ccs_ci_kw_len = ccs->entries[i].kw_len;
2195 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2197 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2199 if (ccs_ci_argc == argc && ccs_ci_flag == flag && ccs_ci_kw_len == kw_len) {
2200 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2202 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2203 VM_ASSERT(ccs_cc->klass == klass);
2204 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2220 const ID mid = vm_ci_mid(ci);
2222 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2228 if (rb_multi_ractor_p()) {
2231 cc = vm_lookup_cc(klass, ci, mid);
2235 cc = vm_populate_cc(klass, ci, mid);
2255 rb_bug(
"attempted to search method '%s' on a garbage collected object",
2256 rb_id2name(vm_ci_mid(ci)));
2261 cc = vm_search_cc(klass, ci);
2264 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2265 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2266 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2267 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2268 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2273#if VM_CHECK_MODE > 0
2278 return cd >= body->call_data && cd < body->call_data + body->ci_size;
2285#if USE_DEBUG_COUNTER
2290 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2293#if OPT_INLINE_METHOD_CACHE
2297 if (cd_owner && cc != empty_cc) {
2300 VM_ASSERT(!vm_ci_markable(cd->ci) ||
2301 vm_cd_owned_by_iseq_p(cd, (
const rb_iseq_t *)cd_owner));
2305#if USE_DEBUG_COUNTER
2306 if (!old_cc || old_cc == empty_cc) {
2308 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2310 else if (old_cc == cc) {
2311 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2313 else if (old_cme == new_cme) {
2314 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2316 else if (old_cme && new_cme && old_cme->def == new_cme->def) {
2317 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2320 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2325 if (new_cme) VM_ASSERT(new_cme->called_id == vm_ci_mid(cd->ci));
2336#if OPT_INLINE_METHOD_CACHE
2337 if (LIKELY(vm_cc_class_check(cc, klass))) {
2338 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2339 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2340 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2341 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2342 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2343 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2347 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2350 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2362 if (vm_cc_hit_p(cc, cd, klass)) {
2366 return vm_search_method_slowpath0((
VALUE)CFP_ISEQ(reg_cfp), cd, klass);
2373 VM_ASSERT(klass !=
Qfalse);
2376 const struct rb_callcache *cc = vm_search_method_fastpath(reg_cfp, cd, klass);
2377 return vm_cc_cme(cc);
2387 if (!vm_cc_hit_p(cc, cd, klass)) {
2388 cc = vm_search_method_slowpath0(cd_owner, cd, klass);
2390 return vm_cc_cme(cc);
2393#if __has_attribute(transparent_union)
2406 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2407 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2408 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2409 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2410 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2411 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2414# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2417# define make_cfunc_type(f) (cfunc_type)(f)
2427 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2428 VM_ASSERT(callable_method_entry_p(me));
2430 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2434#if __has_attribute(transparent_union)
2435 return me->def->body.cfunc.func == func.anyargs;
2437 return me->def->body.cfunc.func == func;
2446 return me && METHOD_ENTRY_BASIC(me);
2452 VM_ASSERT(reg_cfp != NULL);
2454 return check_cfunc(cme, func);
2460 return check_cfunc(me, func);
2467 return check_cfunc(cme, func);
2470#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2471#define vm_method_cfunc_is(reg_cfp, cd, recv, func) vm_method_cfunc_is(reg_cfp, cd, recv, make_cfunc_type(func))
2473#define OP_UNREDEFINED_P(op, t) BASIC_OP_UNREDEFINED_P(BOP_##op, t##_REDEFINED_OP_FLAG)
2474#define EQ_UNREDEFINED_P(t) OP_UNREDEFINED_P(EQ, t)
2506opt_equality_specialized(
VALUE recv,
VALUE obj)
2508 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2509 goto compare_by_identity;
2511 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2512 goto compare_by_identity;
2515 goto compare_by_identity;
2524 return RBOOL(a == b);
2531 return rb_str_eql_internal(obj, recv);
2536 compare_by_identity:
2537 return RBOOL(recv == obj);
2543 VM_ASSERT(reg_cfp != NULL);
2545 VALUE val = opt_equality_specialized(recv, obj);
2546 if (!UNDEF_P(val))
return val;
2548 if (!vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_equal)) {
2552 return RBOOL(recv == obj);
2557NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2560opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2562 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2564 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2565 return RBOOL(recv == obj);
2575 VALUE val = opt_equality_specialized(recv, obj);
2576 if (!UNDEF_P(val)) {
2580 return opt_equality_by_mid_slowpath(recv, obj, mid);
2587 return opt_equality_by_mid(obj1, obj2, idEq);
2593 return opt_equality_by_mid(obj1, obj2, idEqlP);
2603 case VM_CHECKMATCH_TYPE_WHEN:
2605 case VM_CHECKMATCH_TYPE_RESCUE:
2607 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2610 case VM_CHECKMATCH_TYPE_CASE: {
2611 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2614 rb_bug(
"check_match: unreachable");
2620double_cmp_lt(
double a,
double b)
2622 return RBOOL(a < b);
2626double_cmp_le(
double a,
double b)
2628 return RBOOL(a <= b);
2632double_cmp_gt(
double a,
double b)
2634 return RBOOL(a > b);
2638double_cmp_ge(
double a,
double b)
2640 return RBOOL(a >= b);
2644static inline VALUE *
2649 if (CFP_ISEQ(cfp) && VM_FRAME_RUBYFRAME_P(cfp)) {
2650 VALUE *bp = prev_cfp->sp + ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size + VM_ENV_DATA_SIZE;
2652 if (ISEQ_BODY(CFP_ISEQ(cfp))->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2653 int lts = ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size;
2654 int params = ISEQ_BODY(CFP_ISEQ(cfp))->param.size;
2657 bp += vm_ci_argc(ci);
2660 if (ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2664#if VM_DEBUG_BP_CHECK
2665 if (bp != cfp->bp_check) {
2666 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2667 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2668 (
long)(bp - GET_EC()->vm_stack));
2669 rb_bug(
"vm_base_ptr: unreachable");
2682 return vm_base_ptr(cfp);
2697static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2702 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2704 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2710 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2713 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2714 int param = ISEQ_BODY(iseq)->param.size;
2715 int local = ISEQ_BODY(iseq)->local_table_size;
2716 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2722 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2723 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2724 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2725 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2726 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2727 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2728 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2729 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2730 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2734rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2736 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2737 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2738 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2739 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2740 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2741 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2742 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2743 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2744 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2748rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2750 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2751 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2752 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2753 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2754 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2755 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2756 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2757 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2760#define ALLOW_HEAP_ARGV (-2)
2761#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2766 vm_check_canary(GET_EC(), cfp->sp);
2772 int argc = calling->argc;
2774 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2778 VALUE *argv = cfp->sp - argc;
2782 cfp->sp -= argc - 1;
2783 cfp->sp[-1] = argv_ary;
2785 calling->heap_argv = argv_ary;
2791 if (max_args >= 0 &&
len + argc > max_args) {
2799 calling->argc +=
len - (max_args - argc + 1);
2800 len = max_args - argc + 1;
2809 calling->heap_argv = 0;
2811 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2813 for (i = 0; i <
len; i++) {
2814 *cfp->sp++ = ptr[i];
2826 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2827 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2828 const VALUE h = rb_hash_new_capa(kw_len);
2829 VALUE *sp = cfp->sp;
2832 for (i=0; i<kw_len; i++) {
2833 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2837 cfp->sp -= kw_len - 1;
2838 calling->argc -= kw_len - 1;
2839 calling->kw_splat = 1;
2843vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2846 if (keyword_hash !=
Qnil) {
2848 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2851 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2857 keyword_hash = rb_hash_dup(keyword_hash);
2859 return keyword_hash;
2865 const struct rb_callinfo *restrict ci,
int max_args)
2867 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2868 if (IS_ARGS_KW_SPLAT(ci)) {
2870 VM_ASSERT(calling->kw_splat == 1);
2874 VALUE ary = cfp->sp[0];
2875 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2878 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2882 if (UNLIKELY(calling->heap_argv)) {
2884 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2885 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2886 calling->kw_splat = 0;
2894 VM_ASSERT(calling->kw_splat == 1);
2898 calling->kw_splat = 0;
2903 VM_ASSERT(calling->kw_splat == 0);
2907 VALUE ary = cfp->sp[0];
2909 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2914 VALUE last_hash, argv_ary;
2915 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2916 if (!IS_ARGS_KEYWORD(ci) &&
2919 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2924 calling->kw_splat = 1;
2930 if (!IS_ARGS_KEYWORD(ci) &&
2931 calling->argc > 0 &&
2933 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2940 cfp->sp[-1] = rb_hash_dup(last_hash);
2941 calling->kw_splat = 1;
2947 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2949 VM_ASSERT(calling->kw_splat == 1);
2950 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2955 calling->kw_splat = 0;
2961 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2963 VM_ASSERT(calling->kw_splat == 0);
2969 vm_caller_setup_arg_kw(cfp, calling, ci);
2973#define USE_OPT_HIST 0
2976#define OPT_HIST_MAX 64
2977static int opt_hist[OPT_HIST_MAX+1];
2981opt_hist_show_results_at_exit(
void)
2983 for (
int i=0; i<OPT_HIST_MAX; i++) {
2984 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
2994 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2995 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
2996 const int opt = calling->argc - lead_num;
2997 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
2998 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
2999 const int param = ISEQ_BODY(iseq)->param.size;
3000 const int local = ISEQ_BODY(iseq)->local_table_size;
3001 const int delta = opt_num - opt;
3003 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3006 if (opt_pc < OPT_HIST_MAX) {
3010 opt_hist[OPT_HIST_MAX]++;
3014 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3022 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3023 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3024 const int opt = calling->argc - lead_num;
3025 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3027 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3030 if (opt_pc < OPT_HIST_MAX) {
3034 opt_hist[OPT_HIST_MAX]++;
3038 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3043 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3044 VALUE *
const locals);
3051 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3052 int param_size = ISEQ_BODY(iseq)->param.size;
3053 int local_size = ISEQ_BODY(iseq)->local_table_size;
3056 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3058 local_size = local_size + vm_ci_argc(calling->cd->ci);
3059 param_size = param_size + vm_ci_argc(calling->cd->ci);
3061 cfp->sp[0] = (
VALUE)calling->cd->ci;
3063 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3073 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3074 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3076 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3077 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3079 const int ci_kw_len = kw_arg->keyword_len;
3080 const VALUE *
const ci_keywords = kw_arg->keywords;
3081 VALUE *argv = cfp->sp - calling->argc;
3082 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3083 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3085 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3086 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3088 int param = ISEQ_BODY(iseq)->param.size;
3089 int local = ISEQ_BODY(iseq)->local_table_size;
3090 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3097 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3100 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3101 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3103 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3104 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3105 VALUE *
const argv = cfp->sp - calling->argc;
3106 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3109 for (i=0; i<kw_param->num; i++) {
3110 klocals[i] = kw_param->default_values[i];
3117 int param = ISEQ_BODY(iseq)->param.size;
3118 int local = ISEQ_BODY(iseq)->local_table_size;
3119 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3129 cfp->sp -= (calling->argc + 1);
3130 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3131 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3140 set_table *dup_check_table = &vm->unused_block_warning_table;
3150 .v = (
VALUE)cme->def,
3154 if (!strict_unused_block) {
3155 key = (st_data_t)cme->def->original_id;
3157 if (set_table_lookup(dup_check_table, key)) {
3167 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3172 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3173 fprintf(stderr,
"key:%p\n", (
void *)key);
3177 if (set_insert(dup_check_table, key)) {
3182 VALUE name = rb_gen_method_name(cme->defined_class, rb_iseq_base_label(iseq));
3184 if (!
NIL_P(m_loc)) {
3185 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3189 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3196 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3201 VM_ASSERT((vm_ci_argc(ci), 1));
3202 VM_ASSERT(vm_cc_cme(cc) != NULL);
3204 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3205 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3206 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3207 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)CFP_PC(ec->cfp));
3210 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3211 if (LIKELY(rb_simple_iseq_p(iseq))) {
3213 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3214 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3216 if (calling->argc != lead_num) {
3217 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3221 VM_ASSERT(cc == calling->cc);
3223 if (vm_call_iseq_optimizable_p(ci, cc)) {
3224 if ((ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3225 VM_ASSERT(ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_LEAF);
3226 vm_cc_bf_set(cc, (
void *)ISEQ_BODY(iseq)->iseq_encoded[1]);
3227 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3230 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3235 else if (rb_iseq_only_optparam_p(iseq)) {
3238 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3239 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3241 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3242 const int argc = calling->argc;
3243 const int opt = argc - lead_num;
3245 if (opt < 0 || opt > opt_num) {
3246 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3249 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3250 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3251 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3252 vm_call_cacheable(ci, cc));
3255 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3256 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3257 vm_call_cacheable(ci, cc));
3261 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3262 for (
int i=argc; i<lead_num + opt_num; i++) {
3265 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3267 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3268 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3269 const int argc = calling->argc;
3270 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3272 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3275 if (argc - kw_arg->keyword_len == lead_num) {
3276 const int ci_kw_len = kw_arg->keyword_len;
3277 const VALUE *
const ci_keywords = kw_arg->keywords;
3279 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3281 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3282 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3284 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3285 vm_call_cacheable(ci, cc));
3290 else if (argc == lead_num) {
3292 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3293 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3295 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3297 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3298 vm_call_cacheable(ci, cc));
3324 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3325 bool can_fastpath =
true;
3327 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3329 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3330 ci = vm_ci_new_runtime(
3337 ci = forward_cd->caller_ci;
3339 can_fastpath =
false;
3343 if (!vm_ci_markable(ci)) {
3344 ci = vm_ci_new_runtime(
3349 can_fastpath =
false;
3351 argv[param_size - 1] = (
VALUE)ci;
3352 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3356 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3383 const VALUE * lep = VM_CF_LEP(cfp);
3389 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3394 iseq = CFP_ISEQ(rb_vm_search_cf_from_ep(ec, cfp, lep));
3398 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3400 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3401 VALUE * to = cfp->sp - 1;
3405 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3410 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3412 cfp->sp = to + argc;
3431 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3434 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3435 int param_size = ISEQ_BODY(iseq)->param.size;
3436 int local_size = ISEQ_BODY(iseq)->local_table_size;
3438 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3440 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3441 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3447 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3450 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3451 int param_size = ISEQ_BODY(iseq)->param.size;
3452 int local_size = ISEQ_BODY(iseq)->local_table_size;
3454 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3457 local_size = local_size + vm_ci_argc(calling->cd->ci);
3458 param_size = param_size + vm_ci_argc(calling->cd->ci);
3460 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3461 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3466 int opt_pc,
int param_size,
int local_size)
3471 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3472 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3475 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3481 int opt_pc,
int param_size,
int local_size)
3483 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3484 VALUE *argv = cfp->sp - calling->argc;
3485 VALUE *sp = argv + param_size;
3486 cfp->sp = argv - 1 ;
3488 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3489 calling->block_handler, (
VALUE)me,
3490 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3491 local_size - param_size,
3492 ISEQ_BODY(iseq)->stack_max);
3501 VALUE *argv = cfp->sp - calling->argc;
3503 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3504 VALUE *src_argv = argv;
3505 VALUE *sp_orig, *sp;
3506 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3508 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3509 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3510 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3511 dst_captured->code.val = src_captured->code.val;
3512 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3513 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3516 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3520 vm_pop_frame(ec, cfp, cfp->ep);
3523 sp_orig = sp = cfp->sp;
3526 sp[0] = calling->recv;
3530 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3531 *sp++ = src_argv[i];
3534 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3535 calling->recv, calling->block_handler, (
VALUE)me,
3536 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3537 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3538 ISEQ_BODY(iseq)->stack_max);
3546ractor_unsafe_check(
void)
3548 if (!rb_ractor_main_p()) {
3549 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3556 ractor_unsafe_check();
3564 ractor_unsafe_check();
3566 return (*f)(argc, argv, recv);
3572 ractor_unsafe_check();
3580 ractor_unsafe_check();
3582 return (*f)(recv, argv[0]);
3588 ractor_unsafe_check();
3590 return (*f)(recv, argv[0], argv[1]);
3596 ractor_unsafe_check();
3598 return (*f)(recv, argv[0], argv[1], argv[2]);
3604 ractor_unsafe_check();
3606 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3612 ractor_unsafe_check();
3613 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3614 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3620 ractor_unsafe_check();
3621 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3622 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3628 ractor_unsafe_check();
3629 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3630 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3636 ractor_unsafe_check();
3637 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3638 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3644 ractor_unsafe_check();
3645 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3646 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3652 ractor_unsafe_check();
3653 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;
3654 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3660 ractor_unsafe_check();
3661 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;
3662 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]);
3668 ractor_unsafe_check();
3669 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;
3670 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]);
3676 ractor_unsafe_check();
3677 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;
3678 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]);
3684 ractor_unsafe_check();
3685 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;
3686 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]);
3692 ractor_unsafe_check();
3693 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;
3694 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]);
3708 return (*f)(argc, argv, recv);
3722 return (*f)(recv, argv[0]);
3729 return (*f)(recv, argv[0], argv[1]);
3736 return (*f)(recv, argv[0], argv[1], argv[2]);
3743 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3749 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3750 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3756 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3757 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3763 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3764 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3770 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3771 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3777 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3778 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3784 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;
3785 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3791 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;
3792 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]);
3798 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;
3799 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]);
3805 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;
3806 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]);
3812 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;
3813 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]);
3819 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;
3820 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]);
3826 const int ov_flags = RAISED_STACKOVERFLOW;
3827 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3828 if (rb_ec_raised_p(ec, ov_flags)) {
3829 rb_ec_raised_reset(ec, ov_flags);
3835#define CHECK_CFP_CONSISTENCY(func) \
3836 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3837 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3843#if VM_DEBUG_VERIFY_METHOD_CACHE
3844 switch (me->def->type) {
3845 case VM_METHOD_TYPE_CFUNC:
3846 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3848# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3850 METHOD_BUG(ATTRSET);
3852 METHOD_BUG(BMETHOD);
3855 METHOD_BUG(OPTIMIZED);
3856 METHOD_BUG(MISSING);
3857 METHOD_BUG(REFINED);
3861 rb_bug(
"wrong method type: %d", me->def->type);
3864 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3871 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3878 VALUE recv = calling->recv;
3879 VALUE block_handler = calling->block_handler;
3880 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3882 if (UNLIKELY(calling->kw_splat)) {
3883 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3886 VM_ASSERT(reg_cfp == ec->cfp);
3888 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3891 vm_push_frame(ec, NULL, frame_type, recv,
3892 block_handler, (
VALUE)me,
3893 0, ec->cfp->sp, 0, 0);
3895 int len = cfunc->argc;
3898 reg_cfp->sp = stack_bottom;
3899 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3901 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3903 rb_vm_pop_frame(ec);
3905 VM_ASSERT(ec->cfp->sp == stack_bottom);
3907 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3908 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3918 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3920 VALUE *sp = ec->cfp->sp;
3921 VALUE recv = *(sp - recv_idx - 1);
3922 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3923 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3924#if VM_CHECK_MODE > 0
3926 *(GET_EC()->cfp->sp) =
Qfalse;
3928 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3933rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3935 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3941 int argc = calling->argc;
3942 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3943 VALUE *argv = &stack_bottom[1];
3945 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3952 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3954 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3956 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3957 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3960 VALUE *stack_bottom = reg_cfp->sp - 2;
3962 VM_ASSERT(calling->argc == 1);
3966 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3969 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));
3971 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3978 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3981 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3982 return vm_call_cfunc_other(ec, reg_cfp, calling);
3986 calling->kw_splat = 0;
3988 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
3989 VALUE *sp = stack_bottom;
3990 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
3991 for(i = 0; i < argc; i++) {
3996 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4002 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4003 VALUE argv_ary = reg_cfp->sp[-1];
4007 int argc_offset = 0;
4009 if (UNLIKELY(argc > 0 &&
4011 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4013 return vm_call_cfunc_other(ec, reg_cfp, calling);
4017 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4023 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4024 VALUE keyword_hash = reg_cfp->sp[-1];
4027 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4030 return vm_call_cfunc_other(ec, reg_cfp, calling);
4037 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4039 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4040 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4042 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4043 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4045 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4047 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4048 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4052 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4053 return vm_call_cfunc_other(ec, reg_cfp, calling);
4060 RB_DEBUG_COUNTER_INC(ccf_ivar);
4062 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4069 RB_DEBUG_COUNTER_INC(ccf_attrset);
4070 VALUE val = *(cfp->sp - 1);
4072 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_cc_atomic_cache_read(cc));
4073 ID id = vm_cc_cme(cc)->def->body.attr.id;
4074 rb_check_frozen(obj);
4075 VALUE res = vm_setivar(obj, val, cache);
4083 res = vm_setivar_class(obj, val, cache);
4084 if (!UNDEF_P(res)) {
4091 res = vm_setivar_default(obj,
id, val, cache);
4092 if (!UNDEF_P(res)) {
4097 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4105 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4115 VALUE procv = cme->def->body.bmethod.proc;
4118 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4119 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4123 GetProcPtr(procv, proc);
4124 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4134 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4138 VALUE procv = cme->def->body.bmethod.proc;
4141 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4142 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4146 GetProcPtr(procv, proc);
4147 const struct rb_block *block = &proc->block;
4149 while (vm_block_type(block) == block_type_proc) {
4150 block = vm_proc_block(block->as.proc);
4152 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4155 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4156 VALUE *
const argv = cfp->sp - calling->argc;
4157 const int arg_size = ISEQ_BODY(iseq)->param.size;
4160 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4161 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4164 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4169 vm_push_frame(ec, iseq,
4170 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4172 VM_GUARDED_PREV_EP(captured->ep),
4174 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4176 ISEQ_BODY(iseq)->local_table_size - arg_size,
4177 ISEQ_BODY(iseq)->stack_max);
4185 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4189 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4190 if (UNLIKELY(calling->heap_argv)) {
4195 argc = calling->argc;
4198 cfp->sp += - argc - 1;
4201 return vm_call_bmethod_body(ec, calling, argv);
4207 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4211 VALUE procv = cme->def->body.bmethod.proc;
4213 GetProcPtr(procv, proc);
4214 const struct rb_block *block = &proc->block;
4216 while (vm_block_type(block) == block_type_proc) {
4217 block = vm_proc_block(block->as.proc);
4219 if (vm_block_type(block) == block_type_iseq) {
4220 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4221 return vm_call_iseq_bmethod(ec, cfp, calling);
4224 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4225 return vm_call_noniseq_bmethod(ec, cfp, calling);
4229rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4231 VALUE klass = current_class;
4239 while (
RTEST(klass)) {
4241 if (owner == target_owner) {
4247 return current_class;
4256 if (orig_me->defined_class == 0) {
4257 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4258 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4259 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4261 if (me->def->reference_count == 1) {
4262 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4266 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4274 VM_ASSERT(callable_method_entry_p(cme));
4281 return aliased_callable_method_entry(me);
4287 calling->cc = &VM_CC_ON_STACK(
Qundef,
4290 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4292 return vm_call_method_each_type(ec, cfp, calling);
4295static enum method_missing_reason
4298 enum method_missing_reason stat = MISSING_NOENTRY;
4299 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4300 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4301 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4311 ASSUME(calling->argc >= 0);
4313 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4314 int argc = calling->argc;
4315 VALUE recv = calling->recv;
4318 flags |= VM_CALL_OPT_SEND;
4320 if (UNLIKELY(! mid)) {
4321 mid = idMethodMissing;
4322 missing_reason = ci_missing_reason(ci);
4323 ec->method_missing_reason = missing_reason;
4326 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4328 rb_ary_unshift(argv_ary, symbol);
4331 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4332 VALUE exc = rb_make_no_method_exception(
4354 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4357 argc = ++calling->argc;
4362 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4363 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4364 VALUE exc = rb_make_no_method_exception(
4377 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4383 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4384 calling->cd = &new_fcd.cd;
4388 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4389 new_fcd.caller_ci = caller_ci;
4392 calling->cc = &VM_CC_ON_STACK(klass,
4394 { .method_missing_reason = missing_reason },
4395 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4397 if (flags & VM_CALL_FCALL) {
4398 return vm_call_method(ec, reg_cfp, calling);
4402 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4404 if (vm_cc_cme(cc) != NULL) {
4405 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4406 case METHOD_VISI_PUBLIC:
4407 return vm_call_method_each_type(ec, reg_cfp, calling);
4408 case METHOD_VISI_PRIVATE:
4409 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4411 case METHOD_VISI_PROTECTED:
4412 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4415 VM_UNREACHABLE(vm_call_method);
4417 return vm_call_method_missing(ec, reg_cfp, calling);
4420 return vm_call_method_nome(ec, reg_cfp, calling);
4430 i = calling->argc - 1;
4432 if (calling->argc == 0) {
4433 rb_raise(rb_eArgError,
"no method name given");
4457 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4463 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4465 int flags = VM_CALL_FCALL;
4469 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4470 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4472 flags |= VM_CALL_ARGS_SPLAT;
4473 if (calling->kw_splat) {
4474 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4475 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4476 calling->kw_splat = 0;
4478 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4481 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4482 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4488 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4489 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4495 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4498 int flags = vm_ci_flag(ci);
4500 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4501 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4502 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4503 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4504 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4505 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4508 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4509 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4514 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4516 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4518 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4519 unsigned int argc, flag;
4521 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4522 argc = ++calling->argc;
4525 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4526 vm_check_canary(ec, reg_cfp->sp);
4530 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4533 ec->method_missing_reason = reason;
4537 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4543 if (!(flag & VM_CALL_FORWARDING)) {
4544 calling->cd = &new_fcd.cd;
4548 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4549 new_fcd.caller_ci = caller_ci;
4553 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4554 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4555 return vm_call_method(ec, reg_cfp, calling);
4561 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4572 return vm_call_method_nome(ec, cfp, calling);
4574 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4575 cme->def->body.refined.orig_me) {
4576 cme = refined_method_callable_without_refinement(cme);
4579 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4581 return vm_call_method_each_type(ec, cfp, calling);
4585find_refinement(
VALUE refinements,
VALUE klass)
4587 if (
NIL_P(refinements)) {
4590 return rb_hash_lookup(refinements, klass);
4599 if (CFP_ISEQ(cfp) && ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_BLOCK) {
4600 const rb_iseq_t *local_iseq = ISEQ_BODY(CFP_ISEQ(cfp))->local_iseq;
4603 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4604 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4608 }
while (CFP_ISEQ(cfp) != local_iseq);
4619 if (orig_me->defined_class == 0) {
4627 VM_ASSERT(callable_method_entry_p(cme));
4629 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4639 ID mid = vm_ci_mid(calling->cd->ci);
4640 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4644 for (; cref; cref = CREF_NEXT(cref)) {
4645 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4646 if (
NIL_P(refinement))
continue;
4649 rb_callable_method_entry(refinement, mid);
4652 if (vm_cc_call(cc) == vm_call_super_method) {
4655 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4660 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4661 cme->def != ref_me->def) {
4664 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4673 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4674 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4689 if (calling->cd->cc) {
4690 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);
4692 return vm_call_method(ec, cfp, calling);
4695 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4696 calling->cc= ref_cc;
4697 return vm_call_method(ec, cfp, calling);
4701 return vm_call_method_nome(ec, cfp, calling);
4707NOINLINE(
static VALUE
4715 int argc = calling->argc;
4718 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4721 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4727 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4730 VALUE procval = calling->recv;
4731 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4737 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4739 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4742 enum ruby_basic_operators bop;
4743 switch (vm_ci_mid(ci)) {
4744 case idAREF: bop = BOP_AREF;
break;
4745 case idYield: bop = BOP_YIELD;
break;
4746 case idEqq: bop = BOP_EQQ;
break;
4747 default: bop = BOP_CALL;
break;
4750 if (BASIC_OP_UNREDEFINED_P(bop, PROC_REDEFINED_OP_FLAG)) {
4751 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4754 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4755 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4756 return vm_call_general(ec, reg_cfp, calling);
4763 VALUE recv = calling->recv;
4766 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4767 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4769 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4770 return RSTRUCT_GET_RAW(recv,
off);
4776 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4778 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4786 VALUE recv = calling->recv;
4789 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4790 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4792 rb_check_frozen(recv);
4794 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4795 RSTRUCT_SET_RAW(recv,
off, val);
4803 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4805 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4813#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4814 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4815 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4816 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4818 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4819 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4830 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4831 case OPTIMIZED_METHOD_TYPE_SEND:
4832 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4833 return vm_call_opt_send(ec, cfp, calling);
4834 case OPTIMIZED_METHOD_TYPE_CALL:
4835 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4836 return vm_call_opt_call(ec, cfp, calling);
4837 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4838 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4839 return vm_call_opt_block_call(ec, cfp, calling);
4840 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4841 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4845 VM_CALL_METHOD_ATTR(v,
4846 vm_call_opt_struct_aref(ec, cfp, calling),
4847 set_vm_cc_ivar(cc); \
4848 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4851 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4852 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4856 VM_CALL_METHOD_ATTR(v,
4857 vm_call_opt_struct_aset(ec, cfp, calling),
4858 set_vm_cc_ivar(cc); \
4859 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4863 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4875 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4877 switch (cme->def->type) {
4878 case VM_METHOD_TYPE_ISEQ:
4879 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4880 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4881 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4884 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4885 return vm_call_iseq_setup(ec, cfp, calling);
4888 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4889 case VM_METHOD_TYPE_CFUNC:
4890 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4891 return vm_call_cfunc(ec, cfp, calling);
4893 case VM_METHOD_TYPE_ATTRSET:
4894 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4898 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4900 if (vm_cc_markable(cc)) {
4901 vm_cc_attr_index_set(cc, IVAR_CACHE_INIT);
4902 VM_CALL_METHOD_ATTR(v,
4903 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4904 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4910 VM_CALLCACHE_UNMARKABLE |
4911 VM_CALLCACHE_ON_STACK,
4917 .value = IVAR_CACHE_INIT,
4922 VM_CALL_METHOD_ATTR(v,
4923 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4924 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4928 case VM_METHOD_TYPE_IVAR:
4929 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4931 vm_cc_attr_index_set(cc, rb_getivar_cache_pack(ROOT_SHAPE_ID, ATTR_INDEX_NOT_SET));
4932 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4933 VM_CALL_METHOD_ATTR(v,
4934 vm_call_ivar(ec, cfp, calling),
4935 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4938 case VM_METHOD_TYPE_MISSING:
4939 vm_cc_method_missing_reason_set(cc, 0);
4940 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4941 return vm_call_method_missing(ec, cfp, calling);
4943 case VM_METHOD_TYPE_BMETHOD:
4944 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4945 return vm_call_bmethod(ec, cfp, calling);
4947 case VM_METHOD_TYPE_ALIAS:
4948 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4949 return vm_call_alias(ec, cfp, calling);
4951 case VM_METHOD_TYPE_OPTIMIZED:
4952 return vm_call_optimized(ec, cfp, calling, ci, cc);
4954 case VM_METHOD_TYPE_UNDEF:
4957 case VM_METHOD_TYPE_ZSUPER:
4958 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4960 case VM_METHOD_TYPE_REFINED:
4963 return vm_call_refined(ec, cfp, calling);
4966 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4976 const int stat = ci_missing_reason(ci);
4978 if (vm_ci_mid(ci) == idMethodMissing) {
4979 if (UNLIKELY(calling->heap_argv)) {
4984 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4985 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4989 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
5001 VALUE defined_class = me->defined_class;
5002 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
5003 return NIL_P(refined_class) ? defined_class : refined_class;
5012 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5014 if (vm_cc_cme(cc) != NULL) {
5015 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5016 case METHOD_VISI_PUBLIC:
5017 return vm_call_method_each_type(ec, cfp, calling);
5019 case METHOD_VISI_PRIVATE:
5020 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5021 enum method_missing_reason stat = MISSING_PRIVATE;
5022 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5024 vm_cc_method_missing_reason_set(cc, stat);
5025 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5026 return vm_call_method_missing(ec, cfp, calling);
5028 return vm_call_method_each_type(ec, cfp, calling);
5030 case METHOD_VISI_PROTECTED:
5031 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5032 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5034 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5035 return vm_call_method_missing(ec, cfp, calling);
5039 VM_ASSERT(vm_cc_cme(cc) != NULL);
5042 calling->cc = &cc_on_stack;
5043 return vm_call_method_each_type(ec, cfp, calling);
5046 return vm_call_method_each_type(ec, cfp, calling);
5049 rb_bug(
"unreachable");
5053 return vm_call_method_nome(ec, cfp, calling);
5060 RB_DEBUG_COUNTER_INC(ccf_general);
5061 return vm_call_method(ec, reg_cfp, calling);
5067 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5068 VM_ASSERT(cc != vm_cc_empty());
5070 *(vm_call_handler *)&cc->call_ = vm_call_general;
5076 RB_DEBUG_COUNTER_INC(ccf_super_method);
5081 if (ec == NULL) rb_bug(
"unreachable");
5084 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5085 return vm_call_method(ec, reg_cfp, calling);
5091vm_search_normal_superclass(
VALUE klass)
5093 if (RICLASS_FOR_REFINEMENT_P(klass)) {
5094 klass =
RBASIC(klass)->klass;
5096 klass = RCLASS_ORIGIN(klass);
5100NORETURN(
static void vm_super_outside(
void));
5103vm_super_outside(
void)
5109empty_cc_for_super(
void)
5111 return &vm_empty_cc_for_super;
5117 VALUE current_defined_class;
5118 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
5125 current_defined_class = vm_defined_class_for_protected_call(me);
5128 iseq != method_entry_iseqptr(me) &&
5131 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5135 "self has wrong type to call super in this context: "
5136 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5141 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5143 "implicit argument passing of super from method defined"
5144 " by define_method() is not supported."
5145 " Specify all arguments explicitly.");
5148 ID mid = me->def->original_id;
5150 if (!vm_ci_markable(cd->ci)) {
5151 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5155 cd->ci = vm_ci_new_runtime(mid,
5158 vm_ci_kwarg(cd->ci));
5165 VALUE klass = vm_search_normal_superclass(me->defined_class);
5169 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5174 RCLASS_INCLUDER(me->defined_class) == 0) {
5176 "super in a method in a module that has been refined and that is called via super"
5177 " from a refinement method is not supported.");
5180 cc = vm_search_method_fastpath(reg_cfp, cd, klass);
5184 if (cached_cme == NULL) {
5186 cd->cc = empty_cc_for_super();
5188 else if (cached_cme->called_id != mid) {
5191 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5195 cd->cc = cc = empty_cc_for_super();
5199 switch (cached_cme->def->type) {
5201 case VM_METHOD_TYPE_REFINED:
5203 case VM_METHOD_TYPE_ATTRSET:
5204 case VM_METHOD_TYPE_IVAR:
5205 vm_cc_call_set(cc, vm_call_super_method);
5213 VM_ASSERT((vm_cc_cme(cc),
true));
5221block_proc_is_lambda(
const VALUE procval)
5226 GetProcPtr(procval, proc);
5227 return proc->header.is_lambda;
5237 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5240 int is_lambda = FALSE;
5241 VALUE val, arg, blockarg;
5243 const struct vm_ifunc *ifunc = captured->code.ifunc;
5248 else if (argc == 0) {
5255 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5257 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5259 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5262 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5265 VM_GUARDED_PREV_EP(captured->ep),
5267 0, ec->cfp->sp, 0, 0);
5268 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5269 rb_vm_pop_frame(ec);
5277 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5283 VALUE passed_proc = rb_vm_bh_to_procval(ec, block_handler);
5285 if (!rb_box_available()) {
5286 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5298 box = current_box_on_cfp(ec, ruby_cfp);
5299 if (BOX_USER_P(box)) {
5302 ruby_cfp = rb_vm_get_ruby_level_next_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ruby_cfp));
5306 if (!ruby_cfp || !box) {
5307 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5315 const rb_iseq_t *caller_iseq = CFP_ISEQ(ruby_cfp);
5316 VALUE name = rb_sprintf(
"block in %"PRIsVALUE, rb_iseq_label(caller_iseq));
5318 rb_iseq_path(caller_iseq), rb_iseq_realpath(caller_iseq),
5319 rb_vm_get_sourceline(ruby_cfp), caller_iseq, 0,
5320 ISEQ_TYPE_BLOCK, NULL,
Qnil);
5322 enum ruby_tag_type state;
5324 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_FINISH,
5325 ruby_cfp->self, VM_GUARDED_PREV_EP(ruby_cfp->ep),
5327 ISEQ_BODY(iseq)->iseq_encoded, reg_cfp->sp,
5328 ISEQ_BODY(iseq)->local_table_size, ISEQ_BODY(iseq)->stack_max);
5336 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
5337 val = rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5341 if (state != TAG_NONE) {
5343 EC_JUMP_TAG(ec, state);
5346 rb_vm_pop_frame(ec);
5357 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5359 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5367vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5369 VALUE ary, arg0 = argv[0];
5374 VM_ASSERT(argv[0] == arg0);
5382 if (rb_simple_iseq_p(iseq)) {
5386 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5388 if (arg_setup_type == arg_setup_block &&
5389 calling->argc == 1 &&
5390 ISEQ_BODY(iseq)->param.flags.has_lead &&
5391 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5392 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5393 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5396 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5397 if (arg_setup_type == arg_setup_block) {
5398 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5400 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5401 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5402 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5404 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5405 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5409 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5416 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5425 calling = &calling_entry;
5426 calling->argc = argc;
5427 calling->block_handler = block_handler;
5428 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5430 calling->heap_argv = 0;
5432 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5434 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5445 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5446 const int arg_size = ISEQ_BODY(iseq)->param.size;
5447 VALUE *
const rsp = GET_SP() - calling->argc;
5448 VALUE *
const argv = rsp;
5449 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5450 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5455 vm_push_frame(ec, iseq,
5458 VM_GUARDED_PREV_EP(captured->ep), (
VALUE)cref,
5459 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5461 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5469 bool is_lambda,
VALUE block_handler)
5471 return vm_invoke_iseq_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler, NULL);
5477 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5479 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5480 int flags = vm_ci_flag(ci);
5482 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5483 ((calling->argc == 0) ||
5484 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5485 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5486 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5487 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5489 if (UNLIKELY(calling->heap_argv)) {
5490#if VM_ARGC_STACK_MAX < 0
5492 rb_raise(rb_eArgError,
"no receiver given");
5498 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5499 reg_cfp->sp[-2] = calling->recv;
5500 flags |= VM_CALL_ARGS_SPLAT;
5503 if (calling->argc < 1) {
5504 rb_raise(rb_eArgError,
"no receiver given");
5506 calling->recv = TOPN(--calling->argc);
5508 if (calling->kw_splat) {
5509 flags |= VM_CALL_KW_SPLAT;
5513 if (calling->argc < 1) {
5514 rb_raise(rb_eArgError,
"no receiver given");
5516 calling->recv = TOPN(--calling->argc);
5519 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5525 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5530 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5531 argc = calling->argc;
5532 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);
5538vm_block_to_block_handler(
const struct rb_block *block)
5540 switch (vm_block_type(block)) {
5541 case block_type_iseq:
5542 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5543 case block_type_ifunc:
5544 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5545 case block_type_symbol:
5546 return VM_BH_FROM_SYMBOL(block->as.symbol);
5547 case block_type_proc:
5548 return VM_BH_FROM_PROC(block->as.proc);
5550 VM_UNREACHABLE(vm_yield_with_proc);
5555vm_proc_to_block_handler(
VALUE procval)
5557 return vm_block_to_block_handler(vm_proc_block(procval));
5560NOINLINE(
static VALUE
5563 bool is_lambda,
VALUE block_handler,
VALUE refined_procval));
5567 bool is_lambda,
VALUE block_handler,
VALUE refined_procval)
5569 const rb_cref_t *cref = rb_proc_refinements_cref_for_call(refined_procval);
5570 return vm_invoke_iseq_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler, cref);
5576 bool is_lambda,
VALUE block_handler)
5578 VALUE refined_procval = 0;
5580 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5581 VALUE procval = VM_BH_TO_PROC(block_handler);
5583 GetProcPtr(procval, po);
5584 if (po->header.is_refined) refined_procval = procval;
5585 is_lambda = po->header.is_lambda;
5586 block_handler = vm_block_to_block_handler(&po->block);
5589 if (UNLIKELY(refined_procval) && vm_block_handler_type(block_handler) == block_handler_type_iseq) {
5591 return vm_invoke_proc_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler,
5595 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5601 bool is_lambda,
VALUE block_handler)
5605 bool is_lambda,
VALUE block_handler);
5607 switch (vm_block_handler_type(block_handler)) {
5608 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5609 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5610 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5611 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5612 default: rb_bug(
"vm_invoke_block: unreachable");
5615 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5619vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5626 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5629 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5630 captured->code.iseq = blockiseq;
5632 return rb_vm_make_proc(ec, captured,
rb_cProc);
5636vm_once_exec(
VALUE iseq)
5642#define RUNNING_THREAD_ONCE_DONE ((rb_thread_t *)0x1)
5658vm_once_wait_no_gvl(
void *ptr)
5665 running_th = rbimpl_atomic_ptr_load((
void **)&arg->is->once.running_thread, RBIMPL_ATOMIC_ACQUIRE);
5666 if (running_th != NULL && running_th != RUNNING_THREAD_ONCE_DONE) {
5674vm_once_wait_ubf(
void *ptr)
5676 vm_once_broadcast((
rb_vm_t *)ptr);
5680vm_once_clear(
VALUE data)
5683 rbimpl_atomic_ptr_store((
volatile void **)&is->once.running_thread, NULL, RBIMPL_ATOMIC_RELEASE);
5684 vm_once_broadcast(GET_VM());
5696 args[0] = obj; args[1] =
Qfalse;
5698 if (!UNDEF_P(r) &&
RTEST(r)) {
5710 enum defined_type
type = (
enum defined_type)op_type;
5717 return rb_gvar_defined(
SYM2ID(obj));
5719 case DEFINED_CVAR: {
5720 const rb_cref_t *cref = vm_get_cref(GET_EP());
5721 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5726 case DEFINED_CONST_FROM: {
5727 bool allow_nil =
type == DEFINED_CONST;
5729 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5734 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5736 case DEFINED_METHOD:{
5741 switch (METHOD_ENTRY_VISI(cme)) {
5742 case METHOD_VISI_PRIVATE:
5744 case METHOD_VISI_PROTECTED:
5748 case METHOD_VISI_PUBLIC:
5752 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(cme));
5756 return check_respond_to_missing(obj, v);
5761 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5765 case DEFINED_ZSUPER:
5770 VALUE klass = vm_search_normal_superclass(me->defined_class);
5771 if (!klass)
return false;
5773 ID id = me->def->original_id;
5780 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5782 rb_bug(
"unimplemented defined? type (VM)");
5792 return vm_defined(ec, reg_cfp, op_type, obj, v);
5796vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5799 const VALUE *ep = reg_ep;
5800 for (i = 0; i < lv; i++) {
5801 ep = GET_PREV_EP(ep);
5807vm_get_special_object(
const VALUE *
const reg_ep,
5808 enum vm_special_object_type
type)
5811 case VM_SPECIAL_OBJECT_VMCORE:
5812 return rb_mRubyVMFrozenCore;
5813 case VM_SPECIAL_OBJECT_CBASE:
5814 return vm_get_cbase(reg_ep);
5815 case VM_SPECIAL_OBJECT_CONST_BASE:
5816 return vm_get_const_base(reg_ep);
5818 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5825rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5827 return vm_get_special_object(reg_ep,
type);
5833 const VALUE ary2 = ary2st;
5834 VALUE tmp1 = rb_check_to_array(ary1);
5835 VALUE tmp2 = rb_check_to_array(ary2);
5856 const VALUE ary2 = ary2st;
5858 if (
NIL_P(ary2))
return ary1;
5860 VALUE tmp2 = rb_check_to_array(ary2);
5875 return vm_concat_array(ary1, ary2st);
5879rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5881 return vm_concat_to_array(ary1, ary2st);
5890 VALUE tmp = rb_check_to_array(ary);
5894 else if (
RTEST(flag)) {
5907 return vm_splat_array(flag, ary);
5913 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5915 if (flag & VM_CHECKMATCH_ARRAY) {
5919 for (i = 0; i < n; i++) {
5921 VALUE c = check_match(ec, v, target,
type);
5930 return check_match(ec, pattern, target,
type);
5937 return vm_check_match(ec, target, pattern, flag);
5941vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5943 const VALUE kw_bits = *(ep - bits);
5946 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5947 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5960 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5961 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5962 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5963 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5967 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5970 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5973 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5976 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5983vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5988 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5989 return rb_public_const_get_at(cbase,
id);
5997vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
6002 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
6007 "superclass mismatch for class %"PRIsVALUE
"",
6020vm_check_if_module(
ID id,
VALUE mod)
6039vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
6042 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super :
rb_cObject;
6049vm_declare_module(
ID id,
VALUE cbase)
6055NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
6059 VALUE name = rb_id2str(
id);
6060 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
6062 VALUE location = rb_const_source_location_at(cbase,
id);
6063 if (!
NIL_P(location)) {
6064 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
6065 " previous definition of %"PRIsVALUE
" was here",
6072vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
6076 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
6078 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
6082 vm_check_if_namespace(cbase);
6087 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
6088 if (!vm_check_if_class(
id, flags, super, klass))
6089 unmatched_redefinition(
"class", cbase,
id, klass);
6093 return vm_declare_class(
id, flags, cbase, super);
6098vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
6102 vm_check_if_namespace(cbase);
6103 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
6104 if (!vm_check_if_module(
id, mod))
6105 unmatched_redefinition(
"module", cbase,
id, mod);
6109 return vm_declare_module(
id, cbase);
6114vm_find_or_create_class_by_id(
ID id,
6119 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
6122 case VM_DEFINECLASS_TYPE_CLASS:
6124 return vm_define_class(
id, flags, cbase, super);
6126 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
6130 case VM_DEFINECLASS_TYPE_MODULE:
6132 return vm_define_module(
id, flags, cbase);
6135 rb_bug(
"unknown defineclass type: %d", (
int)
type);
6139static rb_method_visibility_t
6144 if (!vm_env_cref_by_cref(cfp->ep)) {
6145 return METHOD_VISI_PUBLIC;
6148 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6157 if (!vm_env_cref_by_cref(cfp->ep)) {
6161 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6169 rb_method_visibility_t visi;
6174 visi = METHOD_VISI_PUBLIC;
6177 klass = CREF_CLASS_FOR_DEFINITION(cref);
6178 visi = vm_scope_visibility_get(ec);
6185 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6188 !RCLASS_SINGLETON_P(klass) && !RCLASS_EXPECT_NO_IVAR(klass) &&
6190 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6193 if (!is_singleton && vm_scope_module_func_check(ec)) {
6195 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6204rb_vm_untag_block_handler(
VALUE block_handler)
6206 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6208 switch (vm_block_handler_type(block_handler)) {
6209 case block_handler_type_iseq:
6210 case block_handler_type_ifunc: {
6212 return captured->code.val;
6214 case block_handler_type_proc:
6215 case block_handler_type_symbol:
6216 return block_handler;
6218 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6225 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6234 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6236 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6237 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6240 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6244enum method_explorer_type {
6246 mexp_search_invokeblock,
6253 enum method_explorer_type method_explorer));
6259 VALUE block_handler,
6260 enum method_explorer_type method_explorer
6265 int argc = vm_ci_argc(ci);
6266 VALUE recv = TOPN(argc);
6268 .block_handler = block_handler,
6269 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6275 switch (method_explorer) {
6276 case mexp_search_method:
6277 calling.cc = cc = vm_search_method_fastpath(reg_cfp, cd,
CLASS_OF(recv));
6278 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6280 case mexp_search_super:
6281 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6282 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6284 case mexp_search_invokeblock:
6285 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6295 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6296 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6310 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6312 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6314 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6315 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6326 VALUE bh = VM_BLOCK_HANDLER_NONE;
6327 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6337 struct rb_callinfo adjusted_ci = VM_CI_ON_STACK(vm_ci_mid(cd->ci),
6340 vm_ci_kwarg(cd->ci));
6341 const struct rb_callcache *original_cc = rbimpl_atomic_ptr_load((
void **)&cd->cc, RBIMPL_ATOMIC_ACQUIRE);
6347 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), adjusted_cd.ci, blockiseq,
true);
6348 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd, bh, mexp_search_super);
6350 if (original_cc != adjusted_cd.cc && vm_cc_markable(adjusted_cd.cc)) {
6351 rbimpl_atomic_ptr_store((
volatile void **)&cd->cc, (
void *)adjusted_cd.cc, RBIMPL_ATOMIC_RELEASE);
6367 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6369 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6371 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6372 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6383 VALUE bh = VM_BLOCK_HANDLER_NONE;
6384 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6412 if (check_method_basic_definition(cme)) {
6418 if (check_cfunc(cme, rb_mod_to_s)) {
6424 val = rb_mod_to_s(recv);
6430 if (check_cfunc(cme, rb_nil_to_s)) {
6431 return rb_nil_to_s(recv);
6435 if (check_cfunc(cme, rb_true_to_s)) {
6436 return rb_true_to_s(recv);
6440 if (check_cfunc(cme, rb_false_to_s)) {
6441 return rb_false_to_s(recv);
6445 if (check_cfunc(cme, rb_int_to_s)) {
6446 return rb_fix_to_s(recv);
6458 return vm_objtostring(reg_cfp, recv, cd);
6462vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6464 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6473vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6475 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6484vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6486 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6500 if (OP_UNREDEFINED_P(INCLUDE_P, ARRAY)) {
6504 VALUE args[1] = {target};
6507 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6510 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6517 return vm_opt_duparray_include_p(ec, ary, target);
6523 if (OP_UNREDEFINED_P(MAX, ARRAY)) {
6524 if (array_len == 0) {
6528 VALUE result = *ptr;
6529 rb_snum_t i = array_len - 1;
6531 const VALUE v = *++ptr;
6532 if (OPTIMIZED_CMP(v, result) > 0) {
6547 return vm_opt_newarray_max(ec, array_len, ptr);
6553 if (OP_UNREDEFINED_P(MIN, ARRAY)) {
6554 if (array_len == 0) {
6558 VALUE result = *ptr;
6559 rb_snum_t i = array_len - 1;
6561 const VALUE v = *++ptr;
6562 if (OPTIMIZED_CMP(v, result) < 0) {
6577 return vm_opt_newarray_min(ec, array_len, ptr);
6584 if (OP_UNREDEFINED_P(HASH, ARRAY)) {
6585 return rb_ary_hash_values(array_len, ptr);
6595 return vm_opt_newarray_hash(ec, array_len, ptr);
6604 if (OP_UNREDEFINED_P(INCLUDE_P, ARRAY)) {
6605 struct RArray fake_ary = {RBASIC_INIT};
6606 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6610 VALUE args[1] = {target};
6618 return vm_opt_newarray_include_p(ec, array_len,
ptr, target);
6624 if (OP_UNREDEFINED_P(PACK, ARRAY)) {
6625 struct RArray fake_ary = {RBASIC_INIT};
6626 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6627 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6637 if (!UNDEF_P(buffer)) {
6638 args[1] = rb_hash_new_capa(1);
6639 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6644 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len,
ptr), idPack, argc, args, kw_splat);
6651 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt, buffer);
6657 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt,
Qundef);
6663vm_track_constant_cache(
ID id,
void *ic)
6666 struct rb_id_table *const_cache = &vm->constant_cache;
6667 VALUE lookup_result;
6670 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6674 ics = set_init_numtable();
6675 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6690 vm->inserting_constant_cache_id = id;
6692 set_insert(ics, (st_data_t)ic);
6694 vm->inserting_constant_cache_id = (
ID)0;
6701 for (
int i = 0; segments[i]; i++) {
6702 ID id = segments[i];
6703 if (
id == idNULL)
continue;
6704 vm_track_constant_cache(
id, ic);
6713 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6714 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6716 return (ic_cref == NULL ||
6717 ic_cref == vm_get_cref(reg_ep));
6725 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6726 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6731rb_vm_ic_hit_p(
IC ic,
const VALUE *reg_ep)
6733 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6739 if (ruby_vm_const_missing_count > 0) {
6740 ruby_vm_const_missing_count = 0;
6747 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6751 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6755 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6756 rb_yjit_constant_ic_update(iseq, ic, pos);
6766 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6773 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments) || rb_multi_ractor_p());
6776 ruby_vm_constant_cache_misses++;
6777 val = vm_get_ev_const_chain(ec, segments);
6778 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6781 vm_ic_update(CFP_ISEQ(GET_CFP()), ic, val, GET_EP(), CFP_PC(GET_CFP()) - 2);
6793 running_th = rbimpl_atomic_ptr_load((
void**)&is->once.running_thread, RBIMPL_ATOMIC_ACQUIRE);
6794 if (running_th == RUNNING_THREAD_ONCE_DONE) {
6795 return is->once.value;
6797 else if (running_th == NULL) {
6799 enum ruby_tag_type state;
6800 if (rbimpl_atomic_ptr_cas((
void**)&is->once.running_thread, running_th, th, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED) != running_th) {
6804 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
6805 val = vm_once_exec((
VALUE)iseq);
6808 if (state != TAG_NONE) {
6809 vm_once_clear((
VALUE)is);
6810 EC_JUMP_TAG(ec, state);
6815 RB_OBJ_SET_SHAREABLE(val);
6820 rbimpl_atomic_ptr_store((
volatile void**)&is->once.running_thread, RUNNING_THREAD_ONCE_DONE, RBIMPL_ATOMIC_RELEASE);
6821 vm_once_broadcast(rb_ec_vm_ptr(ec));
6824 else if (running_th == th) {
6826 return vm_once_exec((
VALUE)iseq);
6831 rb_nogvl(vm_once_wait_no_gvl, &arg, vm_once_wait_ubf, arg.vm,
6833 RUBY_VM_CHECK_INTS(ec);
6839vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6841 switch (OBJ_BUILTIN_TYPE(key)) {
6847 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6848 SYMBOL_REDEFINED_OP_FLAG |
6849 INTEGER_REDEFINED_OP_FLAG |
6850 FLOAT_REDEFINED_OP_FLAG |
6851 NIL_REDEFINED_OP_FLAG |
6852 TRUE_REDEFINED_OP_FLAG |
6853 FALSE_REDEFINED_OP_FLAG |
6854 STRING_REDEFINED_OP_FLAG)) {
6858 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6862 if (st_lookup(rb_imemo_cdhash_tbl(hash), key, &val)) {
6882 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6883 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6884 static const char stack_consistency_error[] =
6885 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6886#if defined RUBY_DEVEL
6887 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6892 rb_bug(stack_consistency_error, nsp, nbp);
6899 if (FIXNUM_2_P(recv, obj) &&
6900 OP_UNREDEFINED_P(PLUS, INTEGER)) {
6901 return rb_fix_plus_fix(recv, obj);
6903 else if (FLONUM_2_P(recv, obj) &&
6904 OP_UNREDEFINED_P(PLUS, FLOAT)) {
6912 OP_UNREDEFINED_P(PLUS, FLOAT)) {
6917 OP_UNREDEFINED_P(PLUS, STRING)) {
6918 return rb_str_opt_plus(recv, obj);
6922 OP_UNREDEFINED_P(PLUS, ARRAY)) {
6933 if (FIXNUM_2_P(recv, obj) &&
6934 OP_UNREDEFINED_P(MINUS, INTEGER)) {
6935 return rb_fix_minus_fix(recv, obj);
6937 else if (FLONUM_2_P(recv, obj) &&
6938 OP_UNREDEFINED_P(MINUS, FLOAT)) {
6946 OP_UNREDEFINED_P(MINUS, FLOAT)) {
6957 if (FIXNUM_2_P(recv, obj) &&
6958 OP_UNREDEFINED_P(MULT, INTEGER)) {
6959 return rb_fix_mul_fix(recv, obj);
6961 else if (FLONUM_2_P(recv, obj) &&
6962 OP_UNREDEFINED_P(MULT, FLOAT)) {
6970 OP_UNREDEFINED_P(MULT, FLOAT)) {
6981 if (FIXNUM_2_P(recv, obj) &&
6982 OP_UNREDEFINED_P(DIV, INTEGER)) {
6983 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6985 else if (FLONUM_2_P(recv, obj) &&
6986 OP_UNREDEFINED_P(DIV, FLOAT)) {
6987 return rb_flo_div_flo(recv, obj);
6994 OP_UNREDEFINED_P(DIV, FLOAT)) {
6995 return rb_flo_div_flo(recv, obj);
7005 if (FIXNUM_2_P(recv, obj) &&
7006 OP_UNREDEFINED_P(MOD, INTEGER)) {
7007 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
7009 else if (FLONUM_2_P(recv, obj) &&
7010 OP_UNREDEFINED_P(MOD, FLOAT)) {
7018 OP_UNREDEFINED_P(MOD, FLOAT)) {
7029 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not_equal)) {
7030 VALUE val = opt_equality(reg_cfp, recv, obj, cd_eq);
7032 if (!UNDEF_P(val)) {
7033 return RBOOL(!
RTEST(val));
7043 if (FIXNUM_2_P(recv, obj) &&
7044 OP_UNREDEFINED_P(LT, INTEGER)) {
7047 else if (FLONUM_2_P(recv, obj) &&
7048 OP_UNREDEFINED_P(LT, FLOAT)) {
7056 OP_UNREDEFINED_P(LT, FLOAT)) {
7067 if (FIXNUM_2_P(recv, obj) &&
7068 OP_UNREDEFINED_P(LE, INTEGER)) {
7071 else if (FLONUM_2_P(recv, obj) &&
7072 OP_UNREDEFINED_P(LE, FLOAT)) {
7080 OP_UNREDEFINED_P(LE, FLOAT)) {
7091 if (FIXNUM_2_P(recv, obj) &&
7092 OP_UNREDEFINED_P(GT, INTEGER)) {
7095 else if (FLONUM_2_P(recv, obj) &&
7096 OP_UNREDEFINED_P(GT, FLOAT)) {
7104 OP_UNREDEFINED_P(GT, FLOAT)) {
7115 if (FIXNUM_2_P(recv, obj) &&
7116 OP_UNREDEFINED_P(GE, INTEGER)) {
7119 else if (FLONUM_2_P(recv, obj) &&
7120 OP_UNREDEFINED_P(GE, FLOAT)) {
7128 OP_UNREDEFINED_P(GE, FLOAT)) {
7144 OP_UNREDEFINED_P(LTLT, STRING)) {
7153 OP_UNREDEFINED_P(LTLT, ARRAY)) {
7171 OP_UNREDEFINED_P(AND, INTEGER)) {
7182 if (FIXNUM_2_P(recv, obj) &&
7183 OP_UNREDEFINED_P(OR, INTEGER)) {
7195 if (FIXNUM_2_P(recv, obj) &&
7196 OP_UNREDEFINED_P(AREF, INTEGER)) {
7197 return rb_fix_aref(recv, obj);
7202 OP_UNREDEFINED_P(AREF, ARRAY)) {
7204 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7207 return rb_ary_aref1(recv, obj);
7211 OP_UNREDEFINED_P(AREF, HASH)) {
7212 return rb_hash_aref(recv, obj);
7226 OP_UNREDEFINED_P(ASET, ARRAY) &&
7232 OP_UNREDEFINED_P(ASET, HASH)) {
7233 rb_hash_aset(recv, obj, set);
7242vm_opt_length(
VALUE recv,
int bop)
7248 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7249 if (bop == BOP_EMPTY_P) {
7250 return LONG2NUM(RSTRING_LEN(recv));
7257 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7261 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7270vm_opt_empty_p(
VALUE recv)
7272 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7285 OP_UNREDEFINED_P(
NIL_P, NIL)) {
7288 else if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_false)) {
7304 case RSHIFT(~0UL, 1):
7307 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7325vm_opt_succ(
VALUE recv)
7328 OP_UNREDEFINED_P(SUCC, INTEGER)) {
7329 return fix_succ(recv);
7335 OP_UNREDEFINED_P(SUCC, STRING)) {
7346 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not)) {
7347 return RBOOL(!
RTEST(recv));
7362 OP_UNREDEFINED_P(MATCH, STRING)) {
7366 OP_UNREDEFINED_P(MATCH, REGEXP)) {
7374#undef EQ_UNREDEFINED_P
7375#undef OP_UNREDEFINED_P
7387 VALUE self = GET_SELF();
7389 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7391 if (local_hooks) local_hooks->running++;
7393 if (event & global_hooks->events) {
7396 vm_dtrace(event, ec);
7397 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7401 if (local_hooks) local_hooks->running--;
7402 if (local_hooks != NULL) {
7403 if (event & local_hooks->events) {
7406 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7416#define VM_TRACE_HOOK(target_event, val) do { \
7417 if ((pc_events & (target_event)) & enabled_flags) { \
7418 if (local_hooks_cnt > 0) local_hooks = rb_iseq_local_hooks(iseq, r, false); \
7419 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7426 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7427 VM_ASSERT(ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_RESCUE);
7428 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7434 const VALUE *pc = reg_cfp->pc;
7436 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7439 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7443 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
7444 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7446 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7448 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7450 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7454 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7458 unsigned int bmethod_hooks_cnt = 0;
7460 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7461 enabled_flags |= iseq_local_events;
7463 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7465 if (bmethod_frame) {
7467 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7468 bmethod_def = me->def;
7469 bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7470 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7472 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7475 if (bmethod_local_hooks) {
7476 bmethod_local_events = bmethod_local_hooks->events;
7481 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7485 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7493 else if (ec->trace_arg != NULL) {
7501 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7504 VALUE path = rb_iseq_path(iseq);
7505 VALUE label = rb_iseq_label(iseq);
7506 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %.*s:%d %.*s\n",
7510 (
int)rb_iseq_line_no(iseq, pos),
7513 VM_ASSERT(reg_cfp->pc == pc);
7514 VM_ASSERT(pc_events != 0);
7524 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7525 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7531 if (bmethod_hooks_cnt > 0) bmethod_local_hooks = rb_method_def_local_hooks(bmethod_def, r,
false);
7539#if VM_CHECK_MODE > 0
7540NORETURN( NOINLINE( COLDFUNC
7541void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7544Init_vm_stack_canary(
void)
7547 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7548 vm_stack_canary |= 0x01;
7550 vm_stack_canary_was_born =
true;
7555rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7559 const char *insn = rb_insns_name(i);
7563 rb_bug(
"dead canary found at %s: %s", insn, str);
7567void Init_vm_stack_canary(
void) { }
7599 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7606 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7613 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7620 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7627 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7634 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7641 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7648 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7655 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7661 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);
7662 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]);
7668 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);
7669 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]);
7675 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);
7676 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]);
7682 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);
7683 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]);
7689 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);
7690 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]);
7696 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);
7697 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]);
7703 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);
7704 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]);
7709static builtin_invoker
7710lookup_builtin_invoker(
int argc)
7712 static const builtin_invoker invokers[] = {
7731 return invokers[argc];
7737 const bool canary_p = ISEQ_BODY(CFP_ISEQ(reg_cfp))->builtin_attrs & BUILTIN_ATTR_LEAF;
7738 SETUP_CANARY(canary_p);
7739 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7740 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7741 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7748 return invoke_bf(ec, cfp, bf, argv);
7755 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7756 for (
int i=0; i<bf->argc; i++) {
7757 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(CFP_ISEQ(cfp))->local_table[i+start_index]));
7759 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7760 (
void *)(uintptr_t)bf->func_ptr);
7763 if (bf->argc == 0) {
7764 return invoke_bf(ec, cfp, bf, NULL);
7767 const VALUE *argv = cfp->ep - ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7768 return invoke_bf(ec, cfp, bf, argv);
7778 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 VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags)
This is an implementation detail of RB_FL_TEST().
static bool RB_FL_ABLE(VALUE obj)
Checks if the object is flaggable.
@ RUBY_FL_SHAREABLE
This flag has something to do with Ractor.
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 UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define CLASS_OF
Old name of rb_class_of.
#define T_NONE
Old name of RUBY_T_NONE.
#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_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.
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.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
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 RB_NOGVL_UBF_ASYNC_SAFE
Passing this flag to rb_nogvl() indicates that the passed UBF is async-signal-safe.
#define RB_NOGVL_INTR_FAIL
Passing this flag to rb_nogvl() prevents it from processing interrupts after the given function retur...
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Identical to rb_thread_call_without_gvl(), except it additionally takes "flags" that change the behav...
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RARRAY_LEN
Just another name of rb_array_len.
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 int RSTRING_LENINT(VALUE str)
Identical to RSTRING_LEN(), except it differs for the return type.
#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 Ruby Box.
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
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_lock.
void rb_native_cond_broadcast(rb_nativethread_cond_t *cond)
Signals a condition variable.
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_unlock.
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
Waits for the passed condition variable to be signalled.
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.