11#include "ruby/internal/config.h"
15#ifdef HAVE_STDATOMIC_H
16 #include <stdatomic.h>
20#include "debug_counter.h"
22#include "internal/class.h"
23#include "internal/compar.h"
24#include "internal/hash.h"
25#include "internal/numeric.h"
26#include "internal/proc.h"
27#include "internal/random.h"
28#include "internal/variable.h"
29#include "internal/set_table.h"
30#include "internal/struct.h"
35#include "insns_info.inc"
41 int argc,
const VALUE *argv,
int priv);
51ruby_vm_special_exception_copy(
VALUE exc)
54 rb_obj_copy_ivar(e, exc);
62 VALUE mesg = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_sysstack];
63 ec->raised_flag = RAISED_STACKOVERFLOW;
65 VALUE at = rb_ec_backtrace_object(ec);
66 mesg = ruby_vm_special_exception_copy(mesg);
71 EC_JUMP_TAG(ec, TAG_RAISE);
74NORETURN(
static void vm_stackoverflow(
void));
79 ec_stack_overflow(GET_EC(), TRUE);
86 rb_bug(
"system stack overflow during GC. Faulty native extension?");
88 if (crit >= rb_stack_overflow_fatal) {
89 ec->raised_flag = RAISED_STACKOVERFLOW;
90 ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
91 EC_JUMP_TAG(ec, TAG_RAISE);
93 ec_stack_overflow(ec, crit < rb_stack_overflow_signal);
100callable_class_p(
VALUE klass)
102#if VM_CHECK_MODE >= 2
103 if (!klass)
return FALSE;
131 VM_ASSERT(IMEMO_TYPE_P((
VALUE)cme, imemo_ment),
"imemo_type:%s", rb_imemo_name(imemo_type((
VALUE)cme)));
133 if (callable_class_p(cme->defined_class)) {
143vm_check_frame_detail(
VALUE type,
int req_block,
int req_me,
int req_cref,
VALUE specval,
VALUE cref_or_me,
int is_cframe,
const rb_iseq_t *iseq)
145 unsigned int magic = (
unsigned int)(
type & VM_FRAME_MAGIC_MASK);
146 enum imemo_type cref_or_me_type = imemo_env;
149 cref_or_me_type = imemo_type(cref_or_me);
151 if (
type & VM_FRAME_FLAG_BMETHOD) {
155 if (req_block && (
type & VM_ENV_FLAG_LOCAL) == 0) {
156 rb_bug(
"vm_push_frame: specval (%p) should be a block_ptr on %x frame", (
void *)specval, magic);
158 if (!req_block && (
type & VM_ENV_FLAG_LOCAL) != 0) {
159 rb_bug(
"vm_push_frame: specval (%p) should not be a block_ptr on %x frame", (
void *)specval, magic);
163 if (cref_or_me_type != imemo_ment) {
164 rb_bug(
"vm_push_frame: (%s) should be method entry on %x frame", rb_obj_info(cref_or_me), magic);
168 if (req_cref && cref_or_me_type != imemo_cref) {
169 rb_bug(
"vm_push_frame: (%s) should be CREF on %x frame", rb_obj_info(cref_or_me), magic);
172 if (cref_or_me !=
Qfalse && cref_or_me_type != imemo_cref) {
173 if (((
type & VM_FRAME_FLAG_LAMBDA) || magic == VM_FRAME_MAGIC_IFUNC || magic == VM_FRAME_MAGIC_DUMMY) && (cref_or_me_type == imemo_ment)) {
177 rb_bug(
"vm_push_frame: (%s) should be false or cref on %x frame", rb_obj_info(cref_or_me), magic);
183 if (cref_or_me_type == imemo_ment) {
186 if (!callable_method_entry_p(me)) {
187 rb_bug(
"vm_push_frame: ment (%s) should be callable on %x frame.", rb_obj_info(cref_or_me), magic);
191 if ((
type & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
192 VM_ASSERT(iseq == NULL ||
194 RUBY_VM_NORMAL_ISEQ_P(iseq)
198 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(iseq));
208 VALUE given_magic =
type & VM_FRAME_MAGIC_MASK;
211#define CHECK(magic, req_block, req_me, req_cref, is_cframe) \
213 vm_check_frame_detail(type, req_block, req_me, req_cref, \
214 specval, cref_or_me, is_cframe, iseq); \
216 switch (given_magic) {
218 CHECK(VM_FRAME_MAGIC_METHOD, TRUE, TRUE, FALSE, FALSE);
219 CHECK(VM_FRAME_MAGIC_CLASS, TRUE, FALSE, TRUE, FALSE);
220 CHECK(VM_FRAME_MAGIC_TOP, TRUE, FALSE, TRUE, FALSE);
221 CHECK(VM_FRAME_MAGIC_CFUNC, TRUE, TRUE, FALSE, TRUE);
222 CHECK(VM_FRAME_MAGIC_BLOCK, FALSE, FALSE, FALSE, FALSE);
223 CHECK(VM_FRAME_MAGIC_IFUNC, FALSE, FALSE, FALSE, TRUE);
224 CHECK(VM_FRAME_MAGIC_EVAL, FALSE, FALSE, FALSE, FALSE);
225 CHECK(VM_FRAME_MAGIC_RESCUE, FALSE, FALSE, FALSE, FALSE);
226 CHECK(VM_FRAME_MAGIC_DUMMY, TRUE, FALSE, FALSE, FALSE);
228 rb_bug(
"vm_push_frame: unknown type (%x)", (
unsigned int)given_magic);
233static VALUE vm_stack_canary;
234static bool vm_stack_canary_was_born =
false;
241 unsigned int pos = 0;
242 while (pos < ISEQ_BODY(iseq)->iseq_size) {
243 int opcode = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[pos]);
244 unsigned int next_pos = pos + insn_len(opcode);
245 if (ISEQ_BODY(iseq)->iseq_encoded + next_pos == pc) {
250 rb_bug(
"failed to find the previous insn");
259 if (! LIKELY(vm_stack_canary_was_born)) {
262 else if ((
VALUE *)reg_cfp == ec->vm_stack + ec->vm_stack_size) {
266 else if (! (iseq = GET_ISEQ())) {
269 else if (LIKELY(sp[0] != vm_stack_canary)) {
278 const VALUE *orig = rb_iseq_original_iseq(iseq);
279 const VALUE iseqw = rb_iseqw_new(iseq);
281 const char *stri = rb_str_to_cstr(inspection);
282 const VALUE disasm = rb_iseq_disasm(iseq);
283 const char *strd = rb_str_to_cstr(disasm);
284 const ptrdiff_t pos = previous_insn_index(iseq, GET_PC());
285 const enum ruby_vminsn_type insn = (
enum ruby_vminsn_type)orig[pos];
286 const char *name = insn_name(insn);
292 "We are killing the stack canary set by %s, "
293 "at %s@pc=%"PRIdPTR
"\n"
294 "watch out the C stack trace.\n"
296 name, stri, pos, strd);
297 rb_bug(
"see above.");
299#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
302#define vm_check_canary(ec, sp)
303#define vm_check_frame(a, b, c, d)
308vm_push_frame_debug_counter_inc(
315 RB_DEBUG_COUNTER_INC(frame_push);
317 if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
318 const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
319 const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
322 RB_DEBUG_COUNTER_INC(frame_R2R);
325 RB_DEBUG_COUNTER_INC(frame_R2C);
330 RB_DEBUG_COUNTER_INC(frame_C2R);
333 RB_DEBUG_COUNTER_INC(frame_C2C);
338 switch (
type & VM_FRAME_MAGIC_MASK) {
339 case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method);
return;
340 case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block);
return;
341 case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class);
return;
342 case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top);
return;
343 case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc);
return;
344 case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc);
return;
345 case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval);
return;
346 case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue);
return;
347 case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy);
return;
350 rb_bug(
"unreachable");
353#define vm_push_frame_debug_counter_inc(ec, cfp, t)
358rb_vm_stack_canary(
void)
361 return vm_stack_canary;
367STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
368STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
369STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
385 vm_check_frame(
type, specval, cref_or_me, iseq);
386 VM_ASSERT(local_size >= 0);
389 CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
390 vm_check_canary(ec, sp);
395 for (
int i=0; i < local_size; i++) {
422 #if defined HAVE_DECL_ATOMIC_SIGNAL_FENCE && HAVE_DECL_ATOMIC_SIGNAL_FENCE
423 atomic_signal_fence(memory_order_seq_cst);
431 vm_push_frame_debug_counter_inc(ec, cfp,
type);
439 if (VMDEBUG == 2) SDR();
441 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
448 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
450 if (VMDEBUG == 2) SDR();
452 RUBY_VM_CHECK_INTS(ec);
453 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
455 return flags & VM_FRAME_FLAG_FINISH;
461 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
469 rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
473 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
475 VM_BLOCK_HANDLER_NONE,
482 return (
VALUE)dmy_iseq;
487rb_arity_error_new(
int argc,
int min,
int max)
489 VALUE err_mess = rb_sprintf(
"wrong number of arguments (given %d, expected %d", argc, min);
497 rb_str_catf(err_mess,
"..%d", max);
504rb_error_arity(
int argc,
int min,
int max)
511NOINLINE(
static void vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v));
514vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v)
517 rb_gc_writebarrier_remember(VM_ENV_ENVVAL(ep));
518 VM_FORCE_WRITE(&ep[index], v);
519 VM_ENV_FLAGS_UNSET(ep, VM_ENV_FLAG_WB_REQUIRED);
520 RB_DEBUG_COUNTER_INC(lvar_set_slowpath);
525vm_env_write(
const VALUE *ep,
int index,
VALUE v)
527 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
528 if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
529 VM_STACK_ENV_WRITE(ep, index, v);
532 vm_env_write_slowpath(ep, index, v);
537rb_vm_env_write(
const VALUE *ep,
int index,
VALUE v)
539 vm_env_write(ep, index, v);
545 if (block_handler == VM_BLOCK_HANDLER_NONE) {
549 switch (vm_block_handler_type(block_handler)) {
550 case block_handler_type_iseq:
551 case block_handler_type_ifunc:
552 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler),
rb_cProc);
553 case block_handler_type_symbol:
554 return rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
555 case block_handler_type_proc:
556 return VM_BH_TO_PROC(block_handler);
558 VM_UNREACHABLE(rb_vm_bh_to_procval);
567vm_svar_valid_p(
VALUE svar)
570 switch (imemo_type(svar)) {
579 rb_bug(
"vm_svar_valid_p: unknown type: %s", rb_obj_info(svar));
589 if (lep && (ec == NULL || ec->root_lep != lep)) {
590 svar = lep[VM_ENV_DATA_INDEX_ME_CREF];
593 svar = ec->root_svar;
596 VM_ASSERT(svar ==
Qfalse || vm_svar_valid_p(svar));
604 VM_ASSERT(vm_svar_valid_p((
VALUE)svar));
606 if (lep && (ec == NULL || ec->root_lep != lep)) {
607 vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (
VALUE)svar);
610 RB_OBJ_WRITE(rb_ec_thread_ptr(ec)->self, &ec->root_svar, svar);
617 const struct vm_svar *svar = lep_svar(ec, lep);
622 case VM_SVAR_LASTLINE:
623 return svar->lastline;
624 case VM_SVAR_BACKREF:
625 return svar->backref;
627 const VALUE ary = svar->others;
642 struct vm_svar *svar = IMEMO_NEW(
struct vm_svar, imemo_svar, obj);
653 struct vm_svar *svar = lep_svar(ec, lep);
656 lep_svar_write(ec, lep, svar = svar_new((
VALUE)svar));
660 case VM_SVAR_LASTLINE:
663 case VM_SVAR_BACKREF:
667 VALUE ary = svar->others;
683 val = lep_svar_get(ec, lep, key);
686 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
703 rb_bug(
"unexpected back-ref");
716 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
726 return rb_reg_last_defined(backref);
728 rb_bug(
"unexpected back-ref");
732 nth = (int)(
type >> 1);
739check_method_entry(
VALUE obj,
int can_be_svar)
741 if (obj ==
Qfalse)
return NULL;
744 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_method_entry: unknown type: %s", rb_obj_info(obj));
747 switch (imemo_type(obj)) {
758 rb_bug(
"check_method_entry: svar should not be there:");
765env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
767 if (obj ==
Qfalse)
return NULL;
769 switch (imemo_type(obj)) {
786 const VALUE *ep = cfp->ep;
789 while (!VM_ENV_LOCAL_P(ep)) {
790 if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
791 ep = VM_ENV_PREV_EP(ep);
794 return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
800 const VALUE *ep = cfp->ep;
803 while (!VM_ENV_LOCAL_P_UNCHECKED(ep)) {
804 if ((me = env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
805 ep = VM_ENV_PREV_EP_UNCHECKED(ep);
808 return env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
814 switch (me->def->type) {
815 case VM_METHOD_TYPE_ISEQ:
816 return me->def->body.iseq.
iseqptr;
825 switch (me->def->type) {
826 case VM_METHOD_TYPE_ISEQ:
827 return me->def->body.iseq.
cref;
833#if VM_CHECK_MODE == 0
837check_cref(
VALUE obj,
int can_be_svar)
839 if (obj ==
Qfalse)
return NULL;
842 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_cref: unknown type: %s", rb_obj_info(obj));
845 switch (imemo_type(obj)) {
856 rb_bug(
"check_method_entry: svar should not be there:");
863vm_env_cref(
const VALUE *ep)
867 while (!VM_ENV_LOCAL_P(ep)) {
868 if ((cref = check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return cref;
869 ep = VM_ENV_PREV_EP(ep);
872 return check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
876is_cref(
const VALUE v,
int can_be_svar)
879 switch (imemo_type(v)) {
892vm_env_cref_by_cref(
const VALUE *ep)
894 while (!VM_ENV_LOCAL_P(ep)) {
895 if (is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE))
return TRUE;
896 ep = VM_ENV_PREV_EP(ep);
898 return is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
902cref_replace_with_duplicated_cref_each_frame(
const VALUE *vptr,
int can_be_svar,
VALUE parent)
904 const VALUE v = *vptr;
908 switch (imemo_type(v)) {
911 new_cref = vm_cref_dup(cref);
916 VM_FORCE_WRITE(vptr, (
VALUE)new_cref);
921 return cref_replace_with_duplicated_cref_each_frame(&((
struct vm_svar *)v)->
cref_or_me, FALSE, v);
925 rb_bug(
"cref_replace_with_duplicated_cref_each_frame: unreachable");
934vm_cref_replace_with_duplicated_cref(
const VALUE *ep)
936 if (vm_env_cref_by_cref(ep)) {
940 while (!VM_ENV_LOCAL_P(ep)) {
941 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
942 if ((cref = cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE, envval)) != NULL) {
945 ep = VM_ENV_PREV_EP(ep);
947 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
948 return cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE, envval);
951 rb_bug(
"vm_cref_dup: unreachable");
956vm_get_cref(
const VALUE *ep)
964 rb_bug(
"vm_get_cref: unreachable");
969rb_vm_get_cref(
const VALUE *ep)
971 return vm_get_cref(ep);
982 return vm_get_cref(cfp->ep);
986vm_get_const_key_cref(
const VALUE *ep)
992 if (CREF_DYNAMIC(cref) ||
993 RCLASS_CLONED_P(CREF_CLASS(cref))) {
996 cref = CREF_NEXT(cref);
1009 #define ADD_NEW_CREF(new_cref) \
1010 if (new_cref_tail) { \
1011 RB_OBJ_WRITE(new_cref_tail, &new_cref_tail->next, new_cref); \
1014 new_cref_head = new_cref; \
1016 new_cref_tail = new_cref;
1020 if (CREF_CLASS(cref) == old_klass) {
1021 new_cref = vm_cref_new_use_prev(new_klass, METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1022 ADD_NEW_CREF(new_cref);
1023 return new_cref_head;
1025 new_cref = vm_cref_new_use_prev(CREF_CLASS(cref), METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1026 cref = CREF_NEXT(cref);
1027 ADD_NEW_CREF(new_cref);
1033 return new_cref_head;
1042 prev_cref = vm_env_cref(ep);
1048 prev_cref = vm_env_cref(cfp->ep);
1052 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1056vm_get_cbase(
const VALUE *ep)
1058 const rb_cref_t *cref = vm_get_cref(ep);
1060 return CREF_CLASS_FOR_DEFINITION(cref);
1064vm_get_const_base(
const VALUE *ep)
1066 const rb_cref_t *cref = vm_get_cref(ep);
1069 if (!CREF_PUSHED_BY_EVAL(cref)) {
1070 return CREF_CLASS_FOR_DEFINITION(cref);
1072 cref = CREF_NEXT(cref);
1079vm_check_if_namespace(
VALUE klass)
1082 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1087vm_ensure_not_refinement_module(
VALUE self)
1090 rb_warn(
"not defined at the refinement, but at the outer class/module");
1106 if (
NIL_P(orig_klass) && allow_nil) {
1108 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1112 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1113 root_cref = CREF_NEXT(root_cref);
1116 while (cref && CREF_NEXT(cref)) {
1117 if (CREF_PUSHED_BY_EVAL(cref)) {
1121 klass = CREF_CLASS(cref);
1123 cref = CREF_NEXT(cref);
1125 if (!
NIL_P(klass)) {
1129 if ((ce = rb_const_lookup(klass,
id))) {
1130 rb_const_warn_if_deprecated(ce, klass,
id);
1133 if (am == klass)
break;
1135 if (is_defined)
return 1;
1136 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1138 goto search_continue;
1145 if (UNLIKELY(!rb_ractor_main_p())) {
1147 rb_raise(rb_eRactorIsolationError,
1148 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" by non-main ractor.",
rb_class_path(klass), rb_id2str(
id));
1159 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1160 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1174 vm_check_if_namespace(orig_klass);
1176 return rb_public_const_defined_from(orig_klass,
id);
1179 return rb_public_const_get_from(orig_klass,
id);
1187 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1195 int allow_nil = TRUE;
1196 if (segments[0] == idNULL) {
1201 while (segments[idx]) {
1202 ID id = segments[idx++];
1203 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1216 rb_bug(
"vm_get_cvar_base: no cref");
1219 while (CREF_NEXT(cref) &&
1220 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1221 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1222 cref = CREF_NEXT(cref);
1224 if (top_level_raise && !CREF_NEXT(cref)) {
1228 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1236ALWAYS_INLINE(
static void fill_ivar_cache(
const rb_iseq_t *iseq,
IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id));
1238fill_ivar_cache(
const rb_iseq_t *iseq,
IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id)
1241 vm_cc_attr_index_set(cc, index, shape_id);
1244 vm_ic_attr_index_set(iseq, ic, index, shape_id);
1248#define ractor_incidental_shareable_p(cond, val) \
1249 (!(cond) || rb_ractor_shareable_p(val))
1250#define ractor_object_incidental_shareable_p(obj, val) \
1251 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1260 return default_value;
1270 if (UNLIKELY(!rb_ractor_main_p())) {
1278 if (default_value ==
Qundef) {
1286 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1290 fields_obj = rb_obj_fields(obj,
id);
1294 return default_value;
1299 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1300 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1302 shape_id_t cached_id;
1306 vm_cc_atomic_shape_and_index(cc, &cached_id, &index);
1309 vm_ic_atomic_shape_and_index(ic, &cached_id, &index);
1312 if (LIKELY(cached_id == shape_id)) {
1315 if (index == ATTR_INDEX_NOT_SET) {
1316 return default_value;
1319 val = ivar_list[index];
1320#if USE_DEBUG_COUNTER
1321 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1324 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1330#if USE_DEBUG_COUNTER
1332 if (cached_id != INVALID_SHAPE_ID) {
1333 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1336 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1340 if (cached_id != INVALID_SHAPE_ID) {
1341 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1344 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1347 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1350 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1354 if (UNLIKELY(rb_shape_too_complex_p(shape_id))) {
1358 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1360 if (!st_lookup(table,
id, &val)) {
1361 val = default_value;
1365 shape_id_t previous_cached_id = cached_id;
1366 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &index, &cached_id)) {
1369 if (cached_id != previous_cached_id) {
1370 fill_ivar_cache(iseq, ic, cc, is_attr, index, cached_id);
1373 if (index == ATTR_INDEX_NOT_SET) {
1374 val = default_value;
1378 val = ivar_list[index];
1384 vm_cc_attr_index_initialize(cc, shape_id);
1387 vm_ic_attr_index_initialize(ic, shape_id);
1390 val = default_value;
1395 if (!UNDEF_P(default_value)) {
1403 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1406 return rb_attr_get(obj,
id);
1414populate_cache(attr_index_t index, shape_id_t next_shape_id,
ID id,
const rb_iseq_t *iseq,
IVC ic,
const struct rb_callcache *cc,
bool is_attr)
1416 RUBY_ASSERT(!rb_shape_too_complex_p(next_shape_id));
1420 vm_cc_attr_index_set(cc, index, next_shape_id);
1423 vm_ic_attr_index_set(iseq, ic, index, next_shape_id);
1435 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1437 rb_check_frozen(obj);
1439 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1440 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1442 if (!rb_shape_too_complex_p(next_shape_id)) {
1443 populate_cache(index, next_shape_id,
id, iseq, ic, cc, is_attr);
1446 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1456 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1462 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1465NOINLINE(
static VALUE vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1467vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1469 if (UNLIKELY(!rb_ractor_main_p())) {
1473 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1474 if (UNLIKELY(!fields_obj)) {
1478 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1481 if (shape_id == dest_shape_id) {
1482 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1484 else if (dest_shape_id != INVALID_SHAPE_ID) {
1485 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1486 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1496 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1498 if (shape_id != dest_shape_id) {
1499 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1500 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1503 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1508NOINLINE(
static VALUE vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1510vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1512 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1515 if (shape_id == dest_shape_id) {
1516 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1518 else if (dest_shape_id != INVALID_SHAPE_ID) {
1519 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1520 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1530 VALUE fields_obj = rb_obj_fields(obj,
id);
1532 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1534 if (shape_id != dest_shape_id) {
1535 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1536 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1539 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1545vm_setivar(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1553 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1554 RUBY_ASSERT(dest_shape_id == INVALID_SHAPE_ID || !rb_shape_too_complex_p(dest_shape_id));
1556 if (LIKELY(shape_id == dest_shape_id)) {
1557 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1560 else if (dest_shape_id != INVALID_SHAPE_ID) {
1561 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1562 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1564 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1566 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1581 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1582 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1588 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1600 VALUE defined_class = 0;
1604 defined_class =
RBASIC(defined_class)->klass;
1607 VALUE rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
1609 rb_bug(
"the cvc table should be set");
1613 if (!rb_marked_id_table_lookup(rb_cvc_tbl,
id, &ent_data)) {
1614 rb_bug(
"should have cvar cache entry");
1619 ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
1634 cref = vm_get_cref(GET_EP());
1636 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1637 RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
1639 VALUE v = rb_ivar_lookup(ic->entry->class_value,
id,
Qundef);
1645 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1647 return update_classvariable_cache(iseq, klass,
id, cref, ic);
1653 return vm_getclassvariable(iseq, cfp,
id, ic);
1660 cref = vm_get_cref(GET_EP());
1662 if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE() && ic->entry->cref == cref && LIKELY(rb_ractor_main_p())) {
1663 RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
1665 rb_class_ivar_set(ic->entry->class_value,
id, val);
1669 VALUE klass = vm_get_cvar_base(cref, reg_cfp, 1);
1673 update_classvariable_cache(iseq, klass,
id, cref, ic);
1679 vm_setclassvariable(iseq, cfp,
id, val, ic);
1686 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1697 shape_id_t dest_shape_id;
1699 vm_ic_atomic_shape_and_index(ic, &dest_shape_id, &index);
1701 if (UNLIKELY(UNDEF_P(vm_setivar(obj,
id, val, dest_shape_id, index)))) {
1707 if (!UNDEF_P(vm_setivar_class(obj,
id, val, dest_shape_id, index))) {
1712 if (!UNDEF_P(vm_setivar_default(obj,
id, val, dest_shape_id, index))) {
1716 vm_setivar_slowpath_ivar(obj,
id, val, iseq, ic);
1723 vm_setinstancevariable(iseq, obj,
id, val, ic);
1729 return vm_getinstancevariable(iseq, obj,
id, ic);
1738 ec->tag->state = RUBY_TAG_FATAL;
1741 ec->tag->state = TAG_THROW;
1743 else if (THROW_DATA_P(err)) {
1744 ec->tag->state = THROW_DATA_STATE((
struct vm_throw_data *)err);
1747 ec->tag->state = TAG_RAISE;
1754 const int flag,
const VALUE throwobj)
1762 else if (state == TAG_BREAK) {
1764 const VALUE *ep = GET_EP();
1765 const rb_iseq_t *base_iseq = GET_ISEQ();
1766 escape_cfp = reg_cfp;
1768 while (ISEQ_BODY(base_iseq)->
type != ISEQ_TYPE_BLOCK) {
1769 if (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1770 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1771 ep = escape_cfp->ep;
1772 base_iseq = CFP_ISEQ(escape_cfp);
1775 ep = VM_ENV_PREV_EP(ep);
1776 base_iseq = ISEQ_BODY(base_iseq)->parent_iseq;
1777 escape_cfp = rb_vm_search_cf_from_ep(ec, escape_cfp, ep);
1778 VM_ASSERT(CFP_ISEQ(escape_cfp) == base_iseq);
1782 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1788 ep = VM_ENV_PREV_EP(ep);
1790 while (escape_cfp < eocfp) {
1791 if (escape_cfp->ep == ep) {
1792 const rb_iseq_t *
const iseq = CFP_ISEQ(escape_cfp);
1793 const VALUE epc = CFP_PC(escape_cfp) - ISEQ_BODY(iseq)->iseq_encoded;
1798 for (i=0; i < ct->size; i++) {
1800 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1802 if (entry->type == CATCH_TYPE_BREAK &&
1803 entry->iseq == base_iseq &&
1804 entry->start < epc && entry->end >= epc) {
1805 if (entry->cont == epc) {
1814 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1819 rb_vm_localjump_error(
"break from proc-closure", throwobj, TAG_BREAK);
1822 else if (state == TAG_RETRY) {
1823 const VALUE *ep = VM_ENV_PREV_EP(GET_EP());
1825 escape_cfp = rb_vm_search_cf_from_ep(ec, reg_cfp, ep);
1827 else if (state == TAG_RETURN) {
1828 const VALUE *current_ep = GET_EP();
1829 const VALUE *target_ep = NULL, *target_lep, *ep = current_ep;
1830 int in_class_frame = 0;
1832 escape_cfp = reg_cfp;
1835 while (!VM_ENV_LOCAL_P(ep)) {
1836 if (VM_ENV_FLAGS(ep, VM_FRAME_FLAG_LAMBDA) && target_ep == NULL) {
1839 ep = VM_ENV_PREV_EP(ep);
1843 while (escape_cfp < eocfp) {
1844 const VALUE *lep = VM_CF_LEP(escape_cfp);
1850 if (lep == target_lep &&
1851 VM_FRAME_RUBYFRAME_P(escape_cfp) &&
1852 ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_CLASS) {
1857 if (lep == target_lep) {
1858 if (VM_FRAME_LAMBDA_P(escape_cfp)) {
1860 if (in_class_frame) {
1865 const VALUE *tep = current_ep;
1867 while (target_lep != tep) {
1868 if (escape_cfp->ep == tep) {
1870 if (tep == target_ep) {
1874 goto unexpected_return;
1877 tep = VM_ENV_PREV_EP(tep);
1881 else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
1882 switch (ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type) {
1884 case ISEQ_TYPE_MAIN:
1886 if (in_class_frame)
goto unexpected_return;
1887 if (target_ep == NULL) {
1891 goto unexpected_return;
1895 case ISEQ_TYPE_EVAL: {
1896 const rb_iseq_t *is = CFP_ISEQ(escape_cfp);
1897 enum rb_iseq_type t = ISEQ_BODY(is)->type;
1898 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE || t == ISEQ_TYPE_EVAL) {
1899 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
1900 t = ISEQ_BODY(is)->type;
1902 toplevel = t == ISEQ_TYPE_TOP || t == ISEQ_TYPE_MAIN;
1905 case ISEQ_TYPE_CLASS:
1914 if (escape_cfp->ep == target_lep && ISEQ_BODY(CFP_ISEQ(escape_cfp))->
type == ISEQ_TYPE_METHOD) {
1915 if (target_ep == NULL) {
1919 goto unexpected_return;
1923 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1926 rb_vm_localjump_error(
"unexpected return", throwobj, TAG_RETURN);
1932 rb_bug(
"isns(throw): unsupported throw type");
1935 ec->tag->state = state;
1936 return (
VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state);
1941 rb_num_t throw_state,
VALUE throwobj)
1943 const int state = (int)(throw_state & VM_THROW_STATE_MASK);
1944 const int flag = (int)(throw_state & VM_THROW_NO_ESCAPE_FLAG);
1947 return vm_throw_start(ec, reg_cfp, state, flag, throwobj);
1950 return vm_throw_continue(ec, throwobj);
1957 return vm_throw(ec, reg_cfp, throw_state, throwobj);
1963 int is_splat = flag & 0x01;
1966 const VALUE obj = ary;
1978 if (num + is_splat == 0) {
1981 else if (flag & 0x02) {
1986 for (i = 0; i < num -
len; i++) {
1991 for (j = 0; i < num; i++, j++) {
2013 for (; i < num -
len; i++) {
2017 for (rb_num_t j = 0; i < num; i++, j++) {
2018 *cfp->sp++ = ptr[
len - j - 1];
2022 for (rb_num_t j = 0; j < num; j++) {
2023 *cfp->sp++ = ptr[num - j - 1];
2038 int initial_capa = 2;
2040#if VM_CHECK_MODE > 0
2041 ccs->debug_sig = ~(
VALUE)ccs;
2043 ccs->capa = initial_capa;
2048 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2056 if (! vm_cc_markable(cc)) {
2060 if (UNLIKELY(ccs->len == ccs->capa)) {
2063 ccs = ruby_xrealloc(ccs, vm_ccs_alloc_size(ccs->capa));
2064#if VM_CHECK_MODE > 0
2065 ccs->debug_sig = ~(
VALUE)ccs;
2068 rb_managed_id_table_insert(cc_tbl, mid, (
VALUE)ccs);
2070 VM_ASSERT(ccs->len < ccs->capa);
2072 const int pos = ccs->len++;
2073 ccs->entries[pos].argc = vm_ci_argc(ci);
2074 ccs->entries[pos].flag = vm_ci_flag(ci);
2077 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
2083#if VM_CHECK_MODE > 0
2087 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
2088 for (
int i=0; i<ccs->len; i++) {
2089 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u\n",
2090 ccs->entries[i].flag,
2091 ccs->entries[i].argc);
2092 rp(ccs->entries[i].cc);
2099 VM_ASSERT(vm_ccs_p(ccs));
2100 VM_ASSERT(ccs->len <= ccs->capa);
2102 for (
int i=0; i<ccs->len; i++) {
2105 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2106 VM_ASSERT(vm_cc_class_check(cc, klass));
2107 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
2108 VM_ASSERT(!vm_cc_super_p(cc));
2109 VM_ASSERT(!vm_cc_refinement_p(cc));
2120 ASSERT_vm_locking();
2122 if (rb_multi_ractor_p()) {
2123 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2130 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2133 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2138 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2139 rb_vm_cc_table_delete(new_table, mid);
2140 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2143 rb_vm_cc_table_delete(cc_tbl, mid);
2150 ASSERT_vm_locking();
2152 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2156 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2160 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2161 return &vm_empty_cc;
2164 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2165 const VALUE original_cc_table = cc_tbl;
2168 cc_tbl = rb_vm_cc_table_create(1);
2170 else if (rb_multi_ractor_p()) {
2171 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2174 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2183 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2188 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2192 cme = rb_check_overloaded_cme(cme, ci);
2194 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2195 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2197 VM_ASSERT(vm_cc_cme(cc) != NULL);
2198 VM_ASSERT(cme->called_id == mid);
2199 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2201 if (original_cc_table != cc_tbl) {
2202 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2214 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2222 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2224 const int ccs_len = ccs->len;
2226 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2228 vm_evict_cc(klass, cc_tbl, mid);
2233 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2238 unsigned int argc = vm_ci_argc(ci);
2239 unsigned int flag = vm_ci_flag(ci);
2241 for (
int i=0; i<ccs_len; i++) {
2242 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2243 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2244 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2246 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2248 if (ccs_ci_argc == argc && ccs_ci_flag == flag) {
2249 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2251 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2252 VM_ASSERT(ccs_cc->klass == klass);
2253 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2269 const ID mid = vm_ci_mid(ci);
2271 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2277 if (rb_multi_ractor_p()) {
2280 cc = vm_lookup_cc(klass, ci, mid);
2284 cc = vm_populate_cc(klass, ci, mid);
2298 cc = vm_search_cc(klass, ci);
2301 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2302 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2303 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2304 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2305 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2313#if USE_DEBUG_COUNTER
2317 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2319#if OPT_INLINE_METHOD_CACHE
2323 if (cd_owner && cc != empty_cc) {
2327#if USE_DEBUG_COUNTER
2328 if (!old_cc || old_cc == empty_cc) {
2330 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2332 else if (old_cc == cc) {
2333 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2335 else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) {
2336 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2338 else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) &&
2339 vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) {
2340 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2343 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2348 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2349 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2360#if OPT_INLINE_METHOD_CACHE
2361 if (LIKELY(vm_cc_class_check(cc, klass))) {
2362 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2363 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2364 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2365 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2366 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2367 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2371 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2374 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2378 return vm_search_method_slowpath0((
VALUE)CFP_ISEQ(reg_cfp), cd, klass);
2385 VM_ASSERT(klass !=
Qfalse);
2388 const struct rb_callcache *cc = vm_search_method_fastpath(reg_cfp, cd, klass);
2389 return vm_cc_cme(cc);
2398 const struct rb_callcache *cc = vm_search_method_slowpath0(cd_owner, cd, klass);
2399 return vm_cc_cme(cc);
2402#if __has_attribute(transparent_union)
2415 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2416 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2417 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2418 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2419 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2420 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2423# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2426# define make_cfunc_type(f) (cfunc_type)(f)
2436 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2437 VM_ASSERT(callable_method_entry_p(me));
2439 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2443#if __has_attribute(transparent_union)
2444 return me->def->body.cfunc.func == func.anyargs;
2446 return me->def->body.cfunc.func == func;
2455 return me && METHOD_ENTRY_BASIC(me);
2461 VM_ASSERT(reg_cfp != NULL);
2463 return check_cfunc(cme, func);
2469 return check_cfunc(me, func);
2478 const struct rb_callcache *cc = vm_search_method_slowpath0((
VALUE)iseq, cd, klass);
2480 return check_cfunc(cme, func);
2483#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2484#define vm_method_cfunc_is(reg_cfp, cd, recv, func) vm_method_cfunc_is(reg_cfp, cd, recv, make_cfunc_type(func))
2486#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
2518opt_equality_specialized(
VALUE recv,
VALUE obj)
2520 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2521 goto compare_by_identity;
2523 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2524 goto compare_by_identity;
2527 goto compare_by_identity;
2536 return RBOOL(a == b);
2543 return rb_str_eql_internal(obj, recv);
2548 compare_by_identity:
2549 return RBOOL(recv == obj);
2555 VM_ASSERT(reg_cfp != NULL);
2557 VALUE val = opt_equality_specialized(recv, obj);
2558 if (!UNDEF_P(val))
return val;
2560 if (!vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_equal)) {
2564 return RBOOL(recv == obj);
2568#undef EQ_UNREDEFINED_P
2571NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2574opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2576 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2578 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2579 return RBOOL(recv == obj);
2589 VALUE val = opt_equality_specialized(recv, obj);
2590 if (!UNDEF_P(val)) {
2594 return opt_equality_by_mid_slowpath(recv, obj, mid);
2601 return opt_equality_by_mid(obj1, obj2, idEq);
2607 return opt_equality_by_mid(obj1, obj2, idEqlP);
2617 case VM_CHECKMATCH_TYPE_WHEN:
2619 case VM_CHECKMATCH_TYPE_RESCUE:
2621 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2624 case VM_CHECKMATCH_TYPE_CASE: {
2625 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2628 rb_bug(
"check_match: unreachable");
2634double_cmp_lt(
double a,
double b)
2636 return RBOOL(a < b);
2640double_cmp_le(
double a,
double b)
2642 return RBOOL(a <= b);
2646double_cmp_gt(
double a,
double b)
2648 return RBOOL(a > b);
2652double_cmp_ge(
double a,
double b)
2654 return RBOOL(a >= b);
2658static inline VALUE *
2663 if (CFP_ISEQ(cfp) && VM_FRAME_RUBYFRAME_P(cfp)) {
2664 VALUE *bp = prev_cfp->sp + ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size + VM_ENV_DATA_SIZE;
2666 if (ISEQ_BODY(CFP_ISEQ(cfp))->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2667 int lts = ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size;
2668 int params = ISEQ_BODY(CFP_ISEQ(cfp))->param.size;
2671 bp += vm_ci_argc(ci);
2674 if (ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2678#if VM_DEBUG_BP_CHECK
2679 if (bp != cfp->bp_check) {
2680 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2681 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2682 (
long)(bp - GET_EC()->vm_stack));
2683 rb_bug(
"vm_base_ptr: unreachable");
2696 return vm_base_ptr(cfp);
2711static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2716 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2718 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2724 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2727 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2728 int param = ISEQ_BODY(iseq)->param.size;
2729 int local = ISEQ_BODY(iseq)->local_table_size;
2730 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2736 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2737 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2738 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2739 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2740 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2741 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2742 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2743 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2744 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2748rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2750 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2751 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2752 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2753 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2754 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2755 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2756 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2757 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2758 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2762rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2764 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2765 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2766 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2767 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2768 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2769 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2770 ISEQ_BODY(iseq)->param.flags.has_block == FALSE &&
2771 ISEQ_BODY(iseq)->param.flags.accepts_no_block == FALSE;
2774#define ALLOW_HEAP_ARGV (-2)
2775#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2780 vm_check_canary(GET_EC(), cfp->sp);
2786 int argc = calling->argc;
2788 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2792 VALUE *argv = cfp->sp - argc;
2796 cfp->sp -= argc - 1;
2797 cfp->sp[-1] = argv_ary;
2799 calling->heap_argv = argv_ary;
2805 if (max_args >= 0 &&
len + argc > max_args) {
2813 calling->argc +=
len - (max_args - argc + 1);
2814 len = max_args - argc + 1;
2823 calling->heap_argv = 0;
2825 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2827 for (i = 0; i <
len; i++) {
2828 *cfp->sp++ = ptr[i];
2840 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2841 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2842 const VALUE h = rb_hash_new_with_size(kw_len);
2843 VALUE *sp = cfp->sp;
2846 for (i=0; i<kw_len; i++) {
2847 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2851 cfp->sp -= kw_len - 1;
2852 calling->argc -= kw_len - 1;
2853 calling->kw_splat = 1;
2857vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2860 if (keyword_hash !=
Qnil) {
2862 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2865 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2871 keyword_hash = rb_hash_dup(keyword_hash);
2873 return keyword_hash;
2879 const struct rb_callinfo *restrict ci,
int max_args)
2881 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2882 if (IS_ARGS_KW_SPLAT(ci)) {
2884 VM_ASSERT(calling->kw_splat == 1);
2888 VALUE ary = cfp->sp[0];
2889 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2892 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2896 if (UNLIKELY(calling->heap_argv)) {
2898 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2899 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2900 calling->kw_splat = 0;
2908 VM_ASSERT(calling->kw_splat == 1);
2912 calling->kw_splat = 0;
2917 VM_ASSERT(calling->kw_splat == 0);
2921 VALUE ary = cfp->sp[0];
2923 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2928 VALUE last_hash, argv_ary;
2929 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2930 if (!IS_ARGS_KEYWORD(ci) &&
2933 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2938 calling->kw_splat = 1;
2944 if (!IS_ARGS_KEYWORD(ci) &&
2945 calling->argc > 0 &&
2947 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2954 cfp->sp[-1] = rb_hash_dup(last_hash);
2955 calling->kw_splat = 1;
2961 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2963 VM_ASSERT(calling->kw_splat == 1);
2964 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2969 calling->kw_splat = 0;
2975 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2977 VM_ASSERT(calling->kw_splat == 0);
2983 vm_caller_setup_arg_kw(cfp, calling, ci);
2987#define USE_OPT_HIST 0
2990#define OPT_HIST_MAX 64
2991static int opt_hist[OPT_HIST_MAX+1];
2995opt_hist_show_results_at_exit(
void)
2997 for (
int i=0; i<OPT_HIST_MAX; i++) {
2998 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
3008 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3009 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3010 const int opt = calling->argc - lead_num;
3011 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3012 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3013 const int param = ISEQ_BODY(iseq)->param.size;
3014 const int local = ISEQ_BODY(iseq)->local_table_size;
3015 const int delta = opt_num - opt;
3017 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3020 if (opt_pc < OPT_HIST_MAX) {
3024 opt_hist[OPT_HIST_MAX]++;
3028 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3036 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3037 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3038 const int opt = calling->argc - lead_num;
3039 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3041 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3044 if (opt_pc < OPT_HIST_MAX) {
3048 opt_hist[OPT_HIST_MAX]++;
3052 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3057 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3058 VALUE *
const locals);
3065 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3066 int param_size = ISEQ_BODY(iseq)->param.size;
3067 int local_size = ISEQ_BODY(iseq)->local_table_size;
3070 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3072 local_size = local_size + vm_ci_argc(calling->cd->ci);
3073 param_size = param_size + vm_ci_argc(calling->cd->ci);
3075 cfp->sp[0] = (
VALUE)calling->cd->ci;
3077 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3087 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3088 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3090 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3091 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3093 const int ci_kw_len = kw_arg->keyword_len;
3094 const VALUE *
const ci_keywords = kw_arg->keywords;
3095 VALUE *argv = cfp->sp - calling->argc;
3096 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3097 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3099 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3100 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3102 int param = ISEQ_BODY(iseq)->param.size;
3103 int local = ISEQ_BODY(iseq)->local_table_size;
3104 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3111 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3114 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3115 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3117 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3118 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3119 VALUE *
const argv = cfp->sp - calling->argc;
3120 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3123 for (i=0; i<kw_param->num; i++) {
3124 klocals[i] = kw_param->default_values[i];
3131 int param = ISEQ_BODY(iseq)->param.size;
3132 int local = ISEQ_BODY(iseq)->local_table_size;
3133 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3143 cfp->sp -= (calling->argc + 1);
3144 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3145 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3154 set_table *dup_check_table = &vm->unused_block_warning_table;
3164 .v = (
VALUE)cme->def,
3168 if (!strict_unused_block) {
3169 key = (st_data_t)cme->def->original_id;
3171 if (set_table_lookup(dup_check_table, key)) {
3181 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3186 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3187 fprintf(stderr,
"key:%p\n", (
void *)key);
3191 if (set_insert(dup_check_table, key)) {
3196 VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label);
3198 if (!
NIL_P(m_loc)) {
3199 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3203 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3210 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3215 VM_ASSERT((vm_ci_argc(ci), 1));
3216 VM_ASSERT(vm_cc_cme(cc) != NULL);
3218 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3219 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3220 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3221 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)CFP_PC(ec->cfp));
3224 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3225 if (LIKELY(rb_simple_iseq_p(iseq))) {
3227 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3228 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3230 if (calling->argc != lead_num) {
3231 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3235 VM_ASSERT(cc == calling->cc);
3237 if (vm_call_iseq_optimizable_p(ci, cc)) {
3238 if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3239 VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF);
3240 vm_cc_bf_set(cc, (
void *)iseq->body->iseq_encoded[1]);
3241 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3244 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3249 else if (rb_iseq_only_optparam_p(iseq)) {
3252 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3253 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3255 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3256 const int argc = calling->argc;
3257 const int opt = argc - lead_num;
3259 if (opt < 0 || opt > opt_num) {
3260 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3263 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3264 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3265 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3266 vm_call_cacheable(ci, cc));
3269 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3270 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3271 vm_call_cacheable(ci, cc));
3275 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3276 for (
int i=argc; i<lead_num + opt_num; i++) {
3279 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3281 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3282 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3283 const int argc = calling->argc;
3284 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3286 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3289 if (argc - kw_arg->keyword_len == lead_num) {
3290 const int ci_kw_len = kw_arg->keyword_len;
3291 const VALUE *
const ci_keywords = kw_arg->keywords;
3293 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3295 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3296 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3298 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3299 vm_call_cacheable(ci, cc));
3304 else if (argc == lead_num) {
3306 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3307 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3309 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3311 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3312 vm_call_cacheable(ci, cc));
3338 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3339 bool can_fastpath =
true;
3341 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3343 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3344 ci = vm_ci_new_runtime(
3351 ci = forward_cd->caller_ci;
3353 can_fastpath =
false;
3357 if (!vm_ci_markable(ci)) {
3358 ci = vm_ci_new_runtime(
3363 can_fastpath =
false;
3365 argv[param_size - 1] = (
VALUE)ci;
3366 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3370 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3397 const VALUE * lep = VM_CF_LEP(cfp);
3403 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3408 iseq = CFP_ISEQ(rb_vm_search_cf_from_ep(ec, cfp, lep));
3412 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3414 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3415 VALUE * to = cfp->sp - 1;
3419 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3424 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3426 cfp->sp = to + argc;
3445 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3448 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3449 int param_size = ISEQ_BODY(iseq)->param.size;
3450 int local_size = ISEQ_BODY(iseq)->local_table_size;
3452 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3454 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3455 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3461 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3464 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3465 int param_size = ISEQ_BODY(iseq)->param.size;
3466 int local_size = ISEQ_BODY(iseq)->local_table_size;
3468 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3471 local_size = local_size + vm_ci_argc(calling->cd->ci);
3472 param_size = param_size + vm_ci_argc(calling->cd->ci);
3474 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3475 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3480 int opt_pc,
int param_size,
int local_size)
3485 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3486 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3489 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3495 int opt_pc,
int param_size,
int local_size)
3497 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3498 VALUE *argv = cfp->sp - calling->argc;
3499 VALUE *sp = argv + param_size;
3500 cfp->sp = argv - 1 ;
3502 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3503 calling->block_handler, (
VALUE)me,
3504 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3505 local_size - param_size,
3506 ISEQ_BODY(iseq)->stack_max);
3515 VALUE *argv = cfp->sp - calling->argc;
3517 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3518 VALUE *src_argv = argv;
3519 VALUE *sp_orig, *sp;
3520 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3522 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3523 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3524 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3525 dst_captured->code.val = src_captured->code.val;
3526 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3527 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3530 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3534 vm_pop_frame(ec, cfp, cfp->ep);
3537 sp_orig = sp = cfp->sp;
3540 sp[0] = calling->recv;
3544 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3545 *sp++ = src_argv[i];
3548 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3549 calling->recv, calling->block_handler, (
VALUE)me,
3550 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3551 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3552 ISEQ_BODY(iseq)->stack_max);
3560ractor_unsafe_check(
void)
3562 if (!rb_ractor_main_p()) {
3563 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3570 ractor_unsafe_check();
3578 ractor_unsafe_check();
3580 return (*f)(argc, argv, recv);
3586 ractor_unsafe_check();
3594 ractor_unsafe_check();
3596 return (*f)(recv, argv[0]);
3602 ractor_unsafe_check();
3604 return (*f)(recv, argv[0], argv[1]);
3610 ractor_unsafe_check();
3612 return (*f)(recv, argv[0], argv[1], argv[2]);
3618 ractor_unsafe_check();
3620 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3626 ractor_unsafe_check();
3627 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3628 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3634 ractor_unsafe_check();
3635 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3636 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3642 ractor_unsafe_check();
3643 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3644 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3650 ractor_unsafe_check();
3651 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3652 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3658 ractor_unsafe_check();
3659 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3660 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3666 ractor_unsafe_check();
3667 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;
3668 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3674 ractor_unsafe_check();
3675 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;
3676 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]);
3682 ractor_unsafe_check();
3683 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;
3684 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]);
3690 ractor_unsafe_check();
3691 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;
3692 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]);
3698 ractor_unsafe_check();
3699 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;
3700 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]);
3706 ractor_unsafe_check();
3707 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;
3708 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]);
3722 return (*f)(argc, argv, recv);
3736 return (*f)(recv, argv[0]);
3743 return (*f)(recv, argv[0], argv[1]);
3750 return (*f)(recv, argv[0], argv[1], argv[2]);
3757 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3763 VALUE(*f)(
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]);
3770 VALUE(*f)(
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]);
3777 VALUE(*f)(
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]);
3784 VALUE(*f)(
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]);
3791 VALUE(*f)(
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]);
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))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]);
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))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]);
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))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]);
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))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]);
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))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]);
3833 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;
3834 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]);
3840 const int ov_flags = RAISED_STACKOVERFLOW;
3841 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3842 if (rb_ec_raised_p(ec, ov_flags)) {
3843 rb_ec_raised_reset(ec, ov_flags);
3849#define CHECK_CFP_CONSISTENCY(func) \
3850 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3851 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3857#if VM_DEBUG_VERIFY_METHOD_CACHE
3858 switch (me->def->type) {
3859 case VM_METHOD_TYPE_CFUNC:
3860 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3862# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3864 METHOD_BUG(ATTRSET);
3866 METHOD_BUG(BMETHOD);
3869 METHOD_BUG(OPTIMIZED);
3870 METHOD_BUG(MISSING);
3871 METHOD_BUG(REFINED);
3875 rb_bug(
"wrong method type: %d", me->def->type);
3878 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3885 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3892 VALUE recv = calling->recv;
3893 VALUE block_handler = calling->block_handler;
3894 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3896 if (UNLIKELY(calling->kw_splat)) {
3897 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3900 VM_ASSERT(reg_cfp == ec->cfp);
3902 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3905 vm_push_frame(ec, NULL, frame_type, recv,
3906 block_handler, (
VALUE)me,
3907 0, ec->cfp->sp, 0, 0);
3909 int len = cfunc->argc;
3912 reg_cfp->sp = stack_bottom;
3913 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3915 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3917 rb_vm_pop_frame(ec);
3919 VM_ASSERT(ec->cfp->sp == stack_bottom);
3921 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3922 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3932 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3934 VALUE *sp = ec->cfp->sp;
3935 VALUE recv = *(sp - recv_idx - 1);
3936 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3937 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3938#if VM_CHECK_MODE > 0
3940 *(GET_EC()->cfp->sp) =
Qfalse;
3942 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3947rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3949 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3955 int argc = calling->argc;
3956 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3957 VALUE *argv = &stack_bottom[1];
3959 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3966 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3968 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3970 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3971 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3974 VALUE *stack_bottom = reg_cfp->sp - 2;
3976 VM_ASSERT(calling->argc == 1);
3980 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3983 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));
3985 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3992 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3995 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3996 return vm_call_cfunc_other(ec, reg_cfp, calling);
4000 calling->kw_splat = 0;
4002 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
4003 VALUE *sp = stack_bottom;
4004 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
4005 for(i = 0; i < argc; i++) {
4010 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4016 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4017 VALUE argv_ary = reg_cfp->sp[-1];
4021 int argc_offset = 0;
4023 if (UNLIKELY(argc > 0 &&
4025 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4027 return vm_call_cfunc_other(ec, reg_cfp, calling);
4031 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4037 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4038 VALUE keyword_hash = reg_cfp->sp[-1];
4041 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4044 return vm_call_cfunc_other(ec, reg_cfp, calling);
4051 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4053 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4054 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4056 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4057 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4059 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4061 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4062 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4066 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4067 return vm_call_cfunc_other(ec, reg_cfp, calling);
4074 RB_DEBUG_COUNTER_INC(ccf_ivar);
4076 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4083 RB_DEBUG_COUNTER_INC(ccf_attrset);
4084 VALUE val = *(cfp->sp - 1);
4087 shape_id_t dest_shape_id;
4088 vm_cc_atomic_shape_and_index(cc, &dest_shape_id, &index);
4089 ID id = vm_cc_cme(cc)->def->body.attr.id;
4090 rb_check_frozen(obj);
4091 VALUE res = vm_setivar(obj,
id, val, dest_shape_id, index);
4099 res = vm_setivar_class(obj,
id, val, dest_shape_id, index);
4100 if (!UNDEF_P(res)) {
4107 res = vm_setivar_default(obj,
id, val, dest_shape_id, index);
4108 if (!UNDEF_P(res)) {
4113 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4121 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4131 VALUE procv = cme->def->body.bmethod.proc;
4134 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4135 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4139 GetProcPtr(procv, proc);
4140 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4150 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4154 VALUE procv = cme->def->body.bmethod.proc;
4157 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4158 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4162 GetProcPtr(procv, proc);
4163 const struct rb_block *block = &proc->block;
4165 while (vm_block_type(block) == block_type_proc) {
4166 block = vm_proc_block(block->as.proc);
4168 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4171 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4172 VALUE *
const argv = cfp->sp - calling->argc;
4173 const int arg_size = ISEQ_BODY(iseq)->param.size;
4176 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4177 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4180 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4185 vm_push_frame(ec, iseq,
4186 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4188 VM_GUARDED_PREV_EP(captured->ep),
4190 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4192 ISEQ_BODY(iseq)->local_table_size - arg_size,
4193 ISEQ_BODY(iseq)->stack_max);
4201 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4205 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4206 if (UNLIKELY(calling->heap_argv)) {
4211 argc = calling->argc;
4214 cfp->sp += - argc - 1;
4217 return vm_call_bmethod_body(ec, calling, argv);
4223 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4227 VALUE procv = cme->def->body.bmethod.proc;
4229 GetProcPtr(procv, proc);
4230 const struct rb_block *block = &proc->block;
4232 while (vm_block_type(block) == block_type_proc) {
4233 block = vm_proc_block(block->as.proc);
4235 if (vm_block_type(block) == block_type_iseq) {
4236 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4237 return vm_call_iseq_bmethod(ec, cfp, calling);
4240 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4241 return vm_call_noniseq_bmethod(ec, cfp, calling);
4245rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4247 VALUE klass = current_class;
4255 while (
RTEST(klass)) {
4257 if (owner == target_owner) {
4263 return current_class;
4272 if (orig_me->defined_class == 0) {
4273 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4274 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4275 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4277 if (me->def->reference_count == 1) {
4278 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4282 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4290 VM_ASSERT(callable_method_entry_p(cme));
4297 return aliased_callable_method_entry(me);
4303 calling->cc = &VM_CC_ON_STACK(
Qundef,
4306 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4308 return vm_call_method_each_type(ec, cfp, calling);
4311static enum method_missing_reason
4314 enum method_missing_reason stat = MISSING_NOENTRY;
4315 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4316 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4317 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4327 ASSUME(calling->argc >= 0);
4329 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4330 int argc = calling->argc;
4331 VALUE recv = calling->recv;
4334 flags |= VM_CALL_OPT_SEND;
4336 if (UNLIKELY(! mid)) {
4337 mid = idMethodMissing;
4338 missing_reason = ci_missing_reason(ci);
4339 ec->method_missing_reason = missing_reason;
4342 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4343 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4344 rb_ary_unshift(argv_ary, symbol);
4347 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4348 VALUE exc = rb_make_no_method_exception(
4370 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4373 argc = ++calling->argc;
4375 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4378 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4379 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4380 VALUE exc = rb_make_no_method_exception(
4393 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4399 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4400 calling->cd = &new_fcd.cd;
4404 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4405 new_fcd.caller_ci = caller_ci;
4408 calling->cc = &VM_CC_ON_STACK(klass,
4410 { .method_missing_reason = missing_reason },
4411 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4413 if (flags & VM_CALL_FCALL) {
4414 return vm_call_method(ec, reg_cfp, calling);
4418 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4420 if (vm_cc_cme(cc) != NULL) {
4421 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4422 case METHOD_VISI_PUBLIC:
4423 return vm_call_method_each_type(ec, reg_cfp, calling);
4424 case METHOD_VISI_PRIVATE:
4425 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4427 case METHOD_VISI_PROTECTED:
4428 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4431 VM_UNREACHABLE(vm_call_method);
4433 return vm_call_method_missing(ec, reg_cfp, calling);
4436 return vm_call_method_nome(ec, reg_cfp, calling);
4446 i = calling->argc - 1;
4448 if (calling->argc == 0) {
4449 rb_raise(rb_eArgError,
"no method name given");
4473 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4479 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4481 int flags = VM_CALL_FCALL;
4485 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4486 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4488 flags |= VM_CALL_ARGS_SPLAT;
4489 if (calling->kw_splat) {
4490 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4491 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4492 calling->kw_splat = 0;
4494 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4497 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4498 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4504 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4505 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4511 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4514 int flags = vm_ci_flag(ci);
4516 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4517 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4518 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4519 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4520 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4521 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4524 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4525 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4530 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4532 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4534 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4535 unsigned int argc, flag;
4537 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4538 argc = ++calling->argc;
4541 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4542 vm_check_canary(ec, reg_cfp->sp);
4546 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4549 ec->method_missing_reason = reason;
4553 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4559 if (!(flag & VM_CALL_FORWARDING)) {
4560 calling->cd = &new_fcd.cd;
4564 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4565 new_fcd.caller_ci = caller_ci;
4569 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4570 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4571 return vm_call_method(ec, reg_cfp, calling);
4577 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4588 return vm_call_method_nome(ec, cfp, calling);
4590 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4591 cme->def->body.refined.orig_me) {
4592 cme = refined_method_callable_without_refinement(cme);
4595 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4597 return vm_call_method_each_type(ec, cfp, calling);
4601find_refinement(
VALUE refinements,
VALUE klass)
4603 if (
NIL_P(refinements)) {
4606 return rb_hash_lookup(refinements, klass);
4615 if (CFP_ISEQ(cfp) && ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_BLOCK) {
4616 const rb_iseq_t *local_iseq = ISEQ_BODY(CFP_ISEQ(cfp))->local_iseq;
4619 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4620 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4624 }
while (CFP_ISEQ(cfp) != local_iseq);
4635 if (orig_me->defined_class == 0) {
4643 VM_ASSERT(callable_method_entry_p(cme));
4645 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4655 ID mid = vm_ci_mid(calling->cd->ci);
4656 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4660 for (; cref; cref = CREF_NEXT(cref)) {
4661 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4662 if (
NIL_P(refinement))
continue;
4665 rb_callable_method_entry(refinement, mid);
4668 if (vm_cc_call(cc) == vm_call_super_method) {
4671 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4676 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4677 cme->def != ref_me->def) {
4680 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4689 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4690 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4705 if (calling->cd->cc) {
4706 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);
4708 return vm_call_method(ec, cfp, calling);
4711 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4712 calling->cc= ref_cc;
4713 return vm_call_method(ec, cfp, calling);
4717 return vm_call_method_nome(ec, cfp, calling);
4723NOINLINE(
static VALUE
4731 int argc = calling->argc;
4734 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4737 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4743 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4746 VALUE procval = calling->recv;
4747 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4753 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4755 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4758 if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
4759 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4762 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4763 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4764 return vm_call_general(ec, reg_cfp, calling);
4771 VALUE recv = calling->recv;
4774 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4775 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4777 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4778 return RSTRUCT_GET_RAW(recv,
off);
4784 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4786 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4794 VALUE recv = calling->recv;
4797 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4798 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4800 rb_check_frozen(recv);
4802 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4803 RSTRUCT_SET_RAW(recv,
off, val);
4811 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4813 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4821#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4822 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4823 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4824 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4826 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4827 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4838 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4839 case OPTIMIZED_METHOD_TYPE_SEND:
4840 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4841 return vm_call_opt_send(ec, cfp, calling);
4842 case OPTIMIZED_METHOD_TYPE_CALL:
4843 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4844 return vm_call_opt_call(ec, cfp, calling);
4845 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4846 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4847 return vm_call_opt_block_call(ec, cfp, calling);
4848 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4849 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4853 VM_CALL_METHOD_ATTR(v,
4854 vm_call_opt_struct_aref(ec, cfp, calling),
4855 set_vm_cc_ivar(cc); \
4856 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4859 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4860 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4864 VM_CALL_METHOD_ATTR(v,
4865 vm_call_opt_struct_aset(ec, cfp, calling),
4866 set_vm_cc_ivar(cc); \
4867 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4871 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4883 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4885 switch (cme->def->type) {
4886 case VM_METHOD_TYPE_ISEQ:
4887 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4888 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4889 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4892 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4893 return vm_call_iseq_setup(ec, cfp, calling);
4896 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4897 case VM_METHOD_TYPE_CFUNC:
4898 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4899 return vm_call_cfunc(ec, cfp, calling);
4901 case VM_METHOD_TYPE_ATTRSET:
4902 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4906 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4908 if (vm_cc_markable(cc)) {
4909 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4910 VM_CALL_METHOD_ATTR(v,
4911 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4912 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4918 VM_CALLCACHE_UNMARKABLE |
4919 VM_CALLCACHE_ON_STACK,
4925 .value = vm_pack_shape_and_index(INVALID_SHAPE_ID, ATTR_INDEX_NOT_SET),
4930 VM_CALL_METHOD_ATTR(v,
4931 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4932 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4936 case VM_METHOD_TYPE_IVAR:
4937 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4939 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4940 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4941 VM_CALL_METHOD_ATTR(v,
4942 vm_call_ivar(ec, cfp, calling),
4943 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4946 case VM_METHOD_TYPE_MISSING:
4947 vm_cc_method_missing_reason_set(cc, 0);
4948 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4949 return vm_call_method_missing(ec, cfp, calling);
4951 case VM_METHOD_TYPE_BMETHOD:
4952 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4953 return vm_call_bmethod(ec, cfp, calling);
4955 case VM_METHOD_TYPE_ALIAS:
4956 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4957 return vm_call_alias(ec, cfp, calling);
4959 case VM_METHOD_TYPE_OPTIMIZED:
4960 return vm_call_optimized(ec, cfp, calling, ci, cc);
4962 case VM_METHOD_TYPE_UNDEF:
4965 case VM_METHOD_TYPE_ZSUPER:
4966 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4968 case VM_METHOD_TYPE_REFINED:
4971 return vm_call_refined(ec, cfp, calling);
4974 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4984 const int stat = ci_missing_reason(ci);
4986 if (vm_ci_mid(ci) == idMethodMissing) {
4987 if (UNLIKELY(calling->heap_argv)) {
4992 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4993 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4997 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
5009 VALUE defined_class = me->defined_class;
5010 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
5011 return NIL_P(refined_class) ? defined_class : refined_class;
5020 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5022 if (vm_cc_cme(cc) != NULL) {
5023 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5024 case METHOD_VISI_PUBLIC:
5025 return vm_call_method_each_type(ec, cfp, calling);
5027 case METHOD_VISI_PRIVATE:
5028 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5029 enum method_missing_reason stat = MISSING_PRIVATE;
5030 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5032 vm_cc_method_missing_reason_set(cc, stat);
5033 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5034 return vm_call_method_missing(ec, cfp, calling);
5036 return vm_call_method_each_type(ec, cfp, calling);
5038 case METHOD_VISI_PROTECTED:
5039 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5040 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5042 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5043 return vm_call_method_missing(ec, cfp, calling);
5047 VM_ASSERT(vm_cc_cme(cc) != NULL);
5050 calling->cc = &cc_on_stack;
5051 return vm_call_method_each_type(ec, cfp, calling);
5054 return vm_call_method_each_type(ec, cfp, calling);
5057 rb_bug(
"unreachable");
5061 return vm_call_method_nome(ec, cfp, calling);
5068 RB_DEBUG_COUNTER_INC(ccf_general);
5069 return vm_call_method(ec, reg_cfp, calling);
5075 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5076 VM_ASSERT(cc != vm_cc_empty());
5078 *(vm_call_handler *)&cc->call_ = vm_call_general;
5084 RB_DEBUG_COUNTER_INC(ccf_super_method);
5089 if (ec == NULL) rb_bug(
"unreachable");
5092 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5093 return vm_call_method(ec, reg_cfp, calling);
5099vm_search_normal_superclass(
VALUE klass)
5104 klass =
RBASIC(klass)->klass;
5106 klass = RCLASS_ORIGIN(klass);
5110NORETURN(
static void vm_super_outside(
void));
5113vm_super_outside(
void)
5119empty_cc_for_super(
void)
5121 return &vm_empty_cc_for_super;
5127 VALUE current_defined_class;
5128 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
5135 current_defined_class = vm_defined_class_for_protected_call(me);
5138 iseq != method_entry_iseqptr(me) &&
5141 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5145 "self has wrong type to call super in this context: "
5146 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5151 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5153 "implicit argument passing of super from method defined"
5154 " by define_method() is not supported."
5155 " Specify all arguments explicitly.");
5158 ID mid = me->def->original_id;
5160 if (!vm_ci_markable(cd->ci)) {
5161 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5165 cd->ci = vm_ci_new_runtime(mid,
5168 vm_ci_kwarg(cd->ci));
5175 VALUE klass = vm_search_normal_superclass(me->defined_class);
5179 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5183 cc = vm_search_method_fastpath(reg_cfp, cd, klass);
5187 if (cached_cme == NULL) {
5189 cd->cc = empty_cc_for_super();
5191 else if (cached_cme->called_id != mid) {
5194 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5198 cd->cc = cc = empty_cc_for_super();
5202 switch (cached_cme->def->type) {
5204 case VM_METHOD_TYPE_REFINED:
5206 case VM_METHOD_TYPE_ATTRSET:
5207 case VM_METHOD_TYPE_IVAR:
5208 vm_cc_call_set(cc, vm_call_super_method);
5216 VM_ASSERT((vm_cc_cme(cc),
true));
5224block_proc_is_lambda(
const VALUE procval)
5229 GetProcPtr(procval, proc);
5230 return proc->is_lambda;
5240 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5243 int is_lambda = FALSE;
5244 VALUE val, arg, blockarg;
5246 const struct vm_ifunc *ifunc = captured->code.ifunc;
5251 else if (argc == 0) {
5258 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5260 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5262 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5265 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5268 VM_GUARDED_PREV_EP(captured->ep),
5270 0, ec->cfp->sp, 0, 0);
5271 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5272 rb_vm_pop_frame(ec);
5280 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5286 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
5295 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5297 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5305vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5307 VALUE ary, arg0 = argv[0];
5312 VM_ASSERT(argv[0] == arg0);
5320 if (rb_simple_iseq_p(iseq)) {
5324 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5326 if (arg_setup_type == arg_setup_block &&
5327 calling->argc == 1 &&
5328 ISEQ_BODY(iseq)->param.flags.has_lead &&
5329 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5330 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5331 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5334 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5335 if (arg_setup_type == arg_setup_block) {
5336 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5338 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5339 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5340 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5342 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5343 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5347 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5354 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5363 calling = &calling_entry;
5364 calling->argc = argc;
5365 calling->block_handler = block_handler;
5366 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5368 calling->heap_argv = 0;
5370 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5372 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5380 bool is_lambda,
VALUE block_handler)
5383 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5384 const int arg_size = ISEQ_BODY(iseq)->param.size;
5385 VALUE *
const rsp = GET_SP() - calling->argc;
5386 VALUE *
const argv = rsp;
5387 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5388 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5392 vm_push_frame(ec, iseq,
5395 VM_GUARDED_PREV_EP(captured->ep), 0,
5396 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5398 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5406 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5408 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5409 int flags = vm_ci_flag(ci);
5411 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5412 ((calling->argc == 0) ||
5413 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5414 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5415 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5416 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5418 if (UNLIKELY(calling->heap_argv)) {
5419#if VM_ARGC_STACK_MAX < 0
5421 rb_raise(rb_eArgError,
"no receiver given");
5427 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5428 reg_cfp->sp[-2] = calling->recv;
5429 flags |= VM_CALL_ARGS_SPLAT;
5432 if (calling->argc < 1) {
5433 rb_raise(rb_eArgError,
"no receiver given");
5435 calling->recv = TOPN(--calling->argc);
5437 if (calling->kw_splat) {
5438 flags |= VM_CALL_KW_SPLAT;
5442 if (calling->argc < 1) {
5443 rb_raise(rb_eArgError,
"no receiver given");
5445 calling->recv = TOPN(--calling->argc);
5448 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5454 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5459 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5460 argc = calling->argc;
5461 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);
5467vm_proc_to_block_handler(
VALUE procval)
5469 const struct rb_block *block = vm_proc_block(procval);
5471 switch (vm_block_type(block)) {
5472 case block_type_iseq:
5473 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5474 case block_type_ifunc:
5475 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5476 case block_type_symbol:
5477 return VM_BH_FROM_SYMBOL(block->as.symbol);
5478 case block_type_proc:
5479 return VM_BH_FROM_PROC(block->as.proc);
5481 VM_UNREACHABLE(vm_yield_with_proc);
5488 bool is_lambda,
VALUE block_handler)
5490 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5491 VALUE proc = VM_BH_TO_PROC(block_handler);
5492 is_lambda = block_proc_is_lambda(proc);
5493 block_handler = vm_proc_to_block_handler(proc);
5496 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5502 bool is_lambda,
VALUE block_handler)
5506 bool is_lambda,
VALUE block_handler);
5508 switch (vm_block_handler_type(block_handler)) {
5509 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5510 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5511 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5512 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5513 default: rb_bug(
"vm_invoke_block: unreachable");
5516 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5520vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5527 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5530 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5531 captured->code.iseq = blockiseq;
5533 return rb_vm_make_proc(ec, captured,
rb_cProc);
5537vm_once_exec(
VALUE iseq)
5544vm_once_clear(
VALUE data)
5547 is->once.running_thread = NULL;
5559 args[0] = obj; args[1] =
Qfalse;
5561 if (!UNDEF_P(r) &&
RTEST(r)) {
5573 enum defined_type
type = (
enum defined_type)op_type;
5580 return rb_gvar_defined(
SYM2ID(obj));
5582 case DEFINED_CVAR: {
5583 const rb_cref_t *cref = vm_get_cref(GET_EP());
5584 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5589 case DEFINED_CONST_FROM: {
5590 bool allow_nil =
type == DEFINED_CONST;
5592 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5597 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5599 case DEFINED_METHOD:{
5604 switch (METHOD_ENTRY_VISI(me)) {
5605 case METHOD_VISI_PRIVATE:
5607 case METHOD_VISI_PROTECTED:
5611 case METHOD_VISI_PUBLIC:
5615 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(me));
5619 return check_respond_to_missing(obj, v);
5624 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5628 case DEFINED_ZSUPER:
5633 VALUE klass = vm_search_normal_superclass(me->defined_class);
5634 if (!klass)
return false;
5636 ID id = me->def->original_id;
5643 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5645 rb_bug(
"unimplemented defined? type (VM)");
5655 return vm_defined(ec, reg_cfp, op_type, obj, v);
5659vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5662 const VALUE *ep = reg_ep;
5663 for (i = 0; i < lv; i++) {
5664 ep = GET_PREV_EP(ep);
5670vm_get_special_object(
const VALUE *
const reg_ep,
5671 enum vm_special_object_type
type)
5674 case VM_SPECIAL_OBJECT_VMCORE:
5675 return rb_mRubyVMFrozenCore;
5676 case VM_SPECIAL_OBJECT_CBASE:
5677 return vm_get_cbase(reg_ep);
5678 case VM_SPECIAL_OBJECT_CONST_BASE:
5679 return vm_get_const_base(reg_ep);
5681 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5688rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5690 return vm_get_special_object(reg_ep,
type);
5696 const VALUE ary2 = ary2st;
5697 VALUE tmp1 = rb_check_to_array(ary1);
5698 VALUE tmp2 = rb_check_to_array(ary2);
5719 const VALUE ary2 = ary2st;
5721 if (
NIL_P(ary2))
return ary1;
5723 VALUE tmp2 = rb_check_to_array(ary2);
5738 return vm_concat_array(ary1, ary2st);
5742rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5744 return vm_concat_to_array(ary1, ary2st);
5753 VALUE tmp = rb_check_to_array(ary);
5757 else if (
RTEST(flag)) {
5770 return vm_splat_array(flag, ary);
5776 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5778 if (flag & VM_CHECKMATCH_ARRAY) {
5782 for (i = 0; i < n; i++) {
5784 VALUE c = check_match(ec, v, target,
type);
5793 return check_match(ec, pattern, target,
type);
5800 return vm_check_match(ec, target, pattern, flag);
5804vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5806 const VALUE kw_bits = *(ep - bits);
5809 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5810 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5823 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5824 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5825 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5826 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5830 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5833 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5836 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5839 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5846vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5851 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5852 return rb_public_const_get_at(cbase,
id);
5860vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
5865 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
5870 "superclass mismatch for class %"PRIsVALUE
"",
5883vm_check_if_module(
ID id,
VALUE mod)
5902vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5905 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super :
rb_cObject;
5912vm_declare_module(
ID id,
VALUE cbase)
5918NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
5922 VALUE name = rb_id2str(
id);
5923 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
5925 VALUE location = rb_const_source_location_at(cbase,
id);
5926 if (!
NIL_P(location)) {
5927 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
5928 " previous definition of %"PRIsVALUE
" was here",
5935vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5939 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
5941 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
5945 vm_check_if_namespace(cbase);
5950 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
5951 if (!vm_check_if_class(
id, flags, super, klass))
5952 unmatched_redefinition(
"class", cbase,
id, klass);
5956 return vm_declare_class(
id, flags, cbase, super);
5961vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
5965 vm_check_if_namespace(cbase);
5966 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
5967 if (!vm_check_if_module(
id, mod))
5968 unmatched_redefinition(
"module", cbase,
id, mod);
5972 return vm_declare_module(
id, cbase);
5977vm_find_or_create_class_by_id(
ID id,
5982 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
5985 case VM_DEFINECLASS_TYPE_CLASS:
5987 return vm_define_class(
id, flags, cbase, super);
5989 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
5993 case VM_DEFINECLASS_TYPE_MODULE:
5995 return vm_define_module(
id, flags, cbase);
5998 rb_bug(
"unknown defineclass type: %d", (
int)
type);
6002static rb_method_visibility_t
6007 if (!vm_env_cref_by_cref(cfp->ep)) {
6008 return METHOD_VISI_PUBLIC;
6011 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6020 if (!vm_env_cref_by_cref(cfp->ep)) {
6024 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6032 rb_method_visibility_t visi;
6037 visi = METHOD_VISI_PUBLIC;
6040 klass = CREF_CLASS_FOR_DEFINITION(cref);
6041 visi = vm_scope_visibility_get(ec);
6048 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6051 !RCLASS_SINGLETON_P(klass) &&
6053 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6056 if (!is_singleton && vm_scope_module_func_check(ec)) {
6058 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6067rb_vm_untag_block_handler(
VALUE block_handler)
6069 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6071 switch (vm_block_handler_type(block_handler)) {
6072 case block_handler_type_iseq:
6073 case block_handler_type_ifunc: {
6075 return captured->code.val;
6077 case block_handler_type_proc:
6078 case block_handler_type_symbol:
6079 return block_handler;
6081 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6088 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6097 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6099 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6100 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6103 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6107enum method_explorer_type {
6109 mexp_search_invokeblock,
6118 VALUE block_handler,
6119 enum method_explorer_type method_explorer
6124 int argc = vm_ci_argc(ci);
6125 VALUE recv = TOPN(argc);
6127 .block_handler = block_handler,
6128 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6134 switch (method_explorer) {
6135 case mexp_search_method:
6136 calling.cc = cc = vm_search_method_fastpath(reg_cfp, cd,
CLASS_OF(recv));
6137 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6139 case mexp_search_super:
6140 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6141 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6143 case mexp_search_invokeblock:
6144 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6154 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6155 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6169 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6171 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6173 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6174 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6185 VALUE bh = VM_BLOCK_HANDLER_NONE;
6186 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6196 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
true);
6197 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super);
6211 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6213 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6215 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6216 RB_OBJ_WRITE(CFP_ISEQ(GET_CFP()), &cd->cc, adjusted_cd.cd.cc);
6227 VALUE bh = VM_BLOCK_HANDLER_NONE;
6228 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6256 if (check_method_basic_definition(cme)) {
6265 if (check_cfunc(cme, rb_mod_to_s)) {
6271 val = rb_mod_to_s(recv);
6277 if (check_cfunc(cme, rb_nil_to_s)) {
6278 return rb_nil_to_s(recv);
6282 if (check_cfunc(cme, rb_true_to_s)) {
6283 return rb_true_to_s(recv);
6287 if (check_cfunc(cme, rb_false_to_s)) {
6288 return rb_false_to_s(recv);
6292 if (check_cfunc(cme, rb_int_to_s)) {
6293 return rb_fix_to_s(recv);
6305 return vm_objtostring(reg_cfp, recv, cd);
6309vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6311 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6320vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6322 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6331vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6333 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6347 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6351 VALUE args[1] = {target};
6354 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6357 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6364 return vm_opt_duparray_include_p(ec, ary, target);
6370 if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
6371 if (array_len == 0) {
6375 VALUE result = *ptr;
6376 rb_snum_t i = array_len - 1;
6378 const VALUE v = *++ptr;
6379 if (OPTIMIZED_CMP(v, result) > 0) {
6394 return vm_opt_newarray_max(ec, array_len, ptr);
6400 if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
6401 if (array_len == 0) {
6405 VALUE result = *ptr;
6406 rb_snum_t i = array_len - 1;
6408 const VALUE v = *++ptr;
6409 if (OPTIMIZED_CMP(v, result) < 0) {
6424 return vm_opt_newarray_min(ec, array_len, ptr);
6431 if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
6432 return rb_ary_hash_values(array_len, ptr);
6442 return vm_opt_newarray_hash(ec, array_len, ptr);
6451 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6452 struct RArray fake_ary = {RBASIC_INIT};
6453 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6457 VALUE args[1] = {target};
6465 return vm_opt_newarray_include_p(ec, array_len,
ptr, target);
6471 if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) {
6472 struct RArray fake_ary = {RBASIC_INIT};
6473 VALUE ary = rb_setup_fake_ary(&fake_ary,
ptr, array_len);
6474 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6484 if (!UNDEF_P(buffer)) {
6485 args[1] = rb_hash_new_with_size(1);
6486 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6491 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len,
ptr), idPack, argc, args, kw_splat);
6498 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt, buffer);
6504 return vm_opt_newarray_pack_buffer(ec, array_len,
ptr, fmt,
Qundef);
6510vm_track_constant_cache(
ID id,
void *ic)
6513 struct rb_id_table *const_cache = &vm->constant_cache;
6514 VALUE lookup_result;
6517 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6521 ics = set_init_numtable();
6522 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6537 vm->inserting_constant_cache_id = id;
6539 set_insert(ics, (st_data_t)ic);
6541 vm->inserting_constant_cache_id = (
ID)0;
6548 for (
int i = 0; segments[i]; i++) {
6549 ID id = segments[i];
6550 if (
id == idNULL)
continue;
6551 vm_track_constant_cache(
id, ic);
6560 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6561 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6563 return (ic_cref == NULL ||
6564 ic_cref == vm_get_cref(reg_ep));
6572 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6573 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6578rb_vm_ic_hit_p(
IC ic,
const VALUE *reg_ep)
6580 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6586 if (ruby_vm_const_missing_count > 0) {
6587 ruby_vm_const_missing_count = 0;
6594 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6598 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6602 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6603 rb_yjit_constant_ic_update(iseq, ic, pos);
6613 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6616 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
6619 ruby_vm_constant_cache_misses++;
6620 val = vm_get_ev_const_chain(ec, segments);
6621 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6624 vm_ic_update(CFP_ISEQ(GET_CFP()), ic, val, GET_EP(), CFP_PC(GET_CFP()) - 2);
6636 if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
6637 return is->once.value;
6639 else if (is->once.running_thread == NULL) {
6641 is->once.running_thread = th;
6646 RB_OBJ_SET_SHAREABLE(val);
6652 is->once.running_thread = RUNNING_THREAD_ONCE_DONE;
6655 else if (is->once.running_thread == th) {
6657 return vm_once_exec((
VALUE)iseq);
6661 RUBY_VM_CHECK_INTS(ec);
6668vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6670 switch (OBJ_BUILTIN_TYPE(key)) {
6676 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6677 SYMBOL_REDEFINED_OP_FLAG |
6678 INTEGER_REDEFINED_OP_FLAG |
6679 FLOAT_REDEFINED_OP_FLAG |
6680 NIL_REDEFINED_OP_FLAG |
6681 TRUE_REDEFINED_OP_FLAG |
6682 FALSE_REDEFINED_OP_FLAG |
6683 STRING_REDEFINED_OP_FLAG)) {
6687 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6691 if (rb_hash_stlike_lookup(hash, key, &val)) {
6711 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6712 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6713 static const char stack_consistency_error[] =
6714 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6715#if defined RUBY_DEVEL
6716 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6721 rb_bug(stack_consistency_error, nsp, nbp);
6728 if (FIXNUM_2_P(recv, obj) &&
6729 BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
6730 return rb_fix_plus_fix(recv, obj);
6732 else if (FLONUM_2_P(recv, obj) &&
6733 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6741 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6746 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
6747 return rb_str_opt_plus(recv, obj);
6751 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
6762 if (FIXNUM_2_P(recv, obj) &&
6763 BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
6764 return rb_fix_minus_fix(recv, obj);
6766 else if (FLONUM_2_P(recv, obj) &&
6767 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6775 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6786 if (FIXNUM_2_P(recv, obj) &&
6787 BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
6788 return rb_fix_mul_fix(recv, obj);
6790 else if (FLONUM_2_P(recv, obj) &&
6791 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6799 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6810 if (FIXNUM_2_P(recv, obj) &&
6811 BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
6812 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6814 else if (FLONUM_2_P(recv, obj) &&
6815 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6816 return rb_flo_div_flo(recv, obj);
6823 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6824 return rb_flo_div_flo(recv, obj);
6834 if (FIXNUM_2_P(recv, obj) &&
6835 BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
6836 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
6838 else if (FLONUM_2_P(recv, obj) &&
6839 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6847 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6858 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not_equal)) {
6859 VALUE val = opt_equality(reg_cfp, recv, obj, cd_eq);
6861 if (!UNDEF_P(val)) {
6862 return RBOOL(!
RTEST(val));
6872 if (FIXNUM_2_P(recv, obj) &&
6873 BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
6876 else if (FLONUM_2_P(recv, obj) &&
6877 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6885 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6896 if (FIXNUM_2_P(recv, obj) &&
6897 BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
6900 else if (FLONUM_2_P(recv, obj) &&
6901 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6909 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6920 if (FIXNUM_2_P(recv, obj) &&
6921 BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
6924 else if (FLONUM_2_P(recv, obj) &&
6925 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6933 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6944 if (FIXNUM_2_P(recv, obj) &&
6945 BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
6948 else if (FLONUM_2_P(recv, obj) &&
6949 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6957 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6973 BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
6982 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
7000 BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
7011 if (FIXNUM_2_P(recv, obj) &&
7012 BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
7024 if (FIXNUM_2_P(recv, obj) &&
7025 BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
7026 return rb_fix_aref(recv, obj);
7031 BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG)) {
7033 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7036 return rb_ary_aref1(recv, obj);
7040 BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
7041 return rb_hash_aref(recv, obj);
7055 BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
7061 BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
7062 rb_hash_aset(recv, obj, set);
7071vm_opt_length(
VALUE recv,
int bop)
7077 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7078 if (bop == BOP_EMPTY_P) {
7079 return LONG2NUM(RSTRING_LEN(recv));
7086 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7090 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7099vm_opt_empty_p(
VALUE recv)
7101 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7114 BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
7117 else if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_false)) {
7133 case RSHIFT(~0UL, 1):
7136 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7154vm_opt_succ(
VALUE recv)
7157 BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
7158 return fix_succ(recv);
7164 BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
7175 if (vm_method_cfunc_is(reg_cfp, cd, recv, rb_obj_not)) {
7176 return RBOOL(!
RTEST(recv));
7191 BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
7195 BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
7213 VALUE self = GET_SELF();
7215 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7217 if (local_hooks) local_hooks->running++;
7219 if (event & global_hooks->events) {
7222 vm_dtrace(event, ec);
7223 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7227 if (local_hooks) local_hooks->running--;
7228 if (local_hooks != NULL) {
7229 if (event & local_hooks->events) {
7232 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7238#define VM_TRACE_HOOK(target_event, val) do { \
7239 if ((pc_events & (target_event)) & enabled_flags) { \
7240 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7247 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7248 VM_ASSERT(ISEQ_BODY(CFP_ISEQ(cfp))->
type == ISEQ_TYPE_RESCUE);
7249 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7255 const VALUE *pc = reg_cfp->pc;
7257 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7260 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7264 const rb_iseq_t *iseq = CFP_ISEQ(reg_cfp);
7265 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7267 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7269 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7271 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7275 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7279 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7280 enabled_flags |= iseq_local_events;
7282 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7284 if (bmethod_frame) {
7286 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7287 unsigned int bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7288 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7290 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7293 if (bmethod_local_hooks) {
7294 bmethod_local_events = bmethod_local_hooks->events;
7299 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7303 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7311 else if (ec->trace_arg != NULL) {
7319 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7322 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %s:%d %s\n",
7325 RSTRING_PTR(rb_iseq_path(iseq)),
7326 (
int)rb_iseq_line_no(iseq, pos),
7327 RSTRING_PTR(rb_iseq_label(iseq)));
7329 VM_ASSERT(reg_cfp->pc == pc);
7330 VM_ASSERT(pc_events != 0);
7340 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7341 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7352#if VM_CHECK_MODE > 0
7353NORETURN( NOINLINE( COLDFUNC
7354void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7357Init_vm_stack_canary(
void)
7360 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7361 vm_stack_canary |= 0x01;
7363 vm_stack_canary_was_born =
true;
7368rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7372 const char *insn = rb_insns_name(i);
7376 rb_bug(
"dead canary found at %s: %s", insn, str);
7380void Init_vm_stack_canary(
void) { }
7412 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7419 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7426 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7433 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7440 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7447 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7454 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7461 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7468 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7474 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);
7475 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]);
7481 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);
7482 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]);
7488 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);
7489 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]);
7495 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);
7496 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]);
7502 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);
7503 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]);
7509 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);
7510 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]);
7516 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);
7517 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]);
7522static builtin_invoker
7523lookup_builtin_invoker(
int argc)
7525 static const builtin_invoker invokers[] = {
7544 return invokers[argc];
7550 const bool canary_p = ISEQ_BODY(CFP_ISEQ(reg_cfp))->builtin_attrs & BUILTIN_ATTR_LEAF;
7551 SETUP_CANARY(canary_p);
7552 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7553 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7554 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7561 return invoke_bf(ec, cfp, bf, argv);
7568 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7569 for (
int i=0; i<bf->argc; i++) {
7570 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(CFP_ISEQ(cfp))->local_table[i+start_index]));
7572 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7573 (
void *)(uintptr_t)bf->func_ptr);
7576 if (bf->argc == 0) {
7577 return invoke_bf(ec, cfp, bf, NULL);
7580 const VALUE *argv = cfp->ep - ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7581 return invoke_bf(ec, cfp, bf, argv);
7591 return cfp->ep[index];
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_EVENT_END
Encountered an end of a class clause.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_B_RETURN
Encountered a next statement.
#define RUBY_EVENT_CLASS
Encountered a new class.
#define RUBY_EVENT_LINE
Encountered a new line.
#define RUBY_EVENT_RETURN
Encountered a return statement.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
#define RUBY_EVENT_B_CALL
Encountered an yield statement.
uint32_t rb_event_flag_t
Represents event(s).
#define RUBY_EVENT_CALL
A method, written in Ruby, is called.
#define RUBY_EVENT_RESCUE
Encountered a rescue statement.
static bool RB_FL_ABLE(VALUE obj)
Checks if the object is flaggable.
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
VALUE rb_module_new(void)
Creates a new, anonymous module.
VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
VALUE rb_define_class_id(ID id, VALUE super)
This is a very badly designed API that creates an anonymous class.
#define TYPE(_)
Old name of rb_type.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define T_NIL
Old name of RUBY_T_NIL.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define T_STRUCT
Old name of RUBY_T_STRUCT.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define SYM2ID
Old name of RB_SYM2ID.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define STATIC_SYM_P
Old name of RB_STATIC_SYM_P.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define T_TRUE
Old name of RUBY_T_TRUE.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define T_HASH
Old name of RUBY_T_HASH.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define T_FALSE
Old name of RUBY_T_FALSE.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define DBL2NUM
Old name of rb_float_new.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define FL_TEST
Old name of RB_FL_TEST.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
void rb_notimplement(void)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eFatal
fatal exception.
VALUE rb_eNoMethodError
NoMethodError exception.
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
void rb_error_frozen_object(VALUE frozen_obj)
Identical to rb_error_frozen(), except it takes arbitrary Ruby object instead of C's string.
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
@ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
Warning is for checking unused block strictly.
VALUE rb_cClass
Class class.
VALUE rb_cArray
Array class.
VALUE rb_cObject
Object class.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_cRegexp
Regexp class.
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
VALUE rb_cHash
Hash class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_cBasicObject
BasicObject class.
VALUE rb_cModule
Module class.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_cFloat
Float class.
VALUE rb_cProc
Proc class.
VALUE rb_cString
String class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_resurrect(VALUE ary)
I guess there is no use case of this function in extension libraries, but this is a routine identical...
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_includes(VALUE ary, VALUE elem)
Queries if the passed array has the passed entry.
VALUE rb_ary_plus(VALUE lhs, VALUE rhs)
Creates a new array, concatenating the former to the latter.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_pop(VALUE ary)
Destructively deletes an element from the end of the passed array and returns what was deleted.
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc)
Identical to rb_proc_call(), except you can additionally pass another proc object,...
VALUE rb_reg_last_match(VALUE md)
This just returns the argument, stringified.
VALUE rb_reg_match(VALUE re, VALUE str)
This is the match operator.
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
VALUE rb_reg_match_post(VALUE md)
The portion of the original string after the given match.
VALUE rb_reg_nth_defined(int n, VALUE md)
Identical to rb_reg_nth_match(), except it just returns Boolean.
VALUE rb_reg_match_pre(VALUE md)
The portion of the original string before the given match.
VALUE rb_reg_match_last(VALUE md)
The portion of the original string that captured at the very last.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_succ(VALUE orig)
Searches for the "successor" of a string.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_length(VALUE)
Identical to rb_str_strlen(), except it returns the value in rb_cInteger.
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
void rb_thread_schedule(void)
Tries to switch to another thread.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
void rb_cvar_set(VALUE klass, ID name, VALUE val)
Assigns a value to a class variable.
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front)
Identical to rb_cvar_get(), except it takes additional "front" pointer.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
void rb_const_set(VALUE space, ID name, VALUE val)
Names a constant.
VALUE rb_autoload_load(VALUE space, ID name)
Kicks the autoload procedure as if it was "touched".
VALUE rb_mod_name(VALUE mod)
Queries the name of a module.
VALUE rb_const_get_at(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name)
Identical to rb_set_class_path(), except it accepts the name as Ruby's string instead of C's.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
int rb_const_defined_at(VALUE space, ID name)
Identical to rb_const_defined(), except it doesn't look for parent classes.
VALUE rb_cvar_defined(VALUE klass, ID name)
Queries if the given class has the given class variable.
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
int rb_const_defined(VALUE space, ID name)
Queries if the constant is defined at the namespace.
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
rb_alloc_func_t rb_get_alloc_func(VALUE klass)
Queries the allocator function of a class.
int rb_method_boundp(VALUE klass, ID id, int ex)
Queries if the klass has this method.
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
int off
Offset inside of ptr.
int len
Length of the buffer.
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define RBASIC(obj)
Convenient casting macro.
#define RCLASS_SUPER
Just another name of rb_class_get_superclass.
#define RHASH_SIZE(h)
Queries the size of the hash.
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
static VALUE * ROBJECT_FIELDS(VALUE obj)
Queries the instance variables.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RB_PASS_KEYWORDS
Pass keywords, final argument must be a hash of keywords.
#define RB_NO_KEYWORDS
Do not pass keywords.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
#define ANYARGS
Functions declared using this macro take arbitrary arguments, including void.
const VALUE ary[1]
Embedded elements.
const VALUE * ptr
Pointer to the C array that holds the elements of the array.
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
rb_cref_t * cref
class reference, should be marked
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
IFUNC (Internal FUNCtion)
const VALUE cref_or_me
class reference or rb_method_entry_t
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.