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.h"
30#include "internal/set_table.h"
31#include "internal/struct.h"
37#include "insns_info.inc"
43 int argc,
const VALUE *argv,
int priv);
53ruby_vm_special_exception_copy(
VALUE exc)
56 rb_obj_copy_ivar(e, exc);
64 VALUE mesg = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_sysstack];
65 ec->raised_flag = RAISED_STACKOVERFLOW;
67 VALUE at = rb_ec_backtrace_object(ec);
68 mesg = ruby_vm_special_exception_copy(mesg);
73 EC_JUMP_TAG(ec, TAG_RAISE);
76NORETURN(
static void vm_stackoverflow(
void));
81 ec_stack_overflow(GET_EC(), TRUE);
88 rb_bug(
"system stack overflow during GC. Faulty native extension?");
90 if (crit >= rb_stack_overflow_fatal) {
91 ec->raised_flag = RAISED_STACKOVERFLOW;
92 ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
93 EC_JUMP_TAG(ec, TAG_RAISE);
95 ec_stack_overflow(ec, crit < rb_stack_overflow_signal);
102callable_class_p(
VALUE klass)
104#if VM_CHECK_MODE >= 2
105 if (!klass)
return FALSE;
133 VM_ASSERT(IMEMO_TYPE_P((
VALUE)cme, imemo_ment),
"imemo_type:%s", rb_imemo_name(imemo_type((
VALUE)cme)));
135 if (callable_class_p(cme->defined_class)) {
145vm_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)
147 unsigned int magic = (
unsigned int)(
type & VM_FRAME_MAGIC_MASK);
148 enum imemo_type cref_or_me_type = imemo_env;
151 cref_or_me_type = imemo_type(cref_or_me);
153 if (
type & VM_FRAME_FLAG_BMETHOD) {
157 if (req_block && (
type & VM_ENV_FLAG_LOCAL) == 0) {
158 rb_bug(
"vm_push_frame: specval (%p) should be a block_ptr on %x frame", (
void *)specval, magic);
160 if (!req_block && (
type & VM_ENV_FLAG_LOCAL) != 0) {
161 rb_bug(
"vm_push_frame: specval (%p) should not be a block_ptr on %x frame", (
void *)specval, magic);
165 if (cref_or_me_type != imemo_ment) {
166 rb_bug(
"vm_push_frame: (%s) should be method entry on %x frame", rb_obj_info(cref_or_me), magic);
170 if (req_cref && cref_or_me_type != imemo_cref) {
171 rb_bug(
"vm_push_frame: (%s) should be CREF on %x frame", rb_obj_info(cref_or_me), magic);
174 if (cref_or_me !=
Qfalse && cref_or_me_type != imemo_cref) {
175 if (((
type & VM_FRAME_FLAG_LAMBDA) || magic == VM_FRAME_MAGIC_IFUNC || magic == VM_FRAME_MAGIC_DUMMY) && (cref_or_me_type == imemo_ment)) {
179 rb_bug(
"vm_push_frame: (%s) should be false or cref on %x frame", rb_obj_info(cref_or_me), magic);
185 if (cref_or_me_type == imemo_ment) {
188 if (!callable_method_entry_p(me)) {
189 rb_bug(
"vm_push_frame: ment (%s) should be callable on %x frame.", rb_obj_info(cref_or_me), magic);
193 if ((
type & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
194 VM_ASSERT(iseq == NULL ||
196 RUBY_VM_NORMAL_ISEQ_P(iseq)
200 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(iseq));
210 VALUE given_magic =
type & VM_FRAME_MAGIC_MASK;
213#define CHECK(magic, req_block, req_me, req_cref, is_cframe) \
215 vm_check_frame_detail(type, req_block, req_me, req_cref, \
216 specval, cref_or_me, is_cframe, iseq); \
218 switch (given_magic) {
220 CHECK(VM_FRAME_MAGIC_METHOD, TRUE, TRUE, FALSE, FALSE);
221 CHECK(VM_FRAME_MAGIC_CLASS, TRUE, FALSE, TRUE, FALSE);
222 CHECK(VM_FRAME_MAGIC_TOP, TRUE, FALSE, TRUE, FALSE);
223 CHECK(VM_FRAME_MAGIC_CFUNC, TRUE, TRUE, FALSE, TRUE);
224 CHECK(VM_FRAME_MAGIC_BLOCK, FALSE, FALSE, FALSE, FALSE);
225 CHECK(VM_FRAME_MAGIC_IFUNC, FALSE, FALSE, FALSE, TRUE);
226 CHECK(VM_FRAME_MAGIC_EVAL, FALSE, FALSE, FALSE, FALSE);
227 CHECK(VM_FRAME_MAGIC_RESCUE, FALSE, FALSE, FALSE, FALSE);
228 CHECK(VM_FRAME_MAGIC_DUMMY, TRUE, FALSE, FALSE, FALSE);
230 rb_bug(
"vm_push_frame: unknown type (%x)", (
unsigned int)given_magic);
235static VALUE vm_stack_canary;
236static bool vm_stack_canary_was_born =
false;
243 unsigned int pos = 0;
244 while (pos < ISEQ_BODY(iseq)->iseq_size) {
245 int opcode = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[pos]);
246 unsigned int next_pos = pos + insn_len(opcode);
247 if (ISEQ_BODY(iseq)->iseq_encoded + next_pos == pc) {
252 rb_bug(
"failed to find the previous insn");
261 if (! LIKELY(vm_stack_canary_was_born)) {
264 else if ((
VALUE *)reg_cfp == ec->vm_stack + ec->vm_stack_size) {
268 else if (! VM_FRAME_RUBYFRAME_P(reg_cfp) || ! (iseq = GET_ISEQ())) {
272 else if (LIKELY(sp[0] != vm_stack_canary)) {
281 const VALUE *orig = rb_iseq_original_iseq(iseq);
282 const VALUE iseqw = rb_iseqw_new(iseq);
284 const char *stri = rb_str_to_cstr(inspection);
285 const VALUE disasm = rb_iseq_disasm(iseq);
286 const char *strd = rb_str_to_cstr(disasm);
287 const ptrdiff_t pos = previous_insn_index(iseq, GET_PC());
288 const enum ruby_vminsn_type insn = (
enum ruby_vminsn_type)orig[pos];
289 const char *name = insn_name(insn);
295 "We are killing the stack canary set by %s, "
296 "at %s@pc=%"PRIdPTR
"\n"
297 "watch out the C stack trace.\n"
299 name, stri, pos, strd);
300 rb_bug(
"see above.");
302#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
305#define vm_check_canary(ec, sp)
306#define vm_check_frame(a, b, c, d)
311vm_push_frame_debug_counter_inc(
318 RB_DEBUG_COUNTER_INC(frame_push);
320 if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
321 const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
322 const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
325 RB_DEBUG_COUNTER_INC(frame_R2R);
328 RB_DEBUG_COUNTER_INC(frame_R2C);
333 RB_DEBUG_COUNTER_INC(frame_C2R);
336 RB_DEBUG_COUNTER_INC(frame_C2C);
341 switch (
type & VM_FRAME_MAGIC_MASK) {
342 case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method);
return;
343 case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block);
return;
344 case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class);
return;
345 case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top);
return;
346 case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc);
return;
347 case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc);
return;
348 case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval);
return;
349 case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue);
return;
350 case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy);
return;
353 rb_bug(
"unreachable");
356#define vm_push_frame_debug_counter_inc(ec, cfp, t)
361rb_vm_stack_canary(
void)
364 return vm_stack_canary;
370STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
371STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
372STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
388 vm_check_frame(
type, specval, cref_or_me, iseq);
389 VM_ASSERT(local_size >= 0);
392 CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
393 vm_check_canary(ec, sp);
398 for (
int i=0; i < local_size; i++) {
425 #if defined HAVE_DECL_ATOMIC_SIGNAL_FENCE && HAVE_DECL_ATOMIC_SIGNAL_FENCE
426 atomic_signal_fence(memory_order_seq_cst);
434 vm_push_frame_debug_counter_inc(ec, cfp,
type);
442 if (VMDEBUG == 2) SDR();
444 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
451 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
453 if (VMDEBUG == 2) SDR();
455 RUBY_VM_CHECK_INTS(ec);
456 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
458 return flags & VM_FRAME_FLAG_FINISH;
464 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
472 rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
476 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
478 VM_BLOCK_HANDLER_NONE,
485 return (
VALUE)dmy_iseq;
490rb_arity_error_new(
int argc,
int min,
int max)
492 VALUE err_mess = rb_sprintf(
"wrong number of arguments (given %d, expected %d", argc, min);
500 rb_str_catf(err_mess,
"..%d", max);
507rb_error_arity(
int argc,
int min,
int max)
514NOINLINE(
static void vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v));
517vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v)
519 const VALUE envval = VM_ENV_ENVVAL(ep);
526 rb_gc_writebarrier(envval, v);
528 VM_FORCE_WRITE(&ep[index], v);
532 rb_gc_writebarrier_remember(envval);
533 VM_FORCE_WRITE(&ep[index], v);
534 VM_ENV_FLAGS_UNSET(ep, VM_ENV_FLAG_WB_REQUIRED);
536 RB_DEBUG_COUNTER_INC(lvar_set_slowpath);
541vm_env_write(
const VALUE *ep,
int index,
VALUE v)
543 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
544 if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
545 VM_STACK_ENV_WRITE(ep, index, v);
548 vm_env_write_slowpath(ep, index, v);
553rb_vm_env_write(
const VALUE *ep,
int index,
VALUE v)
555 vm_env_write(ep, index, v);
561 if (block_handler == VM_BLOCK_HANDLER_NONE) {
565 switch (vm_block_handler_type(block_handler)) {
566 case block_handler_type_iseq:
567 case block_handler_type_ifunc:
568 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler),
rb_cProc);
569 case block_handler_type_symbol:
570 return rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
571 case block_handler_type_proc:
572 return VM_BH_TO_PROC(block_handler);
574 VM_UNREACHABLE(rb_vm_bh_to_procval);
583vm_svar_valid_p(
VALUE svar)
586 switch (imemo_type(svar)) {
595 rb_bug(
"vm_svar_valid_p: unknown type: %s", rb_obj_info(svar));
606 if (!lep)
return false;
607 if (ec == NULL)
return true;
608 if (ec->root_lep == lep)
return false;
612 if (
FIXNUM_P(lep[VM_ENV_DATA_INDEX_FLAGS]) &&
613 VM_ENV_ESCAPED_P(lep) &&
625 if (lep_svar_in_env_p(ec, lep)) {
626 svar = lep[VM_ENV_DATA_INDEX_ME_CREF];
629 svar = ec->root_svar;
632 VM_ASSERT(svar ==
Qfalse || vm_svar_valid_p(svar));
640 VM_ASSERT(vm_svar_valid_p((
VALUE)svar));
642 if (lep_svar_in_env_p(ec, lep)) {
643 vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (
VALUE)svar);
646 RB_OBJ_WRITE(rb_ec_thread_ptr(ec)->self, &ec->root_svar, svar);
653 const struct vm_svar *svar = lep_svar(ec, lep);
658 case VM_SVAR_LASTLINE:
659 return svar->lastline;
660 case VM_SVAR_BACKREF:
661 return svar->backref;
663 const VALUE ary = svar->others;
678 struct vm_svar *svar = IMEMO_NEW(
struct vm_svar, imemo_svar, obj);
689 struct vm_svar *svar = lep_svar(ec, lep);
692 lep_svar_write(ec, lep, svar = svar_new((
VALUE)svar));
696 case VM_SVAR_LASTLINE:
699 case VM_SVAR_BACKREF:
703 VALUE ary = svar->others;
719 val = lep_svar_get(ec, lep, key);
722 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
739 rb_bug(
"unexpected back-ref");
752 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
762 return rb_reg_last_defined(backref);
764 rb_bug(
"unexpected back-ref");
768 nth = (int)(
type >> 1);
775check_method_entry(
VALUE obj,
int can_be_svar)
777 if (obj ==
Qfalse)
return NULL;
780 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_method_entry: unknown type: %s", rb_obj_info(obj));
783 switch (imemo_type(obj)) {
794 rb_bug(
"check_method_entry: svar should not be there:");
801env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
803 if (obj ==
Qfalse)
return NULL;
805 switch (imemo_type(obj)) {
822 const VALUE *ep = cfp->ep;
825 while (!VM_ENV_LOCAL_P(ep)) {
826 if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
827 ep = VM_ENV_PREV_EP(ep);
830 return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
836 const VALUE *ep = cfp->ep;
839 while (!VM_ENV_LOCAL_P_UNCHECKED(ep)) {
840 if ((me = env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
841 ep = VM_ENV_PREV_EP_UNCHECKED(ep);
844 return env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
850 switch (me->def->type) {
851 case VM_METHOD_TYPE_ISEQ:
852 return me->def->body.iseq.
iseqptr;
861 switch (me->def->type) {
862 case VM_METHOD_TYPE_ISEQ:
863 return me->def->body.iseq.
cref;
869#if VM_CHECK_MODE == 0
873check_cref(
VALUE obj,
int can_be_svar)
875 if (obj ==
Qfalse)
return NULL;
878 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_cref: unknown type: %s", rb_obj_info(obj));
881 switch (imemo_type(obj)) {
892 rb_bug(
"check_method_entry: svar should not be there:");
899vm_env_cref(
const VALUE *ep)
903 while (!VM_ENV_LOCAL_P(ep)) {
904 if ((cref = check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return cref;
905 ep = VM_ENV_PREV_EP(ep);
908 return check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
912is_cref(
const VALUE v,
int can_be_svar)
915 switch (imemo_type(v)) {
928vm_env_cref_by_cref(
const VALUE *ep)
930 while (!VM_ENV_LOCAL_P(ep)) {
931 if (is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE))
return TRUE;
932 ep = VM_ENV_PREV_EP(ep);
934 return is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
938cref_replace_with_duplicated_cref_each_frame(
const VALUE *vptr,
int can_be_svar,
VALUE parent)
940 const VALUE v = *vptr;
944 switch (imemo_type(v)) {
947 new_cref = rb_vm_cref_dup(cref);
952 VM_FORCE_WRITE(vptr, (
VALUE)new_cref);
957 return cref_replace_with_duplicated_cref_each_frame(&((
struct vm_svar *)v)->
cref_or_me, FALSE, v);
961 rb_bug(
"cref_replace_with_duplicated_cref_each_frame: unreachable");
970vm_cref_replace_with_duplicated_cref(
const VALUE *ep)
972 if (vm_env_cref_by_cref(ep)) {
976 while (!VM_ENV_LOCAL_P(ep)) {
977 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
978 if ((cref = cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE, envval)) != NULL) {
981 ep = VM_ENV_PREV_EP(ep);
983 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
984 return cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE, envval);
987 rb_bug(
"vm_cref_dup: unreachable");
992vm_get_cref(
const VALUE *ep)
1000 rb_bug(
"vm_get_cref: unreachable");
1005rb_vm_get_cref(
const VALUE *ep)
1007 return vm_get_cref(ep);
1018 return vm_get_cref(cfp->ep);
1022vm_get_const_key_cref(
const VALUE *ep)
1024 const rb_cref_t *cref = vm_get_cref(ep);
1028 if (CREF_DYNAMIC(cref)) {
1031 cref = CREF_NEXT(cref);
1044 prev_cref = vm_env_cref(ep);
1050 prev_cref = vm_env_cref(cfp->ep);
1054 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1058vm_get_cbase(
const VALUE *ep)
1060 const rb_cref_t *cref = vm_get_cref(ep);
1062 return CREF_CLASS_FOR_DEFINITION(cref);
1066vm_get_const_base(
const VALUE *ep)
1068 const rb_cref_t *cref = vm_get_cref(ep);
1071 if (!CREF_PUSHED_BY_EVAL(cref)) {
1072 return CREF_CLASS_FOR_DEFINITION(cref);
1074 cref = CREF_NEXT(cref);
1081vm_check_if_namespace(
VALUE klass)
1084 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1089vm_ensure_not_refinement_module(
VALUE self)
1092 rb_warn(
"not defined at the refinement, but at the outer class/module");
1108 if (
NIL_P(orig_klass) && allow_nil) {
1110 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1114 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1115 root_cref = CREF_NEXT(root_cref);
1118 while (cref && CREF_NEXT(cref)) {
1119 if (CREF_PUSHED_BY_EVAL(cref)) {
1123 klass = CREF_CLASS(cref);
1125 cref = CREF_NEXT(cref);
1127 if (!
NIL_P(klass)) {
1131 if ((ce = rb_const_lookup(klass,
id))) {
1132 rb_const_warn_if_deprecated(ce, klass,
id);
1135 if (am == klass)
break;
1137 if (is_defined)
return 1;
1138 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1140 goto search_continue;
1147 if (UNLIKELY(!rb_class_owned_p(klass))) {
1149 rb_raise(rb_eRactorIsolationError,
1150 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" of a class/module created by another Ractor.",
rb_class_path(klass), rb_id2str(
id));
1161 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1162 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1176 vm_check_if_namespace(orig_klass);
1178 return rb_public_const_defined_from(orig_klass,
id);
1181 return rb_public_const_get_from(orig_klass,
id);
1189 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1197 int allow_nil = TRUE;
1198 if (segments[0] == idNULL) {
1203 while (segments[idx]) {
1204 ID id = segments[idx++];
1205 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1218 rb_bug(
"vm_get_cvar_base: no cref");
1221 while (CREF_NEXT(cref) &&
1222 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1223 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1224 cref = CREF_NEXT(cref);
1226 if (top_level_raise && !CREF_NEXT(cref)) {
1230 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1238#define ractor_incidental_shareable_p(cond, val) \
1239 (!(cond) || rb_ractor_shareable_p(val))
1240#define ractor_object_incidental_shareable_p(obj, val) \
1241 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1250 return default_value;
1255 fields_obj = ROBJECT_FIELDS_OBJ(obj);
1260 if (UNLIKELY(!rb_class_owned_p(obj))) {
1268 if (default_value ==
Qundef) {
1276 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1280 fields_obj = rb_obj_fields(obj,
id);
1284 return default_value;
1289 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1290 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1292 rb_getivar_cache cache = rb_getivar_cache_unpack(vm_cache_attr_index_atomic_read(is_attr, ic, cc));
1294 if (LIKELY(cache.shape_offset == shape_id)) {
1295 if (cache.index == ATTR_INDEX_NOT_SET) {
1296 return default_value;
1299 val = ivar_list[cache.index];
1300#if USE_DEBUG_COUNTER
1301 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1304 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1310#if USE_DEBUG_COUNTER
1312 if (cache.shape_offset != INVALID_SHAPE_ID) {
1313 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1316 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1320 if (cache.shape_offset != INVALID_SHAPE_ID) {
1321 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1324 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1327 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1330 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1334 if (UNLIKELY(rb_shape_complex_p(shape_id))) {
1338 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1340 if (!st_lookup(table,
id, &val)) {
1341 val = default_value;
1345 shape_id_t previous_cached_offset = cache.shape_offset;
1346 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &cache.index, &cache.shape_offset)) {
1347 if (cache.shape_offset != previous_cached_offset) {
1348 RUBY_ASSERT(!rb_shape_complex_p(cache.shape_offset));
1349 RUBY_ASSERT(cache.shape_offset != INVALID_SHAPE_ID);
1351 uint64_t packed_cache = rb_getivar_cache_pack(cache.shape_offset, cache.index);
1352 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1355 if (cache.index == ATTR_INDEX_NOT_SET) {
1356 val = default_value;
1360 val = ivar_list[cache.index];
1365 vm_cache_attr_index_set(is_attr, ic, cc, rb_getivar_cache_pack(shape_id, ATTR_INDEX_NOT_SET));
1366 val = default_value;
1371 if (!UNDEF_P(default_value)) {
1379 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1382 return rb_attr_get(obj,
id);
1397 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1399 rb_check_ivar_modifiable(obj);
1401 shape_id_t previous_shape_id = RBASIC_SHAPE_ID(obj);
1402 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1403 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1405 if (!rb_shape_complex_p(next_shape_id)) {
1406 uint64_t packed_cache = rb_setivar_cache_pack(RSHAPE_OFFSET(previous_shape_id), RSHAPE_OFFSET(next_shape_id), index);
1407 vm_cache_attr_index_set(is_attr, ic, cc, packed_cache);
1410 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1420 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1426 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1433 if (UNLIKELY(!rb_class_owned_p(obj))) {
1437 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1438 if (UNLIKELY(!fields_obj)) {
1442 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1443 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, RBASIC_SHAPE_ID(fields_obj), cache);
1444 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1448 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1450 if (shape_id != dest_shape_id) {
1451 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1452 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1455 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1464 VALUE fields_obj = rb_obj_fields(obj,
id);
1465 if (UNLIKELY(!fields_obj)) {
1469 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1470 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, RBASIC_SHAPE_ID(fields_obj), cache);
1471 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1475 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1477 if (shape_id != dest_shape_id) {
1478 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1479 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1482 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1496 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1497 shape_id_t dest_shape_id = rb_setivar_cache_revalidate(shape_id, shape_id, cache);
1498 if (UNLIKELY(dest_shape_id == INVALID_SHAPE_ID)) {
1502 VALUE fields_obj = ROBJECT_FIELDS_OBJ(obj);
1503 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
1504 if (shape_id != dest_shape_id) {
1505 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1506 if (fields_obj != obj) {
1507 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1511 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1512 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1518 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1530 VALUE defined_class = 0;
1534 defined_class =
RBASIC(defined_class)->klass;
1537 VALUE rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
1539 rb_bug(
"the cvc table should be set");
1543 if (!rb_marked_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
1544 rb_bug(
"should have cvar cache entry");
1549 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
1562 cref = vm_get_cref(GET_EP());
1566 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref &&
1567 LIKELY(rb_class_owned_p(ic->entry->class_value))) {
1568 RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
1570 VALUE v = rb_ivar_lookup(ic->entry->class_value,
id,
Qundef);
1576 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1578 return update_classvariable_cache(iseq, klass,
id, cref, ic);
1584 return vm_getclassvariable(iseq, cfp,
id, ic);
1591 cref = vm_get_cref(GET_EP());
1594 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref &&
1595 LIKELY(rb_class_owned_p(ic->entry->class_value))) {
1596 RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
1598 rb_class_ivar_set(ic->entry->class_value,
id, val);
1602 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1606 update_classvariable_cache(iseq, klass,
id, cref, ic);
1612 vm_setclassvariable(iseq, cfp,
id, val, ic);
1619 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1630 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_ic_atomic_cache_read(ic));
1631 if (UNLIKELY(UNDEF_P(vm_setivar(obj, val, cache)))) {
1637 if (!UNDEF_P(vm_setivar_class(obj, val, cache))) {
1642 if (!UNDEF_P(vm_setivar_default(obj,
id, val, cache))) {
1646 vm_setivar_slowpath_ivar(obj,
id, val, iseq, ic);
1653 vm_setinstancevariable(iseq, obj,
id, val, ic);
1659 return vm_getinstancevariable(iseq, obj,
id, ic);
1668 ec->tag->state = RUBY_TAG_FATAL;
1671 ec->tag->state = TAG_THROW;
1673 else if (THROW_DATA_P(err)) {
1674 ec->tag->state = THROW_DATA_STATE((
struct vm_throw_data *)err);
1677 ec->tag->state = TAG_RAISE;
1684 const int flag,
const VALUE throwobj)
1692 else if (state == TAG_BREAK) {
1694 const VALUE *ep = GET_EP();
1695 const rb_iseq_t *base_iseq = GET_ISEQ();
1696 escape_cfp = reg_cfp;
1698 while (ISEQ_BODY(base_iseq)->
type != ISEQ_TYPE_BLOCK) {
1699 if (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1700 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1701 ep = escape_cfp->ep;
1702 base_iseq = CFP_ISEQ(escape_cfp);
1705 ep = VM_ENV_PREV_EP(ep);
1706 base_iseq = ISEQ_BODY(base_iseq)->parent_iseq;
1707 escape_cfp = rb_vm_search_cf_from_ep(ec, escape_cfp, ep);
1708 VM_ASSERT(CFP_ISEQ(escape_cfp) == base_iseq);
1712 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1718 ep = VM_ENV_PREV_EP(ep);
1720 while (escape_cfp < eocfp) {
1721 if (escape_cfp->ep == ep) {
1722 const rb_iseq_t *
const iseq = CFP_ISEQ(escape_cfp);
1723 const VALUE epc = CFP_PC(escape_cfp) - ISEQ_BODY(iseq)->iseq_encoded;
1728 for (i=0; i < ct->size; i++) {
1730 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1732 if (entry->type == CATCH_TYPE_BREAK &&
1733 entry->iseq == base_iseq &&
1734 entry->start < epc && entry->end >= epc) {
1735 if (entry->cont == epc) {
1744 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1749 rb_vm_localjump_error(
"break from proc-closure", throwobj, TAG_BREAK);
1752 else if (state == TAG_RETRY) {
1753 const VALUE *ep = VM_ENV_PREV_EP(GET_EP());
1755 escape_cfp = rb_vm_search_cf_from_ep(ec, reg_cfp, ep);
1757 else if (state == TAG_RETURN) {
1758 const VALUE *current_ep = GET_EP();
1759 const VALUE *target_ep = NULL, *target_lep, *ep = current_ep;
1760 int in_class_frame = 0;
1762 escape_cfp = reg_cfp;
1765 while (!VM_ENV_LOCAL_P(ep)) {
1766 if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) {
1769 ep = VM_ENV_PREV_EP(ep);
1773 while (escape_cfp < eocfp) {
1774 const VALUE *lep = VM_CF_LEP(escape_cfp);
1780 if (lep == target_lep &&
1781 VM_FRAME_RUBYFRAME_P(escape_cfp) &&
1782 ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1787 if (lep == target_lep) {
1788 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1790 if (in_class_frame) {
1795 const VALUE *tep = current_ep;
1797 while (target_lep != tep) {
1798 if (escape_cfp->ep == tep) {
1800 if (tep == target_ep) {
1804 goto unexpected_return;
1807 tep = VM_ENV_PREV_EP(tep);
1811 else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
1812 switch (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type) {
1814 case ISEQ_TYPE_MAIN:
1816 if (in_class_frame)
goto unexpected_return;
1817 if (target_ep == NULL) {
1821 goto unexpected_return;
1825 case ISEQ_TYPE_EVAL: {
1826 const rb_iseq_t *is = CFP_ISEQ(escape_cfp);
1827 enum rb_iseq_type t = ISEQ_BODY(is)->type;
1828 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE || t == ISEQ_TYPE_EVAL) {
1829 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
1830 t = ISEQ_BODY(is)->type;
1832 toplevel = t == ISEQ_TYPE_TOP || t == ISEQ_TYPE_MAIN;
1835 case ISEQ_TYPE_CLASS:
1844 if (escape_cfp->ep == target_lep && ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_METHOD) {
1845 if (target_ep == NULL) {
1849 goto unexpected_return;
1853 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1856 rb_vm_localjump_error(
"unexpected return", throwobj, TAG_RETURN);
1862 rb_bug(
"isns(throw): unsupported throw type");
1865 ec->tag->state = state;
1866 return (
VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state);
1871 rb_num_t throw_state,
VALUE throwobj)
1873 const int state = (int)(throw_state & VM_THROW_STATE_MASK);
1874 const int flag = (int)(throw_state & VM_THROW_NO_ESCAPE_FLAG);
1877 return vm_throw_start(ec, reg_cfp, state, flag, throwobj);
1880 return vm_throw_continue(ec, throwobj);
1888 return vm_throw(ec, reg_cfp, throw_state, throwobj);
1897 VALUE val = vm_throw(ec, reg_cfp, throw_state, throwobj);
1902 enum ruby_tag_type state = ec->tag->state;
1904 EC_JUMP_TAG(ec, state);
1912 int is_splat = flag & 0x01;
1915 const VALUE obj = ary;
1927 if (num + is_splat == 0) {
1930 else if (flag & 0x02) {
1935 for (i = 0; i < num -
len; i++) {
1940 for (j = 0; i < num; i++, j++) {
1962 for (; i < num -
len; i++) {
1966 for (rb_num_t j = 0; i < num; i++, j++) {
1967 *cfp->sp++ = ptr[
len - j - 1];
1971 for (rb_num_t j = 0; j < num; j++) {
1972 *cfp->sp++ = ptr[num - j - 1];
1987 int initial_capa = 2;
1989#if VM_CHECK_MODE > 0
1990 ccs->debug_sig = ~(
VALUE)ccs;
1992 ccs->capa = initial_capa;
1997 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2005 if (! vm_cc_markable(cc)) {
2009 if (UNLIKELY(ccs->len == ccs->capa)) {
2012 ccs = ruby_xrealloc(ccs, vm_ccs_alloc_size(ccs->capa));
2013#if VM_CHECK_MODE > 0
2014 ccs->debug_sig = ~(
VALUE)ccs;
2017 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2019 VM_ASSERT(ccs->len < ccs->capa);
2022 const int pos = ccs->len++;
2023 ccs->entries[pos].argc = vm_ci_argc(ci);
2024 ccs->entries[pos].flag = (
unsigned short)vm_ci_flag(ci);
2025 ccs->entries[pos].kw_len = (
unsigned short)(kwarg ? kwarg->keyword_len : 0);
2028 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
2034#if VM_CHECK_MODE > 0
2038 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
2039 for (
int i=0; i<ccs->len; i++) {
2040 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u kw_len:%u\n",
2041 ccs->entries[i].flag,
2042 ccs->entries[i].argc,
2043 ccs->entries[i].kw_len);
2044 rp(ccs->entries[i].cc);
2051 VM_ASSERT(vm_ccs_p(ccs));
2052 VM_ASSERT(ccs->len <= ccs->capa);
2054 for (
int i=0; i<ccs->len; i++) {
2057 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2058 VM_ASSERT(vm_cc_class_check(cc, klass));
2059 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
2060 VM_ASSERT(!vm_cc_super_p(cc));
2061 VM_ASSERT(!vm_cc_refinement_p(cc));
2072 ASSERT_vm_locking();
2074 if (rb_multi_ractor_p()) {
2075 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2082 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2085 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2090 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2091 rb_vm_cc_table_delete(new_table, mid);
2092 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2095 rb_vm_cc_table_delete(cc_tbl, mid);
2102 ASSERT_vm_locking();
2104 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2108 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2112 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2113 return &vm_empty_cc;
2116 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2117 const VALUE original_cc_table = cc_tbl;
2120 cc_tbl = rb_vm_cc_table_create(1);
2122 else if (rb_multi_ractor_p()) {
2123 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2126 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2135 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2140 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2144 cme = rb_check_overloaded_cme(cme, ci);
2146 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2147 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2149 VM_ASSERT(vm_cc_cme(cc) != NULL);
2150 VM_ASSERT(cme->called_id == mid);
2151 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2153 if (original_cc_table != cc_tbl) {
2154 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2166 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2174 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2176 const int ccs_len = ccs->len;
2178 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2180 vm_evict_cc(klass, cc_tbl, mid);
2185 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2194 unsigned int argc = vm_ci_argc(ci);
2195 unsigned int flag = vm_ci_flag(ci);
2196 unsigned int kw_len = kwarg ? kwarg->keyword_len : 0;
2198 for (
int i=0; i<ccs_len; i++) {
2199 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2200 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2201 unsigned int ccs_ci_kw_len = ccs->entries[i].kw_len;
2202 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2204 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2206 if (ccs_ci_argc == argc && ccs_ci_flag == flag && ccs_ci_kw_len == kw_len) {
2207 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2209 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2210 VM_ASSERT(ccs_cc->klass == klass);
2211 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2227 const ID mid = vm_ci_mid(ci);
2229 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2235 if (rb_multi_ractor_p()) {
2238 cc = vm_lookup_cc(klass, ci, mid);
2242 cc = vm_populate_cc(klass, ci, mid);
2262 rb_bug(
"attempted to search method '%s' on a garbage collected object",
2263 rb_id2name(vm_ci_mid(ci)));
2268 cc = vm_search_cc(klass, ci);
2271 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2272 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2273 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2274 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2275 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2280#if VM_CHECK_MODE > 0
2285 return cd >= body->call_data && cd < body->call_data + body->ci_size;
2292#if USE_DEBUG_COUNTER
2297 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2300#if OPT_INLINE_METHOD_CACHE
2304 if (cd_owner && cc != empty_cc) {
2307 VM_ASSERT(!vm_ci_markable(cd->ci) ||
2308 vm_cd_owned_by_iseq_p(cd, (
const rb_iseq_t *)cd_owner));
2312#if USE_DEBUG_COUNTER
2313 if (!old_cc || old_cc == empty_cc) {
2315 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2317 else if (old_cc == cc) {
2318 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2320 else if (old_cme == new_cme) {
2321 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2323 else if (old_cme && new_cme && old_cme->def == new_cme->def) {
2324 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2327 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2332 if (new_cme) VM_ASSERT(new_cme->called_id == vm_ci_mid(cd->ci));
2343#if OPT_INLINE_METHOD_CACHE
2344 if (LIKELY(vm_cc_class_check(cc, klass))) {
2345 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2346 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2347 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2348 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2349 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2350 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2354 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2357 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2369 if (vm_cc_hit_p(cc, cd, klass)) {
2373 return vm_search_method_slowpath0((
VALUE)CFP_ISEQ(reg_cfp), cd, klass);
2380 VM_ASSERT(klass !=
Qfalse);
2383 const struct rb_callcache *cc = vm_search_method_fastpath(reg_cfp, cd, klass);
2384 return vm_cc_cme(cc);
2394 if (!vm_cc_hit_p(cc, cd, klass)) {
2395 cc = vm_search_method_slowpath0(cd_owner, cd, klass);
2397 return vm_cc_cme(cc);
2400#if __has_attribute(transparent_union)
2413 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2414 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2415 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2416 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2417 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2418 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2421# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2424# define make_cfunc_type(f) (cfunc_type)(f)
2434 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2435 VM_ASSERT(callable_method_entry_p(me));
2437 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2441#if __has_attribute(transparent_union)
2442 return me->def->body.cfunc.func == func.anyargs;
2444 return me->def->body.cfunc.func == func;
2453 return me && METHOD_ENTRY_BASIC(me);
2459 VM_ASSERT(reg_cfp != NULL);
2461 return check_cfunc(cme, func);
2467 return check_cfunc(me, func);
2474 return check_cfunc(cme, func);
2477#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2478#define vm_method_cfunc_is(reg_cfp, cd, recv, func) vm_method_cfunc_is(reg_cfp, cd, recv, make_cfunc_type(func))
2480#define OP_UNREDEFINED_P(op, t) BASIC_OP_UNREDEFINED_P(BOP_##op, t##_REDEFINED_OP_FLAG)
2481#define EQ_UNREDEFINED_P(t) OP_UNREDEFINED_P(EQ, t)
2513opt_equality_specialized(
VALUE recv,
VALUE obj)
2515 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2516 goto compare_by_identity;
2518 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2519 goto compare_by_identity;
2522 goto compare_by_identity;
2531 return RBOOL(a == b);
2538 return rb_str_eql_internal(obj, recv);
2543 compare_by_identity:
2544 return RBOOL(recv == obj);
2550 VM_ASSERT(reg_cfp != NULL);
2552 VALUE val = opt_equality_specialized(recv, obj);
2553 if (!UNDEF_P(val))
return val;
2555 if (!vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_equal)) {
2559 return RBOOL(recv == obj);
2564NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2567opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2569 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2571 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2572 return RBOOL(recv == obj);
2582 VALUE val = opt_equality_specialized(recv, obj);
2583 if (!UNDEF_P(val)) {
2587 return opt_equality_by_mid_slowpath(recv, obj, mid);
2594 return opt_equality_by_mid(obj1, obj2, idEq);
2600 return opt_equality_by_mid(obj1, obj2, idEqlP);
2610 case VM_CHECKMATCH_TYPE_WHEN:
2612 case VM_CHECKMATCH_TYPE_RESCUE:
2614 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2617 case VM_CHECKMATCH_TYPE_CASE: {
2618 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2621 rb_bug(
"check_match: unreachable");
2627double_cmp_lt(
double a,
double b)
2629 return RBOOL(a < b);
2633double_cmp_le(
double a,
double b)
2635 return RBOOL(a <= b);
2639double_cmp_gt(
double a,
double b)
2641 return RBOOL(a > b);
2645double_cmp_ge(
double a,
double b)
2647 return RBOOL(a >= b);
2651static inline VALUE *
2656 if (CFP_ISEQ(cfp) && VM_FRAME_RUBYFRAME_P(cfp)) {
2657 VALUE *bp = prev_cfp->sp + ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size + VM_ENV_DATA_SIZE;
2659 if (ISEQ_BODY(CFP_ISEQ(cfp))->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2660 int lts = ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size;
2661 int params = ISEQ_BODY(CFP_ISEQ(cfp))->param.size;
2664 bp += vm_ci_argc(ci);
2667 if (ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2671#if VM_DEBUG_BP_CHECK
2672 if (bp != cfp->bp_check) {
2673 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2674 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2675 (
long)(bp - GET_EC()->vm_stack));
2676 rb_bug(
"vm_base_ptr: unreachable");
2689 return vm_base_ptr(cfp);
2704static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2709 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2711 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2717 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2720 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2721 int param = ISEQ_BODY(iseq)->param.size;
2722 int local = ISEQ_BODY(iseq)->local_table_size;
2723 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2729 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2730 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2731 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2732 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2733 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2734 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2735 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2736 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2737 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2741rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2743 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2744 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2745 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2746 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2747 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2748 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2749 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2750 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2751 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2755rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2757 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2758 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2759 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2760 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2761 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2762 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2763 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2764 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2767#define ALLOW_HEAP_ARGV (-2)
2768#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2773 vm_check_canary(GET_EC(), cfp->sp);
2779 int argc = calling->argc;
2781 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2785 VALUE *argv = cfp->sp - argc;
2789 cfp->sp -= argc - 1;
2790 cfp->sp[-1] = argv_ary;
2792 calling->heap_argv = argv_ary;
2798 if (max_args >= 0 &&
len + argc > max_args) {
2806 calling->argc +=
len - (max_args - argc + 1);
2807 len = max_args - argc + 1;
2816 calling->heap_argv = 0;
2818 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2820 for (i = 0; i <
len; i++) {
2821 *cfp->sp++ = ptr[i];
2833 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2834 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2835 const VALUE h = rb_hash_new_capa(kw_len);
2836 VALUE *sp = cfp->sp;
2839 for (i=0; i<kw_len; i++) {
2840 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2844 cfp->sp -= kw_len - 1;
2845 calling->argc -= kw_len - 1;
2846 calling->kw_splat = 1;
2850vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2853 if (keyword_hash !=
Qnil) {
2855 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2858 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2864 keyword_hash = rb_hash_dup(keyword_hash);
2866 return keyword_hash;
2872 const struct rb_callinfo *restrict ci,
int max_args)
2874 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2875 if (IS_ARGS_KW_SPLAT(ci)) {
2877 VM_ASSERT(calling->kw_splat == 1);
2881 VALUE ary = cfp->sp[0];
2882 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2885 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2889 if (UNLIKELY(calling->heap_argv)) {
2891 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2892 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2893 calling->kw_splat = 0;
2901 VM_ASSERT(calling->kw_splat == 1);
2905 calling->kw_splat = 0;
2910 VM_ASSERT(calling->kw_splat == 0);
2914 VALUE ary = cfp->sp[0];
2916 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2921 VALUE last_hash, argv_ary;
2922 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2923 if (!IS_ARGS_KEYWORD(ci) &&
2926 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2931 calling->kw_splat = 1;
2937 if (!IS_ARGS_KEYWORD(ci) &&
2938 calling->argc > 0 &&
2940 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2947 cfp->sp[-1] = rb_hash_dup(last_hash);
2948 calling->kw_splat = 1;
2954 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2956 VM_ASSERT(calling->kw_splat == 1);
2957 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2962 calling->kw_splat = 0;
2968 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2970 VM_ASSERT(calling->kw_splat == 0);
2976 vm_caller_setup_arg_kw(cfp, calling, ci);
2980#define USE_OPT_HIST 0
2983#define OPT_HIST_MAX 64
2984static int opt_hist[OPT_HIST_MAX+1];
2988opt_hist_show_results_at_exit(
void)
2990 for (
int i=0; i<OPT_HIST_MAX; i++) {
2991 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
3001 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3002 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3003 const int opt = calling->argc - lead_num;
3004 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3005 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3006 const int param = ISEQ_BODY(iseq)->param.size;
3007 const int local = ISEQ_BODY(iseq)->local_table_size;
3008 const int delta = opt_num - opt;
3010 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3013 if (opt_pc < OPT_HIST_MAX) {
3017 opt_hist[OPT_HIST_MAX]++;
3021 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3029 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3030 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3031 const int opt = calling->argc - lead_num;
3032 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3034 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3037 if (opt_pc < OPT_HIST_MAX) {
3041 opt_hist[OPT_HIST_MAX]++;
3045 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3050 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3051 VALUE *
const locals);
3058 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3059 int param_size = ISEQ_BODY(iseq)->param.size;
3060 int local_size = ISEQ_BODY(iseq)->local_table_size;
3063 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3065 local_size = local_size + vm_ci_argc(calling->cd->ci);
3066 param_size = param_size + vm_ci_argc(calling->cd->ci);
3068 cfp->sp[0] = (
VALUE)calling->cd->ci;
3070 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3080 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3081 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3083 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3084 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3086 const int ci_kw_len = kw_arg->keyword_len;
3087 const VALUE *
const ci_keywords = kw_arg->keywords;
3088 VALUE *argv = cfp->sp - calling->argc;
3089 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3090 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3092 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3093 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3095 int param = ISEQ_BODY(iseq)->param.size;
3096 int local = ISEQ_BODY(iseq)->local_table_size;
3097 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3104 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3107 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3108 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3110 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3111 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3112 VALUE *
const argv = cfp->sp - calling->argc;
3113 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3116 for (i=0; i<kw_param->num; i++) {
3117 klocals[i] = kw_param->default_values[i];
3124 int param = ISEQ_BODY(iseq)->param.size;
3125 int local = ISEQ_BODY(iseq)->local_table_size;
3126 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3136 cfp->sp -= (calling->argc + 1);
3137 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3138 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3147 set_table *dup_check_table = &vm->unused_block_warning_table;
3157 .v = (
VALUE)cme->def,
3161 if (!strict_unused_block) {
3162 key = (st_data_t)cme->def->original_id;
3164 if (set_table_lookup(dup_check_table, key)) {
3174 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3179 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3180 fprintf(stderr,
"key:%p\n", (
void *)key);
3184 if (set_insert(dup_check_table, key)) {
3189 VALUE name = rb_gen_method_name(cme->defined_class, rb_iseq_base_label(iseq));
3191 if (!
NIL_P(m_loc)) {
3192 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3196 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3203 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3208 VM_ASSERT((vm_ci_argc(ci), 1));
3209 VM_ASSERT(vm_cc_cme(cc) != NULL);
3211 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3212 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3213 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3214 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)CFP_PC(ec->cfp));
3217 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3218 if (LIKELY(rb_simple_iseq_p(iseq))) {
3220 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3221 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3223 if (calling->argc != lead_num) {
3224 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3228 VM_ASSERT(cc == calling->cc);
3230 if (vm_call_iseq_optimizable_p(ci, cc)) {
3231 if ((ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3232 VM_ASSERT(ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_LEAF);
3233 vm_cc_bf_set(cc, (
void *)ISEQ_BODY(iseq)->iseq_encoded[1]);
3234 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3237 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3242 else if (rb_iseq_only_optparam_p(iseq)) {
3245 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3246 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3248 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3249 const int argc = calling->argc;
3250 const int opt = argc - lead_num;
3252 if (opt < 0 || opt > opt_num) {
3253 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3256 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3257 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3258 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3259 vm_call_cacheable(ci, cc));
3262 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3263 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3264 vm_call_cacheable(ci, cc));
3268 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3269 for (
int i=argc; i<lead_num + opt_num; i++) {
3272 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3274 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3275 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3276 const int argc = calling->argc;
3277 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3279 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3282 if (argc - kw_arg->keyword_len == lead_num) {
3283 const int ci_kw_len = kw_arg->keyword_len;
3284 const VALUE *
const ci_keywords = kw_arg->keywords;
3286 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3288 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3289 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3291 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3292 vm_call_cacheable(ci, cc));
3297 else if (argc == lead_num) {
3299 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3300 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3302 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3304 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3305 vm_call_cacheable(ci, cc));
3331 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3332 bool can_fastpath =
true;
3334 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3336 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3337 ci = vm_ci_new_runtime(
3344 ci = forward_cd->caller_ci;
3346 can_fastpath =
false;
3350 if (!vm_ci_markable(ci)) {
3351 ci = vm_ci_new_runtime(
3356 can_fastpath =
false;
3358 argv[param_size - 1] = (
VALUE)ci;
3359 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3363 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3390 const VALUE * lep = VM_CF_LEP(cfp);
3396 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3401 iseq = CFP_ISEQ(rb_vm_search_cf_from_ep(ec, cfp, lep));
3405 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3407 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3408 VALUE * to = cfp->sp - 1;
3412 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3417 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3419 cfp->sp = to + argc;
3438 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3441 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3442 int param_size = ISEQ_BODY(iseq)->param.size;
3443 int local_size = ISEQ_BODY(iseq)->local_table_size;
3445 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3447 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3448 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3454 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3457 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3458 int param_size = ISEQ_BODY(iseq)->param.size;
3459 int local_size = ISEQ_BODY(iseq)->local_table_size;
3461 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3464 local_size = local_size + vm_ci_argc(calling->cd->ci);
3465 param_size = param_size + vm_ci_argc(calling->cd->ci);
3467 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3468 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3473 int opt_pc,
int param_size,
int local_size)
3478 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3479 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3482 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3488 int opt_pc,
int param_size,
int local_size)
3490 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3491 VALUE *argv = cfp->sp - calling->argc;
3492 VALUE *sp = argv + param_size;
3493 cfp->sp = argv - 1 ;
3495 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3496 calling->block_handler, (
VALUE)me,
3497 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3498 local_size - param_size,
3499 ISEQ_BODY(iseq)->stack_max);
3508 VALUE *argv = cfp->sp - calling->argc;
3510 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3511 VALUE *src_argv = argv;
3512 VALUE *sp_orig, *sp;
3513 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3515 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3516 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3517 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3518 dst_captured->code.val = src_captured->code.val;
3519 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3520 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3523 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3527 vm_pop_frame(ec, cfp, cfp->ep);
3530 sp_orig = sp = cfp->sp;
3533 sp[0] = calling->recv;
3537 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3538 *sp++ = src_argv[i];
3541 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3542 calling->recv, calling->block_handler, (
VALUE)me,
3543 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3544 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3545 ISEQ_BODY(iseq)->stack_max);
3553ractor_unsafe_check(
void)
3555 if (!rb_ractor_main_p()) {
3556 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3563 ractor_unsafe_check();
3571 ractor_unsafe_check();
3573 return (*f)(argc, argv, recv);
3579 ractor_unsafe_check();
3587 ractor_unsafe_check();
3589 return (*f)(recv, argv[0]);
3595 ractor_unsafe_check();
3597 return (*f)(recv, argv[0], argv[1]);
3603 ractor_unsafe_check();
3605 return (*f)(recv, argv[0], argv[1], argv[2]);
3611 ractor_unsafe_check();
3613 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3619 ractor_unsafe_check();
3620 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3621 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3627 ractor_unsafe_check();
3628 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3629 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3635 ractor_unsafe_check();
3636 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3637 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3643 ractor_unsafe_check();
3644 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3645 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3651 ractor_unsafe_check();
3652 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3653 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3659 ractor_unsafe_check();
3660 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;
3661 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3667 ractor_unsafe_check();
3668 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;
3669 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]);
3675 ractor_unsafe_check();
3676 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;
3677 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]);
3683 ractor_unsafe_check();
3684 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;
3685 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]);
3691 ractor_unsafe_check();
3692 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;
3693 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]);
3699 ractor_unsafe_check();
3700 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;
3701 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]);
3715 return (*f)(argc, argv, recv);
3729 return (*f)(recv, argv[0]);
3736 return (*f)(recv, argv[0], argv[1]);
3743 return (*f)(recv, argv[0], argv[1], argv[2]);
3750 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3756 VALUE(*f)(
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]);
3763 VALUE(*f)(
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]);
3770 VALUE(*f)(
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]);
3777 VALUE(*f)(
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]);
3784 VALUE(*f)(
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]);
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))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]);
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))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]);
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))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]);
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))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]);
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))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]);
3826 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;
3827 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]);
3833 const int ov_flags = RAISED_STACKOVERFLOW;
3834 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3835 if (rb_ec_raised_p(ec, ov_flags)) {
3836 rb_ec_raised_reset(ec, ov_flags);
3842#define CHECK_CFP_CONSISTENCY(func) \
3843 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3844 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3850#if VM_DEBUG_VERIFY_METHOD_CACHE
3851 switch (me->def->type) {
3852 case VM_METHOD_TYPE_CFUNC:
3853 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3855# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3857 METHOD_BUG(ATTRSET);
3859 METHOD_BUG(BMETHOD);
3862 METHOD_BUG(OPTIMIZED);
3863 METHOD_BUG(MISSING);
3864 METHOD_BUG(REFINED);
3868 rb_bug(
"wrong method type: %d", me->def->type);
3871 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3878 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3885 VALUE recv = calling->recv;
3886 VALUE block_handler = calling->block_handler;
3887 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3889 if (UNLIKELY(calling->kw_splat)) {
3890 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3893 VM_ASSERT(reg_cfp == ec->cfp);
3895 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3898 vm_push_frame(ec, NULL, frame_type, recv,
3899 block_handler, (
VALUE)me,
3900 0, ec->cfp->sp, 0, 0);
3902 int len = cfunc->argc;
3905 reg_cfp->sp = stack_bottom;
3906 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3908 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3910 rb_vm_pop_frame(ec);
3912 VM_ASSERT(ec->cfp->sp == stack_bottom);
3914 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3915 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3925 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3927 VALUE *sp = ec->cfp->sp;
3928 VALUE recv = *(sp - recv_idx - 1);
3929 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3930 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3931#if VM_CHECK_MODE > 0
3933 *(GET_EC()->cfp->sp) =
Qfalse;
3935 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3940rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3942 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3948 int argc = calling->argc;
3949 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3950 VALUE *argv = &stack_bottom[1];
3952 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3959 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3961 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3963 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3964 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3967 VALUE *stack_bottom = reg_cfp->sp - 2;
3969 VM_ASSERT(calling->argc == 1);
3973 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3976 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));
3978 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3985 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3988 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3989 return vm_call_cfunc_other(ec, reg_cfp, calling);
3993 calling->kw_splat = 0;
3995 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
3996 VALUE *sp = stack_bottom;
3997 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
3998 for(i = 0; i < argc; i++) {
4003 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4009 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4010 VALUE argv_ary = reg_cfp->sp[-1];
4014 int argc_offset = 0;
4016 if (UNLIKELY(argc > 0 &&
4018 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4020 return vm_call_cfunc_other(ec, reg_cfp, calling);
4024 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4030 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4031 VALUE keyword_hash = reg_cfp->sp[-1];
4034 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4037 return vm_call_cfunc_other(ec, reg_cfp, calling);
4044 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4046 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4047 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4049 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4050 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4052 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4054 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4055 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4059 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4060 return vm_call_cfunc_other(ec, reg_cfp, calling);
4067 RB_DEBUG_COUNTER_INC(ccf_ivar);
4069 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4076 RB_DEBUG_COUNTER_INC(ccf_attrset);
4077 VALUE val = *(cfp->sp - 1);
4079 rb_setivar_cache cache = rb_setivar_cache_unpack(vm_cc_atomic_cache_read(cc));
4080 ID id = vm_cc_cme(cc)->def->body.attr.id;
4081 rb_check_frozen(obj);
4082 VALUE res = vm_setivar(obj, val, cache);
4090 res = vm_setivar_class(obj, val, cache);
4091 if (!UNDEF_P(res)) {
4098 res = vm_setivar_default(obj,
id, val, cache);
4099 if (!UNDEF_P(res)) {
4104 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4112 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4122 VALUE procv = cme->def->body.bmethod.proc;
4125 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4126 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4130 GetProcPtr(procv, proc);
4131 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4141 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4145 VALUE procv = cme->def->body.bmethod.proc;
4148 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4149 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4153 GetProcPtr(procv, proc);
4154 const struct rb_block *block = &proc->block;
4156 while (vm_block_type(block) == block_type_proc) {
4157 block = vm_proc_block(block->as.proc);
4159 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4162 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4163 VALUE *
const argv = cfp->sp - calling->argc;
4164 const int arg_size = ISEQ_BODY(iseq)->param.size;
4167 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4168 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4171 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4176 vm_push_frame(ec, iseq,
4177 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4179 VM_GUARDED_PREV_EP(captured->ep),
4181 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4183 ISEQ_BODY(iseq)->local_table_size - arg_size,
4184 ISEQ_BODY(iseq)->stack_max);
4192 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4196 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4197 if (UNLIKELY(calling->heap_argv)) {
4202 argc = calling->argc;
4205 cfp->sp += - argc - 1;
4208 return vm_call_bmethod_body(ec, calling, argv);
4214 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4218 VALUE procv = cme->def->body.bmethod.proc;
4220 GetProcPtr(procv, proc);
4221 const struct rb_block *block = &proc->block;
4223 while (vm_block_type(block) == block_type_proc) {
4224 block = vm_proc_block(block->as.proc);
4226 if (vm_block_type(block) == block_type_iseq) {
4227 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4228 return vm_call_iseq_bmethod(ec, cfp, calling);
4231 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4232 return vm_call_noniseq_bmethod(ec, cfp, calling);
4236rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4238 VALUE klass = current_class;
4246 while (
RTEST(klass)) {
4248 if (owner == target_owner) {
4254 return current_class;
4263 if (orig_me->defined_class == 0) {
4264 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4265 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4266 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4268 if (me->def->reference_count == 1) {
4269 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4273 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4281 VM_ASSERT(callable_method_entry_p(cme));
4288 return aliased_callable_method_entry(me);
4294 calling->cc = &VM_CC_ON_STACK(
Qundef,
4297 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4299 return vm_call_method_each_type(ec, cfp, calling);
4302static enum method_missing_reason
4305 enum method_missing_reason stat = MISSING_NOENTRY;
4306 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4307 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4308 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4318 ASSUME(calling->argc >= 0);
4320 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4321 int argc = calling->argc;
4322 VALUE recv = calling->recv;
4325 flags |= VM_CALL_OPT_SEND;
4327 if (UNLIKELY(! mid)) {
4328 mid = idMethodMissing;
4329 missing_reason = ci_missing_reason(ci);
4330 ec->method_missing_reason = missing_reason;
4333 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4335 rb_ary_unshift(argv_ary, symbol);
4338 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4339 VALUE exc = rb_make_no_method_exception(
4361 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4364 argc = ++calling->argc;
4369 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4370 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4371 VALUE exc = rb_make_no_method_exception(
4384 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4390 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4391 calling->cd = &new_fcd.cd;
4395 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4396 new_fcd.caller_ci = caller_ci;
4399 calling->cc = &VM_CC_ON_STACK(klass,
4401 { .method_missing_reason = missing_reason },
4402 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4404 if (flags & VM_CALL_FCALL) {
4405 return vm_call_method(ec, reg_cfp, calling);
4409 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4411 if (vm_cc_cme(cc) != NULL) {
4412 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4413 case METHOD_VISI_PUBLIC:
4414 return vm_call_method_each_type(ec, reg_cfp, calling);
4415 case METHOD_VISI_PRIVATE:
4416 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4418 case METHOD_VISI_PROTECTED:
4419 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4422 VM_UNREACHABLE(vm_call_method);
4424 return vm_call_method_missing(ec, reg_cfp, calling);
4427 return vm_call_method_nome(ec, reg_cfp, calling);
4437 i = calling->argc - 1;
4439 if (calling->argc == 0) {
4440 rb_raise(rb_eArgError,
"no method name given");
4464 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4470 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4472 int flags = VM_CALL_FCALL;
4476 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4477 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4479 flags |= VM_CALL_ARGS_SPLAT;
4480 if (calling->kw_splat) {
4481 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4482 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4483 calling->kw_splat = 0;
4485 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4488 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4489 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4495 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4496 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4502 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4505 int flags = vm_ci_flag(ci);
4507 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4508 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4509 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4510 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4511 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4512 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4515 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4516 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4521 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4523 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4525 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4526 unsigned int argc, flag;
4528 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4529 argc = ++calling->argc;
4532 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4533 vm_check_canary(ec, reg_cfp->sp);
4537 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4540 ec->method_missing_reason = reason;
4544 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4550 if (!(flag & VM_CALL_FORWARDING)) {
4551 calling->cd = &new_fcd.cd;
4555 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4556 new_fcd.caller_ci = caller_ci;
4560 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4561 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4562 return vm_call_method(ec, reg_cfp, calling);
4568 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4579 return vm_call_method_nome(ec, cfp, calling);
4581 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4582 cme->def->body.refined.orig_me) {
4583 cme = refined_method_callable_without_refinement(cme);
4586 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4588 return vm_call_method_each_type(ec, cfp, calling);
4592find_refinement(
VALUE refinements,
VALUE klass)
4594 if (
NIL_P(refinements)) {
4597 return rb_hash_lookup(refinements, klass);
4606 if (CFP_ISEQ(cfp) && ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_BLOCK) {
4607 const rb_iseq_t *local_iseq = ISEQ_BODY(CFP_ISEQ(cfp))->local_iseq;
4610 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4611 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4615 }
while (CFP_ISEQ(cfp) != local_iseq);
4626 if (orig_me->defined_class == 0) {
4634 VM_ASSERT(callable_method_entry_p(cme));
4636 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4646 ID mid = vm_ci_mid(calling->cd->ci);
4647 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4651 for (; cref; cref = CREF_NEXT(cref)) {
4652 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4653 if (
NIL_P(refinement))
continue;
4656 rb_callable_method_entry(refinement, mid);
4659 if (vm_cc_call(cc) == vm_call_super_method) {
4662 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4667 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4668 cme->def != ref_me->def) {
4671 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4680 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4681 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4696 if (calling->cd->cc) {
4697 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);
4699 return vm_call_method(ec, cfp, calling);
4702 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4703 calling->cc= ref_cc;
4704 return vm_call_method(ec, cfp, calling);
4708 return vm_call_method_nome(ec, cfp, calling);
4714NOINLINE(
static VALUE
4722 int argc = calling->argc;
4725 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4728 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4734 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4737 VALUE procval = calling->recv;
4738 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4744 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4746 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4749 enum ruby_basic_operators bop;
4750 switch (vm_ci_mid(ci)) {
4751 case idAREF: bop = BOP_AREF;
break;
4752 case idYield: bop = BOP_YIELD;
break;
4753 case idEqq: bop = BOP_EQQ;
break;
4754 default: bop = BOP_CALL;
break;
4757 if (BASIC_OP_UNREDEFINED_P(bop, PROC_REDEFINED_OP_FLAG)) {
4758 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4761 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4762 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4763 return vm_call_general(ec, reg_cfp, calling);
4770 VALUE recv = calling->recv;
4773 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4774 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4776 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4777 return RSTRUCT_GET_RAW(recv,
off);
4783 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4785 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4793 VALUE recv = calling->recv;
4796 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4797 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4799 rb_check_frozen(recv);
4801 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4802 RSTRUCT_SET_RAW(recv,
off, val);
4810 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4812 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4820#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4821 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4822 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4823 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4825 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4826 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4837 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4838 case OPTIMIZED_METHOD_TYPE_SEND:
4839 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4840 return vm_call_opt_send(ec, cfp, calling);
4841 case OPTIMIZED_METHOD_TYPE_CALL:
4842 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4843 return vm_call_opt_call(ec, cfp, calling);
4844 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4845 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4846 return vm_call_opt_block_call(ec, cfp, calling);
4847 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4848 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4852 VM_CALL_METHOD_ATTR(v,
4853 vm_call_opt_struct_aref(ec, cfp, calling),
4854 set_vm_cc_ivar(cc); \
4855 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4858 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4859 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4863 VM_CALL_METHOD_ATTR(v,
4864 vm_call_opt_struct_aset(ec, cfp, calling),
4865 set_vm_cc_ivar(cc); \
4866 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4870 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4882 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4884 switch (cme->def->type) {
4885 case VM_METHOD_TYPE_ISEQ:
4886 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4887 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4888 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4891 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4892 return vm_call_iseq_setup(ec, cfp, calling);
4895 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4896 case VM_METHOD_TYPE_CFUNC:
4897 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4898 return vm_call_cfunc(ec, cfp, calling);
4900 case VM_METHOD_TYPE_ATTRSET:
4901 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4905 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4907 if (vm_cc_markable(cc)) {
4908 vm_cc_attr_index_set(cc, IVAR_CACHE_INIT);
4909 VM_CALL_METHOD_ATTR(v,
4910 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4911 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4917 VM_CALLCACHE_UNMARKABLE |
4918 VM_CALLCACHE_ON_STACK,
4924 .value = IVAR_CACHE_INIT,
4929 VM_CALL_METHOD_ATTR(v,
4930 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4931 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4935 case VM_METHOD_TYPE_IVAR:
4936 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4938 vm_cc_attr_index_set(cc, rb_getivar_cache_pack(ROOT_SHAPE_ID, ATTR_INDEX_NOT_SET));
4939 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4940 VM_CALL_METHOD_ATTR(v,
4941 vm_call_ivar(ec, cfp, calling),
4942 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4945 case VM_METHOD_TYPE_MISSING:
4946 vm_cc_method_missing_reason_set(cc, 0);
4947 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4948 return vm_call_method_missing(ec, cfp, calling);
4950 case VM_METHOD_TYPE_BMETHOD:
4951 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4952 return vm_call_bmethod(ec, cfp, calling);
4954 case VM_METHOD_TYPE_ALIAS:
4955 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4956 return vm_call_alias(ec, cfp, calling);
4958 case VM_METHOD_TYPE_OPTIMIZED:
4959 return vm_call_optimized(ec, cfp, calling, ci, cc);
4961 case VM_METHOD_TYPE_UNDEF:
4964 case VM_METHOD_TYPE_ZSUPER:
4965 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4967 case VM_METHOD_TYPE_REFINED:
4970 return vm_call_refined(ec, cfp, calling);
4973 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4983 const int stat = ci_missing_reason(ci);
4985 if (vm_ci_mid(ci) == idMethodMissing) {
4986 if (UNLIKELY(calling->heap_argv)) {
4991 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4992 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4996 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
5008 VALUE defined_class = me->defined_class;
5009 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
5010 return NIL_P(refined_class) ? defined_class : refined_class;
5019 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5021 if (vm_cc_cme(cc) != NULL) {
5022 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5023 case METHOD_VISI_PUBLIC:
5024 return vm_call_method_each_type(ec, cfp, calling);
5026 case METHOD_VISI_PRIVATE:
5027 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5028 enum method_missing_reason stat = MISSING_PRIVATE;
5029 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5031 vm_cc_method_missing_reason_set(cc, stat);
5032 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5033 return vm_call_method_missing(ec, cfp, calling);
5035 return vm_call_method_each_type(ec, cfp, calling);
5037 case METHOD_VISI_PROTECTED:
5038 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5039 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5041 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5042 return vm_call_method_missing(ec, cfp, calling);
5046 VM_ASSERT(vm_cc_cme(cc) != NULL);
5049 calling->cc = &cc_on_stack;
5050 return vm_call_method_each_type(ec, cfp, calling);
5053 return vm_call_method_each_type(ec, cfp, calling);
5056 rb_bug(
"unreachable");
5060 return vm_call_method_nome(ec, cfp, calling);
5067 RB_DEBUG_COUNTER_INC(ccf_general);
5068 return vm_call_method(ec, reg_cfp, calling);
5074 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5075 VM_ASSERT(cc != vm_cc_empty());
5077 *(vm_call_handler *)&cc->call_ = vm_call_general;
5083 RB_DEBUG_COUNTER_INC(ccf_super_method);
5088 if (ec == NULL) rb_bug(
"unreachable");
5091 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5092 return vm_call_method(ec, reg_cfp, calling);
5098vm_search_normal_superclass(
VALUE klass)
5100 if (RICLASS_FOR_REFINEMENT_P(klass)) {
5101 klass =
RBASIC(klass)->klass;
5103 klass = RCLASS_ORIGIN(klass);
5107NORETURN(
static void vm_super_outside(
void));
5110vm_super_outside(
void)
5116empty_cc_for_super(
void)
5118 return &vm_empty_cc_for_super;
5124 VALUE current_defined_class;
5125 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
5132 current_defined_class = vm_defined_class_for_protected_call(me);
5135 iseq != method_entry_iseqptr(me) &&
5138 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5142 "self has wrong type to call super in this context: "
5143 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5148 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5150 "implicit argument passing of super from method defined"
5151 " by define_method() is not supported."
5152 " Specify all arguments explicitly.");
5155 ID mid = me->def->original_id;
5157 if (!vm_ci_markable(cd->ci)) {
5158 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5162 cd->ci = vm_ci_new_runtime(mid,
5165 vm_ci_kwarg(cd->ci));
5172 VALUE klass = vm_search_normal_superclass(me->defined_class);
5176 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5181 RCLASS_INCLUDER(me->defined_class) == 0) {
5183 "super in a method in a module that has been refined and that is called via super"
5184 " from a refinement method is not supported.");
5187 cc = vm_search_method_fastpath(reg_cfp, cd, klass);
5191 if (cached_cme == NULL) {
5193 cd->cc = empty_cc_for_super();
5195 else if (cached_cme->called_id != mid) {
5198 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5202 cd->cc = cc = empty_cc_for_super();
5206 switch (cached_cme->def->type) {
5208 case VM_METHOD_TYPE_REFINED:
5210 case VM_METHOD_TYPE_ATTRSET:
5211 case VM_METHOD_TYPE_IVAR:
5212 vm_cc_call_set(cc, vm_call_super_method);
5220 VM_ASSERT((vm_cc_cme(cc),
true));
5228block_proc_is_lambda(
const VALUE procval)
5233 GetProcPtr(procval, proc);
5234 return proc->header.is_lambda;
5244 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5247 int is_lambda = FALSE;
5248 VALUE val, arg, blockarg;
5250 const struct vm_ifunc *ifunc = captured->code.ifunc;
5255 else if (argc == 0) {
5262 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5264 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5266 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5269 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5272 VM_GUARDED_PREV_EP(captured->ep),
5274 0, ec->cfp->sp, 0, 0);
5275 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5276 rb_vm_pop_frame(ec);
5284 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5290 VALUE passed_proc = rb_vm_bh_to_procval(ec, block_handler);
5292 if (!rb_box_available()) {
5293 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5305 box = current_box_on_cfp(ec, ruby_cfp);
5306 if (BOX_USER_P(box)) {
5309 ruby_cfp = rb_vm_get_ruby_level_next_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ruby_cfp));
5313 if (!ruby_cfp || !box) {
5314 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5322 const rb_iseq_t *caller_iseq = CFP_ISEQ(ruby_cfp);
5323 VALUE name = rb_sprintf(
"block in %"PRIsVALUE, rb_iseq_label(caller_iseq));
5325 rb_iseq_path(caller_iseq), rb_iseq_realpath(caller_iseq),
5326 rb_vm_get_sourceline(ruby_cfp), caller_iseq, 0,
5327 ISEQ_TYPE_BLOCK, NULL,
Qnil);
5329 enum ruby_tag_type state;
5331 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_FINISH,
5332 ruby_cfp->self, VM_GUARDED_PREV_EP(ruby_cfp->ep),
5334 ISEQ_BODY(iseq)->iseq_encoded, reg_cfp->sp,
5335 ISEQ_BODY(iseq)->local_table_size, ISEQ_BODY(iseq)->stack_max);
5343 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
5344 val = rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, passed_proc);
5348 if (state != TAG_NONE) {
5350 EC_JUMP_TAG(ec, state);
5353 rb_vm_pop_frame(ec);
5364 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5366 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5374vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5376 VALUE ary, arg0 = argv[0];
5381 VM_ASSERT(argv[0] == arg0);
5389 if (rb_simple_iseq_p(iseq)) {
5393 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5395 if (arg_setup_type == arg_setup_block &&
5396 calling->argc == 1 &&
5397 ISEQ_BODY(iseq)->param.flags.has_lead &&
5398 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5399 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5400 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5403 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5404 if (arg_setup_type == arg_setup_block) {
5405 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5407 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5408 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5409 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5411 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5412 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5416 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5423 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5432 calling = &calling_entry;
5433 calling->argc = argc;
5434 calling->block_handler = block_handler;
5435 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5437 calling->heap_argv = 0;
5439 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5441 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5452 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5453 const int arg_size = ISEQ_BODY(iseq)->param.size;
5454 VALUE *
const rsp = GET_SP() - calling->argc;
5455 VALUE *
const argv = rsp;
5456 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5457 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5462 vm_push_frame(ec, iseq,
5465 VM_GUARDED_PREV_EP(captured->ep), (
VALUE)cref,
5466 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5468 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5476 bool is_lambda,
VALUE block_handler)
5478 return vm_invoke_iseq_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler, NULL);
5484 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5486 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5487 int flags = vm_ci_flag(ci);
5489 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5490 ((calling->argc == 0) ||
5491 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5492 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5493 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5494 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5496 if (UNLIKELY(calling->heap_argv)) {
5497#if VM_ARGC_STACK_MAX < 0
5499 rb_raise(rb_eArgError,
"no receiver given");
5505 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5506 reg_cfp->sp[-2] = calling->recv;
5507 flags |= VM_CALL_ARGS_SPLAT;
5510 if (calling->argc < 1) {
5511 rb_raise(rb_eArgError,
"no receiver given");
5513 calling->recv = TOPN(--calling->argc);
5515 if (calling->kw_splat) {
5516 flags |= VM_CALL_KW_SPLAT;
5520 if (calling->argc < 1) {
5521 rb_raise(rb_eArgError,
"no receiver given");
5523 calling->recv = TOPN(--calling->argc);
5526 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5532 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5537 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5538 argc = calling->argc;
5539 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);
5545vm_block_to_block_handler(
const struct rb_block *block)
5547 switch (vm_block_type(block)) {
5548 case block_type_iseq:
5549 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5550 case block_type_ifunc:
5551 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5552 case block_type_symbol:
5553 return VM_BH_FROM_SYMBOL(block->as.symbol);
5554 case block_type_proc:
5555 return VM_BH_FROM_PROC(block->as.proc);
5557 VM_UNREACHABLE(vm_yield_with_proc);
5562vm_proc_to_block_handler(
VALUE procval)
5564 return vm_block_to_block_handler(vm_proc_block(procval));
5567NOINLINE(
static VALUE
5570 bool is_lambda,
VALUE block_handler,
VALUE refined_procval));
5574 bool is_lambda,
VALUE block_handler,
VALUE refined_procval)
5576 const rb_cref_t *cref = rb_proc_refinements_cref_for_call(refined_procval);
5577 return vm_invoke_iseq_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler, cref);
5583 bool is_lambda,
VALUE block_handler)
5585 VALUE refined_procval = 0;
5587 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5588 VALUE procval = VM_BH_TO_PROC(block_handler);
5590 GetProcPtr(procval, po);
5591 if (po->header.is_refined) refined_procval = procval;
5592 is_lambda = po->header.is_lambda;
5593 block_handler = vm_block_to_block_handler(&po->block);
5596 if (UNLIKELY(refined_procval) && vm_block_handler_type(block_handler) == block_handler_type_iseq) {
5598 return vm_invoke_proc_block_with_cref(ec, reg_cfp, calling, ci, is_lambda, block_handler,
5602 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5608 bool is_lambda,
VALUE block_handler)
5612 bool is_lambda,
VALUE block_handler);
5614 switch (vm_block_handler_type(block_handler)) {
5615 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5616 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5617 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5618 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5619 default: rb_bug(
"vm_invoke_block: unreachable");
5622 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5626vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5633 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5636 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5637 captured->code.iseq = blockiseq;
5639 return rb_vm_make_proc(ec, captured,
rb_cProc);
5643vm_once_exec(
VALUE iseq)
5649#define RUNNING_THREAD_ONCE_DONE ((rb_thread_t *)0x1)
5665vm_once_wait_no_gvl(
void *ptr)
5672 running_th = rbimpl_atomic_ptr_load((
void **)&arg->is->once.running_thread, RBIMPL_ATOMIC_ACQUIRE);
5673 if (running_th != NULL && running_th != RUNNING_THREAD_ONCE_DONE) {
5681vm_once_wait_ubf(
void *ptr)
5683 vm_once_broadcast((
rb_vm_t *)ptr);
5687vm_once_clear(
VALUE data)
5690 rbimpl_atomic_ptr_store((
volatile void **)&is->once.running_thread, NULL, RBIMPL_ATOMIC_RELEASE);
5691 vm_once_broadcast(GET_VM());
5703 args[0] = obj; args[1] =
Qfalse;
5705 if (!UNDEF_P(r) &&
RTEST(r)) {
5717 enum defined_type
type = (
enum defined_type)op_type;
5724 return rb_gvar_defined(
SYM2ID(obj));
5726 case DEFINED_CVAR: {
5727 const rb_cref_t *cref = vm_get_cref(GET_EP());
5728 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5733 case DEFINED_CONST_FROM: {
5734 bool allow_nil =
type == DEFINED_CONST;
5736 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5741 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5743 case DEFINED_METHOD:{
5748 switch (METHOD_ENTRY_VISI(cme)) {
5749 case METHOD_VISI_PRIVATE:
5751 case METHOD_VISI_PROTECTED:
5755 case METHOD_VISI_PUBLIC:
5759 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(cme));
5763 return check_respond_to_missing(obj, v);
5768 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5772 case DEFINED_ZSUPER:
5777 VALUE klass = vm_search_normal_superclass(me->defined_class);
5778 if (!klass)
return false;
5780 ID id = me->def->original_id;
5787 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5789 rb_bug(
"unimplemented defined? type (VM)");
5799 return vm_defined(ec, reg_cfp, op_type, obj, v);
5803vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5806 const VALUE *ep = reg_ep;
5807 for (i = 0; i < lv; i++) {
5808 ep = GET_PREV_EP(ep);
5814vm_get_special_object(
const VALUE *
const reg_ep,
5815 enum vm_special_object_type
type)
5818 case VM_SPECIAL_OBJECT_VMCORE:
5819 return rb_mRubyVMFrozenCore;
5820 case VM_SPECIAL_OBJECT_CBASE:
5821 return vm_get_cbase(reg_ep);
5822 case VM_SPECIAL_OBJECT_CONST_BASE:
5823 return vm_get_const_base(reg_ep);
5825 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5832rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5834 return vm_get_special_object(reg_ep,
type);
5840 const VALUE ary2 = ary2st;
5841 VALUE tmp1 = rb_check_to_array(ary1);
5842 VALUE tmp2 = rb_check_to_array(ary2);
5863 const VALUE ary2 = ary2st;
5865 if (
NIL_P(ary2))
return ary1;
5867 VALUE tmp2 = rb_check_to_array(ary2);
5882 return vm_concat_array(ary1, ary2st);
5886rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5888 return vm_concat_to_array(ary1, ary2st);
5897 VALUE tmp = rb_check_to_array(ary);
5901 else if (
RTEST(flag)) {
5914 return vm_splat_array(flag, ary);
5920 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5922 if (flag & VM_CHECKMATCH_ARRAY) {
5926 for (i = 0; i < n; i++) {
5928 VALUE c = check_match(ec, v, target,
type);
5937 return check_match(ec, pattern, target,
type);
5944 return vm_check_match(ec, target, pattern, flag);
5948vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5950 const VALUE kw_bits = *(ep - bits);
5953 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5954 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5958 VM_ASSERT(rb_set_p(kw_bits),
"%s", rb_obj_info(kw_bits));
5967 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5968 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5969 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5970 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5974 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5977 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5980 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5983 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5990vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5995 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5996 return rb_public_const_get_at(cbase,
id);
6004vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
6009 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
6014 "superclass mismatch for class %"PRIsVALUE
"",
6027vm_check_if_module(
ID id,
VALUE mod)
6046vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
6049 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super :
rb_cObject;
6056vm_declare_module(
ID id,
VALUE cbase)
6062NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
6066 VALUE name = rb_id2str(
id);
6067 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
6069 VALUE location = rb_const_source_location_at(cbase,
id);
6070 if (!
NIL_P(location)) {
6071 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
6072 " previous definition of %"PRIsVALUE
" was here",
6079vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
6083 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
6085 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
6089 vm_check_if_namespace(cbase);
6094 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
6095 if (!vm_check_if_class(
id, flags, super, klass))
6096 unmatched_redefinition(
"class", cbase,
id, klass);
6100 return vm_declare_class(
id, flags, cbase, super);
6105vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
6109 vm_check_if_namespace(cbase);
6110 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
6111 if (!vm_check_if_module(
id, mod))
6112 unmatched_redefinition(
"module", cbase,
id, mod);
6116 return vm_declare_module(
id, cbase);
6121vm_find_or_create_class_by_id(
ID id,
6126 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
6129 case VM_DEFINECLASS_TYPE_CLASS:
6131 return vm_define_class(
id, flags, cbase, super);
6133 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
6137 case VM_DEFINECLASS_TYPE_MODULE:
6139 return vm_define_module(
id, flags, cbase);
6142 rb_bug(
"unknown defineclass type: %d", (
int)
type);
6146static rb_method_visibility_t
6151 if (!vm_env_cref_by_cref(cfp->ep)) {
6152 return METHOD_VISI_PUBLIC;
6155 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6164 if (!vm_env_cref_by_cref(cfp->ep)) {
6168 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6176 rb_method_visibility_t visi;
6181 visi = METHOD_VISI_PUBLIC;
6184 klass = CREF_CLASS_FOR_DEFINITION(cref);
6185 visi = vm_scope_visibility_get(ec);
6192 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6195 !RCLASS_SINGLETON_P(klass) && !RCLASS_EXPECT_NO_IVAR(klass) &&
6197 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6200 if (!is_singleton && vm_scope_module_func_check(ec)) {
6202 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6211rb_vm_untag_block_handler(
VALUE block_handler)
6213 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6215 switch (vm_block_handler_type(block_handler)) {
6216 case block_handler_type_iseq:
6217 case block_handler_type_ifunc: {
6219 return captured->code.val;
6221 case block_handler_type_proc:
6222 case block_handler_type_symbol:
6223 return block_handler;
6225 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6232 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6241 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6243 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6244 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6247 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6251enum method_explorer_type {
6253 mexp_search_invokeblock,
6260 enum method_explorer_type method_explorer));
6266 VALUE block_handler,
6267 enum method_explorer_type method_explorer
6272 int argc = vm_ci_argc(ci);
6273 VALUE recv = TOPN(argc);
6275 .block_handler = block_handler,
6276 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6282 switch (method_explorer) {
6283 case mexp_search_method:
6284 calling.cc = cc = vm_search_method_fastpath(reg_cfp, cd,
CLASS_OF(recv));
6285 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6287 case mexp_search_super:
6288 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6289 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6291 case mexp_search_invokeblock:
6292 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6302 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6303 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6317 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6319 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6321 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6322 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6333 VALUE bh = VM_BLOCK_HANDLER_NONE;
6334 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6344 struct rb_callinfo adjusted_ci = VM_CI_ON_STACK(vm_ci_mid(cd->ci),
6347 vm_ci_kwarg(cd->ci));
6348 const struct rb_callcache *original_cc = rbimpl_atomic_ptr_load((
void **)&cd->cc, RBIMPL_ATOMIC_ACQUIRE);
6354 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), adjusted_cd.ci, blockiseq,
true);
6355 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd, bh, mexp_search_super);
6357 if (original_cc != adjusted_cd.cc && vm_cc_markable(adjusted_cd.cc)) {
6358 rbimpl_atomic_ptr_store((
volatile void **)&cd->cc, (
void *)adjusted_cd.cc, RBIMPL_ATOMIC_RELEASE);
6374 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6376 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6378 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6379 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6390 VALUE bh = VM_BLOCK_HANDLER_NONE;
6391 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6419 if (check_method_basic_definition(cme)) {
6425 if (check_cfunc(cme, rb_mod_to_s)) {
6431 val = rb_mod_to_s(recv);
6437 if (check_cfunc(cme, rb_nil_to_s)) {
6438 return rb_nil_to_s(recv);
6442 if (check_cfunc(cme, rb_true_to_s)) {
6443 return rb_true_to_s(recv);
6447 if (check_cfunc(cme, rb_false_to_s)) {
6448 return rb_false_to_s(recv);
6452 if (check_cfunc(cme, rb_int_to_s)) {
6453 return rb_fix_to_s(recv);
6465 return vm_objtostring(reg_cfp, recv, cd);
6469vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6471 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6480vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6482 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6491vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6493 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6507 if (OP_UNREDEFINED_P(INCLUDE_P, ARRAY)) {
6511 VALUE args[1] = {target};
6514 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6517 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6524 return vm_opt_duparray_include_p(ec, ary, target);
6530 if (OP_UNREDEFINED_P(MAX, ARRAY)) {
6531 if (array_len == 0) {
6535 VALUE result = *ptr;
6536 rb_snum_t i = array_len - 1;
6538 const VALUE v = *++ptr;
6539 if (OPTIMIZED_CMP(v, result) > 0) {
6554 return vm_opt_newarray_max(ec, array_len, ptr);
6560 if (OP_UNREDEFINED_P(MIN, ARRAY)) {
6561 if (array_len == 0) {
6565 VALUE result = *ptr;
6566 rb_snum_t i = array_len - 1;
6568 const VALUE v = *++ptr;
6569 if (OPTIMIZED_CMP(v, result) < 0) {
6584 return vm_opt_newarray_min(ec, array_len, ptr);
6591 if (OP_UNREDEFINED_P(HASH, ARRAY)) {
6592 return rb_ary_hash_values(array_len, ptr);
6602 return vm_opt_newarray_hash(ec, array_len, ptr);
6611 if (OP_UNREDEFINED_P(INCLUDE_P, ARRAY)) {
6612 struct RArray fake_ary = {RBASIC_INIT};
6613 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6617 VALUE args[1] = {target};
6625 return vm_opt_newarray_include_p(ec, array_len,
ptr, target);
6631 if (OP_UNREDEFINED_P(PACK, ARRAY)) {
6632 struct RArray fake_ary = {RBASIC_INIT};
6633 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6634 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6644 if (!UNDEF_P(buffer)) {
6645 args[1] = rb_hash_new_capa(1);
6646 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6651 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len,
ptr), idPack, argc, args, kw_splat);
6658 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt, buffer);
6665vm_track_constant_cache(
ID id,
void *ic)
6668 struct rb_id_table *const_cache = &vm->constant_cache;
6669 VALUE lookup_result;
6672 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6676 ics = set_init_numtable();
6677 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6692 vm->inserting_constant_cache_id = id;
6694 set_insert(ics, (st_data_t)ic);
6696 vm->inserting_constant_cache_id = (
ID)0;
6703 for (
int i = 0; segments[i]; i++) {
6704 ID id = segments[i];
6705 if (
id == idNULL)
continue;
6706 vm_track_constant_cache(
id, ic);
6717 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || ractor_id == rb_ractor_id(GET_RACTOR())) {
6718 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6720 return (ic_cref == NULL ||
6721 ic_cref == vm_get_cref(reg_ep));
6729 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6730 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, ice->ractor_id, reg_ep);
6735rb_vm_ic_hit_p(
IC ic,
const VALUE *reg_ep)
6737 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6743 if (ruby_vm_const_missing_count > 0) {
6744 ruby_vm_const_missing_count = 0;
6751 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6752 ice->ractor_id = rb_ractor_id(GET_RACTOR());
6756 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6760 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6761 rb_yjit_constant_ic_update(iseq, ic, pos);
6771 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6778 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments) || rb_multi_ractor_p());
6781 ruby_vm_constant_cache_misses++;
6782 val = vm_get_ev_const_chain(ec, segments);
6783 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6786 vm_ic_update(CFP_ISEQ(GET_CFP()), ic, val, GET_EP(), CFP_PC(GET_CFP()) - 2);
6795rb_vm_once_done_value(
ISE is,
VALUE *result)
6797 rb_thread_t *running_th = rbimpl_atomic_ptr_load((
void**)&is->once.running_thread, RBIMPL_ATOMIC_ACQUIRE);
6798 if (running_th == RUNNING_THREAD_ONCE_DONE) {
6799 *result = is->once.value;
6812 running_th = rbimpl_atomic_ptr_load((
void**)&is->once.running_thread, RBIMPL_ATOMIC_ACQUIRE);
6813 if (running_th == RUNNING_THREAD_ONCE_DONE) {
6814 return is->once.value;
6816 else if (running_th == NULL) {
6818 enum ruby_tag_type state;
6819 if (rbimpl_atomic_ptr_cas((
void**)&is->once.running_thread, running_th, th, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED) != running_th) {
6823 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
6824 val = vm_once_exec((
VALUE)iseq);
6827 if (state != TAG_NONE) {
6828 vm_once_clear((
VALUE)is);
6829 EC_JUMP_TAG(ec, state);
6839 rbimpl_atomic_ptr_store((
volatile void**)&is->once.running_thread, RUNNING_THREAD_ONCE_DONE, RBIMPL_ATOMIC_RELEASE);
6840 vm_once_broadcast(rb_ec_vm_ptr(ec));
6843 else if (running_th == th) {
6845 return vm_once_exec((
VALUE)iseq);
6850 rb_nogvl(vm_once_wait_no_gvl, &arg, vm_once_wait_ubf, arg.vm,
6852 RUBY_VM_CHECK_INTS(ec);
6858vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6860 switch (OBJ_BUILTIN_TYPE(key)) {
6866 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6867 SYMBOL_REDEFINED_OP_FLAG |
6868 INTEGER_REDEFINED_OP_FLAG |
6869 FLOAT_REDEFINED_OP_FLAG |
6870 NIL_REDEFINED_OP_FLAG |
6871 TRUE_REDEFINED_OP_FLAG |
6872 FALSE_REDEFINED_OP_FLAG |
6873 STRING_REDEFINED_OP_FLAG)) {
6877 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6881 if (st_lookup(rb_imemo_cdhash_tbl(hash), key, &val)) {
6901 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6902 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6903 static const char stack_consistency_error[] =
6904 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6905#if defined RUBY_DEVEL
6906 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6911 rb_bug(stack_consistency_error, nsp, nbp);
6918 if (FIXNUM_2_P(recv, obj) &&
6919 OP_UNREDEFINED_P(PLUS, INTEGER)) {
6920 return rb_fix_plus_fix(recv, obj);
6922 else if (FLONUM_2_P(recv, obj) &&
6923 OP_UNREDEFINED_P(PLUS, FLOAT)) {
6931 OP_UNREDEFINED_P(PLUS, FLOAT)) {
6936 OP_UNREDEFINED_P(PLUS, STRING)) {
6937 return rb_str_opt_plus(recv, obj);
6941 OP_UNREDEFINED_P(PLUS, ARRAY)) {
6952 if (FIXNUM_2_P(recv, obj) &&
6953 OP_UNREDEFINED_P(MINUS, INTEGER)) {
6954 return rb_fix_minus_fix(recv, obj);
6956 else if (FLONUM_2_P(recv, obj) &&
6957 OP_UNREDEFINED_P(MINUS, FLOAT)) {
6965 OP_UNREDEFINED_P(MINUS, FLOAT)) {
6976 if (FIXNUM_2_P(recv, obj) &&
6977 OP_UNREDEFINED_P(MULT, INTEGER)) {
6978 return rb_fix_mul_fix(recv, obj);
6980 else if (FLONUM_2_P(recv, obj) &&
6981 OP_UNREDEFINED_P(MULT, FLOAT)) {
6989 OP_UNREDEFINED_P(MULT, FLOAT)) {
7000 if (FIXNUM_2_P(recv, obj) &&
7001 OP_UNREDEFINED_P(DIV, INTEGER)) {
7002 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
7004 else if (FLONUM_2_P(recv, obj) &&
7005 OP_UNREDEFINED_P(DIV, FLOAT)) {
7006 return rb_flo_div_flo(recv, obj);
7013 OP_UNREDEFINED_P(DIV, FLOAT)) {
7014 return rb_flo_div_flo(recv, obj);
7024 if (FIXNUM_2_P(recv, obj) &&
7025 OP_UNREDEFINED_P(MOD, INTEGER)) {
7026 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
7028 else if (FLONUM_2_P(recv, obj) &&
7029 OP_UNREDEFINED_P(MOD, FLOAT)) {
7037 OP_UNREDEFINED_P(MOD, FLOAT)) {
7048 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not_equal)) {
7049 VALUE val = opt_equality(reg_cfp, recv, obj, cd_eq);
7051 if (!UNDEF_P(val)) {
7052 return RBOOL(!
RTEST(val));
7062 if (FIXNUM_2_P(recv, obj) &&
7063 OP_UNREDEFINED_P(LT, INTEGER)) {
7066 else if (FLONUM_2_P(recv, obj) &&
7067 OP_UNREDEFINED_P(LT, FLOAT)) {
7075 OP_UNREDEFINED_P(LT, FLOAT)) {
7086 if (FIXNUM_2_P(recv, obj) &&
7087 OP_UNREDEFINED_P(LE, INTEGER)) {
7090 else if (FLONUM_2_P(recv, obj) &&
7091 OP_UNREDEFINED_P(LE, FLOAT)) {
7099 OP_UNREDEFINED_P(LE, FLOAT)) {
7110 if (FIXNUM_2_P(recv, obj) &&
7111 OP_UNREDEFINED_P(GT, INTEGER)) {
7114 else if (FLONUM_2_P(recv, obj) &&
7115 OP_UNREDEFINED_P(GT, FLOAT)) {
7123 OP_UNREDEFINED_P(GT, FLOAT)) {
7134 if (FIXNUM_2_P(recv, obj) &&
7135 OP_UNREDEFINED_P(GE, INTEGER)) {
7138 else if (FLONUM_2_P(recv, obj) &&
7139 OP_UNREDEFINED_P(GE, FLOAT)) {
7147 OP_UNREDEFINED_P(GE, FLOAT)) {
7163 OP_UNREDEFINED_P(LTLT, STRING)) {
7172 OP_UNREDEFINED_P(LTLT, ARRAY)) {
7190 OP_UNREDEFINED_P(AND, INTEGER)) {
7201 if (FIXNUM_2_P(recv, obj) &&
7202 OP_UNREDEFINED_P(OR, INTEGER)) {
7214 if (FIXNUM_2_P(recv, obj) &&
7215 OP_UNREDEFINED_P(AREF, INTEGER)) {
7216 return rb_fix_aref(recv, obj);
7221 OP_UNREDEFINED_P(AREF, ARRAY)) {
7223 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7226 return rb_ary_aref1(recv, obj);
7230 OP_UNREDEFINED_P(AREF, HASH)) {
7231 return rb_hash_aref(recv, obj);
7245 OP_UNREDEFINED_P(ASET, ARRAY) &&
7251 OP_UNREDEFINED_P(ASET, HASH)) {
7252 rb_hash_aset(recv, obj, set);
7261vm_opt_length(
VALUE recv,
int bop)
7267 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7268 if (bop == BOP_EMPTY_P) {
7269 return LONG2NUM(RSTRING_LEN(recv));
7276 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7280 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7289vm_opt_empty_p(
VALUE recv)
7291 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7304 OP_UNREDEFINED_P(
NIL_P, NIL)) {
7307 else if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_false)) {
7323 case RSHIFT(~0UL, 1):
7326 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7344vm_opt_succ(
VALUE recv)
7347 OP_UNREDEFINED_P(SUCC, INTEGER)) {
7348 return fix_succ(recv);
7354 OP_UNREDEFINED_P(SUCC, STRING)) {
7365 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not)) {
7366 return RBOOL(!
RTEST(recv));
7381 OP_UNREDEFINED_P(MATCH, STRING)) {
7385 OP_UNREDEFINED_P(MATCH, REGEXP)) {
7393#undef EQ_UNREDEFINED_P
7394#undef OP_UNREDEFINED_P
7406 VALUE self = GET_SELF();
7408 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7410 if (local_hooks) local_hooks->running++;
7412 if (event & global_hooks->events) {
7415 vm_dtrace(event, ec);
7416 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7420 if (local_hooks) local_hooks->running--;
7421 if (local_hooks != NULL) {
7422 if (event & local_hooks->events) {
7425 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7435#define VM_TRACE_HOOK(target_event, val) do { \
7436 if ((pc_events & (target_event)) & enabled_flags) { \
7437 if (local_hooks_cnt > 0) local_hooks = rb_iseq_local_hooks(iseq, r, false); \
7438 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7445 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7446 VM_ASSERT(ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_RESCUE);
7447 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7453 const VALUE *pc = reg_cfp->pc;
7455 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7458 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7462 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
7463 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7465 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7467 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7469 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7473 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7477 unsigned int bmethod_hooks_cnt = 0;
7479 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7480 enabled_flags |= iseq_local_events;
7482 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7484 if (bmethod_frame) {
7486 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7487 bmethod_def = me->def;
7488 bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7489 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7491 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7494 if (bmethod_local_hooks) {
7495 bmethod_local_events = bmethod_local_hooks->events;
7500 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7504 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7512 else if (ec->trace_arg != NULL) {
7520 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7523 VALUE path = rb_iseq_path(iseq);
7524 VALUE label = rb_iseq_label(iseq);
7525 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %.*s:%d %.*s\n",
7529 (
int)rb_iseq_line_no(iseq, pos),
7532 VM_ASSERT(reg_cfp->pc == pc);
7533 VM_ASSERT(pc_events != 0);
7543 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7544 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7550 if (bmethod_hooks_cnt > 0) bmethod_local_hooks = rb_method_def_local_hooks(bmethod_def, r,
false);
7558#if VM_CHECK_MODE > 0
7559NORETURN( NOINLINE( COLDFUNC
7560void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7563Init_vm_stack_canary(
void)
7566 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7569 vm_stack_canary >>= 2;
7571 vm_stack_canary |= 0x01;
7573 vm_stack_canary_was_born =
true;
7578rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7582 const char *insn = rb_insns_name(i);
7586 rb_bug(
"dead canary found at %s: %s", insn, str);
7590void Init_vm_stack_canary(
void) { }
7622 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7629 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7636 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7643 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7650 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7657 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7664 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7671 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7678 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7684 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);
7685 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]);
7691 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);
7692 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]);
7698 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);
7699 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]);
7705 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);
7706 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]);
7712 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);
7713 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]);
7719 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);
7720 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]);
7726 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);
7727 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]);
7732static builtin_invoker
7733lookup_builtin_invoker(
int argc)
7735 static const builtin_invoker invokers[] = {
7754 return invokers[argc];
7760 const bool canary_p = ISEQ_BODY(CFP_ISEQ(reg_cfp))->builtin_attrs & BUILTIN_ATTR_LEAF;
7761 SETUP_CANARY(canary_p);
7762 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7763 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7764 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7771 return invoke_bf(ec, cfp, bf, argv);
7778 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7779 for (
int i=0; i<bf->argc; i++) {
7780 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(CFP_ISEQ(cfp))->local_table[i+start_index]));
7782 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7783 (
void *)(uintptr_t)bf->func_ptr);
7786 if (bf->argc == 0) {
7787 return invoke_bf(ec, cfp, bf, NULL);
7790 const VALUE *argv = cfp->ep - ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7791 return invoke_bf(ec, cfp, bf, argv);
7801 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)
Same as RB_OBJ_FROZEN(), but returns Qtrue/Qfalse instead of #bool.
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.
bool rb_set_lookup(VALUE set, VALUE element)
Whether the set contains the given element.
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.
#define RB_OBJ_SET_SHAREABLE(obj)
Wrapper of rb_obj_set_shareable().
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.