11#include "ruby/internal/config.h"
15#ifdef HAVE_STDATOMIC_H
16 #include <stdatomic.h>
20#include "debug_counter.h"
22#include "internal/class.h"
23#include "internal/compar.h"
24#include "internal/hash.h"
25#include "internal/numeric.h"
26#include "internal/proc.h"
27#include "internal/random.h"
28#include "internal/variable.h"
29#include "internal/set_table.h"
30#include "internal/struct.h"
35#include "insns_info.inc"
37extern rb_method_definition_t *rb_method_definition_create(rb_method_type_t
type,
ID mid);
38extern void rb_method_definition_set(
const rb_method_entry_t *me, rb_method_definition_t *def,
void *opts);
39extern int rb_method_definition_eq(
const rb_method_definition_t *d1,
const rb_method_definition_t *d2);
41 int argc,
const VALUE *argv,
int priv);
48static rb_control_frame_t *vm_get_ruby_level_caller_cfp(
const rb_execution_context_t *ec,
const rb_control_frame_t *cfp);
51ruby_vm_special_exception_copy(
VALUE exc)
54 rb_obj_copy_ivar(e, exc);
58NORETURN(
static void ec_stack_overflow(rb_execution_context_t *ec,
int));
60ec_stack_overflow(rb_execution_context_t *ec,
int setup)
62 VALUE mesg = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_sysstack];
63 ec->raised_flag = RAISED_STACKOVERFLOW;
65 VALUE at = rb_ec_backtrace_object(ec);
66 mesg = ruby_vm_special_exception_copy(mesg);
71 EC_JUMP_TAG(ec, TAG_RAISE);
74NORETURN(
static void vm_stackoverflow(
void));
79 ec_stack_overflow(GET_EC(), TRUE);
83rb_ec_stack_overflow(rb_execution_context_t *ec, ruby_stack_overflow_critical_level crit)
86 rb_bug(
"system stack overflow during GC. Faulty native extension?");
88 if (crit >= rb_stack_overflow_fatal) {
89 ec->raised_flag = RAISED_STACKOVERFLOW;
90 ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
91 EC_JUMP_TAG(ec, TAG_RAISE);
93 ec_stack_overflow(ec, crit < rb_stack_overflow_signal);
96static inline void stack_check(rb_execution_context_t *ec);
100callable_class_p(
VALUE klass)
102#if VM_CHECK_MODE >= 2
103 if (!klass)
return FALSE;
125callable_method_entry_p(
const rb_callable_method_entry_t *cme)
131 VM_ASSERT(IMEMO_TYPE_P((
VALUE)cme, imemo_ment),
"imemo_type:%s", rb_imemo_name(imemo_type((
VALUE)cme)));
133 if (callable_class_p(cme->defined_class)) {
143vm_check_frame_detail(
VALUE type,
int req_block,
int req_me,
int req_cref,
VALUE specval,
VALUE cref_or_me,
int is_cframe,
const rb_iseq_t *iseq)
145 unsigned int magic = (
unsigned int)(
type & VM_FRAME_MAGIC_MASK);
146 enum imemo_type cref_or_me_type = imemo_env;
149 cref_or_me_type = imemo_type(cref_or_me);
151 if (
type & VM_FRAME_FLAG_BMETHOD) {
155 if (req_block && (
type & VM_ENV_FLAG_LOCAL) == 0) {
156 rb_bug(
"vm_push_frame: specval (%p) should be a block_ptr on %x frame", (
void *)specval, magic);
158 if (!req_block && (
type & VM_ENV_FLAG_LOCAL) != 0) {
159 rb_bug(
"vm_push_frame: specval (%p) should not be a block_ptr on %x frame", (
void *)specval, magic);
163 if (cref_or_me_type != imemo_ment) {
164 rb_bug(
"vm_push_frame: (%s) should be method entry on %x frame", rb_obj_info(cref_or_me), magic);
168 if (req_cref && cref_or_me_type != imemo_cref) {
169 rb_bug(
"vm_push_frame: (%s) should be CREF on %x frame", rb_obj_info(cref_or_me), magic);
172 if (cref_or_me !=
Qfalse && cref_or_me_type != imemo_cref) {
173 if (((
type & VM_FRAME_FLAG_LAMBDA) || magic == VM_FRAME_MAGIC_IFUNC || magic == VM_FRAME_MAGIC_DUMMY) && (cref_or_me_type == imemo_ment)) {
177 rb_bug(
"vm_push_frame: (%s) should be false or cref on %x frame", rb_obj_info(cref_or_me), magic);
183 if (cref_or_me_type == imemo_ment) {
184 const rb_callable_method_entry_t *me = (
const rb_callable_method_entry_t *)cref_or_me;
186 if (!callable_method_entry_p(me)) {
187 rb_bug(
"vm_push_frame: ment (%s) should be callable on %x frame.", rb_obj_info(cref_or_me), magic);
191 if ((
type & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
192 VM_ASSERT(iseq == NULL ||
194 RUBY_VM_NORMAL_ISEQ_P(iseq)
198 VM_ASSERT(is_cframe == !RUBY_VM_NORMAL_ISEQ_P(iseq));
206 const rb_iseq_t *iseq)
208 VALUE given_magic =
type & VM_FRAME_MAGIC_MASK;
211#define CHECK(magic, req_block, req_me, req_cref, is_cframe) \
213 vm_check_frame_detail(type, req_block, req_me, req_cref, \
214 specval, cref_or_me, is_cframe, iseq); \
216 switch (given_magic) {
218 CHECK(VM_FRAME_MAGIC_METHOD, TRUE, TRUE, FALSE, FALSE);
219 CHECK(VM_FRAME_MAGIC_CLASS, TRUE, FALSE, TRUE, FALSE);
220 CHECK(VM_FRAME_MAGIC_TOP, TRUE, FALSE, TRUE, FALSE);
221 CHECK(VM_FRAME_MAGIC_CFUNC, TRUE, TRUE, FALSE, TRUE);
222 CHECK(VM_FRAME_MAGIC_BLOCK, FALSE, FALSE, FALSE, FALSE);
223 CHECK(VM_FRAME_MAGIC_IFUNC, FALSE, FALSE, FALSE, TRUE);
224 CHECK(VM_FRAME_MAGIC_EVAL, FALSE, FALSE, FALSE, FALSE);
225 CHECK(VM_FRAME_MAGIC_RESCUE, FALSE, FALSE, FALSE, FALSE);
226 CHECK(VM_FRAME_MAGIC_DUMMY, TRUE, FALSE, FALSE, FALSE);
228 rb_bug(
"vm_push_frame: unknown type (%x)", (
unsigned int)given_magic);
233static VALUE vm_stack_canary;
234static bool vm_stack_canary_was_born =
false;
239previous_insn_index(
const rb_iseq_t *iseq,
const VALUE *pc)
241 unsigned int pos = 0;
242 while (pos < ISEQ_BODY(iseq)->iseq_size) {
243 int opcode = rb_vm_insn_addr2opcode((
void *)ISEQ_BODY(iseq)->iseq_encoded[pos]);
244 unsigned int next_pos = pos + insn_len(opcode);
245 if (ISEQ_BODY(iseq)->iseq_encoded + next_pos == pc) {
250 rb_bug(
"failed to find the previous insn");
254rb_vm_check_canary(
const rb_execution_context_t *ec,
VALUE *sp)
259 if (! LIKELY(vm_stack_canary_was_born)) {
262 else if ((
VALUE *)reg_cfp == ec->vm_stack + ec->vm_stack_size) {
266 else if (! (iseq = GET_ISEQ())) {
269 else if (LIKELY(sp[0] != vm_stack_canary)) {
278 const VALUE *orig = rb_iseq_original_iseq(iseq);
279 const VALUE iseqw = rb_iseqw_new(iseq);
281 const char *stri = rb_str_to_cstr(inspection);
282 const VALUE disasm = rb_iseq_disasm(iseq);
283 const char *strd = rb_str_to_cstr(disasm);
284 const ptrdiff_t pos = previous_insn_index(iseq, GET_PC());
285 const enum ruby_vminsn_type insn = (
enum ruby_vminsn_type)orig[pos];
286 const char *name = insn_name(insn);
292 "We are killing the stack canary set by %s, "
293 "at %s@pc=%"PRIdPTR
"\n"
294 "watch out the C stack trace.\n"
296 name, stri, pos, strd);
297 rb_bug(
"see above.");
299#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
302#define vm_check_canary(ec, sp)
303#define vm_check_frame(a, b, c, d)
308vm_push_frame_debug_counter_inc(
315 RB_DEBUG_COUNTER_INC(frame_push);
317 if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
318 const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
319 const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
322 RB_DEBUG_COUNTER_INC(frame_R2R);
325 RB_DEBUG_COUNTER_INC(frame_R2C);
330 RB_DEBUG_COUNTER_INC(frame_C2R);
333 RB_DEBUG_COUNTER_INC(frame_C2C);
338 switch (
type & VM_FRAME_MAGIC_MASK) {
339 case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method);
return;
340 case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block);
return;
341 case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class);
return;
342 case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top);
return;
343 case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc);
return;
344 case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc);
return;
345 case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval);
return;
346 case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue);
return;
347 case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy);
return;
350 rb_bug(
"unreachable");
353#define vm_push_frame_debug_counter_inc(ec, cfp, t)
358rb_vm_stack_canary(
void)
361 return vm_stack_canary;
367STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
368STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
369STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
372vm_push_frame(rb_execution_context_t *ec,
373 const rb_iseq_t *iseq,
383 rb_control_frame_t *
const cfp = RUBY_VM_NEXT_CONTROL_FRAME(ec->cfp);
385 vm_check_frame(
type, specval, cref_or_me, iseq);
386 VM_ASSERT(local_size >= 0);
389 CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
390 vm_check_canary(ec, sp);
395 for (
int i=0; i < local_size; i++) {
422 #if defined HAVE_DECL_ATOMIC_SIGNAL_FENCE && HAVE_DECL_ATOMIC_SIGNAL_FENCE
423 atomic_signal_fence(memory_order_seq_cst);
431 vm_push_frame_debug_counter_inc(ec, cfp,
type);
435rb_vm_pop_frame_no_int(rb_execution_context_t *ec)
437 rb_control_frame_t *cfp = ec->cfp;
439 if (VMDEBUG == 2) SDR();
441 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
446vm_pop_frame(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const VALUE *ep)
448 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
450 if (VMDEBUG == 2) SDR();
452 RUBY_VM_CHECK_INTS(ec);
453 ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
455 return flags & VM_FRAME_FLAG_FINISH;
459rb_vm_pop_frame(rb_execution_context_t *ec)
461 vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
466rb_vm_push_frame_fname(rb_execution_context_t *ec,
VALUE fname)
468 rb_iseq_t *rb_iseq_alloc_with_dummy_path(
VALUE fname);
469 rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);
473 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
475 VM_BLOCK_HANDLER_NONE,
482 return (
VALUE)dmy_iseq;
487rb_arity_error_new(
int argc,
int min,
int max)
489 VALUE err_mess = rb_sprintf(
"wrong number of arguments (given %d, expected %d", argc, min);
497 rb_str_catf(err_mess,
"..%d", max);
504rb_error_arity(
int argc,
int min,
int max)
511NOINLINE(
static void vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v));
514vm_env_write_slowpath(
const VALUE *ep,
int index,
VALUE v)
517 rb_gc_writebarrier_remember(VM_ENV_ENVVAL(ep));
518 VM_FORCE_WRITE(&ep[index], v);
519 VM_ENV_FLAGS_UNSET(ep, VM_ENV_FLAG_WB_REQUIRED);
520 RB_DEBUG_COUNTER_INC(lvar_set_slowpath);
525vm_env_write(
const VALUE *ep,
int index,
VALUE v)
527 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
528 if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
529 VM_STACK_ENV_WRITE(ep, index, v);
532 vm_env_write_slowpath(ep, index, v);
537rb_vm_env_write(
const VALUE *ep,
int index,
VALUE v)
539 vm_env_write(ep, index, v);
543rb_vm_bh_to_procval(
const rb_execution_context_t *ec,
VALUE block_handler)
545 if (block_handler == VM_BLOCK_HANDLER_NONE) {
549 switch (vm_block_handler_type(block_handler)) {
550 case block_handler_type_iseq:
551 case block_handler_type_ifunc:
552 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler),
rb_cProc);
553 case block_handler_type_symbol:
554 return rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
555 case block_handler_type_proc:
556 return VM_BH_TO_PROC(block_handler);
558 VM_UNREACHABLE(rb_vm_bh_to_procval);
567vm_svar_valid_p(
VALUE svar)
570 switch (imemo_type(svar)) {
579 rb_bug(
"vm_svar_valid_p: unknown type: %s", rb_obj_info(svar));
585lep_svar(
const rb_execution_context_t *ec,
const VALUE *lep)
589 if (lep && (ec == NULL || ec->root_lep != lep)) {
590 svar = lep[VM_ENV_DATA_INDEX_ME_CREF];
593 svar = ec->root_svar;
596 VM_ASSERT(svar ==
Qfalse || vm_svar_valid_p(svar));
602lep_svar_write(
const rb_execution_context_t *ec,
const VALUE *lep,
const struct vm_svar *svar)
604 VM_ASSERT(vm_svar_valid_p((
VALUE)svar));
606 if (lep && (ec == NULL || ec->root_lep != lep)) {
607 vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (
VALUE)svar);
610 RB_OBJ_WRITE(rb_ec_thread_ptr(ec)->self, &ec->root_svar, svar);
615lep_svar_get(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key)
617 const struct vm_svar *svar = lep_svar(ec, lep);
622 case VM_SVAR_LASTLINE:
623 return svar->lastline;
624 case VM_SVAR_BACKREF:
625 return svar->backref;
627 const VALUE ary = svar->others;
642 struct vm_svar *svar = IMEMO_NEW(
struct vm_svar, imemo_svar, obj);
651lep_svar_set(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key,
VALUE val)
653 struct vm_svar *svar = lep_svar(ec, lep);
656 lep_svar_write(ec, lep, svar = svar_new((
VALUE)svar));
660 case VM_SVAR_LASTLINE:
663 case VM_SVAR_BACKREF:
667 VALUE ary = svar->others;
678vm_getspecial(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t key, rb_num_t
type)
683 val = lep_svar_get(ec, lep, key);
686 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
703 rb_bug(
"unexpected back-ref");
714vm_backref_defined(
const rb_execution_context_t *ec,
const VALUE *lep, rb_num_t
type)
716 VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF);
726 return rb_reg_last_defined(backref);
728 rb_bug(
"unexpected back-ref");
732 nth = (int)(
type >> 1);
737PUREFUNC(
static rb_callable_method_entry_t *check_method_entry(
VALUE obj,
int can_be_svar));
738static rb_callable_method_entry_t *
739check_method_entry(
VALUE obj,
int can_be_svar)
741 if (obj ==
Qfalse)
return NULL;
744 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_method_entry: unknown type: %s", rb_obj_info(obj));
747 switch (imemo_type(obj)) {
749 return (rb_callable_method_entry_t *)obj;
758 rb_bug(
"check_method_entry: svar should not be there:");
764static rb_callable_method_entry_t *
765env_method_entry_unchecked(
VALUE obj,
int can_be_svar)
767 if (obj ==
Qfalse)
return NULL;
769 switch (imemo_type(obj)) {
771 return (rb_callable_method_entry_t *)obj;
783const rb_callable_method_entry_t *
784rb_vm_frame_method_entry(
const rb_control_frame_t *cfp)
786 const VALUE *ep = cfp->ep;
787 rb_callable_method_entry_t *me;
789 while (!VM_ENV_LOCAL_P(ep)) {
790 if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
791 ep = VM_ENV_PREV_EP(ep);
794 return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
797const rb_callable_method_entry_t *
798rb_vm_frame_method_entry_unchecked(
const rb_control_frame_t *cfp)
800 const VALUE *ep = cfp->ep;
801 rb_callable_method_entry_t *me;
803 while (!VM_ENV_LOCAL_P_UNCHECKED(ep)) {
804 if ((me = env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return me;
805 ep = VM_ENV_PREV_EP_UNCHECKED(ep);
808 return env_method_entry_unchecked(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
811static const rb_iseq_t *
812method_entry_iseqptr(
const rb_callable_method_entry_t *me)
814 switch (me->def->type) {
815 case VM_METHOD_TYPE_ISEQ:
816 return me->def->body.iseq.
iseqptr;
823method_entry_cref(
const rb_callable_method_entry_t *me)
825 switch (me->def->type) {
826 case VM_METHOD_TYPE_ISEQ:
827 return me->def->body.iseq.
cref;
833#if VM_CHECK_MODE == 0
834PUREFUNC(
static rb_cref_t *check_cref(
VALUE,
int));
837check_cref(
VALUE obj,
int can_be_svar)
839 if (obj ==
Qfalse)
return NULL;
842 if (!
RB_TYPE_P(obj,
T_IMEMO)) rb_bug(
"check_cref: unknown type: %s", rb_obj_info(obj));
845 switch (imemo_type(obj)) {
847 return method_entry_cref((rb_callable_method_entry_t *)obj);
849 return (rb_cref_t *)obj;
856 rb_bug(
"check_method_entry: svar should not be there:");
862static inline rb_cref_t *
863vm_env_cref(
const VALUE *ep)
867 while (!VM_ENV_LOCAL_P(ep)) {
868 if ((cref = check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL)
return cref;
869 ep = VM_ENV_PREV_EP(ep);
872 return check_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
876is_cref(
const VALUE v,
int can_be_svar)
879 switch (imemo_type(v)) {
892vm_env_cref_by_cref(
const VALUE *ep)
894 while (!VM_ENV_LOCAL_P(ep)) {
895 if (is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE))
return TRUE;
896 ep = VM_ENV_PREV_EP(ep);
898 return is_cref(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
902cref_replace_with_duplicated_cref_each_frame(
const VALUE *vptr,
int can_be_svar,
VALUE parent)
904 const VALUE v = *vptr;
905 rb_cref_t *cref, *new_cref;
908 switch (imemo_type(v)) {
910 cref = (rb_cref_t *)v;
911 new_cref = vm_cref_dup(cref);
916 VM_FORCE_WRITE(vptr, (
VALUE)new_cref);
918 return (rb_cref_t *)new_cref;
921 return cref_replace_with_duplicated_cref_each_frame(&((
struct vm_svar *)v)->
cref_or_me, FALSE, v);
925 rb_bug(
"cref_replace_with_duplicated_cref_each_frame: unreachable");
934vm_cref_replace_with_duplicated_cref(
const VALUE *ep)
936 if (vm_env_cref_by_cref(ep)) {
940 while (!VM_ENV_LOCAL_P(ep)) {
941 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
942 if ((cref = cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE, envval)) != NULL) {
945 ep = VM_ENV_PREV_EP(ep);
947 envval = VM_ENV_ESCAPED_P(ep) ? VM_ENV_ENVVAL(ep) :
Qfalse;
948 return cref_replace_with_duplicated_cref_each_frame(&ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE, envval);
951 rb_bug(
"vm_cref_dup: unreachable");
956vm_get_cref(
const VALUE *ep)
958 rb_cref_t *cref = vm_env_cref(ep);
964 rb_bug(
"vm_get_cref: unreachable");
969rb_vm_get_cref(
const VALUE *ep)
971 return vm_get_cref(ep);
975vm_ec_cref(
const rb_execution_context_t *ec)
977 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
982 return vm_get_cref(cfp->ep);
985static const rb_cref_t *
986vm_get_const_key_cref(
const VALUE *ep)
988 const rb_cref_t *cref = vm_get_cref(ep);
989 const rb_cref_t *key_cref = cref;
992 if (RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
993 RCLASS_CLONED_P(CREF_CLASS(cref)) ) {
996 cref = CREF_NEXT(cref);
1004rb_vm_rewrite_cref(rb_cref_t *cref,
VALUE old_klass,
VALUE new_klass)
1006 rb_cref_t *new_cref_head = NULL;
1007 rb_cref_t *new_cref_tail = NULL;
1009 #define ADD_NEW_CREF(new_cref) \
1010 if (new_cref_tail) { \
1011 RB_OBJ_WRITE(new_cref_tail, &new_cref_tail->next, new_cref); \
1014 new_cref_head = new_cref; \
1016 new_cref_tail = new_cref;
1019 rb_cref_t *new_cref;
1020 if (CREF_CLASS(cref) == old_klass) {
1021 new_cref = vm_cref_new_use_prev(new_klass, METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1022 ADD_NEW_CREF(new_cref);
1023 return new_cref_head;
1025 new_cref = vm_cref_new_use_prev(CREF_CLASS(cref), METHOD_VISI_UNDEF, FALSE, cref, FALSE);
1026 cref = CREF_NEXT(cref);
1027 ADD_NEW_CREF(new_cref);
1033 return new_cref_head;
1037vm_cref_push(
const rb_execution_context_t *ec,
VALUE klass,
const VALUE *ep,
int pushed_by_eval,
int singleton)
1039 rb_cref_t *prev_cref = NULL;
1042 prev_cref = vm_env_cref(ep);
1045 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, ec->cfp);
1048 prev_cref = vm_env_cref(cfp->ep);
1052 return vm_cref_new(klass, METHOD_VISI_PUBLIC, FALSE, prev_cref, pushed_by_eval, singleton);
1056vm_get_cbase(
const VALUE *ep)
1058 const rb_cref_t *cref = vm_get_cref(ep);
1060 return CREF_CLASS_FOR_DEFINITION(cref);
1064vm_get_const_base(
const VALUE *ep)
1066 const rb_cref_t *cref = vm_get_cref(ep);
1069 if (!CREF_PUSHED_BY_EVAL(cref)) {
1070 return CREF_CLASS_FOR_DEFINITION(cref);
1072 cref = CREF_NEXT(cref);
1079vm_check_if_namespace(
VALUE klass)
1082 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a class/module", klass);
1087vm_ensure_not_refinement_module(
VALUE self)
1090 rb_warn(
"not defined at the refinement, but at the outer class/module");
1095vm_get_iclass(
const rb_control_frame_t *cfp,
VALUE klass)
1101vm_get_ev_const(rb_execution_context_t *ec,
VALUE orig_klass,
ID id,
bool allow_nil,
int is_defined)
1103 void rb_const_warn_if_deprecated(
const rb_const_entry_t *ce,
VALUE klass,
ID id);
1106 if (
NIL_P(orig_klass) && allow_nil) {
1108 const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
1109 const rb_cref_t *cref;
1112 while (root_cref && CREF_PUSHED_BY_EVAL(root_cref)) {
1113 root_cref = CREF_NEXT(root_cref);
1116 while (cref && CREF_NEXT(cref)) {
1117 if (CREF_PUSHED_BY_EVAL(cref)) {
1121 klass = CREF_CLASS(cref);
1123 cref = CREF_NEXT(cref);
1125 if (!
NIL_P(klass)) {
1127 rb_const_entry_t *ce;
1129 if ((ce = rb_const_lookup(klass,
id))) {
1130 rb_const_warn_if_deprecated(ce, klass,
id);
1133 if (am == klass)
break;
1135 if (is_defined)
return 1;
1136 if (rb_autoloading_value(klass,
id, &av, NULL))
return av;
1138 goto search_continue;
1145 if (UNLIKELY(!rb_ractor_main_p())) {
1147 rb_raise(rb_eRactorIsolationError,
1148 "can not access non-shareable objects in constant %"PRIsVALUE
"::%"PRIsVALUE
" by non-main ractor.",
rb_class_path(klass), rb_id2str(
id));
1159 if (root_cref && !
NIL_P(CREF_CLASS(root_cref))) {
1160 klass = vm_get_iclass(ec->cfp, CREF_CLASS(root_cref));
1174 vm_check_if_namespace(orig_klass);
1176 return rb_public_const_defined_from(orig_klass,
id);
1179 return rb_public_const_get_from(orig_klass,
id);
1185rb_vm_get_ev_const(rb_execution_context_t *ec,
VALUE orig_klass,
ID id,
VALUE allow_nil)
1187 return vm_get_ev_const(ec, orig_klass,
id, allow_nil ==
Qtrue, 0);
1191vm_get_ev_const_chain(rb_execution_context_t *ec,
const ID *segments)
1195 int allow_nil = TRUE;
1196 if (segments[0] == idNULL) {
1201 while (segments[idx]) {
1202 ID id = segments[idx++];
1203 val = vm_get_ev_const(ec, val,
id, allow_nil, 0);
1211vm_get_cvar_base(
const rb_cref_t *cref,
const rb_control_frame_t *cfp,
int top_level_raise)
1216 rb_bug(
"vm_get_cvar_base: no cref");
1219 while (CREF_NEXT(cref) &&
1220 (
NIL_P(CREF_CLASS(cref)) || RCLASS_SINGLETON_P(CREF_CLASS(cref)) ||
1221 CREF_PUSHED_BY_EVAL(cref) || CREF_SINGLETON(cref))) {
1222 cref = CREF_NEXT(cref);
1224 if (top_level_raise && !CREF_NEXT(cref)) {
1228 klass = vm_get_iclass(cfp, CREF_CLASS(cref));
1236ALWAYS_INLINE(
static void fill_ivar_cache(
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id));
1238fill_ivar_cache(
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr, attr_index_t index, shape_id_t shape_id)
1241 vm_cc_attr_index_set(cc, index, shape_id);
1244 vm_ic_attr_index_set(iseq, ic, index, shape_id);
1248#define ractor_incidental_shareable_p(cond, val) \
1249 (!(cond) || rb_ractor_shareable_p(val))
1250#define ractor_object_incidental_shareable_p(obj, val) \
1251 ractor_incidental_shareable_p(rb_ractor_shareable_p(obj), val)
1255vm_getivar(
VALUE obj,
ID id,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr,
VALUE default_value)
1260 return default_value;
1270 if (UNLIKELY(!rb_ractor_main_p())) {
1278 if (default_value ==
Qundef) {
1286 fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1290 fields_obj = rb_obj_fields(obj,
id);
1294 return default_value;
1299 shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(fields_obj);
1300 VALUE *ivar_list = rb_imemo_fields_ptr(fields_obj);
1302 shape_id_t cached_id;
1306 vm_cc_atomic_shape_and_index(cc, &cached_id, &index);
1309 vm_ic_atomic_shape_and_index(ic, &cached_id, &index);
1312 if (LIKELY(cached_id == shape_id)) {
1315 if (index == ATTR_INDEX_NOT_SET) {
1316 return default_value;
1319 val = ivar_list[index];
1320#if USE_DEBUG_COUNTER
1321 RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
1324 RB_DEBUG_COUNTER_INC(ivar_get_obj_hit);
1330#if USE_DEBUG_COUNTER
1332 if (cached_id != INVALID_SHAPE_ID) {
1333 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
1336 RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
1340 if (cached_id != INVALID_SHAPE_ID) {
1341 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
1344 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
1347 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1350 RB_DEBUG_COUNTER_INC(ivar_get_obj_miss);
1354 if (UNLIKELY(rb_shape_too_complex_p(shape_id))) {
1355 st_table *table = (st_table *)ivar_list;
1358 RUBY_ASSERT(table == rb_imemo_fields_complex_tbl(fields_obj));
1360 if (!st_lookup(table,
id, &val)) {
1361 val = default_value;
1365 shape_id_t previous_cached_id = cached_id;
1366 if (rb_shape_get_iv_index_with_hint(shape_id,
id, &index, &cached_id)) {
1369 if (cached_id != previous_cached_id) {
1370 fill_ivar_cache(iseq, ic, cc, is_attr, index, cached_id);
1373 if (index == ATTR_INDEX_NOT_SET) {
1374 val = default_value;
1378 val = ivar_list[index];
1384 vm_cc_attr_index_initialize(cc, shape_id);
1387 vm_ic_attr_index_initialize(ic, shape_id);
1390 val = default_value;
1395 if (!UNDEF_P(default_value)) {
1403 RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
1406 return rb_attr_get(obj,
id);
1414populate_cache(attr_index_t index, shape_id_t next_shape_id,
ID id,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
bool is_attr)
1416 RUBY_ASSERT(!rb_shape_too_complex_p(next_shape_id));
1420 vm_cc_attr_index_set(cc, index, next_shape_id);
1423 vm_ic_attr_index_set(iseq, ic, index, next_shape_id);
1427ALWAYS_INLINE(
static VALUE vm_setivar_slowpath(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr));
1428NOINLINE(
static VALUE vm_setivar_slowpath_ivar(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic));
1432vm_setivar_slowpath(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic,
const struct rb_callcache *cc,
int is_attr)
1435 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
1437 rb_check_frozen(obj);
1439 attr_index_t index = rb_ivar_set_index(obj,
id, val);
1440 shape_id_t next_shape_id = RBASIC_SHAPE_ID(obj);
1442 if (!rb_shape_too_complex_p(next_shape_id)) {
1443 populate_cache(index, next_shape_id,
id, iseq, ic, cc, is_attr);
1446 RB_DEBUG_COUNTER_INC(ivar_set_obj_miss);
1454vm_setivar_slowpath_ivar(
VALUE obj,
ID id,
VALUE val,
const rb_iseq_t *iseq, IVC ic)
1456 return vm_setivar_slowpath(obj,
id, val, iseq, ic, NULL,
false);
1462 return vm_setivar_slowpath(obj,
id, val, NULL, NULL, cc,
true);
1465NOINLINE(
static VALUE vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1467vm_setivar_class(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1469 if (UNLIKELY(!rb_ractor_main_p())) {
1473 VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
1474 if (UNLIKELY(!fields_obj)) {
1478 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
1481 if (shape_id == dest_shape_id) {
1482 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1484 else if (dest_shape_id != INVALID_SHAPE_ID) {
1485 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1486 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1496 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1498 if (shape_id != dest_shape_id) {
1499 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1500 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1503 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1508NOINLINE(
static VALUE vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index));
1510vm_setivar_default(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1512 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1515 if (shape_id == dest_shape_id) {
1516 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1518 else if (dest_shape_id != INVALID_SHAPE_ID) {
1519 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1520 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1530 VALUE fields_obj = rb_obj_fields(obj,
id);
1532 RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[index], val);
1534 if (shape_id != dest_shape_id) {
1535 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1536 RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
1539 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1545vm_setivar(
VALUE obj,
ID id,
VALUE val, shape_id_t dest_shape_id, attr_index_t index)
1553 shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
1554 RUBY_ASSERT(dest_shape_id == INVALID_SHAPE_ID || !rb_shape_too_complex_p(dest_shape_id));
1556 if (LIKELY(shape_id == dest_shape_id)) {
1557 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1560 else if (dest_shape_id != INVALID_SHAPE_ID) {
1561 if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) ==
id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) {
1562 RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
1564 RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
1566 RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id));
1581 RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
1582 RB_DEBUG_COUNTER_INC(ivar_set_obj_hit);
1588 RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
1598update_classvariable_cache(
const rb_iseq_t *iseq,
VALUE klass,
ID id,
const rb_cref_t * cref, ICVARC ic)
1600 VALUE defined_class = 0;
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();
1631vm_getclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *reg_cfp,
ID id, ICVARC ic)
1633 const rb_cref_t *cref;
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);
1651rb_vm_getclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *cfp,
ID id, ICVARC ic)
1653 return vm_getclassvariable(iseq, cfp,
id, ic);
1657vm_setclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *reg_cfp,
ID id,
VALUE val, ICVARC ic)
1659 const rb_cref_t *cref;
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);
1677rb_vm_setclassvariable(
const rb_iseq_t *iseq,
const rb_control_frame_t *cfp,
ID id,
VALUE val, ICVARC ic)
1679 vm_setclassvariable(iseq, cfp,
id, val, ic);
1682ALWAYS_INLINE(
static VALUE vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic));
1684vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic)
1686 return vm_getivar(obj,
id, iseq, ic, NULL, FALSE,
Qnil);
1690vm_setinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id,
VALUE val, IVC ic)
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);
1721rb_vm_setinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id,
VALUE val, IVC ic)
1723 vm_setinstancevariable(iseq, obj,
id, val, ic);
1727rb_vm_getinstancevariable(
const rb_iseq_t *iseq,
VALUE obj,
ID id, IVC ic)
1729 return vm_getinstancevariable(iseq, obj,
id, ic);
1733vm_throw_continue(
const rb_execution_context_t *ec,
VALUE err)
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;
1753vm_throw_start(
const rb_execution_context_t *ec, rb_control_frame_t *
const reg_cfp,
enum ruby_tag_type state,
1754 const int flag,
const VALUE throwobj)
1756 const rb_control_frame_t *escape_cfp = NULL;
1757 const rb_control_frame_t *
const eocfp = RUBY_VM_END_CONTROL_FRAME(ec);
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(escape_cfp->iseq)->type == ISEQ_TYPE_CLASS) {
1770 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
1771 ep = escape_cfp->ep;
1772 base_iseq = escape_cfp->iseq;
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(escape_cfp->iseq == 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 = escape_cfp->iseq;
1793 const VALUE epc = escape_cfp->pc - 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(escape_cfp->iseq)->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(escape_cfp->iseq)->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 = escape_cfp->iseq;
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(escape_cfp->iseq)->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);
1940vm_throw(
const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
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);
1955rb_vm_throw(
const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t throw_state,
VALUE 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];
2031static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
2036vm_ccs_create(
VALUE klass,
VALUE cc_tbl,
ID mid,
const rb_callable_method_entry_t *cme)
2038 int initial_capa = 2;
2040#if VM_CHECK_MODE > 0
2041 ccs->debug_sig = ~(
VALUE)ccs;
2043 ccs->capa = initial_capa;
2046 METHOD_ENTRY_CACHED_SET((rb_callable_method_entry_t *)cme);
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));
2115const rb_callable_method_entry_t *rb_check_overloaded_cme(
const rb_callable_method_entry_t *cme,
const struct rb_callinfo *
const ci);
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);
2154 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
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(cd_owner, cd, klass);
2385 VM_ASSERT(klass !=
Qfalse);
2388 const struct rb_callcache *cc = vm_search_method_fastpath(cd_owner, cd, klass);
2389 return vm_cc_cme(cc);
2395 return vm_search_method(cd_owner, cd, recv);
2398#if __has_attribute(transparent_union)
2411 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2412 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2413 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2414 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2415 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2416 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2419# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2422# define make_cfunc_type(f) (cfunc_type)(f)
2426check_cfunc(
const rb_callable_method_entry_t *me, cfunc_type func)
2432 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2433 VM_ASSERT(callable_method_entry_p(me));
2435 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2439#if __has_attribute(transparent_union)
2440 return me->def->body.cfunc.func == func.anyargs;
2442 return me->def->body.cfunc.func == func;
2449check_method_basic_definition(
const rb_callable_method_entry_t *me)
2451 return me && METHOD_ENTRY_BASIC(me);
2455vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2457 VM_ASSERT(iseq != NULL);
2459 return check_cfunc(cme, func);
2463rb_zjit_cme_is_cfunc(
const rb_callable_method_entry_t *me,
const cfunc_type func)
2465 return check_cfunc(me, func);
2469rb_vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2471 return vm_method_cfunc_is(iseq, cd, recv, func);
2474#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2475#define vm_method_cfunc_is(iseq, cd, recv, func) vm_method_cfunc_is(iseq, cd, recv, make_cfunc_type(func))
2477#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
2509opt_equality_specialized(
VALUE recv,
VALUE obj)
2511 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2512 goto compare_by_identity;
2514 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2515 goto compare_by_identity;
2518 goto compare_by_identity;
2527 return RBOOL(a == b);
2534 return rb_str_eql_internal(obj, recv);
2539 compare_by_identity:
2540 return RBOOL(recv == obj);
2544opt_equality(
const rb_iseq_t *cd_owner,
VALUE recv,
VALUE obj, CALL_DATA cd)
2546 VM_ASSERT(cd_owner != NULL);
2548 VALUE val = opt_equality_specialized(recv, obj);
2549 if (!UNDEF_P(val))
return val;
2551 if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) {
2555 return RBOOL(recv == obj);
2559#undef EQ_UNREDEFINED_P
2562NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2565opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2567 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2569 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2570 return RBOOL(recv == obj);
2580 VALUE val = opt_equality_specialized(recv, obj);
2581 if (!UNDEF_P(val)) {
2585 return opt_equality_by_mid_slowpath(recv, obj, mid);
2592 return opt_equality_by_mid(obj1, obj2, idEq);
2598 return opt_equality_by_mid(obj1, obj2, idEqlP);
2601extern VALUE rb_vm_call0(rb_execution_context_t *ec,
VALUE,
ID,
int,
const VALUE*,
const rb_callable_method_entry_t *,
int kw_splat);
2602extern VALUE rb_vm_call_with_refinements(rb_execution_context_t *,
VALUE,
ID,
int,
const VALUE *,
int);
2605check_match(rb_execution_context_t *ec,
VALUE pattern,
VALUE target,
enum vm_check_match_type
type)
2608 case VM_CHECKMATCH_TYPE_WHEN:
2610 case VM_CHECKMATCH_TYPE_RESCUE:
2612 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2615 case VM_CHECKMATCH_TYPE_CASE: {
2616 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2619 rb_bug(
"check_match: unreachable");
2625double_cmp_lt(
double a,
double b)
2627 return RBOOL(a < b);
2631double_cmp_le(
double a,
double b)
2633 return RBOOL(a <= b);
2637double_cmp_gt(
double a,
double b)
2639 return RBOOL(a > b);
2643double_cmp_ge(
double a,
double b)
2645 return RBOOL(a >= b);
2649static inline VALUE *
2650vm_base_ptr(
const rb_control_frame_t *cfp)
2652 const rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2654 if (cfp->iseq && VM_FRAME_RUBYFRAME_P(cfp)) {
2655 VALUE *bp = prev_cfp->sp + ISEQ_BODY(cfp->iseq)->local_table_size + VM_ENV_DATA_SIZE;
2657 if (ISEQ_BODY(cfp->iseq)->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2658 int lts = ISEQ_BODY(cfp->iseq)->local_table_size;
2659 int params = ISEQ_BODY(cfp->iseq)->param.size;
2661 CALL_INFO ci = (CALL_INFO)cfp->ep[-(VM_ENV_DATA_SIZE + (lts - params))];
2662 bp += vm_ci_argc(ci);
2665 if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2669#if VM_DEBUG_BP_CHECK
2670 if (bp != cfp->bp_check) {
2671 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2672 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2673 (
long)(bp - GET_EC()->vm_stack));
2674 rb_bug(
"vm_base_ptr: unreachable");
2685rb_vm_base_ptr(
const rb_control_frame_t *cfp)
2687 return vm_base_ptr(cfp);
2694static inline VALUE vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc,
int param_size,
int local_size);
2695ALWAYS_INLINE(
static VALUE vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
const rb_callable_method_entry_t *me,
int opt_pc,
int param_size,
int local_size));
2696static inline VALUE vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc);
2697static VALUE vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
2698static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2699static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2700static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2702static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2705vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2707 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2709 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2713vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2715 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2718 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2719 int param = ISEQ_BODY(iseq)->param.size;
2720 int local = ISEQ_BODY(iseq)->local_table_size;
2721 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2725rb_simple_iseq_p(
const rb_iseq_t *iseq)
2727 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2728 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2729 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2730 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2731 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2732 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2733 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2734 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2738rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2740 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2741 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2742 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2743 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2744 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2745 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2746 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2747 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2751rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2753 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2754 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2755 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2756 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2757 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2758 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2759 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2762#define ALLOW_HEAP_ARGV (-2)
2763#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2766vm_caller_setup_arg_splat(rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE ary,
int max_args)
2768 vm_check_canary(GET_EC(), cfp->sp);
2774 int argc = calling->argc;
2776 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2780 VALUE *argv = cfp->sp - argc;
2784 cfp->sp -= argc - 1;
2785 cfp->sp[-1] = argv_ary;
2787 calling->heap_argv = argv_ary;
2793 if (max_args >= 0 &&
len + argc > max_args) {
2801 calling->argc +=
len - (max_args - argc + 1);
2802 len = max_args - argc + 1;
2811 calling->heap_argv = 0;
2813 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2815 for (i = 0; i <
len; i++) {
2816 *cfp->sp++ = ptr[i];
2828 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2829 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2830 const VALUE h = rb_hash_new_with_size(kw_len);
2831 VALUE *sp = cfp->sp;
2834 for (i=0; i<kw_len; i++) {
2835 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2839 cfp->sp -= kw_len - 1;
2840 calling->argc -= kw_len - 1;
2841 calling->kw_splat = 1;
2845vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2848 if (keyword_hash !=
Qnil) {
2850 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2853 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2859 keyword_hash = rb_hash_dup(keyword_hash);
2861 return keyword_hash;
2867 const struct rb_callinfo *restrict ci,
int max_args)
2869 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2870 if (IS_ARGS_KW_SPLAT(ci)) {
2872 VM_ASSERT(calling->kw_splat == 1);
2876 VALUE ary = cfp->sp[0];
2877 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2880 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2884 if (UNLIKELY(calling->heap_argv)) {
2886 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2887 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2888 calling->kw_splat = 0;
2896 VM_ASSERT(calling->kw_splat == 1);
2900 calling->kw_splat = 0;
2905 VM_ASSERT(calling->kw_splat == 0);
2909 VALUE ary = cfp->sp[0];
2911 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2916 VALUE last_hash, argv_ary;
2917 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2918 if (!IS_ARGS_KEYWORD(ci) &&
2921 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2926 calling->kw_splat = 1;
2932 if (!IS_ARGS_KEYWORD(ci) &&
2933 calling->argc > 0 &&
2935 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2942 cfp->sp[-1] = rb_hash_dup(last_hash);
2943 calling->kw_splat = 1;
2949 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2951 VM_ASSERT(calling->kw_splat == 1);
2952 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2957 calling->kw_splat = 0;
2963 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2965 VM_ASSERT(calling->kw_splat == 0);
2971 vm_caller_setup_arg_kw(cfp, calling, ci);
2975#define USE_OPT_HIST 0
2978#define OPT_HIST_MAX 64
2979static int opt_hist[OPT_HIST_MAX+1];
2983opt_hist_show_results_at_exit(
void)
2985 for (
int i=0; i<OPT_HIST_MAX; i++) {
2986 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
2992vm_call_iseq_setup_normal_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
2996 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2997 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
2998 const int opt = calling->argc - lead_num;
2999 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3000 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3001 const int param = ISEQ_BODY(iseq)->param.size;
3002 const int local = ISEQ_BODY(iseq)->local_table_size;
3003 const int delta = opt_num - opt;
3005 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3008 if (opt_pc < OPT_HIST_MAX) {
3012 opt_hist[OPT_HIST_MAX]++;
3016 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3020vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3024 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3025 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3026 const int opt = calling->argc - lead_num;
3027 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3029 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3032 if (opt_pc < OPT_HIST_MAX) {
3036 opt_hist[OPT_HIST_MAX]++;
3040 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3044args_setup_kw_parameters(rb_execution_context_t *
const ec,
const rb_iseq_t *
const iseq,
const rb_callable_method_entry_t *cme,
3045 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3046 VALUE *
const locals);
3049vm_call_iseq_forwardable(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3053 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3054 int param_size = ISEQ_BODY(iseq)->param.size;
3055 int local_size = ISEQ_BODY(iseq)->local_table_size;
3058 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3060 local_size = local_size + vm_ci_argc(calling->cd->ci);
3061 param_size = param_size + vm_ci_argc(calling->cd->ci);
3063 cfp->sp[0] = (
VALUE)calling->cd->ci;
3065 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3069vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3075 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3076 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3078 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3079 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3081 const int ci_kw_len = kw_arg->keyword_len;
3082 const VALUE *
const ci_keywords = kw_arg->keywords;
3083 VALUE *argv = cfp->sp - calling->argc;
3084 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3085 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3087 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3088 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3090 int param = ISEQ_BODY(iseq)->param.size;
3091 int local = ISEQ_BODY(iseq)->local_table_size;
3092 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3096vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3099 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3102 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3103 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3105 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3106 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3107 VALUE *
const argv = cfp->sp - calling->argc;
3108 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3111 for (i=0; i<kw_param->num; i++) {
3112 klocals[i] = kw_param->default_values[i];
3119 int param = ISEQ_BODY(iseq)->param.size;
3120 int local = ISEQ_BODY(iseq)->local_table_size;
3121 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3124static VALUE builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
3127vm_call_single_noarg_leaf_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3131 cfp->sp -= (calling->argc + 1);
3132 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3133 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3139warn_unused_block(
const rb_callable_method_entry_t *cme,
const rb_iseq_t *iseq,
void *pc)
3141 rb_vm_t *vm = GET_VM();
3142 set_table *dup_check_table = vm->unused_block_warning_table;
3152 .v = (
VALUE)cme->def,
3156 if (!strict_unused_block) {
3157 key = (st_data_t)cme->def->original_id;
3159 if (set_table_lookup(dup_check_table, key)) {
3169 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3174 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3175 fprintf(stderr,
"key:%p\n", (
void *)key);
3179 if (set_insert(dup_check_table, key)) {
3183 VALUE m_loc = rb_method_entry_location((
const rb_method_entry_t *)cme);
3184 VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label);
3186 if (!
NIL_P(m_loc)) {
3187 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3191 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3197vm_callee_setup_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
3198 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3203 VM_ASSERT((vm_ci_argc(ci), 1));
3204 VM_ASSERT(vm_cc_cme(cc) != NULL);
3206 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3207 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3208 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3209 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)ec->cfp->pc);
3212 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3213 if (LIKELY(rb_simple_iseq_p(iseq))) {
3214 rb_control_frame_t *cfp = ec->cfp;
3215 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3216 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3218 if (calling->argc != lead_num) {
3219 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3223 VM_ASSERT(cc == calling->cc);
3225 if (vm_call_iseq_optimizable_p(ci, cc)) {
3226 if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3227 VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF);
3228 vm_cc_bf_set(cc, (
void *)iseq->body->iseq_encoded[1]);
3229 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3232 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3237 else if (rb_iseq_only_optparam_p(iseq)) {
3238 rb_control_frame_t *cfp = ec->cfp;
3240 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3241 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3243 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3244 const int argc = calling->argc;
3245 const int opt = argc - lead_num;
3247 if (opt < 0 || opt > opt_num) {
3248 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3251 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3252 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3253 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3254 vm_call_cacheable(ci, cc));
3257 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3258 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3259 vm_call_cacheable(ci, cc));
3263 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3264 for (
int i=argc; i<lead_num + opt_num; i++) {
3267 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3269 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3270 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3271 const int argc = calling->argc;
3272 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3274 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3277 if (argc - kw_arg->keyword_len == lead_num) {
3278 const int ci_kw_len = kw_arg->keyword_len;
3279 const VALUE *
const ci_keywords = kw_arg->keywords;
3281 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3283 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3284 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3286 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3287 vm_call_cacheable(ci, cc));
3292 else if (argc == lead_num) {
3294 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3295 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3297 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3299 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3300 vm_call_cacheable(ci, cc));
3326 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3327 bool can_fastpath =
true;
3329 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3331 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3332 ci = vm_ci_new_runtime(
3339 ci = forward_cd->caller_ci;
3341 can_fastpath =
false;
3345 if (!vm_ci_markable(ci)) {
3346 ci = vm_ci_new_runtime(
3351 can_fastpath =
false;
3353 argv[param_size - 1] = (
VALUE)ci;
3354 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3358 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3385 const VALUE * lep = VM_CF_LEP(cfp);
3387 const rb_iseq_t *iseq;
3391 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3396 iseq = rb_vm_search_cf_from_ep(ec, cfp, lep)->iseq;
3400 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3402 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3403 VALUE * to = cfp->sp - 1;
3407 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3412 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3414 cfp->sp = to + argc;
3431vm_call_iseq_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3433 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3436 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3437 int param_size = ISEQ_BODY(iseq)->param.size;
3438 int local_size = ISEQ_BODY(iseq)->local_table_size;
3440 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3442 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3443 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3447vm_call_iseq_fwd_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3449 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3452 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3453 int param_size = ISEQ_BODY(iseq)->param.size;
3454 int local_size = ISEQ_BODY(iseq)->local_table_size;
3456 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3459 local_size = local_size + vm_ci_argc(calling->cd->ci);
3460 param_size = param_size + vm_ci_argc(calling->cd->ci);
3462 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3463 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3467vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
3468 int opt_pc,
int param_size,
int local_size)
3473 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3474 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3477 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3482vm_call_iseq_setup_normal(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
const rb_callable_method_entry_t *me,
3483 int opt_pc,
int param_size,
int local_size)
3485 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3486 VALUE *argv = cfp->sp - calling->argc;
3487 VALUE *sp = argv + param_size;
3488 cfp->sp = argv - 1 ;
3490 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3491 calling->block_handler, (
VALUE)me,
3492 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3493 local_size - param_size,
3494 ISEQ_BODY(iseq)->stack_max);
3499vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc)
3503 VALUE *argv = cfp->sp - calling->argc;
3504 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3505 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3506 VALUE *src_argv = argv;
3507 VALUE *sp_orig, *sp;
3508 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3510 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3511 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3512 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3513 dst_captured->code.val = src_captured->code.val;
3514 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3515 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3518 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3522 vm_pop_frame(ec, cfp, cfp->ep);
3525 sp_orig = sp = cfp->sp;
3528 sp[0] = calling->recv;
3532 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3533 *sp++ = src_argv[i];
3536 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3537 calling->recv, calling->block_handler, (
VALUE)me,
3538 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3539 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3540 ISEQ_BODY(iseq)->stack_max);
3548ractor_unsafe_check(
void)
3550 if (!rb_ractor_main_p()) {
3551 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3558 ractor_unsafe_check();
3566 ractor_unsafe_check();
3568 return (*f)(argc, argv, recv);
3574 ractor_unsafe_check();
3582 ractor_unsafe_check();
3584 return (*f)(recv, argv[0]);
3590 ractor_unsafe_check();
3592 return (*f)(recv, argv[0], argv[1]);
3598 ractor_unsafe_check();
3600 return (*f)(recv, argv[0], argv[1], argv[2]);
3606 ractor_unsafe_check();
3608 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3614 ractor_unsafe_check();
3615 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3616 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3622 ractor_unsafe_check();
3623 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3624 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3630 ractor_unsafe_check();
3631 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3632 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3638 ractor_unsafe_check();
3639 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3640 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3646 ractor_unsafe_check();
3647 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3648 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3654 ractor_unsafe_check();
3655 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;
3656 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3662 ractor_unsafe_check();
3663 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;
3664 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]);
3670 ractor_unsafe_check();
3671 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;
3672 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]);
3678 ractor_unsafe_check();
3679 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;
3680 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]);
3686 ractor_unsafe_check();
3687 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;
3688 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]);
3694 ractor_unsafe_check();
3695 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;
3696 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]);
3710 return (*f)(argc, argv, recv);
3724 return (*f)(recv, argv[0]);
3731 return (*f)(recv, argv[0], argv[1]);
3738 return (*f)(recv, argv[0], argv[1], argv[2]);
3745 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3751 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3752 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3758 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3759 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3765 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3766 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3772 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3773 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3779 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3780 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3786 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;
3787 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3793 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;
3794 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]);
3800 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;
3801 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]);
3807 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;
3808 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]);
3814 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;
3815 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]);
3821 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;
3822 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]);
3826vm_cfp_consistent_p(rb_execution_context_t *ec,
const rb_control_frame_t *reg_cfp)
3828 const int ov_flags = RAISED_STACKOVERFLOW;
3829 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3830 if (rb_ec_raised_p(ec, ov_flags)) {
3831 rb_ec_raised_reset(ec, ov_flags);
3837#define CHECK_CFP_CONSISTENCY(func) \
3838 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3839 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3842const rb_method_cfunc_t *
3843vm_method_cfunc_entry(
const rb_callable_method_entry_t *me)
3845#if VM_DEBUG_VERIFY_METHOD_CACHE
3846 switch (me->def->type) {
3847 case VM_METHOD_TYPE_CFUNC:
3848 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3850# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3852 METHOD_BUG(ATTRSET);
3854 METHOD_BUG(BMETHOD);
3857 METHOD_BUG(OPTIMIZED);
3858 METHOD_BUG(MISSING);
3859 METHOD_BUG(REFINED);
3863 rb_bug(
"wrong method type: %d", me->def->type);
3866 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3870vm_call_cfunc_with_frame_(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
3873 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3877 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3878 const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me);
3880 VALUE recv = calling->recv;
3881 VALUE block_handler = calling->block_handler;
3882 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3884 if (UNLIKELY(calling->kw_splat)) {
3885 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3888 VM_ASSERT(reg_cfp == ec->cfp);
3890 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3893 vm_push_frame(ec, NULL, frame_type, recv,
3894 block_handler, (
VALUE)me,
3895 0, ec->cfp->sp, 0, 0);
3897 int len = cfunc->argc;
3900 reg_cfp->sp = stack_bottom;
3901 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3903 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3905 rb_vm_pop_frame(ec);
3907 VM_ASSERT(ec->cfp->sp == stack_bottom);
3909 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3910 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3918rb_vm_push_cfunc_frame(
const rb_callable_method_entry_t *cme,
int recv_idx)
3920 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3921 rb_execution_context_t *ec = GET_EC();
3922 VALUE *sp = ec->cfp->sp;
3923 VALUE recv = *(sp - recv_idx - 1);
3924 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3925 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3926#if VM_CHECK_MODE > 0
3928 *(GET_EC()->cfp->sp) =
Qfalse;
3930 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3935rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3937 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3941vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3943 int argc = calling->argc;
3944 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3945 VALUE *argv = &stack_bottom[1];
3947 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3951vm_call_cfunc_other(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3954 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3956 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3958 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3959 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3962 VALUE *stack_bottom = reg_cfp->sp - 2;
3964 VM_ASSERT(calling->argc == 1);
3968 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3971 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));
3973 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3978vm_call_cfunc_array_argv(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
int stack_offset,
int argc_offset)
3980 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3983 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3984 return vm_call_cfunc_other(ec, reg_cfp, calling);
3988 calling->kw_splat = 0;
3990 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
3991 VALUE *sp = stack_bottom;
3992 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
3993 for(i = 0; i < argc; i++) {
3998 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4002vm_call_cfunc_only_splat(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4004 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4005 VALUE argv_ary = reg_cfp->sp[-1];
4009 int argc_offset = 0;
4011 if (UNLIKELY(argc > 0 &&
4013 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4015 return vm_call_cfunc_other(ec, reg_cfp, calling);
4019 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4023vm_call_cfunc_only_splat_kw(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4025 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4026 VALUE keyword_hash = reg_cfp->sp[-1];
4029 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4032 return vm_call_cfunc_other(ec, reg_cfp, calling);
4036vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4039 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4041 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4042 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4044 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4045 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4047 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4049 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4050 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4054 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4055 return vm_call_cfunc_other(ec, reg_cfp, calling);
4059vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4062 RB_DEBUG_COUNTER_INC(ccf_ivar);
4064 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4069vm_call_attrset_direct(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_callcache *cc,
VALUE obj)
4071 RB_DEBUG_COUNTER_INC(ccf_attrset);
4072 VALUE val = *(cfp->sp - 1);
4075 shape_id_t dest_shape_id;
4076 vm_cc_atomic_shape_and_index(cc, &dest_shape_id, &index);
4077 ID id = vm_cc_cme(cc)->def->body.attr.id;
4078 rb_check_frozen(obj);
4079 VALUE res = vm_setivar(obj,
id, val, dest_shape_id, index);
4087 res = vm_setivar_class(obj,
id, val, dest_shape_id, index);
4088 if (!UNDEF_P(res)) {
4095 res = vm_setivar_default(obj,
id, val, dest_shape_id, index);
4096 if (!UNDEF_P(res)) {
4101 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4107vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4109 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4113vm_call_bmethod_body(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const VALUE *argv)
4118 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4119 VALUE procv = cme->def->body.bmethod.proc;
4122 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4123 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4127 GetProcPtr(procv, proc);
4128 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4133static int vm_callee_setup_block_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
const rb_iseq_t *iseq,
VALUE *argv,
const enum arg_setup_type arg_setup_type);
4136vm_call_iseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4138 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4141 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4142 VALUE procv = cme->def->body.bmethod.proc;
4145 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4146 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4150 GetProcPtr(procv, proc);
4151 const struct rb_block *block = &proc->block;
4153 while (vm_block_type(block) == block_type_proc) {
4154 block = vm_proc_block(block->as.proc);
4156 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4159 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4160 VALUE *
const argv = cfp->sp - calling->argc;
4161 const int arg_size = ISEQ_BODY(iseq)->param.size;
4164 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4165 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4168 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4173 vm_push_frame(ec, iseq,
4174 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4176 VM_GUARDED_PREV_EP(captured->ep),
4178 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4180 ISEQ_BODY(iseq)->local_table_size - arg_size,
4181 ISEQ_BODY(iseq)->stack_max);
4187vm_call_noniseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4189 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4193 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4194 if (UNLIKELY(calling->heap_argv)) {
4199 argc = calling->argc;
4202 cfp->sp += - argc - 1;
4205 return vm_call_bmethod_body(ec, calling, argv);
4209vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4211 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4214 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4215 VALUE procv = cme->def->body.bmethod.proc;
4217 GetProcPtr(procv, proc);
4218 const struct rb_block *block = &proc->block;
4220 while (vm_block_type(block) == block_type_proc) {
4221 block = vm_proc_block(block->as.proc);
4223 if (vm_block_type(block) == block_type_iseq) {
4224 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4225 return vm_call_iseq_bmethod(ec, cfp, calling);
4228 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4229 return vm_call_noniseq_bmethod(ec, cfp, calling);
4233rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4235 VALUE klass = current_class;
4243 while (
RTEST(klass)) {
4245 if (owner == target_owner) {
4251 return current_class;
4254static const rb_callable_method_entry_t *
4255aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4257 const rb_method_entry_t *orig_me = me->def->body.alias.original_me;
4258 const rb_callable_method_entry_t *cme;
4260 if (orig_me->defined_class == 0) {
4261 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4262 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4263 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4265 if (me->def->reference_count == 1) {
4266 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4269 rb_method_definition_t *def =
4270 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4271 rb_method_definition_set((rb_method_entry_t *)me, def, (
void *)cme);
4275 cme = (
const rb_callable_method_entry_t *)orig_me;
4278 VM_ASSERT(callable_method_entry_p(cme));
4282const rb_callable_method_entry_t *
4283rb_aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4285 return aliased_callable_method_entry(me);
4289vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4291 calling->cc = &VM_CC_ON_STACK(
Qundef,
4294 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4296 return vm_call_method_each_type(ec, cfp, calling);
4299static enum method_missing_reason
4302 enum method_missing_reason stat = MISSING_NOENTRY;
4303 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4304 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4305 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4309static VALUE vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
4312vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4315 ASSUME(calling->argc >= 0);
4317 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4318 int argc = calling->argc;
4319 VALUE recv = calling->recv;
4322 flags |= VM_CALL_OPT_SEND;
4324 if (UNLIKELY(! mid)) {
4325 mid = idMethodMissing;
4326 missing_reason = ci_missing_reason(ci);
4327 ec->method_missing_reason = missing_reason;
4330 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4331 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4332 rb_ary_unshift(argv_ary, symbol);
4335 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4336 VALUE exc = rb_make_no_method_exception(
4358 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4361 argc = ++calling->argc;
4363 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4366 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4367 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4368 VALUE exc = rb_make_no_method_exception(
4381 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4387 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4388 calling->cd = &new_fcd.cd;
4392 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4393 new_fcd.caller_ci = caller_ci;
4396 calling->cc = &VM_CC_ON_STACK(klass,
4398 { .method_missing_reason = missing_reason },
4399 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4401 if (flags & VM_CALL_FCALL) {
4402 return vm_call_method(ec, reg_cfp, calling);
4406 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4408 if (vm_cc_cme(cc) != NULL) {
4409 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4410 case METHOD_VISI_PUBLIC:
4411 return vm_call_method_each_type(ec, reg_cfp, calling);
4412 case METHOD_VISI_PRIVATE:
4413 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4415 case METHOD_VISI_PROTECTED:
4416 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4419 VM_UNREACHABLE(vm_call_method);
4421 return vm_call_method_missing(ec, reg_cfp, calling);
4424 return vm_call_method_nome(ec, reg_cfp, calling);
4428vm_call_opt_send0(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
int flags)
4434 i = calling->argc - 1;
4436 if (calling->argc == 0) {
4437 rb_raise(rb_eArgError,
"no method name given");
4461 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4465vm_call_opt_send_complex(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4467 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4469 int flags = VM_CALL_FCALL;
4473 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4474 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4476 flags |= VM_CALL_ARGS_SPLAT;
4477 if (calling->kw_splat) {
4478 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4479 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4480 calling->kw_splat = 0;
4482 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4485 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4486 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4490vm_call_opt_send_simple(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4492 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4493 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4497vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4499 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4502 int flags = vm_ci_flag(ci);
4504 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4505 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4506 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4507 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4508 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4509 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4512 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4513 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4517vm_call_method_missing_body(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
4518 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4520 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4522 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4523 unsigned int argc, flag;
4525 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4526 argc = ++calling->argc;
4529 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4530 vm_check_canary(ec, reg_cfp->sp);
4534 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4537 ec->method_missing_reason = reason;
4541 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4547 if (!(flag & VM_CALL_FORWARDING)) {
4548 calling->cd = &new_fcd.cd;
4552 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4553 new_fcd.caller_ci = caller_ci;
4557 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4558 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4559 return vm_call_method(ec, reg_cfp, calling);
4563vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4565 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4568static const rb_callable_method_entry_t *refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me);
4570vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE klass)
4574 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, vm_ci_mid(calling->cd->ci)) : NULL;
4576 return vm_call_method_nome(ec, cfp, calling);
4578 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4579 cme->def->body.refined.orig_me) {
4580 cme = refined_method_callable_without_refinement(cme);
4583 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4585 return vm_call_method_each_type(ec, cfp, calling);
4589find_refinement(
VALUE refinements,
VALUE klass)
4591 if (
NIL_P(refinements)) {
4594 return rb_hash_lookup(refinements, klass);
4597PUREFUNC(
static rb_control_frame_t * current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp));
4598static rb_control_frame_t *
4599current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp)
4601 rb_control_frame_t *top_cfp = cfp;
4603 if (cfp->iseq && ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_BLOCK) {
4604 const rb_iseq_t *local_iseq = ISEQ_BODY(cfp->iseq)->local_iseq;
4607 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4608 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4612 }
while (cfp->iseq != local_iseq);
4617static const rb_callable_method_entry_t *
4618refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me)
4620 const rb_method_entry_t *orig_me = me->def->body.refined.orig_me;
4621 const rb_callable_method_entry_t *cme;
4623 if (orig_me->defined_class == 0) {
4628 cme = (
const rb_callable_method_entry_t *)orig_me;
4631 VM_ASSERT(callable_method_entry_p(cme));
4633 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4640static const rb_callable_method_entry_t *
4641search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4643 ID mid = vm_ci_mid(calling->cd->ci);
4644 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4646 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4648 for (; cref; cref = CREF_NEXT(cref)) {
4649 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4650 if (
NIL_P(refinement))
continue;
4652 const rb_callable_method_entry_t *
const ref_me =
4653 rb_callable_method_entry(refinement, mid);
4656 if (vm_cc_call(cc) == vm_call_super_method) {
4657 const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp);
4658 const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp);
4659 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4664 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4665 cme->def != ref_me->def) {
4668 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4677 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4678 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4682 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, mid) : NULL;
4688vm_call_refined(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4690 const rb_callable_method_entry_t *ref_cme = search_refined_method(ec, cfp, calling);
4693 if (calling->cd->cc) {
4694 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);
4696 return vm_call_method(ec, cfp, calling);
4699 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4700 calling->cc= ref_cc;
4701 return vm_call_method(ec, cfp, calling);
4705 return vm_call_method_nome(ec, cfp, calling);
4709static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
bool is_lambda,
VALUE block_handler);
4711NOINLINE(
static VALUE
4712 vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4716vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4719 int argc = calling->argc;
4722 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4725 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4729vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4731 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4734 VALUE procval = calling->recv;
4735 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4739vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4741 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4743 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4746 if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
4747 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4750 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4751 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4752 return vm_call_general(ec, reg_cfp, calling);
4757vm_call_opt_struct_aref0(rb_execution_context_t *ec,
struct rb_calling_info *calling)
4759 VALUE recv = calling->recv;
4762 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4763 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4765 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4766 return internal_RSTRUCT_GET(recv,
off);
4770vm_call_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4772 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4774 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4780vm_call_opt_struct_aset0(rb_execution_context_t *ec,
struct rb_calling_info *calling,
VALUE val)
4782 VALUE recv = calling->recv;
4785 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4786 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4788 rb_check_frozen(recv);
4790 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4791 internal_RSTRUCT_SET(recv,
off, val);
4797vm_call_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4799 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4801 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4806NOINLINE(
static VALUE vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4809#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4810 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4811 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4812 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4814 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4815 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4823vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4826 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4827 case OPTIMIZED_METHOD_TYPE_SEND:
4828 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4829 return vm_call_opt_send(ec, cfp, calling);
4830 case OPTIMIZED_METHOD_TYPE_CALL:
4831 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4832 return vm_call_opt_call(ec, cfp, calling);
4833 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4834 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4835 return vm_call_opt_block_call(ec, cfp, calling);
4836 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4837 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4841 VM_CALL_METHOD_ATTR(v,
4842 vm_call_opt_struct_aref(ec, cfp, calling),
4843 set_vm_cc_ivar(cc); \
4844 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4847 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4848 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4852 VM_CALL_METHOD_ATTR(v,
4853 vm_call_opt_struct_aset(ec, cfp, calling),
4854 set_vm_cc_ivar(cc); \
4855 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4859 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4864vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4868 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4871 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4873 switch (cme->def->type) {
4874 case VM_METHOD_TYPE_ISEQ:
4875 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4876 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4877 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4880 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4881 return vm_call_iseq_setup(ec, cfp, calling);
4884 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4885 case VM_METHOD_TYPE_CFUNC:
4886 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4887 return vm_call_cfunc(ec, cfp, calling);
4889 case VM_METHOD_TYPE_ATTRSET:
4890 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4894 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4896 if (vm_cc_markable(cc)) {
4897 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4898 VM_CALL_METHOD_ATTR(v,
4899 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4900 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4906 VM_CALLCACHE_UNMARKABLE |
4907 VM_CALLCACHE_ON_STACK,
4913 .value = vm_pack_shape_and_index(INVALID_SHAPE_ID, ATTR_INDEX_NOT_SET),
4918 VM_CALL_METHOD_ATTR(v,
4919 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4920 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4924 case VM_METHOD_TYPE_IVAR:
4925 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4927 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4928 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4929 VM_CALL_METHOD_ATTR(v,
4930 vm_call_ivar(ec, cfp, calling),
4931 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4934 case VM_METHOD_TYPE_MISSING:
4935 vm_cc_method_missing_reason_set(cc, 0);
4936 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4937 return vm_call_method_missing(ec, cfp, calling);
4939 case VM_METHOD_TYPE_BMETHOD:
4940 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4941 return vm_call_bmethod(ec, cfp, calling);
4943 case VM_METHOD_TYPE_ALIAS:
4944 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4945 return vm_call_alias(ec, cfp, calling);
4947 case VM_METHOD_TYPE_OPTIMIZED:
4948 return vm_call_optimized(ec, cfp, calling, ci, cc);
4950 case VM_METHOD_TYPE_UNDEF:
4953 case VM_METHOD_TYPE_ZSUPER:
4954 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4956 case VM_METHOD_TYPE_REFINED:
4959 return vm_call_refined(ec, cfp, calling);
4962 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4965NORETURN(
static void vm_raise_method_missing(rb_execution_context_t *ec,
int argc,
const VALUE *argv,
VALUE obj,
int call_status));
4968vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4972 const int stat = ci_missing_reason(ci);
4974 if (vm_ci_mid(ci) == idMethodMissing) {
4975 if (UNLIKELY(calling->heap_argv)) {
4979 rb_control_frame_t *reg_cfp = cfp;
4980 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4981 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4985 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
4995vm_defined_class_for_protected_call(
const rb_callable_method_entry_t *me)
4997 VALUE defined_class = me->defined_class;
4998 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
4999 return NIL_P(refined_class) ? defined_class : refined_class;
5003vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
5008 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5010 if (vm_cc_cme(cc) != NULL) {
5011 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5012 case METHOD_VISI_PUBLIC:
5013 return vm_call_method_each_type(ec, cfp, calling);
5015 case METHOD_VISI_PRIVATE:
5016 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5017 enum method_missing_reason stat = MISSING_PRIVATE;
5018 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5020 vm_cc_method_missing_reason_set(cc, stat);
5021 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5022 return vm_call_method_missing(ec, cfp, calling);
5024 return vm_call_method_each_type(ec, cfp, calling);
5026 case METHOD_VISI_PROTECTED:
5027 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5028 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5030 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5031 return vm_call_method_missing(ec, cfp, calling);
5035 VM_ASSERT(vm_cc_cme(cc) != NULL);
5038 calling->cc = &cc_on_stack;
5039 return vm_call_method_each_type(ec, cfp, calling);
5042 return vm_call_method_each_type(ec, cfp, calling);
5045 rb_bug(
"unreachable");
5049 return vm_call_method_nome(ec, cfp, calling);
5054vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5056 RB_DEBUG_COUNTER_INC(ccf_general);
5057 return vm_call_method(ec, reg_cfp, calling);
5063 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5064 VM_ASSERT(cc != vm_cc_empty());
5066 *(vm_call_handler *)&cc->call_ = vm_call_general;
5070vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5072 RB_DEBUG_COUNTER_INC(ccf_super_method);
5077 if (ec == NULL) rb_bug(
"unreachable");
5080 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5081 return vm_call_method(ec, reg_cfp, calling);
5087vm_search_normal_superclass(
VALUE klass)
5092 klass =
RBASIC(klass)->klass;
5094 klass = RCLASS_ORIGIN(klass);
5098NORETURN(
static void vm_super_outside(
void));
5101vm_super_outside(
void)
5107empty_cc_for_super(
void)
5109 return &vm_empty_cc_for_super;
5113vm_search_super_method(
const rb_control_frame_t *reg_cfp,
struct rb_call_data *cd,
VALUE recv)
5115 VALUE current_defined_class;
5116 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
5122 current_defined_class = vm_defined_class_for_protected_call(me);
5125 reg_cfp->iseq != method_entry_iseqptr(me) &&
5128 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5132 "self has wrong type to call super in this context: "
5133 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5138 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5140 "implicit argument passing of super from method defined"
5141 " by define_method() is not supported."
5142 " Specify all arguments explicitly.");
5145 ID mid = me->def->original_id;
5147 if (!vm_ci_markable(cd->ci)) {
5148 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5152 cd->ci = vm_ci_new_runtime(mid,
5155 vm_ci_kwarg(cd->ci));
5162 VALUE klass = vm_search_normal_superclass(me->defined_class);
5166 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5170 cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd, klass);
5171 const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc);
5174 if (cached_cme == NULL) {
5176 cd->cc = empty_cc_for_super();
5178 else if (cached_cme->called_id != mid) {
5179 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
5181 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5185 cd->cc = cc = empty_cc_for_super();
5189 switch (cached_cme->def->type) {
5191 case VM_METHOD_TYPE_REFINED:
5193 case VM_METHOD_TYPE_ATTRSET:
5194 case VM_METHOD_TYPE_IVAR:
5195 vm_cc_call_set(cc, vm_call_super_method);
5203 VM_ASSERT((vm_cc_cme(cc),
true));
5211block_proc_is_lambda(
const VALUE procval)
5216 GetProcPtr(procval, proc);
5217 return proc->is_lambda;
5225vm_yield_with_cfunc(rb_execution_context_t *ec,
5227 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5228 const rb_callable_method_entry_t *me)
5230 int is_lambda = FALSE;
5231 VALUE val, arg, blockarg;
5233 const struct vm_ifunc *ifunc = captured->code.ifunc;
5238 else if (argc == 0) {
5245 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5247 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5249 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5252 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5255 VM_GUARDED_PREV_EP(captured->ep),
5257 0, ec->cfp->sp, 0, 0);
5258 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5259 rb_vm_pop_frame(ec);
5265rb_vm_yield_with_cfunc(rb_execution_context_t *ec,
const struct rb_captured_block *captured,
int argc,
const VALUE *argv)
5267 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5271vm_yield_with_symbol(rb_execution_context_t *ec,
VALUE symbol,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler)
5273 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
5277vm_callee_setup_block_arg_arg0_splat(rb_control_frame_t *cfp,
const rb_iseq_t *iseq,
VALUE *argv,
VALUE ary)
5282 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5284 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5292vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5294 VALUE ary, arg0 = argv[0];
5299 VM_ASSERT(argv[0] == arg0);
5305vm_callee_setup_block_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const struct rb_callinfo *ci,
const rb_iseq_t *iseq,
VALUE *argv,
const enum arg_setup_type arg_setup_type)
5307 if (rb_simple_iseq_p(iseq)) {
5308 rb_control_frame_t *cfp = ec->cfp;
5311 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5313 if (arg_setup_type == arg_setup_block &&
5314 calling->argc == 1 &&
5315 ISEQ_BODY(iseq)->param.flags.has_lead &&
5316 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5317 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5318 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5321 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5322 if (arg_setup_type == arg_setup_block) {
5323 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5325 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5326 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5327 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5329 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5330 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5334 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5341 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5346vm_yield_setup_args(rb_execution_context_t *ec,
const rb_iseq_t *iseq,
const int argc,
VALUE *argv,
int flags,
VALUE block_handler,
enum arg_setup_type arg_setup_type)
5350 calling = &calling_entry;
5351 calling->argc = argc;
5352 calling->block_handler = block_handler;
5353 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5355 calling->heap_argv = 0;
5357 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5359 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5365vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5367 bool is_lambda,
VALUE block_handler)
5370 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5371 const int arg_size = ISEQ_BODY(iseq)->param.size;
5372 VALUE *
const rsp = GET_SP() - calling->argc;
5373 VALUE *
const argv = rsp;
5374 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5375 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5379 vm_push_frame(ec, iseq,
5382 VM_GUARDED_PREV_EP(captured->ep), 0,
5383 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5385 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5391vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5393 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5395 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5396 int flags = vm_ci_flag(ci);
5398 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5399 ((calling->argc == 0) ||
5400 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5401 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5402 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5403 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5405 if (UNLIKELY(calling->heap_argv)) {
5406#if VM_ARGC_STACK_MAX < 0
5408 rb_raise(rb_eArgError,
"no receiver given");
5414 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5415 reg_cfp->sp[-2] = calling->recv;
5416 flags |= VM_CALL_ARGS_SPLAT;
5419 if (calling->argc < 1) {
5420 rb_raise(rb_eArgError,
"no receiver given");
5422 calling->recv = TOPN(--calling->argc);
5424 if (calling->kw_splat) {
5425 flags |= VM_CALL_KW_SPLAT;
5429 if (calling->argc < 1) {
5430 rb_raise(rb_eArgError,
"no receiver given");
5432 calling->recv = TOPN(--calling->argc);
5435 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5439vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5441 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5446 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5447 argc = calling->argc;
5448 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);
5454vm_proc_to_block_handler(
VALUE procval)
5456 const struct rb_block *block = vm_proc_block(procval);
5458 switch (vm_block_type(block)) {
5459 case block_type_iseq:
5460 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5461 case block_type_ifunc:
5462 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5463 case block_type_symbol:
5464 return VM_BH_FROM_SYMBOL(block->as.symbol);
5465 case block_type_proc:
5466 return VM_BH_FROM_PROC(block->as.proc);
5468 VM_UNREACHABLE(vm_yield_with_proc);
5473vm_invoke_proc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5475 bool is_lambda,
VALUE block_handler)
5477 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5478 VALUE proc = VM_BH_TO_PROC(block_handler);
5479 is_lambda = block_proc_is_lambda(proc);
5480 block_handler = vm_proc_to_block_handler(proc);
5483 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5487vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5489 bool is_lambda,
VALUE block_handler)
5491 VALUE (*func)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5493 bool is_lambda,
VALUE block_handler);
5495 switch (vm_block_handler_type(block_handler)) {
5496 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5497 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5498 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5499 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5500 default: rb_bug(
"vm_invoke_block: unreachable");
5503 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5507vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5509 const rb_execution_context_t *ec = GET_EC();
5510 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
5514 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5517 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5518 captured->code.iseq = blockiseq;
5520 return rb_vm_make_proc(ec, captured,
rb_cProc);
5524vm_once_exec(
VALUE iseq)
5526 VALUE proc = vm_make_proc_with_iseq((rb_iseq_t *)iseq);
5531vm_once_clear(
VALUE data)
5534 is->once.running_thread = NULL;
5546 args[0] = obj; args[1] =
Qfalse;
5548 if (!UNDEF_P(r) &&
RTEST(r)) {
5557vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5560 enum defined_type
type = (
enum defined_type)op_type;
5567 return rb_gvar_defined(
SYM2ID(obj));
5569 case DEFINED_CVAR: {
5570 const rb_cref_t *cref = vm_get_cref(GET_EP());
5571 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5576 case DEFINED_CONST_FROM: {
5577 bool allow_nil =
type == DEFINED_CONST;
5579 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5584 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5586 case DEFINED_METHOD:{
5588 const rb_method_entry_t *me = rb_method_entry_with_refinements(klass,
SYM2ID(obj), NULL);
5591 switch (METHOD_ENTRY_VISI(me)) {
5592 case METHOD_VISI_PRIVATE:
5594 case METHOD_VISI_PROTECTED:
5598 case METHOD_VISI_PUBLIC:
5602 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(me));
5606 return check_respond_to_missing(obj, v);
5611 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5615 case DEFINED_ZSUPER:
5617 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(GET_CFP());
5620 VALUE klass = vm_search_normal_superclass(me->defined_class);
5621 if (!klass)
return false;
5623 ID id = me->def->original_id;
5630 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5632 rb_bug(
"unimplemented defined? type (VM)");
5640rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5642 return vm_defined(ec, reg_cfp, op_type, obj, v);
5646vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5649 const VALUE *ep = reg_ep;
5650 for (i = 0; i < lv; i++) {
5651 ep = GET_PREV_EP(ep);
5657vm_get_special_object(
const VALUE *
const reg_ep,
5658 enum vm_special_object_type
type)
5661 case VM_SPECIAL_OBJECT_VMCORE:
5662 return rb_mRubyVMFrozenCore;
5663 case VM_SPECIAL_OBJECT_CBASE:
5664 return vm_get_cbase(reg_ep);
5665 case VM_SPECIAL_OBJECT_CONST_BASE:
5666 return vm_get_const_base(reg_ep);
5668 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5675rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5677 return vm_get_special_object(reg_ep,
type);
5683 const VALUE ary2 = ary2st;
5684 VALUE tmp1 = rb_check_to_array(ary1);
5685 VALUE tmp2 = rb_check_to_array(ary2);
5706 const VALUE ary2 = ary2st;
5708 if (
NIL_P(ary2))
return ary1;
5710 VALUE tmp2 = rb_check_to_array(ary2);
5725 return vm_concat_array(ary1, ary2st);
5729rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5731 return vm_concat_to_array(ary1, ary2st);
5740 VALUE tmp = rb_check_to_array(ary);
5744 else if (
RTEST(flag)) {
5757 return vm_splat_array(flag, ary);
5761vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5763 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5765 if (flag & VM_CHECKMATCH_ARRAY) {
5769 for (i = 0; i < n; i++) {
5771 VALUE c = check_match(ec, v, target,
type);
5780 return check_match(ec, pattern, target,
type);
5785rb_vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5787 return vm_check_match(ec, target, pattern, flag);
5791vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5793 const VALUE kw_bits = *(ep - bits);
5796 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5797 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5810 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5811 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5812 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5813 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5817 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5820 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5823 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5826 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5833vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5838 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5839 return rb_public_const_get_at(cbase,
id);
5847vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
5852 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
5857 "superclass mismatch for class %"PRIsVALUE
"",
5870vm_check_if_module(
ID id,
VALUE mod)
5889vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5892 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super : rb_cObject;
5900vm_declare_module(
ID id,
VALUE cbase)
5906NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
5910 VALUE name = rb_id2str(
id);
5911 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
5913 VALUE location = rb_const_source_location_at(cbase,
id);
5914 if (!
NIL_P(location)) {
5915 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
5916 " previous definition of %"PRIsVALUE
" was here",
5923vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5927 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
5929 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
5933 vm_check_if_namespace(cbase);
5938 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
5939 if (!vm_check_if_class(
id, flags, super, klass))
5940 unmatched_redefinition(
"class", cbase,
id, klass);
5944 return vm_declare_class(
id, flags, cbase, super);
5949vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
5953 vm_check_if_namespace(cbase);
5954 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
5955 if (!vm_check_if_module(
id, mod))
5956 unmatched_redefinition(
"module", cbase,
id, mod);
5960 return vm_declare_module(
id, cbase);
5965vm_find_or_create_class_by_id(
ID id,
5970 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
5973 case VM_DEFINECLASS_TYPE_CLASS:
5975 return vm_define_class(
id, flags, cbase, super);
5977 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
5981 case VM_DEFINECLASS_TYPE_MODULE:
5983 return vm_define_module(
id, flags, cbase);
5986 rb_bug(
"unknown defineclass type: %d", (
int)
type);
5990static rb_method_visibility_t
5991vm_scope_visibility_get(
const rb_execution_context_t *ec)
5993 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
5995 if (!vm_env_cref_by_cref(cfp->ep)) {
5996 return METHOD_VISI_PUBLIC;
5999 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6004vm_scope_module_func_check(
const rb_execution_context_t *ec)
6006 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
6008 if (!vm_env_cref_by_cref(cfp->ep)) {
6012 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6017vm_define_method(
const rb_execution_context_t *ec,
VALUE obj,
ID id,
VALUE iseqval,
int is_singleton)
6020 rb_method_visibility_t visi;
6021 rb_cref_t *cref = vm_ec_cref(ec);
6025 visi = METHOD_VISI_PUBLIC;
6028 klass = CREF_CLASS_FOR_DEFINITION(cref);
6029 visi = vm_scope_visibility_get(ec);
6036 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6039 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6042 if (!is_singleton && vm_scope_module_func_check(ec)) {
6044 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6053rb_vm_untag_block_handler(
VALUE block_handler)
6055 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6057 switch (vm_block_handler_type(block_handler)) {
6058 case block_handler_type_iseq:
6059 case block_handler_type_ifunc: {
6061 return captured->code.val;
6063 case block_handler_type_proc:
6064 case block_handler_type_symbol:
6065 return block_handler;
6067 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6072rb_vm_get_untagged_block_handler(rb_control_frame_t *reg_cfp)
6074 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6083 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6085 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6086 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6089 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6093enum method_explorer_type {
6095 mexp_search_invokeblock,
6104 VALUE block_handler,
6105 enum method_explorer_type method_explorer
6110 int argc = vm_ci_argc(ci);
6111 VALUE recv = TOPN(argc);
6113 .block_handler = block_handler,
6114 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6120 switch (method_explorer) {
6121 case mexp_search_method:
6122 calling.cc = cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd,
CLASS_OF(recv));
6123 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6125 case mexp_search_super:
6126 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6127 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6129 case mexp_search_invokeblock:
6130 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6137rb_vm_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6140 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6141 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6147rb_vm_sendforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6154 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6156 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6158 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6167rb_vm_opt_send_without_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6170 VALUE bh = VM_BLOCK_HANDLER_NONE;
6171 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6177rb_vm_invokesuper(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6181 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
true);
6182 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super);
6189rb_vm_invokesuperforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6195 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6197 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6199 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6208rb_vm_invokeblock(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6211 VALUE bh = VM_BLOCK_HANDLER_NONE;
6212 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6229vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6240 if (check_method_basic_definition(cme)) {
6249 if (check_cfunc(cme, rb_mod_to_s)) {
6255 val = rb_mod_to_s(recv);
6261 if (check_cfunc(cme, rb_nil_to_s)) {
6262 return rb_nil_to_s(recv);
6266 if (check_cfunc(cme, rb_true_to_s)) {
6267 return rb_true_to_s(recv);
6271 if (check_cfunc(cme, rb_false_to_s)) {
6272 return rb_false_to_s(recv);
6276 if (check_cfunc(cme, rb_int_to_s)) {
6277 return rb_fix_to_s(recv);
6287rb_vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6289 return vm_objtostring(iseq, recv, cd);
6293vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6295 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6304vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6306 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6315vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6317 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6329vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6331 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6335 VALUE args[1] = {target};
6338 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6341 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6346rb_vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6348 return vm_opt_duparray_include_p(ec, ary, target);
6352vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6354 if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
6355 if (array_len == 0) {
6359 VALUE result = *ptr;
6360 rb_snum_t i = array_len - 1;
6362 const VALUE v = *++ptr;
6363 if (OPTIMIZED_CMP(v, result) > 0) {
6376rb_vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6378 return vm_opt_newarray_max(ec, array_len, ptr);
6382vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6384 if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
6385 if (array_len == 0) {
6389 VALUE result = *ptr;
6390 rb_snum_t i = array_len - 1;
6392 const VALUE v = *++ptr;
6393 if (OPTIMIZED_CMP(v, result) < 0) {
6406rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6408 return vm_opt_newarray_min(ec, array_len, ptr);
6412vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6415 if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
6416 return rb_ary_hash_values(array_len, ptr);
6424rb_vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6426 return vm_opt_newarray_hash(ec, array_len, ptr);
6433vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE target)
6435 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6436 struct RArray fake_ary = {RBASIC_INIT};
6437 VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, array_len);
6441 VALUE args[1] = {target};
6447rb_vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE target)
6449 return vm_opt_newarray_include_p(ec, array_len, ptr, target);
6453vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt,
VALUE buffer)
6455 if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) {
6456 struct RArray fake_ary = {RBASIC_INIT};
6457 VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, array_len);
6458 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6468 if (!UNDEF_P(buffer)) {
6469 args[1] = rb_hash_new_with_size(1);
6470 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6475 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len, ptr), idPack, argc, args, kw_splat);
6480rb_vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt,
VALUE buffer)
6482 return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt, buffer);
6486rb_vm_opt_newarray_pack(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt)
6488 return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt,
Qundef);
6494vm_track_constant_cache(
ID id,
void *ic)
6496 rb_vm_t *vm = GET_VM();
6497 struct rb_id_table *const_cache = vm->constant_cache;
6498 VALUE lookup_result;
6501 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6505 ics = set_init_numtable();
6506 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6521 vm->inserting_constant_cache_id = id;
6523 set_insert(ics, (st_data_t)ic);
6525 vm->inserting_constant_cache_id = (
ID)0;
6529vm_ic_track_const_chain(rb_control_frame_t *cfp, IC ic,
const ID *segments)
6532 for (
int i = 0; segments[i]; i++) {
6533 ID id = segments[i];
6534 if (
id == idNULL)
continue;
6535 vm_track_constant_cache(
id, ic);
6542vm_inlined_ic_hit_p(
VALUE flags,
VALUE value,
const rb_cref_t *ic_cref,
const VALUE *reg_ep)
6544 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6545 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6547 return (ic_cref == NULL ||
6548 ic_cref == vm_get_cref(reg_ep));
6556 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6557 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6562rb_vm_ic_hit_p(IC ic,
const VALUE *reg_ep)
6564 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6568vm_ic_update(
const rb_iseq_t *iseq, IC ic,
VALUE val,
const VALUE *reg_ep,
const VALUE *pc)
6570 if (ruby_vm_const_missing_count > 0) {
6571 ruby_vm_const_missing_count = 0;
6578 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6582 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6586 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6587 rb_yjit_constant_ic_update(iseq, ic, pos);
6591rb_vm_opt_getconstant_path(rb_execution_context_t *ec, rb_control_frame_t *
const reg_cfp, IC ic)
6597 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6600 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
6603 ruby_vm_constant_cache_misses++;
6604 val = vm_get_ev_const_chain(ec, segments);
6605 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6608 vm_ic_update(GET_ISEQ(), ic, val, GET_EP(), GET_PC() - 2);
6614vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, ISE is)
6616 rb_thread_t *th = rb_ec_thread_ptr(ec);
6617 rb_thread_t *
const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1);
6620 if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
6621 return is->once.value;
6623 else if (is->once.running_thread == NULL) {
6625 is->once.running_thread = th;
6630 RB_OBJ_SET_SHAREABLE(val);
6636 is->once.running_thread = RUNNING_THREAD_ONCE_DONE;
6639 else if (is->once.running_thread == th) {
6641 return vm_once_exec((
VALUE)iseq);
6645 RUBY_VM_CHECK_INTS(ec);
6652vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6654 switch (OBJ_BUILTIN_TYPE(key)) {
6660 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6661 SYMBOL_REDEFINED_OP_FLAG |
6662 INTEGER_REDEFINED_OP_FLAG |
6663 FLOAT_REDEFINED_OP_FLAG |
6664 NIL_REDEFINED_OP_FLAG |
6665 TRUE_REDEFINED_OP_FLAG |
6666 FALSE_REDEFINED_OP_FLAG |
6667 STRING_REDEFINED_OP_FLAG)) {
6671 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6675 if (rb_hash_stlike_lookup(hash, key, &val)) {
6687 vm_stack_consistency_error(
const rb_execution_context_t *ec,
6688 const rb_control_frame_t *,
6691vm_stack_consistency_error(
const rb_execution_context_t *ec,
6692 const rb_control_frame_t *cfp,
6695 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6696 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6697 static const char stack_consistency_error[] =
6698 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6699#if defined RUBY_DEVEL
6700 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6705 rb_bug(stack_consistency_error, nsp, nbp);
6712 if (FIXNUM_2_P(recv, obj) &&
6713 BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
6714 return rb_fix_plus_fix(recv, obj);
6716 else if (FLONUM_2_P(recv, obj) &&
6717 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6725 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6730 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
6731 return rb_str_opt_plus(recv, obj);
6735 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
6746 if (FIXNUM_2_P(recv, obj) &&
6747 BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
6748 return rb_fix_minus_fix(recv, obj);
6750 else if (FLONUM_2_P(recv, obj) &&
6751 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6759 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6770 if (FIXNUM_2_P(recv, obj) &&
6771 BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
6772 return rb_fix_mul_fix(recv, obj);
6774 else if (FLONUM_2_P(recv, obj) &&
6775 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6783 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6794 if (FIXNUM_2_P(recv, obj) &&
6795 BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
6796 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6798 else if (FLONUM_2_P(recv, obj) &&
6799 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6800 return rb_flo_div_flo(recv, obj);
6807 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6808 return rb_flo_div_flo(recv, obj);
6818 if (FIXNUM_2_P(recv, obj) &&
6819 BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
6820 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
6822 else if (FLONUM_2_P(recv, obj) &&
6823 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6831 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6840vm_opt_neq(
const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq,
VALUE recv,
VALUE obj)
6842 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not_equal)) {
6843 VALUE val = opt_equality(iseq, recv, obj, cd_eq);
6845 if (!UNDEF_P(val)) {
6846 return RBOOL(!
RTEST(val));
6856 if (FIXNUM_2_P(recv, obj) &&
6857 BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
6860 else if (FLONUM_2_P(recv, obj) &&
6861 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6869 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6880 if (FIXNUM_2_P(recv, obj) &&
6881 BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
6884 else if (FLONUM_2_P(recv, obj) &&
6885 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6893 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6904 if (FIXNUM_2_P(recv, obj) &&
6905 BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
6908 else if (FLONUM_2_P(recv, obj) &&
6909 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6917 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6928 if (FIXNUM_2_P(recv, obj) &&
6929 BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
6932 else if (FLONUM_2_P(recv, obj) &&
6933 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6941 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6957 BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
6966 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
6984 BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
6995 if (FIXNUM_2_P(recv, obj) &&
6996 BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
7008 if (FIXNUM_2_P(recv, obj) &&
7009 BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
7010 return rb_fix_aref(recv, obj);
7015 BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG)) {
7017 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7020 return rb_ary_aref1(recv, obj);
7024 BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
7025 return rb_hash_aref(recv, obj);
7039 BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
7045 BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
7046 rb_hash_aset(recv, obj, set);
7055vm_opt_length(
VALUE recv,
int bop)
7061 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7062 if (bop == BOP_EMPTY_P) {
7063 return LONG2NUM(RSTRING_LEN(recv));
7070 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7074 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7083vm_opt_empty_p(
VALUE recv)
7085 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7095vm_opt_nil_p(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7098 BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
7101 else if (vm_method_cfunc_is(iseq, cd, recv, rb_false)) {
7117 case RSHIFT(~0UL, 1):
7120 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7138vm_opt_succ(
VALUE recv)
7141 BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
7142 return fix_succ(recv);
7148 BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
7157vm_opt_not(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7159 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not)) {
7160 return RBOOL(!
RTEST(recv));
7175 BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
7179 BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
7187rb_event_flag_t rb_iseq_event_flags(
const rb_iseq_t *iseq,
size_t pos);
7189NOINLINE(
static void vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp));
7192vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const VALUE *pc,
7194 rb_hook_list_t *global_hooks, rb_hook_list_t *local_hooks,
VALUE val)
7197 VALUE self = GET_SELF();
7199 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7201 if (local_hooks) local_hooks->running++;
7203 if (event & global_hooks->events) {
7206 vm_dtrace(event, ec);
7207 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7211 if (local_hooks) local_hooks->running--;
7212 if (local_hooks != NULL) {
7213 if (event & local_hooks->events) {
7216 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7222#define VM_TRACE_HOOK(target_event, val) do { \
7223 if ((pc_events & (target_event)) & enabled_flags) { \
7224 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7229rescue_errinfo(rb_execution_context_t *ec, rb_control_frame_t *cfp)
7231 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7232 VM_ASSERT(ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE);
7233 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7237vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
7239 const VALUE *pc = reg_cfp->pc;
7240 rb_ractor_t *r = rb_ec_ractor_ptr(ec);
7241 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7244 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7248 const rb_iseq_t *iseq = reg_cfp->iseq;
7249 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7251 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7252 rb_hook_list_t *local_hooks = NULL;
7253 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7255 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7256 local_hooks = (rb_hook_list_t*)val;
7259 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7261 rb_hook_list_t *bmethod_local_hooks = NULL;
7263 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7264 enabled_flags |= iseq_local_events;
7266 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7268 if (bmethod_frame) {
7269 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
7270 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7271 unsigned int bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7272 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7274 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7275 bmethod_local_hooks = (rb_hook_list_t*)val;
7277 if (bmethod_local_hooks) {
7278 bmethod_local_events = bmethod_local_hooks->events;
7283 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7287 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7295 else if (ec->trace_arg != NULL) {
7300 rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(ec);
7303 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7306 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %s:%d %s\n",
7309 RSTRING_PTR(rb_iseq_path(iseq)),
7310 (
int)rb_iseq_line_no(iseq, pos),
7311 RSTRING_PTR(rb_iseq_label(iseq)));
7313 VM_ASSERT(reg_cfp->pc == pc);
7314 VM_ASSERT(pc_events != 0);
7324 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7325 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7336#if VM_CHECK_MODE > 0
7337NORETURN( NOINLINE( COLDFUNC
7338void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7341Init_vm_stack_canary(
void)
7344 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7345 vm_stack_canary |= 0x01;
7347 vm_stack_canary_was_born =
true;
7352rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7356 const char *insn = rb_insns_name(i);
7360 rb_bug(
"dead canary found at %s: %s", insn, str);
7364void Init_vm_stack_canary(
void) { }
7393builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7395 typedef VALUE (*rb_invoke_funcptr0_t)(rb_execution_context_t *ec,
VALUE self);
7396 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7400builtin_invoker1(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7402 typedef VALUE (*rb_invoke_funcptr1_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1);
7403 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7407builtin_invoker2(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7409 typedef VALUE (*rb_invoke_funcptr2_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2);
7410 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7414builtin_invoker3(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7417 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7421builtin_invoker4(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7424 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7428builtin_invoker5(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7431 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7435builtin_invoker6(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7438 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7442builtin_invoker7(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7445 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7449builtin_invoker8(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7452 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7456builtin_invoker9(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7458 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);
7459 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]);
7463builtin_invoker10(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7465 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);
7466 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]);
7470builtin_invoker11(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7472 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);
7473 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]);
7477builtin_invoker12(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7479 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);
7480 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]);
7484builtin_invoker13(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7486 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);
7487 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]);
7491builtin_invoker14(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7493 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);
7494 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]);
7498builtin_invoker15(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7500 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);
7501 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]);
7504typedef VALUE (*builtin_invoker)(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
7506static builtin_invoker
7507lookup_builtin_invoker(
int argc)
7509 static const builtin_invoker invokers[] = {
7528 return invokers[argc];
7532invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7534 const bool canary_p = ISEQ_BODY(reg_cfp->iseq)->builtin_attrs & BUILTIN_ATTR_LEAF;
7535 SETUP_CANARY(canary_p);
7536 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7537 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7538 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7543vm_invoke_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7545 return invoke_bf(ec, cfp, bf, argv);
7549vm_invoke_builtin_delegate(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function *bf,
unsigned int start_index)
7552 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7553 for (
int i=0; i<bf->argc; i++) {
7554 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(cfp->iseq)->local_table[i+start_index]));
7556 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7557 (
void *)(uintptr_t)bf->func_ptr);
7560 if (bf->argc == 0) {
7561 return invoke_bf(ec, cfp, bf, NULL);
7564 const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7565 return invoke_bf(ec, cfp, bf, argv);
7572rb_vm_lvar_exposed(rb_execution_context_t *ec,
int index)
7574 const rb_control_frame_t *cfp = ec->cfp;
7575 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_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.
int rb_during_gc(void)
Queries if the GC is busy.
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.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
int rb_method_boundp(VALUE klass, ID id, int ex)
Queries if the klass has this method.
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
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 should 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 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.