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);
2073 const int pos = ccs->len++;
2074 ccs->entries[pos].argc = vm_ci_argc(ci);
2075 ccs->entries[pos].flag = (
unsigned short)vm_ci_flag(ci);
2076 ccs->entries[pos].kw_len = (
unsigned short)(kwarg ? kwarg->keyword_len : 0);
2079 if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
2085#if VM_CHECK_MODE > 0
2089 ruby_debug_printf(
"ccs:%p (%d,%d)\n", (
void *)ccs, ccs->len, ccs->capa);
2090 for (
int i=0; i<ccs->len; i++) {
2091 ruby_debug_printf(
"CCS CI ID:flag:%x argc:%u kw_len:%u\n",
2092 ccs->entries[i].flag,
2093 ccs->entries[i].argc,
2094 ccs->entries[i].kw_len);
2095 rp(ccs->entries[i].cc);
2102 VM_ASSERT(vm_ccs_p(ccs));
2103 VM_ASSERT(ccs->len <= ccs->capa);
2105 for (
int i=0; i<ccs->len; i++) {
2108 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2109 VM_ASSERT(vm_cc_class_check(cc, klass));
2110 VM_ASSERT(vm_cc_check_cme(cc, ccs->cme));
2111 VM_ASSERT(!vm_cc_super_p(cc));
2112 VM_ASSERT(!vm_cc_refinement_p(cc));
2118const rb_callable_method_entry_t *rb_check_overloaded_cme(
const rb_callable_method_entry_t *cme,
const struct rb_callinfo *
const ci);
2123 ASSERT_vm_locking();
2125 if (rb_multi_ractor_p()) {
2126 if (RCLASS_WRITABLE_CC_TBL(klass) != cc_tbl) {
2133 rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj);
2136 if (!ccs || !METHOD_ENTRY_INVALIDATED(ccs->cme)) {
2141 VALUE new_table = rb_vm_cc_table_dup(cc_tbl);
2142 rb_vm_cc_table_delete(new_table, mid);
2143 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), new_table);
2146 rb_vm_cc_table_delete(cc_tbl, mid);
2153 ASSERT_vm_locking();
2155 RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
2157 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
2159 VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
2163 VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
2164 return &vm_empty_cc;
2167 VALUE cc_tbl = RCLASS_WRITABLE_CC_TBL(klass);
2168 const VALUE original_cc_table = cc_tbl;
2171 cc_tbl = rb_vm_cc_table_create(1);
2173 else if (rb_multi_ractor_p()) {
2174 cc_tbl = rb_vm_cc_table_dup(cc_tbl);
2177 VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
2186 if (UNLIKELY(rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj))) {
2191 ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
2195 cme = rb_check_overloaded_cme(cme, ci);
2197 const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
2198 vm_ccs_push(cc_tbl, mid, ccs, ci, cc);
2200 VM_ASSERT(vm_cc_cme(cc) != NULL);
2201 VM_ASSERT(cme->called_id == mid);
2202 VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
2204 if (original_cc_table != cc_tbl) {
2205 RB_OBJ_ATOMIC_WRITE(klass, &RCLASS_WRITABLE_CC_TBL(klass), cc_tbl);
2217 cc_tbl = RUBY_ATOMIC_VALUE_LOAD(RCLASS_WRITABLE_CC_TBL(klass));
2225 if (rb_managed_id_table_lookup(cc_tbl, mid, &ccs_obj)) {
2227 const int ccs_len = ccs->len;
2229 if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
2231 vm_evict_cc(klass, cc_tbl, mid);
2236 VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
2245 unsigned int argc = vm_ci_argc(ci);
2246 unsigned int flag = vm_ci_flag(ci);
2247 unsigned int kw_len = kwarg ? kwarg->keyword_len : 0;
2249 for (
int i=0; i<ccs_len; i++) {
2250 unsigned int ccs_ci_argc = ccs->entries[i].argc;
2251 unsigned int ccs_ci_flag = ccs->entries[i].flag;
2252 unsigned int ccs_ci_kw_len = ccs->entries[i].kw_len;
2253 const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
2255 VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
2257 if (ccs_ci_argc == argc && ccs_ci_flag == flag && ccs_ci_kw_len == kw_len) {
2258 RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
2260 VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
2261 VM_ASSERT(ccs_cc->klass == klass);
2262 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
2278 const ID mid = vm_ci_mid(ci);
2280 const struct rb_callcache *cc = vm_lookup_cc(klass, ci, mid);
2286 if (rb_multi_ractor_p()) {
2289 cc = vm_lookup_cc(klass, ci, mid);
2293 cc = vm_populate_cc(klass, ci, mid);
2307 cc = vm_search_cc(klass, ci);
2310 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
2311 VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
2312 VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
2313 VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
2314 VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
2322#if USE_DEBUG_COUNTER
2326 const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
2328#if OPT_INLINE_METHOD_CACHE
2332 if (cd_owner && cc != empty_cc) {
2336#if USE_DEBUG_COUNTER
2337 if (!old_cc || old_cc == empty_cc) {
2339 RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
2341 else if (old_cc == cc) {
2342 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
2344 else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) {
2345 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
2347 else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) &&
2348 vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) {
2349 RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
2352 RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
2357 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2358 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2371#if OPT_INLINE_METHOD_CACHE
2372 if (LIKELY(vm_cc_class_check(cc, klass))) {
2373 if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) {
2374 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
2375 RB_DEBUG_COUNTER_INC(mc_inline_hit);
2376 VM_ASSERT(vm_cc_cme(cc) == NULL ||
2377 (vm_ci_flag(cd->ci) & VM_CALL_SUPER) ||
2378 vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
2382 RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
2385 RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
2389 return vm_search_method_slowpath0(cd_owner, cd, klass);
2396 VM_ASSERT(klass !=
Qfalse);
2399 const struct rb_callcache *cc = vm_search_method_fastpath(cd_owner, cd, klass);
2400 return vm_cc_cme(cc);
2406 return vm_search_method(cd_owner, cd, recv);
2409#if __has_attribute(transparent_union)
2422 VALUE (*f10)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2423 VALUE (*f11)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2424 VALUE (*f12)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2425 VALUE (*f13)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2426 VALUE (*f14)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2427 VALUE (*f15)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE);
2430# define make_cfunc_type(f) (cfunc_type){.anyargs = (VALUE (*)(ANYARGS))(f)}
2433# define make_cfunc_type(f) (cfunc_type)(f)
2437check_cfunc(
const rb_callable_method_entry_t *me, cfunc_type func)
2443 VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
2444 VM_ASSERT(callable_method_entry_p(me));
2446 if (me->def->type != VM_METHOD_TYPE_CFUNC) {
2450#if __has_attribute(transparent_union)
2451 return me->def->body.cfunc.func == func.anyargs;
2453 return me->def->body.cfunc.func == func;
2460check_method_basic_definition(
const rb_callable_method_entry_t *me)
2462 return me && METHOD_ENTRY_BASIC(me);
2466vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2468 VM_ASSERT(iseq != NULL);
2470 return check_cfunc(cme, func);
2474rb_zjit_cme_is_cfunc(
const rb_callable_method_entry_t *me,
const cfunc_type func)
2476 return check_cfunc(me, func);
2480rb_vm_method_cfunc_is(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv, cfunc_type func)
2482 return vm_method_cfunc_is(iseq, cd, recv, func);
2485#define check_cfunc(me, func) check_cfunc(me, make_cfunc_type(func))
2486#define vm_method_cfunc_is(iseq, cd, recv, func) vm_method_cfunc_is(iseq, cd, recv, make_cfunc_type(func))
2488#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
2520opt_equality_specialized(
VALUE recv,
VALUE obj)
2522 if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
2523 goto compare_by_identity;
2525 else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
2526 goto compare_by_identity;
2529 goto compare_by_identity;
2538 return RBOOL(a == b);
2545 return rb_str_eql_internal(obj, recv);
2550 compare_by_identity:
2551 return RBOOL(recv == obj);
2555opt_equality(
const rb_iseq_t *cd_owner,
VALUE recv,
VALUE obj, CALL_DATA cd)
2557 VM_ASSERT(cd_owner != NULL);
2559 VALUE val = opt_equality_specialized(recv, obj);
2560 if (!UNDEF_P(val))
return val;
2562 if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) {
2566 return RBOOL(recv == obj);
2570#undef EQ_UNREDEFINED_P
2573NOINLINE(
static VALUE opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid));
2576opt_equality_by_mid_slowpath(
VALUE recv,
VALUE obj,
ID mid)
2578 const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, &VM_CI_ON_STACK(mid, 0, 1, NULL));
2580 if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
2581 return RBOOL(recv == obj);
2591 VALUE val = opt_equality_specialized(recv, obj);
2592 if (!UNDEF_P(val)) {
2596 return opt_equality_by_mid_slowpath(recv, obj, mid);
2603 return opt_equality_by_mid(obj1, obj2, idEq);
2609 return opt_equality_by_mid(obj1, obj2, idEqlP);
2612extern VALUE rb_vm_call0(rb_execution_context_t *ec,
VALUE,
ID,
int,
const VALUE*,
const rb_callable_method_entry_t *,
int kw_splat);
2613extern VALUE rb_vm_call_with_refinements(rb_execution_context_t *,
VALUE,
ID,
int,
const VALUE *,
int);
2616check_match(rb_execution_context_t *ec,
VALUE pattern,
VALUE target,
enum vm_check_match_type
type)
2619 case VM_CHECKMATCH_TYPE_WHEN:
2621 case VM_CHECKMATCH_TYPE_RESCUE:
2623 rb_raise(
rb_eTypeError,
"class or module required for rescue clause");
2626 case VM_CHECKMATCH_TYPE_CASE: {
2627 return rb_vm_call_with_refinements(ec, pattern, idEqq, 1, &target,
RB_NO_KEYWORDS);
2630 rb_bug(
"check_match: unreachable");
2636double_cmp_lt(
double a,
double b)
2638 return RBOOL(a < b);
2642double_cmp_le(
double a,
double b)
2644 return RBOOL(a <= b);
2648double_cmp_gt(
double a,
double b)
2650 return RBOOL(a > b);
2654double_cmp_ge(
double a,
double b)
2656 return RBOOL(a >= b);
2660static inline VALUE *
2661vm_base_ptr(
const rb_control_frame_t *cfp)
2663 const rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2665 if (cfp->iseq && VM_FRAME_RUBYFRAME_P(cfp)) {
2666 VALUE *bp = prev_cfp->sp + ISEQ_BODY(cfp->iseq)->local_table_size + VM_ENV_DATA_SIZE;
2668 if (ISEQ_BODY(cfp->iseq)->param.flags.forwardable && VM_ENV_LOCAL_P(cfp->ep)) {
2669 int lts = ISEQ_BODY(cfp->iseq)->local_table_size;
2670 int params = ISEQ_BODY(cfp->iseq)->param.size;
2672 CALL_INFO ci = (CALL_INFO)cfp->ep[-(VM_ENV_DATA_SIZE + (lts - params))];
2673 bp += vm_ci_argc(ci);
2676 if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
2680#if VM_DEBUG_BP_CHECK
2681 if (bp != cfp->bp_check) {
2682 ruby_debug_printf(
"bp_check: %ld, bp: %ld\n",
2683 (
long)(cfp->bp_check - GET_EC()->vm_stack),
2684 (
long)(bp - GET_EC()->vm_stack));
2685 rb_bug(
"vm_base_ptr: unreachable");
2696rb_vm_base_ptr(
const rb_control_frame_t *cfp)
2698 return vm_base_ptr(cfp);
2705static 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);
2706ALWAYS_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));
2707static 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);
2708static VALUE vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
2709static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2710static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2711static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling);
2713static vm_call_handler vm_call_iseq_setup_func(
const struct rb_callinfo *ci,
const int param_size,
const int local_size);
2716vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2718 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_tailcall_0start);
2720 return vm_call_iseq_setup_tailcall(ec, cfp, calling, 0);
2724vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
2726 RB_DEBUG_COUNTER_INC(ccf_iseq_setup_0start);
2729 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
2730 int param = ISEQ_BODY(iseq)->param.size;
2731 int local = ISEQ_BODY(iseq)->local_table_size;
2732 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
2736rb_simple_iseq_p(
const rb_iseq_t *iseq)
2738 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2739 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2740 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2741 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2742 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2743 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2744 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2745 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2749rb_iseq_only_optparam_p(
const rb_iseq_t *iseq)
2751 return ISEQ_BODY(iseq)->param.flags.has_opt == TRUE &&
2752 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2753 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2754 ISEQ_BODY(iseq)->param.flags.has_kw == FALSE &&
2755 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2756 ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg == FALSE &&
2757 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2758 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2762rb_iseq_only_kwparam_p(
const rb_iseq_t *iseq)
2764 return ISEQ_BODY(iseq)->param.flags.has_opt == FALSE &&
2765 ISEQ_BODY(iseq)->param.flags.has_rest == FALSE &&
2766 ISEQ_BODY(iseq)->param.flags.has_post == FALSE &&
2767 ISEQ_BODY(iseq)->param.flags.has_kw == TRUE &&
2768 ISEQ_BODY(iseq)->param.flags.has_kwrest == FALSE &&
2769 ISEQ_BODY(iseq)->param.flags.forwardable == FALSE &&
2770 ISEQ_BODY(iseq)->param.flags.has_block == FALSE;
2773#define ALLOW_HEAP_ARGV (-2)
2774#define ALLOW_HEAP_ARGV_KEEP_KWSPLAT (-3)
2777vm_caller_setup_arg_splat(rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE ary,
int max_args)
2779 vm_check_canary(GET_EC(), cfp->sp);
2785 int argc = calling->argc;
2787 if (UNLIKELY(max_args <= ALLOW_HEAP_ARGV && len + argc > VM_ARGC_STACK_MAX)) {
2791 VALUE *argv = cfp->sp - argc;
2795 cfp->sp -= argc - 1;
2796 cfp->sp[-1] = argv_ary;
2798 calling->heap_argv = argv_ary;
2804 if (max_args >= 0 &&
len + argc > max_args) {
2812 calling->argc +=
len - (max_args - argc + 1);
2813 len = max_args - argc + 1;
2822 calling->heap_argv = 0;
2824 CHECK_VM_STACK_OVERFLOW(cfp,
len);
2826 for (i = 0; i <
len; i++) {
2827 *cfp->sp++ = ptr[i];
2839 const VALUE *
const passed_keywords = vm_ci_kwarg(ci)->keywords;
2840 const int kw_len = vm_ci_kwarg(ci)->keyword_len;
2841 const VALUE h = rb_hash_new_with_size(kw_len);
2842 VALUE *sp = cfp->sp;
2845 for (i=0; i<kw_len; i++) {
2846 rb_hash_aset(h, passed_keywords[i], (sp - kw_len)[i]);
2850 cfp->sp -= kw_len - 1;
2851 calling->argc -= kw_len - 1;
2852 calling->kw_splat = 1;
2856vm_caller_setup_keyword_hash(
const struct rb_callinfo *ci,
VALUE keyword_hash)
2859 if (keyword_hash !=
Qnil) {
2861 keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash));
2864 else if (!IS_ARGS_KW_SPLAT_MUT(ci) && !
RHASH_EMPTY_P(keyword_hash)) {
2870 keyword_hash = rb_hash_dup(keyword_hash);
2872 return keyword_hash;
2878 const struct rb_callinfo *restrict ci,
int max_args)
2880 if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
2881 if (IS_ARGS_KW_SPLAT(ci)) {
2883 VM_ASSERT(calling->kw_splat == 1);
2887 VALUE ary = cfp->sp[0];
2888 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[1]);
2891 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args))
return;
2895 if (UNLIKELY(calling->heap_argv)) {
2897 ((
struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
2898 if (max_args != ALLOW_HEAP_ARGV_KEEP_KWSPLAT) {
2899 calling->kw_splat = 0;
2907 VM_ASSERT(calling->kw_splat == 1);
2911 calling->kw_splat = 0;
2916 VM_ASSERT(calling->kw_splat == 0);
2920 VALUE ary = cfp->sp[0];
2922 if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) {
2927 VALUE last_hash, argv_ary;
2928 if (UNLIKELY(argv_ary = calling->heap_argv)) {
2929 if (!IS_ARGS_KEYWORD(ci) &&
2932 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2937 calling->kw_splat = 1;
2943 if (!IS_ARGS_KEYWORD(ci) &&
2944 calling->argc > 0 &&
2946 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
2953 cfp->sp[-1] = rb_hash_dup(last_hash);
2954 calling->kw_splat = 1;
2960 else if (UNLIKELY(IS_ARGS_KW_SPLAT(ci))) {
2962 VM_ASSERT(calling->kw_splat == 1);
2963 VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]);
2968 calling->kw_splat = 0;
2974 else if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
2976 VM_ASSERT(calling->kw_splat == 0);
2982 vm_caller_setup_arg_kw(cfp, calling, ci);
2986#define USE_OPT_HIST 0
2989#define OPT_HIST_MAX 64
2990static int opt_hist[OPT_HIST_MAX+1];
2994opt_hist_show_results_at_exit(
void)
2996 for (
int i=0; i<OPT_HIST_MAX; i++) {
2997 ruby_debug_printf(
"opt_hist\t%d\t%d\n", i, opt_hist[i]);
3003vm_call_iseq_setup_normal_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3007 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3008 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3009 const int opt = calling->argc - lead_num;
3010 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3011 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3012 const int param = ISEQ_BODY(iseq)->param.size;
3013 const int local = ISEQ_BODY(iseq)->local_table_size;
3014 const int delta = opt_num - opt;
3016 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3019 if (opt_pc < OPT_HIST_MAX) {
3023 opt_hist[OPT_HIST_MAX]++;
3027 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param - delta, local);
3031vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3035 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3036 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3037 const int opt = calling->argc - lead_num;
3038 const int opt_pc = (int)ISEQ_BODY(iseq)->param.opt_table[opt];
3040 RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
3043 if (opt_pc < OPT_HIST_MAX) {
3047 opt_hist[OPT_HIST_MAX]++;
3051 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3055args_setup_kw_parameters(rb_execution_context_t *
const ec,
const rb_iseq_t *
const iseq,
const rb_callable_method_entry_t *cme,
3056 VALUE *
const passed_values,
const int passed_keyword_len,
const VALUE *
const passed_keywords,
3057 VALUE *
const locals);
3060vm_call_iseq_forwardable(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3064 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3065 int param_size = ISEQ_BODY(iseq)->param.size;
3066 int local_size = ISEQ_BODY(iseq)->local_table_size;
3069 VM_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3071 local_size = local_size + vm_ci_argc(calling->cd->ci);
3072 param_size = param_size + vm_ci_argc(calling->cd->ci);
3074 cfp->sp[0] = (
VALUE)calling->cd->ci;
3076 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param_size, local_size);
3080vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3086 VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
3087 RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
3089 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3090 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3092 const int ci_kw_len = kw_arg->keyword_len;
3093 const VALUE *
const ci_keywords = kw_arg->keywords;
3094 VALUE *argv = cfp->sp - calling->argc;
3095 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3096 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3098 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3099 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3101 int param = ISEQ_BODY(iseq)->param.size;
3102 int local = ISEQ_BODY(iseq)->local_table_size;
3103 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3107vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3110 const struct rb_callinfo *MAYBE_UNUSED(ci) = calling->cd->ci;
3113 VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
3114 RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
3116 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3117 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3118 VALUE *
const argv = cfp->sp - calling->argc;
3119 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3122 for (i=0; i<kw_param->num; i++) {
3123 klocals[i] = kw_param->default_values[i];
3130 int param = ISEQ_BODY(iseq)->param.size;
3131 int local = ISEQ_BODY(iseq)->local_table_size;
3132 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), 0, param, local);
3135static VALUE builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
3138vm_call_single_noarg_leaf_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
3142 cfp->sp -= (calling->argc + 1);
3143 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
3144 return builtin_invoker0(ec, calling->recv, NULL, func_ptr);
3150warn_unused_block(
const rb_callable_method_entry_t *cme,
const rb_iseq_t *iseq,
void *pc)
3152 rb_vm_t *vm = GET_VM();
3153 set_table *dup_check_table = vm->unused_block_warning_table;
3163 .v = (
VALUE)cme->def,
3167 if (!strict_unused_block) {
3168 key = (st_data_t)cme->def->original_id;
3170 if (set_table_lookup(dup_check_table, key)) {
3180 key |= (st_data_t)(k1.b[i] ^ k2.b[
SIZEOF_VALUE-1-i]) << (8 * i);
3185 fprintf(stderr,
"pc:%p def:%p\n", pc, (
void *)cme->def);
3186 fprintf(stderr,
"key:%p\n", (
void *)key);
3190 if (set_insert(dup_check_table, key)) {
3194 VALUE m_loc = rb_method_entry_location((
const rb_method_entry_t *)cme);
3195 VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label);
3197 if (!
NIL_P(m_loc)) {
3198 rb_warn(
"the block passed to '%"PRIsVALUE
"' defined at %"PRIsVALUE
":%"PRIsVALUE
" may be ignored",
3202 rb_warn(
"the block may be ignored because '%"PRIsVALUE
"' does not use a block", name);
3208vm_callee_setup_arg(rb_execution_context_t *ec,
struct rb_calling_info *calling,
3209 const rb_iseq_t *iseq,
VALUE *argv,
int param_size,
int local_size)
3214 VM_ASSERT((vm_ci_argc(ci), 1));
3215 VM_ASSERT(vm_cc_cme(cc) != NULL);
3217 if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
3218 calling->block_handler != VM_BLOCK_HANDLER_NONE &&
3219 !(vm_ci_flag(calling->cd->ci) & (VM_CALL_OPT_SEND | VM_CALL_SUPER)))) {
3220 warn_unused_block(vm_cc_cme(cc), iseq, (
void *)ec->cfp->pc);
3223 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
3224 if (LIKELY(rb_simple_iseq_p(iseq))) {
3225 rb_control_frame_t *cfp = ec->cfp;
3226 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3227 CALLER_SETUP_ARG(cfp, calling, ci, lead_num);
3229 if (calling->argc != lead_num) {
3230 argument_arity_error(ec, iseq, vm_cc_cme(cc), calling->argc, lead_num, lead_num);
3234 VM_ASSERT(cc == calling->cc);
3236 if (vm_call_iseq_optimizable_p(ci, cc)) {
3237 if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && ruby_vm_c_events_enabled == 0) {
3238 VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF);
3239 vm_cc_bf_set(cc, (
void *)iseq->body->iseq_encoded[1]);
3240 CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin,
true);
3243 CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
true);
3248 else if (rb_iseq_only_optparam_p(iseq)) {
3249 rb_control_frame_t *cfp = ec->cfp;
3251 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3252 const int opt_num = ISEQ_BODY(iseq)->param.opt_num;
3254 CALLER_SETUP_ARG(cfp, calling, ci, lead_num + opt_num);
3255 const int argc = calling->argc;
3256 const int opt = argc - lead_num;
3258 if (opt < 0 || opt > opt_num) {
3259 argument_arity_error(ec, iseq, vm_cc_cme(cc), argc, lead_num, lead_num + opt_num);
3262 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3263 CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
3264 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3265 vm_call_cacheable(ci, cc));
3268 CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
3269 !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
3270 vm_call_cacheable(ci, cc));
3274 VM_ASSERT((
int)ISEQ_BODY(iseq)->param.size == lead_num + opt_num);
3275 for (
int i=argc; i<lead_num + opt_num; i++) {
3278 return (
int)ISEQ_BODY(iseq)->param.opt_table[opt];
3280 else if (rb_iseq_only_kwparam_p(iseq) && !IS_ARGS_SPLAT(ci)) {
3281 const int lead_num = ISEQ_BODY(iseq)->param.lead_num;
3282 const int argc = calling->argc;
3283 const struct rb_iseq_param_keyword *kw_param = ISEQ_BODY(iseq)->param.keyword;
3285 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
3288 if (argc - kw_arg->keyword_len == lead_num) {
3289 const int ci_kw_len = kw_arg->keyword_len;
3290 const VALUE *
const ci_keywords = kw_arg->keywords;
3292 MEMCPY(ci_kws, argv + lead_num,
VALUE, ci_kw_len);
3294 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3295 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), ci_kws, ci_kw_len, ci_keywords, klocals);
3297 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg,
3298 vm_call_cacheable(ci, cc));
3303 else if (argc == lead_num) {
3305 VALUE *
const klocals = argv + kw_param->bits_start - kw_param->num;
3306 args_setup_kw_parameters(ec, iseq, vm_cc_cme(cc), NULL, 0, NULL, klocals);
3308 if (klocals[kw_param->num] ==
INT2FIX(0)) {
3310 CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg,
3311 vm_call_cacheable(ci, cc));
3337 if (ISEQ_BODY(iseq)->param.flags.forwardable) {
3338 bool can_fastpath =
true;
3340 if ((vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
3342 if (vm_ci_argc(ci) != vm_ci_argc(forward_cd->caller_ci)) {
3343 ci = vm_ci_new_runtime(
3350 ci = forward_cd->caller_ci;
3352 can_fastpath =
false;
3356 if (!vm_ci_markable(ci)) {
3357 ci = vm_ci_new_runtime(
3362 can_fastpath =
false;
3364 argv[param_size - 1] = (
VALUE)ci;
3365 CC_SET_FASTPATH(cc, vm_call_iseq_forwardable, can_fastpath);
3369 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_method);
3396 const VALUE * lep = VM_CF_LEP(cfp);
3398 const rb_iseq_t *iseq;
3402 if (VM_ENV_FLAGS(lep, VM_ENV_FLAG_ESCAPED)) {
3407 iseq = rb_vm_search_cf_from_ep(ec, cfp, lep)->iseq;
3411 int local_size = ISEQ_BODY(iseq)->local_table_size + argc;
3413 const VALUE * from = lep - (local_size + VM_ENV_DATA_SIZE - 1);
3414 VALUE * to = cfp->sp - 1;
3418 CHECK_VM_STACK_OVERFLOW0(cfp, to,
RARRAY_LEN(splat));
3423 CHECK_VM_STACK_OVERFLOW0(cfp, to, argc);
3425 cfp->sp = to + argc;
3442vm_call_iseq_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3444 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3447 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3448 int param_size = ISEQ_BODY(iseq)->param.size;
3449 int local_size = ISEQ_BODY(iseq)->local_table_size;
3451 RUBY_ASSERT(!ISEQ_BODY(iseq)->param.flags.forwardable);
3453 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3454 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3458vm_call_iseq_fwd_setup(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
3460 RB_DEBUG_COUNTER_INC(ccf_iseq_setup);
3463 const rb_iseq_t *iseq = def_iseq_ptr(vm_cc_cme(cc)->def);
3464 int param_size = ISEQ_BODY(iseq)->param.size;
3465 int local_size = ISEQ_BODY(iseq)->local_table_size;
3467 RUBY_ASSERT(ISEQ_BODY(iseq)->param.flags.forwardable);
3470 local_size = local_size + vm_ci_argc(calling->cd->ci);
3471 param_size = param_size + vm_ci_argc(calling->cd->ci);
3473 const int opt_pc = vm_callee_setup_arg(ec, calling, iseq, cfp->sp - calling->argc, param_size, local_size);
3474 return vm_call_iseq_setup_2(ec, cfp, calling, opt_pc, param_size, local_size);
3478vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
3479 int opt_pc,
int param_size,
int local_size)
3484 if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
3485 return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(cc), opt_pc, param_size, local_size);
3488 return vm_call_iseq_setup_tailcall(ec, cfp, calling, opt_pc);
3493vm_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,
3494 int opt_pc,
int param_size,
int local_size)
3496 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3497 VALUE *argv = cfp->sp - calling->argc;
3498 VALUE *sp = argv + param_size;
3499 cfp->sp = argv - 1 ;
3501 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL, calling->recv,
3502 calling->block_handler, (
VALUE)me,
3503 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3504 local_size - param_size,
3505 ISEQ_BODY(iseq)->stack_max);
3510vm_call_iseq_setup_tailcall(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
int opt_pc)
3514 VALUE *argv = cfp->sp - calling->argc;
3515 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3516 const rb_iseq_t *iseq = def_iseq_ptr(me->def);
3517 VALUE *src_argv = argv;
3518 VALUE *sp_orig, *sp;
3519 VALUE finish_flag = VM_FRAME_FINISHED_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
3521 if (VM_BH_FROM_CFP_P(calling->block_handler, cfp)) {
3522 struct rb_captured_block *dst_captured = VM_CFP_TO_CAPTURED_BLOCK(RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
3523 const struct rb_captured_block *src_captured = VM_BH_TO_CAPT_BLOCK(calling->block_handler);
3524 dst_captured->code.val = src_captured->code.val;
3525 if (VM_BH_ISEQ_BLOCK_P(calling->block_handler)) {
3526 calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(dst_captured);
3529 calling->block_handler = VM_BH_FROM_IFUNC_BLOCK(dst_captured);
3533 vm_pop_frame(ec, cfp, cfp->ep);
3536 sp_orig = sp = cfp->sp;
3539 sp[0] = calling->recv;
3543 for (i=0; i < ISEQ_BODY(iseq)->param.size; i++) {
3544 *sp++ = src_argv[i];
3547 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL | finish_flag,
3548 calling->recv, calling->block_handler, (
VALUE)me,
3549 ISEQ_BODY(iseq)->iseq_encoded + opt_pc, sp,
3550 ISEQ_BODY(iseq)->local_table_size - ISEQ_BODY(iseq)->param.size,
3551 ISEQ_BODY(iseq)->stack_max);
3559ractor_unsafe_check(
void)
3561 if (!rb_ractor_main_p()) {
3562 rb_raise(rb_eRactorUnsafeError,
"ractor unsafe method called from not main ractor");
3569 ractor_unsafe_check();
3577 ractor_unsafe_check();
3579 return (*f)(argc, argv, recv);
3585 ractor_unsafe_check();
3593 ractor_unsafe_check();
3595 return (*f)(recv, argv[0]);
3601 ractor_unsafe_check();
3603 return (*f)(recv, argv[0], argv[1]);
3609 ractor_unsafe_check();
3611 return (*f)(recv, argv[0], argv[1], argv[2]);
3617 ractor_unsafe_check();
3619 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3625 ractor_unsafe_check();
3626 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3627 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3633 ractor_unsafe_check();
3634 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3635 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3641 ractor_unsafe_check();
3642 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3643 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3649 ractor_unsafe_check();
3650 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3651 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3657 ractor_unsafe_check();
3658 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3659 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3665 ractor_unsafe_check();
3666 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;
3667 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3673 ractor_unsafe_check();
3674 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;
3675 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]);
3681 ractor_unsafe_check();
3682 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3683 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
3689 ractor_unsafe_check();
3690 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;
3691 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]);
3697 ractor_unsafe_check();
3698 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;
3699 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]);
3705 ractor_unsafe_check();
3706 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;
3707 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]);
3721 return (*f)(argc, argv, recv);
3735 return (*f)(recv, argv[0]);
3742 return (*f)(recv, argv[0], argv[1]);
3749 return (*f)(recv, argv[0], argv[1], argv[2]);
3756 return (*f)(recv, argv[0], argv[1], argv[2], argv[3]);
3762 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3763 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
3769 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3770 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
3776 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3777 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
3783 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3784 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
3790 VALUE(*f)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE) = (
VALUE(*)(
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE,
VALUE))func;
3791 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
3797 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;
3798 return (*f)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
3804 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;
3805 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]);
3811 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;
3812 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]);
3818 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;
3819 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]);
3825 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;
3826 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]);
3832 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;
3833 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]);
3837vm_cfp_consistent_p(rb_execution_context_t *ec,
const rb_control_frame_t *reg_cfp)
3839 const int ov_flags = RAISED_STACKOVERFLOW;
3840 if (LIKELY(reg_cfp == ec->cfp + 1))
return TRUE;
3841 if (rb_ec_raised_p(ec, ov_flags)) {
3842 rb_ec_raised_reset(ec, ov_flags);
3848#define CHECK_CFP_CONSISTENCY(func) \
3849 (LIKELY(vm_cfp_consistent_p(ec, reg_cfp)) ? (void)0 : \
3850 rb_bug(func ": cfp consistency error (%p, %p)", (void *)reg_cfp, (void *)(ec->cfp+1)))
3853const rb_method_cfunc_t *
3854vm_method_cfunc_entry(
const rb_callable_method_entry_t *me)
3856#if VM_DEBUG_VERIFY_METHOD_CACHE
3857 switch (me->def->type) {
3858 case VM_METHOD_TYPE_CFUNC:
3859 case VM_METHOD_TYPE_NOTIMPLEMENTED:
3861# define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
3863 METHOD_BUG(ATTRSET);
3865 METHOD_BUG(BMETHOD);
3868 METHOD_BUG(OPTIMIZED);
3869 METHOD_BUG(MISSING);
3870 METHOD_BUG(REFINED);
3874 rb_bug(
"wrong method type: %d", me->def->type);
3877 return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
3881vm_call_cfunc_with_frame_(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
3884 RB_DEBUG_COUNTER_INC(ccf_cfunc_with_frame);
3888 const rb_callable_method_entry_t *me = vm_cc_cme(cc);
3889 const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me);
3891 VALUE recv = calling->recv;
3892 VALUE block_handler = calling->block_handler;
3893 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3895 if (UNLIKELY(calling->kw_splat)) {
3896 frame_type |= VM_FRAME_FLAG_CFRAME_KW;
3899 VM_ASSERT(reg_cfp == ec->cfp);
3901 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
3904 vm_push_frame(ec, NULL, frame_type, recv,
3905 block_handler, (
VALUE)me,
3906 0, ec->cfp->sp, 0, 0);
3908 int len = cfunc->argc;
3911 reg_cfp->sp = stack_bottom;
3912 val = (*cfunc->invoker)(recv, argc, argv, cfunc->func);
3914 CHECK_CFP_CONSISTENCY(
"vm_call_cfunc");
3916 rb_vm_pop_frame(ec);
3918 VM_ASSERT(ec->cfp->sp == stack_bottom);
3920 EXEC_EVENT_HOOK(ec,
RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
3921 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
3929rb_vm_push_cfunc_frame(
const rb_callable_method_entry_t *cme,
int recv_idx)
3931 VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC);
3932 rb_execution_context_t *ec = GET_EC();
3933 VALUE *sp = ec->cfp->sp;
3934 VALUE recv = *(sp - recv_idx - 1);
3935 VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
3936 VALUE block_handler = VM_BLOCK_HANDLER_NONE;
3937#if VM_CHECK_MODE > 0
3939 *(GET_EC()->cfp->sp) =
Qfalse;
3941 vm_push_frame(ec, NULL, frame_type, recv, block_handler, (
VALUE)cme, 0, ec->cfp->sp, 0, 0);
3946rb_splat_or_kwargs_p(
const struct rb_callinfo *restrict ci)
3948 return IS_ARGS_SPLAT(ci) || IS_ARGS_KW_OR_KW_SPLAT(ci);
3952vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3954 int argc = calling->argc;
3955 VALUE *stack_bottom = reg_cfp->sp - argc - 1;
3956 VALUE *argv = &stack_bottom[1];
3958 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3962vm_call_cfunc_other(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
3965 RB_DEBUG_COUNTER_INC(ccf_cfunc_other);
3967 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
3969 if (UNLIKELY(argv_ary = calling->heap_argv)) {
3970 VM_ASSERT(!IS_ARGS_KEYWORD(ci));
3973 VALUE *stack_bottom = reg_cfp->sp - 2;
3975 VM_ASSERT(calling->argc == 1);
3979 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, argv, stack_bottom);
3982 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));
3984 return vm_call_cfunc_with_frame(ec, reg_cfp, calling);
3989vm_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)
3991 VALUE argv_ary = reg_cfp->sp[-1 - stack_offset];
3994 if (UNLIKELY(argc > VM_ARGC_STACK_MAX)) {
3995 return vm_call_cfunc_other(ec, reg_cfp, calling);
3999 calling->kw_splat = 0;
4001 VALUE *stack_bottom = reg_cfp->sp - 2 - stack_offset;
4002 VALUE *sp = stack_bottom;
4003 CHECK_VM_STACK_OVERFLOW(reg_cfp, argc);
4004 for(i = 0; i < argc; i++) {
4009 return vm_call_cfunc_with_frame_(ec, reg_cfp, calling, argc, stack_bottom+1, stack_bottom);
4013vm_call_cfunc_only_splat(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4015 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat);
4016 VALUE argv_ary = reg_cfp->sp[-1];
4020 int argc_offset = 0;
4022 if (UNLIKELY(argc > 0 &&
4024 (((
struct RHash *)last_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS))) {
4026 return vm_call_cfunc_other(ec, reg_cfp, calling);
4030 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 0, argc_offset);
4034vm_call_cfunc_only_splat_kw(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4036 RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw);
4037 VALUE keyword_hash = reg_cfp->sp[-1];
4040 return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0);
4043 return vm_call_cfunc_other(ec, reg_cfp, calling);
4047vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4050 RB_DEBUG_COUNTER_INC(ccf_cfunc);
4052 if (IS_ARGS_SPLAT(ci) && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4053 if (!IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 1) {
4055 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat, TRUE);
4056 return vm_call_cfunc_only_splat(ec, reg_cfp, calling);
4058 if (IS_ARGS_KW_SPLAT(ci) && vm_ci_argc(ci) == 2) {
4060 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_only_splat_kw, TRUE);
4061 return vm_call_cfunc_only_splat_kw(ec, reg_cfp, calling);
4065 CC_SET_FASTPATH(calling->cc, vm_call_cfunc_other, TRUE);
4066 return vm_call_cfunc_other(ec, reg_cfp, calling);
4070vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4073 RB_DEBUG_COUNTER_INC(ccf_ivar);
4075 VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE,
Qnil);
4080vm_call_attrset_direct(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_callcache *cc,
VALUE obj)
4082 RB_DEBUG_COUNTER_INC(ccf_attrset);
4083 VALUE val = *(cfp->sp - 1);
4086 shape_id_t dest_shape_id;
4087 vm_cc_atomic_shape_and_index(cc, &dest_shape_id, &index);
4088 ID id = vm_cc_cme(cc)->def->body.attr.id;
4089 rb_check_frozen(obj);
4090 VALUE res = vm_setivar(obj,
id, val, dest_shape_id, index);
4098 res = vm_setivar_class(obj,
id, val, dest_shape_id, index);
4099 if (!UNDEF_P(res)) {
4106 res = vm_setivar_default(obj,
id, val, dest_shape_id, index);
4107 if (!UNDEF_P(res)) {
4112 res = vm_setivar_slowpath_attr(obj,
id, val, cc);
4118vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4120 return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
4124vm_call_bmethod_body(rb_execution_context_t *ec,
struct rb_calling_info *calling,
const VALUE *argv)
4129 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4130 VALUE procv = cme->def->body.bmethod.proc;
4133 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4134 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4138 GetProcPtr(procv, proc);
4139 val = vm_invoke_bmethod(ec, proc, calling->recv, CALLING_ARGC(calling), argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc));
4144static 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);
4147vm_call_iseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4149 RB_DEBUG_COUNTER_INC(ccf_iseq_bmethod);
4152 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4153 VALUE procv = cme->def->body.bmethod.proc;
4156 cme->def->body.bmethod.defined_ractor_id != rb_ec_ractor_id(ec)) {
4157 rb_raise(
rb_eRuntimeError,
"defined with an un-shareable Proc in a different Ractor");
4161 GetProcPtr(procv, proc);
4162 const struct rb_block *block = &proc->block;
4164 while (vm_block_type(block) == block_type_proc) {
4165 block = vm_proc_block(block->as.proc);
4167 VM_ASSERT(vm_block_type(block) == block_type_iseq);
4170 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
4171 VALUE *
const argv = cfp->sp - calling->argc;
4172 const int arg_size = ISEQ_BODY(iseq)->param.size;
4175 if (vm_ci_flag(calling->cd->ci) & VM_CALL_ARGS_SIMPLE) {
4176 opt_pc = vm_callee_setup_block_arg(ec, calling, calling->cd->ci, iseq, argv, arg_setup_method);
4179 opt_pc = setup_parameters_complex(ec, iseq, calling, calling->cd->ci, argv, arg_setup_method);
4184 vm_push_frame(ec, iseq,
4185 VM_FRAME_MAGIC_BLOCK | VM_FRAME_FLAG_BMETHOD | VM_FRAME_FLAG_LAMBDA,
4187 VM_GUARDED_PREV_EP(captured->ep),
4189 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
4191 ISEQ_BODY(iseq)->local_table_size - arg_size,
4192 ISEQ_BODY(iseq)->stack_max);
4198vm_call_noniseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4200 RB_DEBUG_COUNTER_INC(ccf_noniseq_bmethod);
4204 CALLER_SETUP_ARG(cfp, calling, calling->cd->ci, ALLOW_HEAP_ARGV);
4205 if (UNLIKELY(calling->heap_argv)) {
4210 argc = calling->argc;
4213 cfp->sp += - argc - 1;
4216 return vm_call_bmethod_body(ec, calling, argv);
4220vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4222 RB_DEBUG_COUNTER_INC(ccf_bmethod);
4225 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4226 VALUE procv = cme->def->body.bmethod.proc;
4228 GetProcPtr(procv, proc);
4229 const struct rb_block *block = &proc->block;
4231 while (vm_block_type(block) == block_type_proc) {
4232 block = vm_proc_block(block->as.proc);
4234 if (vm_block_type(block) == block_type_iseq) {
4235 CC_SET_FASTPATH(cc, vm_call_iseq_bmethod, TRUE);
4236 return vm_call_iseq_bmethod(ec, cfp, calling);
4239 CC_SET_FASTPATH(cc, vm_call_noniseq_bmethod, TRUE);
4240 return vm_call_noniseq_bmethod(ec, cfp, calling);
4244rb_find_defined_class_by_owner(
VALUE current_class,
VALUE target_owner)
4246 VALUE klass = current_class;
4254 while (
RTEST(klass)) {
4256 if (owner == target_owner) {
4262 return current_class;
4265static const rb_callable_method_entry_t *
4266aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4268 const rb_method_entry_t *orig_me = me->def->body.alias.original_me;
4269 const rb_callable_method_entry_t *cme;
4271 if (orig_me->defined_class == 0) {
4272 VALUE defined_class = rb_find_defined_class_by_owner(me->defined_class, orig_me->owner);
4273 VM_ASSERT_TYPE(orig_me->owner,
T_MODULE);
4274 cme = rb_method_entry_complement_defined_class(orig_me, me->called_id, defined_class);
4276 if (me->def->reference_count == 1) {
4277 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
4280 rb_method_definition_t *def =
4281 rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id);
4282 rb_method_definition_set((rb_method_entry_t *)me, def, (
void *)cme);
4286 cme = (
const rb_callable_method_entry_t *)orig_me;
4289 VM_ASSERT(callable_method_entry_p(cme));
4293const rb_callable_method_entry_t *
4294rb_aliased_callable_method_entry(
const rb_callable_method_entry_t *me)
4296 return aliased_callable_method_entry(me);
4300vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4302 calling->cc = &VM_CC_ON_STACK(
Qundef,
4305 aliased_callable_method_entry(vm_cc_cme(calling->cc)));
4307 return vm_call_method_each_type(ec, cfp, calling);
4310static enum method_missing_reason
4313 enum method_missing_reason stat = MISSING_NOENTRY;
4314 if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
4315 if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
4316 if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
4320static VALUE vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling);
4323vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4326 ASSUME(calling->argc >= 0);
4328 enum method_missing_reason missing_reason = MISSING_NOENTRY;
4329 int argc = calling->argc;
4330 VALUE recv = calling->recv;
4333 flags |= VM_CALL_OPT_SEND;
4335 if (UNLIKELY(! mid)) {
4336 mid = idMethodMissing;
4337 missing_reason = ci_missing_reason(ci);
4338 ec->method_missing_reason = missing_reason;
4341 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4342 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4343 rb_ary_unshift(argv_ary, symbol);
4346 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4347 VALUE exc = rb_make_no_method_exception(
4369 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4372 argc = ++calling->argc;
4374 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
4377 int priv = vm_ci_flag(ci) & (VM_CALL_FCALL | VM_CALL_VCALL);
4378 const VALUE *argv = STACK_ADDR_FROM_TOP(argc);
4379 VALUE exc = rb_make_no_method_exception(
4392 .ci = &VM_CI_ON_STACK(mid, flags, argc, vm_ci_kwarg(ci)),
4398 if (!(vm_ci_flag(ci) & VM_CALL_FORWARDING)) {
4399 calling->cd = &new_fcd.cd;
4403 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4404 new_fcd.caller_ci = caller_ci;
4407 calling->cc = &VM_CC_ON_STACK(klass,
4409 { .method_missing_reason = missing_reason },
4410 rb_callable_method_entry_with_refinements(klass, mid, NULL));
4412 if (flags & VM_CALL_FCALL) {
4413 return vm_call_method(ec, reg_cfp, calling);
4417 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
4419 if (vm_cc_cme(cc) != NULL) {
4420 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
4421 case METHOD_VISI_PUBLIC:
4422 return vm_call_method_each_type(ec, reg_cfp, calling);
4423 case METHOD_VISI_PRIVATE:
4424 vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
4426 case METHOD_VISI_PROTECTED:
4427 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
4430 VM_UNREACHABLE(vm_call_method);
4432 return vm_call_method_missing(ec, reg_cfp, calling);
4435 return vm_call_method_nome(ec, reg_cfp, calling);
4439vm_call_opt_send0(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
int flags)
4445 i = calling->argc - 1;
4447 if (calling->argc == 0) {
4448 rb_raise(rb_eArgError,
"no method name given");
4472 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4476vm_call_opt_send_complex(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4478 RB_DEBUG_COUNTER_INC(ccf_opt_send_complex);
4480 int flags = VM_CALL_FCALL;
4484 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
4485 if (UNLIKELY(argv_ary = calling->heap_argv)) {
4487 flags |= VM_CALL_ARGS_SPLAT;
4488 if (calling->kw_splat) {
4489 VALUE last_hash = rb_ary_last(0, NULL, argv_ary);
4490 ((
struct RHash *)last_hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
4491 calling->kw_splat = 0;
4493 return vm_call_symbol(ec, reg_cfp, calling, ci, sym, flags);
4496 if (calling->kw_splat) flags |= VM_CALL_KW_SPLAT;
4497 return vm_call_opt_send0(ec, reg_cfp, calling, flags);
4501vm_call_opt_send_simple(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4503 RB_DEBUG_COUNTER_INC(ccf_opt_send_simple);
4504 return vm_call_opt_send0(ec, reg_cfp, calling, vm_ci_flag(calling->cd->ci) | VM_CALL_FCALL);
4508vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4510 RB_DEBUG_COUNTER_INC(ccf_opt_send);
4513 int flags = vm_ci_flag(ci);
4515 if (UNLIKELY((flags & VM_CALL_FORWARDING) || (!(flags & VM_CALL_ARGS_SIMPLE) &&
4516 ((calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
4517 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
4518 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc)))))) {
4519 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_complex, TRUE);
4520 return vm_call_opt_send_complex(ec, reg_cfp, calling);
4523 CC_SET_FASTPATH(calling->cc, vm_call_opt_send_simple, TRUE);
4524 return vm_call_opt_send_simple(ec, reg_cfp, calling);
4528vm_call_method_missing_body(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling,
4529 const struct rb_callinfo *orig_ci,
enum method_missing_reason reason)
4531 RB_DEBUG_COUNTER_INC(ccf_method_missing);
4533 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4534 unsigned int argc, flag;
4536 flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | vm_ci_flag(orig_ci);
4537 argc = ++calling->argc;
4540 CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
4541 vm_check_canary(ec, reg_cfp->sp);
4545 argv[0] =
ID2SYM(vm_ci_mid(orig_ci));
4548 ec->method_missing_reason = reason;
4552 .ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci)),
4558 if (!(flag & VM_CALL_FORWARDING)) {
4559 calling->cd = &new_fcd.cd;
4563 VM_ASSERT((vm_ci_argc(caller_ci), 1));
4564 new_fcd.caller_ci = caller_ci;
4568 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }},
4569 rb_callable_method_entry_without_refinements(
CLASS_OF(calling->recv), idMethodMissing, NULL));
4570 return vm_call_method(ec, reg_cfp, calling);
4574vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4576 return vm_call_method_missing_body(ec, reg_cfp, calling, calling->cd->ci, vm_cc_cmethod_missing_reason(calling->cc));
4579static const rb_callable_method_entry_t *refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me);
4581vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
VALUE klass)
4585 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, vm_ci_mid(calling->cd->ci)) : NULL;
4587 return vm_call_method_nome(ec, cfp, calling);
4589 if (cme->def->type == VM_METHOD_TYPE_REFINED &&
4590 cme->def->body.refined.orig_me) {
4591 cme = refined_method_callable_without_refinement(cme);
4594 calling->cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, cme);
4596 return vm_call_method_each_type(ec, cfp, calling);
4600find_refinement(
VALUE refinements,
VALUE klass)
4602 if (
NIL_P(refinements)) {
4605 return rb_hash_lookup(refinements, klass);
4608PUREFUNC(
static rb_control_frame_t * current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp));
4609static rb_control_frame_t *
4610current_method_entry(
const rb_execution_context_t *ec, rb_control_frame_t *cfp)
4612 rb_control_frame_t *top_cfp = cfp;
4614 if (cfp->iseq && ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_BLOCK) {
4615 const rb_iseq_t *local_iseq = ISEQ_BODY(cfp->iseq)->local_iseq;
4618 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
4619 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
4623 }
while (cfp->iseq != local_iseq);
4628static const rb_callable_method_entry_t *
4629refined_method_callable_without_refinement(
const rb_callable_method_entry_t *me)
4631 const rb_method_entry_t *orig_me = me->def->body.refined.orig_me;
4632 const rb_callable_method_entry_t *cme;
4634 if (orig_me->defined_class == 0) {
4639 cme = (
const rb_callable_method_entry_t *)orig_me;
4642 VM_ASSERT(callable_method_entry_p(cme));
4644 if (UNDEFINED_METHOD_ENTRY_P(cme)) {
4651static const rb_callable_method_entry_t *
4652search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4654 ID mid = vm_ci_mid(calling->cd->ci);
4655 const rb_cref_t *cref = vm_get_cref(cfp->ep);
4657 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4659 for (; cref; cref = CREF_NEXT(cref)) {
4660 const VALUE refinement = find_refinement(CREF_REFINEMENTS(cref), vm_cc_cme(cc)->owner);
4661 if (
NIL_P(refinement))
continue;
4663 const rb_callable_method_entry_t *
const ref_me =
4664 rb_callable_method_entry(refinement, mid);
4667 if (vm_cc_call(cc) == vm_call_super_method) {
4668 const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp);
4669 const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp);
4670 if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
4675 if (cme->def->type != VM_METHOD_TYPE_REFINED ||
4676 cme->def != ref_me->def) {
4679 if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
4688 if (vm_cc_cme(cc)->def->body.refined.orig_me) {
4689 return refined_method_callable_without_refinement(vm_cc_cme(cc));
4693 const rb_callable_method_entry_t *cme = klass ? rb_callable_method_entry(klass, mid) : NULL;
4699vm_call_refined(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4701 const rb_callable_method_entry_t *ref_cme = search_refined_method(ec, cfp, calling);
4704 if (calling->cd->cc) {
4705 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);
4707 return vm_call_method(ec, cfp, calling);
4710 struct rb_callcache *ref_cc = &VM_CC_ON_STACK(
Qundef, vm_call_general, {{ 0 }}, ref_cme);
4711 calling->cc= ref_cc;
4712 return vm_call_method(ec, cfp, calling);
4716 return vm_call_method_nome(ec, cfp, calling);
4720static 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);
4722NOINLINE(
static VALUE
4723 vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4727vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
4730 int argc = calling->argc;
4733 if (argc > 0)
MEMMOVE(&TOPN(argc), &TOPN(argc-1),
VALUE, argc);
4736 return vm_invoke_block(ec, reg_cfp, calling, ci,
false, block_handler);
4740vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4742 RB_DEBUG_COUNTER_INC(ccf_opt_call);
4745 VALUE procval = calling->recv;
4746 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
4750vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4752 RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
4754 VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
4757 if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
4758 return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
4761 calling->recv = rb_vm_bh_to_procval(ec, block_handler);
4762 calling->cc = rb_vm_search_method_slowpath(ci,
CLASS_OF(calling->recv));
4763 return vm_call_general(ec, reg_cfp, calling);
4768vm_call_opt_struct_aref0(rb_execution_context_t *ec,
struct rb_calling_info *calling)
4770 VALUE recv = calling->recv;
4773 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4774 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_AREF);
4776 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4777 return internal_RSTRUCT_GET(recv,
off);
4781vm_call_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4783 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aref);
4785 VALUE ret = vm_call_opt_struct_aref0(ec, calling);
4791vm_call_opt_struct_aset0(rb_execution_context_t *ec,
struct rb_calling_info *calling,
VALUE val)
4793 VALUE recv = calling->recv;
4796 VM_ASSERT(vm_cc_cme(calling->cc)->def->type == VM_METHOD_TYPE_OPTIMIZED);
4797 VM_ASSERT(vm_cc_cme(calling->cc)->def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET);
4799 rb_check_frozen(recv);
4801 const unsigned int off = vm_cc_cme(calling->cc)->def->body.optimized.index;
4802 internal_RSTRUCT_SET(recv,
off, val);
4808vm_call_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
4810 RB_DEBUG_COUNTER_INC(ccf_opt_struct_aset);
4812 VALUE ret = vm_call_opt_struct_aset0(ec, calling, *(reg_cfp->sp - 1));
4817NOINLINE(
static VALUE vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4820#define VM_CALL_METHOD_ATTR(var, func, nohook) \
4821 if (UNLIKELY(ruby_vm_c_events_enabled > 0)) { \
4822 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id, \
4823 vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef); \
4825 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id, \
4826 vm_ci_mid(ci), vm_cc_cme(cc)->owner, (var)); \
4834vm_call_optimized(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling,
4837 switch (vm_cc_cme(cc)->def->body.optimized.type) {
4838 case OPTIMIZED_METHOD_TYPE_SEND:
4839 CC_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
4840 return vm_call_opt_send(ec, cfp, calling);
4841 case OPTIMIZED_METHOD_TYPE_CALL:
4842 CC_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
4843 return vm_call_opt_call(ec, cfp, calling);
4844 case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
4845 CC_SET_FASTPATH(cc, vm_call_opt_block_call, TRUE);
4846 return vm_call_opt_block_call(ec, cfp, calling);
4847 case OPTIMIZED_METHOD_TYPE_STRUCT_AREF: {
4848 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4852 VM_CALL_METHOD_ATTR(v,
4853 vm_call_opt_struct_aref(ec, cfp, calling),
4854 set_vm_cc_ivar(cc); \
4855 CC_SET_FASTPATH(cc, vm_call_opt_struct_aref, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4858 case OPTIMIZED_METHOD_TYPE_STRUCT_ASET: {
4859 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4863 VM_CALL_METHOD_ATTR(v,
4864 vm_call_opt_struct_aset(ec, cfp, calling),
4865 set_vm_cc_ivar(cc); \
4866 CC_SET_FASTPATH(cc, vm_call_opt_struct_aset, (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)))
4870 rb_bug(
"vm_call_method: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimized.type);
4875vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4879 const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
4882 VM_ASSERT(! METHOD_ENTRY_INVALIDATED(cme));
4884 switch (cme->def->type) {
4885 case VM_METHOD_TYPE_ISEQ:
4886 if (ISEQ_BODY(def_iseq_ptr(cme->def))->param.flags.forwardable) {
4887 CC_SET_FASTPATH(cc, vm_call_iseq_fwd_setup, TRUE);
4888 return vm_call_iseq_fwd_setup(ec, cfp, calling);
4891 CC_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
4892 return vm_call_iseq_setup(ec, cfp, calling);
4895 case VM_METHOD_TYPE_NOTIMPLEMENTED:
4896 case VM_METHOD_TYPE_CFUNC:
4897 CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
4898 return vm_call_cfunc(ec, cfp, calling);
4900 case VM_METHOD_TYPE_ATTRSET:
4901 CALLER_SETUP_ARG(cfp, calling, ci, 1);
4905 const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_FORWARDING);
4907 if (vm_cc_markable(cc)) {
4908 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4909 VM_CALL_METHOD_ATTR(v,
4910 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4911 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4917 VM_CALLCACHE_UNMARKABLE |
4918 VM_CALLCACHE_ON_STACK,
4924 .value = vm_pack_shape_and_index(INVALID_SHAPE_ID, ATTR_INDEX_NOT_SET),
4929 VM_CALL_METHOD_ATTR(v,
4930 vm_call_attrset_direct(ec, cfp, cc, calling->recv),
4931 CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
4935 case VM_METHOD_TYPE_IVAR:
4936 CALLER_SETUP_ARG(cfp, calling, ci, 0);
4938 vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
4939 const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING);
4940 VM_CALL_METHOD_ATTR(v,
4941 vm_call_ivar(ec, cfp, calling),
4942 CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & ivar_mask)));
4945 case VM_METHOD_TYPE_MISSING:
4946 vm_cc_method_missing_reason_set(cc, 0);
4947 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
4948 return vm_call_method_missing(ec, cfp, calling);
4950 case VM_METHOD_TYPE_BMETHOD:
4951 CC_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
4952 return vm_call_bmethod(ec, cfp, calling);
4954 case VM_METHOD_TYPE_ALIAS:
4955 CC_SET_FASTPATH(cc, vm_call_alias, TRUE);
4956 return vm_call_alias(ec, cfp, calling);
4958 case VM_METHOD_TYPE_OPTIMIZED:
4959 return vm_call_optimized(ec, cfp, calling, ci, cc);
4961 case VM_METHOD_TYPE_UNDEF:
4964 case VM_METHOD_TYPE_ZSUPER:
4965 return vm_call_zsuper(ec, cfp, calling, RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class));
4967 case VM_METHOD_TYPE_REFINED:
4970 return vm_call_refined(ec, cfp, calling);
4973 rb_bug(
"vm_call_method: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
4976NORETURN(
static void vm_raise_method_missing(rb_execution_context_t *ec,
int argc,
const VALUE *argv,
VALUE obj,
int call_status));
4979vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
4983 const int stat = ci_missing_reason(ci);
4985 if (vm_ci_mid(ci) == idMethodMissing) {
4986 if (UNLIKELY(calling->heap_argv)) {
4990 rb_control_frame_t *reg_cfp = cfp;
4991 VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
4992 vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
4996 return vm_call_method_missing_body(ec, cfp, calling, ci, stat);
5006vm_defined_class_for_protected_call(
const rb_callable_method_entry_t *me)
5008 VALUE defined_class = me->defined_class;
5009 VALUE refined_class = RCLASS_REFINED_CLASS(defined_class);
5010 return NIL_P(refined_class) ? defined_class : refined_class;
5014vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp,
struct rb_calling_info *calling)
5019 VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
5021 if (vm_cc_cme(cc) != NULL) {
5022 switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
5023 case METHOD_VISI_PUBLIC:
5024 return vm_call_method_each_type(ec, cfp, calling);
5026 case METHOD_VISI_PRIVATE:
5027 if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
5028 enum method_missing_reason stat = MISSING_PRIVATE;
5029 if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
5031 vm_cc_method_missing_reason_set(cc, stat);
5032 CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
5033 return vm_call_method_missing(ec, cfp, calling);
5035 return vm_call_method_each_type(ec, cfp, calling);
5037 case METHOD_VISI_PROTECTED:
5038 if (!(vm_ci_flag(ci) & (VM_CALL_OPT_SEND | VM_CALL_FCALL))) {
5039 VALUE defined_class = vm_defined_class_for_protected_call(vm_cc_cme(cc));
5041 vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
5042 return vm_call_method_missing(ec, cfp, calling);
5046 VM_ASSERT(vm_cc_cme(cc) != NULL);
5049 calling->cc = &cc_on_stack;
5050 return vm_call_method_each_type(ec, cfp, calling);
5053 return vm_call_method_each_type(ec, cfp, calling);
5056 rb_bug(
"unreachable");
5060 return vm_call_method_nome(ec, cfp, calling);
5065vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5067 RB_DEBUG_COUNTER_INC(ccf_general);
5068 return vm_call_method(ec, reg_cfp, calling);
5074 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
5075 VM_ASSERT(cc != vm_cc_empty());
5077 *(vm_call_handler *)&cc->call_ = vm_call_general;
5081vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling)
5083 RB_DEBUG_COUNTER_INC(ccf_super_method);
5088 if (ec == NULL) rb_bug(
"unreachable");
5091 VM_ASSERT(vm_cc_call(calling->cc) == vm_call_super_method);
5092 return vm_call_method(ec, reg_cfp, calling);
5098vm_search_normal_superclass(
VALUE klass)
5103 klass =
RBASIC(klass)->klass;
5105 klass = RCLASS_ORIGIN(klass);
5109NORETURN(
static void vm_super_outside(
void));
5112vm_super_outside(
void)
5118empty_cc_for_super(
void)
5120 return &vm_empty_cc_for_super;
5124vm_search_super_method(
const rb_control_frame_t *reg_cfp,
struct rb_call_data *cd,
VALUE recv)
5126 VALUE current_defined_class;
5127 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
5133 current_defined_class = vm_defined_class_for_protected_call(me);
5136 reg_cfp->iseq != method_entry_iseqptr(me) &&
5139 RCLASS_INCLUDER(current_defined_class) : current_defined_class;
5143 "self has wrong type to call super in this context: "
5144 "%"PRIsVALUE
" (expected %"PRIsVALUE
")",
5149 if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
5151 "implicit argument passing of super from method defined"
5152 " by define_method() is not supported."
5153 " Specify all arguments explicitly.");
5156 ID mid = me->def->original_id;
5158 if (!vm_ci_markable(cd->ci)) {
5159 VM_FORCE_WRITE((
const VALUE *)&cd->ci->mid, (
VALUE)mid);
5163 cd->ci = vm_ci_new_runtime(mid,
5166 vm_ci_kwarg(cd->ci));
5173 VALUE klass = vm_search_normal_superclass(me->defined_class);
5177 cc = vm_cc_new(
Qundef, NULL, vm_call_method_missing, cc_type_super);
5181 cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd, klass);
5182 const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc);
5185 if (cached_cme == NULL) {
5187 cd->cc = empty_cc_for_super();
5189 else if (cached_cme->called_id != mid) {
5190 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
5192 cc = vm_cc_new(klass, cme, vm_call_super_method, cc_type_super);
5196 cd->cc = cc = empty_cc_for_super();
5200 switch (cached_cme->def->type) {
5202 case VM_METHOD_TYPE_REFINED:
5204 case VM_METHOD_TYPE_ATTRSET:
5205 case VM_METHOD_TYPE_IVAR:
5206 vm_cc_call_set(cc, vm_call_super_method);
5214 VM_ASSERT((vm_cc_cme(cc),
true));
5222block_proc_is_lambda(
const VALUE procval)
5227 GetProcPtr(procval, proc);
5228 return proc->is_lambda;
5236vm_yield_with_cfunc(rb_execution_context_t *ec,
5238 VALUE self,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler,
5239 const rb_callable_method_entry_t *me)
5241 int is_lambda = FALSE;
5242 VALUE val, arg, blockarg;
5244 const struct vm_ifunc *ifunc = captured->code.ifunc;
5249 else if (argc == 0) {
5256 blockarg = rb_vm_bh_to_procval(ec, block_handler);
5258 frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
5260 frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
5263 vm_push_frame(ec, (
const rb_iseq_t *)captured->code.ifunc,
5266 VM_GUARDED_PREV_EP(captured->ep),
5268 0, ec->cfp->sp, 0, 0);
5269 val = (*ifunc->func)(arg, (
VALUE)ifunc->data, argc, argv, blockarg);
5270 rb_vm_pop_frame(ec);
5276rb_vm_yield_with_cfunc(rb_execution_context_t *ec,
const struct rb_captured_block *captured,
int argc,
const VALUE *argv)
5278 return vm_yield_with_cfunc(ec, captured, captured->self, argc, argv, 0, VM_BLOCK_HANDLER_NONE, NULL);
5282vm_yield_with_symbol(rb_execution_context_t *ec,
VALUE symbol,
int argc,
const VALUE *argv,
int kw_splat,
VALUE block_handler)
5284 return rb_sym_proc_call(
SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
5288vm_callee_setup_block_arg_arg0_splat(rb_control_frame_t *cfp,
const rb_iseq_t *iseq,
VALUE *argv,
VALUE ary)
5293 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5295 for (i=0; i<
len && i<ISEQ_BODY(iseq)->param.lead_num; i++) {
5303vm_callee_setup_block_arg_arg0_check(
VALUE *argv)
5305 VALUE ary, arg0 = argv[0];
5310 VM_ASSERT(argv[0] == arg0);
5316vm_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)
5318 if (rb_simple_iseq_p(iseq)) {
5319 rb_control_frame_t *cfp = ec->cfp;
5322 CALLER_SETUP_ARG(cfp, calling, ci, ISEQ_BODY(iseq)->param.lead_num);
5324 if (arg_setup_type == arg_setup_block &&
5325 calling->argc == 1 &&
5326 ISEQ_BODY(iseq)->param.flags.has_lead &&
5327 !ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
5328 !
NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) {
5329 calling->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0);
5332 if (calling->argc != ISEQ_BODY(iseq)->param.lead_num) {
5333 if (arg_setup_type == arg_setup_block) {
5334 if (calling->argc < ISEQ_BODY(iseq)->param.lead_num) {
5336 CHECK_VM_STACK_OVERFLOW(cfp, ISEQ_BODY(iseq)->param.lead_num);
5337 for (i=calling->argc; i<ISEQ_BODY(iseq)->param.lead_num; i++) argv[i] =
Qnil;
5338 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5340 else if (calling->argc > ISEQ_BODY(iseq)->param.lead_num) {
5341 calling->argc = ISEQ_BODY(iseq)->param.lead_num;
5345 argument_arity_error(ec, iseq, NULL, calling->argc, ISEQ_BODY(iseq)->param.lead_num, ISEQ_BODY(iseq)->param.lead_num);
5352 return setup_parameters_complex(ec, iseq, calling, ci, argv, arg_setup_type);
5357vm_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)
5361 calling = &calling_entry;
5362 calling->argc = argc;
5363 calling->block_handler = block_handler;
5364 calling->kw_splat = (flags & VM_CALL_KW_SPLAT) ? 1 : 0;
5366 calling->heap_argv = 0;
5368 struct rb_callinfo dummy_ci = VM_CI_ON_STACK(0, flags, 0, 0);
5370 return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
5376vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5378 bool is_lambda,
VALUE block_handler)
5381 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
5382 const int arg_size = ISEQ_BODY(iseq)->param.size;
5383 VALUE *
const rsp = GET_SP() - calling->argc;
5384 VALUE *
const argv = rsp;
5385 int opt_pc = vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, is_lambda ? arg_setup_method : arg_setup_block);
5386 int frame_flag = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
5390 vm_push_frame(ec, iseq,
5393 VM_GUARDED_PREV_EP(captured->ep), 0,
5394 ISEQ_BODY(iseq)->iseq_encoded + opt_pc,
5396 ISEQ_BODY(iseq)->local_table_size - arg_size, ISEQ_BODY(iseq)->stack_max);
5402vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5404 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5406 VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
5407 int flags = vm_ci_flag(ci);
5409 if (UNLIKELY(!(flags & VM_CALL_ARGS_SIMPLE) &&
5410 ((calling->argc == 0) ||
5411 (calling->argc == 1 && (flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT))) ||
5412 (calling->argc == 2 && (flags & VM_CALL_ARGS_SPLAT) && (flags & VM_CALL_KW_SPLAT)) ||
5413 ((flags & VM_CALL_KWARG) && (vm_ci_kwarg(ci)->keyword_len == calling->argc))))) {
5414 CALLER_SETUP_ARG(reg_cfp, calling, ci, ALLOW_HEAP_ARGV);
5416 if (UNLIKELY(calling->heap_argv)) {
5417#if VM_ARGC_STACK_MAX < 0
5419 rb_raise(rb_eArgError,
"no receiver given");
5425 reg_cfp->sp[-1] = reg_cfp->sp[-2];
5426 reg_cfp->sp[-2] = calling->recv;
5427 flags |= VM_CALL_ARGS_SPLAT;
5430 if (calling->argc < 1) {
5431 rb_raise(rb_eArgError,
"no receiver given");
5433 calling->recv = TOPN(--calling->argc);
5435 if (calling->kw_splat) {
5436 flags |= VM_CALL_KW_SPLAT;
5440 if (calling->argc < 1) {
5441 rb_raise(rb_eArgError,
"no receiver given");
5443 calling->recv = TOPN(--calling->argc);
5446 return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, flags);
5450vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5452 MAYBE_UNUSED(
bool is_lambda),
VALUE block_handler)
5457 CALLER_SETUP_ARG(ec->cfp, calling, ci, ALLOW_HEAP_ARGV_KEEP_KWSPLAT);
5458 argc = calling->argc;
5459 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);
5465vm_proc_to_block_handler(
VALUE procval)
5467 const struct rb_block *block = vm_proc_block(procval);
5469 switch (vm_block_type(block)) {
5470 case block_type_iseq:
5471 return VM_BH_FROM_ISEQ_BLOCK(&block->as.captured);
5472 case block_type_ifunc:
5473 return VM_BH_FROM_IFUNC_BLOCK(&block->as.captured);
5474 case block_type_symbol:
5475 return VM_BH_FROM_SYMBOL(block->as.symbol);
5476 case block_type_proc:
5477 return VM_BH_FROM_PROC(block->as.proc);
5479 VM_UNREACHABLE(vm_yield_with_proc);
5484vm_invoke_proc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5486 bool is_lambda,
VALUE block_handler)
5488 while (vm_block_handler_type(block_handler) == block_handler_type_proc) {
5489 VALUE proc = VM_BH_TO_PROC(block_handler);
5490 is_lambda = block_proc_is_lambda(proc);
5491 block_handler = vm_proc_to_block_handler(proc);
5494 return vm_invoke_block(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5498vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5500 bool is_lambda,
VALUE block_handler)
5502 VALUE (*func)(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
5504 bool is_lambda,
VALUE block_handler);
5506 switch (vm_block_handler_type(block_handler)) {
5507 case block_handler_type_iseq: func = vm_invoke_iseq_block;
break;
5508 case block_handler_type_ifunc: func = vm_invoke_ifunc_block;
break;
5509 case block_handler_type_proc: func = vm_invoke_proc_block;
break;
5510 case block_handler_type_symbol: func = vm_invoke_symbol_block;
break;
5511 default: rb_bug(
"vm_invoke_block: unreachable");
5514 return func(ec, reg_cfp, calling, ci, is_lambda, block_handler);
5518vm_make_proc_with_iseq(
const rb_iseq_t *blockiseq)
5520 const rb_execution_context_t *ec = GET_EC();
5521 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
5525 rb_bug(
"vm_make_proc_with_iseq: unreachable");
5528 captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
5529 captured->code.iseq = blockiseq;
5531 return rb_vm_make_proc(ec, captured,
rb_cProc);
5535vm_once_exec(
VALUE iseq)
5537 VALUE proc = vm_make_proc_with_iseq((rb_iseq_t *)iseq);
5542vm_once_clear(
VALUE data)
5545 is->once.running_thread = NULL;
5557 args[0] = obj; args[1] =
Qfalse;
5559 if (!UNDEF_P(r) &&
RTEST(r)) {
5568vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5571 enum defined_type
type = (
enum defined_type)op_type;
5578 return rb_gvar_defined(
SYM2ID(obj));
5580 case DEFINED_CVAR: {
5581 const rb_cref_t *cref = vm_get_cref(GET_EP());
5582 klass = vm_get_cvar_base(cref, GET_CFP(), 0);
5587 case DEFINED_CONST_FROM: {
5588 bool allow_nil =
type == DEFINED_CONST;
5590 return vm_get_ev_const(ec, klass,
SYM2ID(obj), allow_nil,
true);
5595 return rb_ec_obj_respond_to(ec, v,
SYM2ID(obj), TRUE);
5597 case DEFINED_METHOD:{
5599 const rb_callable_method_entry_t *cme = rb_callable_method_entry_with_refinements(klass,
SYM2ID(obj), NULL);
5602 switch (METHOD_ENTRY_VISI(cme)) {
5603 case METHOD_VISI_PRIVATE:
5605 case METHOD_VISI_PROTECTED:
5609 case METHOD_VISI_PUBLIC:
5613 rb_bug(
"vm_defined: unreachable: %u", (
unsigned int)METHOD_ENTRY_VISI(cme));
5617 return check_respond_to_missing(obj, v);
5622 if (GET_BLOCK_HANDLER() != VM_BLOCK_HANDLER_NONE) {
5626 case DEFINED_ZSUPER:
5628 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(GET_CFP());
5631 VALUE klass = vm_search_normal_superclass(me->defined_class);
5632 if (!klass)
return false;
5634 ID id = me->def->original_id;
5641 return RTEST(vm_backref_defined(ec, GET_LEP(),
FIX2INT(obj)));
5643 rb_bug(
"unimplemented defined? type (VM)");
5651rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type,
VALUE obj,
VALUE v)
5653 return vm_defined(ec, reg_cfp, op_type, obj, v);
5657vm_get_ep(
const VALUE *
const reg_ep, rb_num_t lv)
5660 const VALUE *ep = reg_ep;
5661 for (i = 0; i < lv; i++) {
5662 ep = GET_PREV_EP(ep);
5668vm_get_special_object(
const VALUE *
const reg_ep,
5669 enum vm_special_object_type
type)
5672 case VM_SPECIAL_OBJECT_VMCORE:
5673 return rb_mRubyVMFrozenCore;
5674 case VM_SPECIAL_OBJECT_CBASE:
5675 return vm_get_cbase(reg_ep);
5676 case VM_SPECIAL_OBJECT_CONST_BASE:
5677 return vm_get_const_base(reg_ep);
5679 rb_bug(
"putspecialobject insn: unknown value_type %d",
type);
5686rb_vm_get_special_object(
const VALUE *reg_ep,
enum vm_special_object_type
type)
5688 return vm_get_special_object(reg_ep,
type);
5694 const VALUE ary2 = ary2st;
5695 VALUE tmp1 = rb_check_to_array(ary1);
5696 VALUE tmp2 = rb_check_to_array(ary2);
5717 const VALUE ary2 = ary2st;
5719 if (
NIL_P(ary2))
return ary1;
5721 VALUE tmp2 = rb_check_to_array(ary2);
5736 return vm_concat_array(ary1, ary2st);
5740rb_vm_concat_to_array(
VALUE ary1,
VALUE ary2st)
5742 return vm_concat_to_array(ary1, ary2st);
5751 VALUE tmp = rb_check_to_array(ary);
5755 else if (
RTEST(flag)) {
5768 return vm_splat_array(flag, ary);
5772vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5774 enum vm_check_match_type
type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
5776 if (flag & VM_CHECKMATCH_ARRAY) {
5780 for (i = 0; i < n; i++) {
5782 VALUE c = check_match(ec, v, target,
type);
5791 return check_match(ec, pattern, target,
type);
5796rb_vm_check_match(rb_execution_context_t *ec,
VALUE target,
VALUE pattern, rb_num_t flag)
5798 return vm_check_match(ec, target, pattern, flag);
5802vm_check_keyword(lindex_t bits, lindex_t idx,
const VALUE *ep)
5804 const VALUE kw_bits = *(ep - bits);
5807 unsigned int b = (
unsigned int)
FIX2ULONG(kw_bits);
5808 if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
5821 if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
5822 RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
5823 RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
5824 RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
5828 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, 0, 0);
5831 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, 0, 0);
5834 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
5837 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, 0, 0);
5844vm_const_get_under(
ID id, rb_num_t flags,
VALUE cbase)
5849 else if (VM_DEFINECLASS_SCOPED_P(flags)) {
5850 return rb_public_const_get_at(cbase,
id);
5858vm_check_if_class(
ID id, rb_num_t flags,
VALUE super,
VALUE klass)
5863 else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
5868 "superclass mismatch for class %"PRIsVALUE
"",
5881vm_check_if_module(
ID id,
VALUE mod)
5900vm_declare_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5903 VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super : rb_cObject;
5911vm_declare_module(
ID id,
VALUE cbase)
5917NORETURN(
static void unmatched_redefinition(
const char *
type,
VALUE cbase,
ID id,
VALUE old));
5921 VALUE name = rb_id2str(
id);
5922 VALUE message = rb_sprintf(
"%"PRIsVALUE
" is not a %s",
5924 VALUE location = rb_const_source_location_at(cbase,
id);
5925 if (!
NIL_P(location)) {
5926 rb_str_catf(message,
"\n%"PRIsVALUE
":%"PRIsVALUE
":"
5927 " previous definition of %"PRIsVALUE
" was here",
5934vm_define_class(
ID id, rb_num_t flags,
VALUE cbase,
VALUE super)
5938 if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !
RB_TYPE_P(super,
T_CLASS)) {
5940 "superclass must be an instance of Class (given an instance of %"PRIsVALUE
")",
5944 vm_check_if_namespace(cbase);
5949 if ((klass = vm_const_get_under(
id, flags, cbase)) != 0) {
5950 if (!vm_check_if_class(
id, flags, super, klass))
5951 unmatched_redefinition(
"class", cbase,
id, klass);
5955 return vm_declare_class(
id, flags, cbase, super);
5960vm_define_module(
ID id, rb_num_t flags,
VALUE cbase)
5964 vm_check_if_namespace(cbase);
5965 if ((mod = vm_const_get_under(
id, flags, cbase)) != 0) {
5966 if (!vm_check_if_module(
id, mod))
5967 unmatched_redefinition(
"module", cbase,
id, mod);
5971 return vm_declare_module(
id, cbase);
5976vm_find_or_create_class_by_id(
ID id,
5981 rb_vm_defineclass_type_t
type = VM_DEFINECLASS_TYPE(flags);
5984 case VM_DEFINECLASS_TYPE_CLASS:
5986 return vm_define_class(
id, flags, cbase, super);
5988 case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
5992 case VM_DEFINECLASS_TYPE_MODULE:
5994 return vm_define_module(
id, flags, cbase);
5997 rb_bug(
"unknown defineclass type: %d", (
int)
type);
6001static rb_method_visibility_t
6002vm_scope_visibility_get(
const rb_execution_context_t *ec)
6004 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
6006 if (!vm_env_cref_by_cref(cfp->ep)) {
6007 return METHOD_VISI_PUBLIC;
6010 return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
6015vm_scope_module_func_check(
const rb_execution_context_t *ec)
6017 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
6019 if (!vm_env_cref_by_cref(cfp->ep)) {
6023 return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
6028vm_define_method(
const rb_execution_context_t *ec,
VALUE obj,
ID id,
VALUE iseqval,
int is_singleton)
6031 rb_method_visibility_t visi;
6032 rb_cref_t *cref = vm_ec_cref(ec);
6036 visi = METHOD_VISI_PUBLIC;
6039 klass = CREF_CLASS_FOR_DEFINITION(cref);
6040 visi = vm_scope_visibility_get(ec);
6047 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, visi);
6050 RCLASS_SET_MAX_IV_COUNT(klass, rb_estimate_iv_count(klass, (
const rb_iseq_t *)iseqval));
6053 if (!is_singleton && vm_scope_module_func_check(ec)) {
6055 rb_add_method_iseq(klass,
id, (
const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
6064rb_vm_untag_block_handler(
VALUE block_handler)
6066 if (VM_BLOCK_HANDLER_NONE == block_handler)
return Qnil;
6068 switch (vm_block_handler_type(block_handler)) {
6069 case block_handler_type_iseq:
6070 case block_handler_type_ifunc: {
6072 return captured->code.val;
6074 case block_handler_type_proc:
6075 case block_handler_type_symbol:
6076 return block_handler;
6078 rb_bug(
"rb_vm_untag_block_handler: unreachable");
6083rb_vm_get_untagged_block_handler(rb_control_frame_t *reg_cfp)
6085 return rb_vm_untag_block_handler(VM_CF_BLOCK_HANDLER(reg_cfp));
6094 VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
6096 if (block_handler == VM_BLOCK_HANDLER_NONE) {
6097 rb_vm_localjump_error(
"no block given (yield)",
Qnil, 0);
6100 return vm_invoke_block(ec, GET_CFP(), calling, ci,
false, block_handler);
6104enum method_explorer_type {
6106 mexp_search_invokeblock,
6115 VALUE block_handler,
6116 enum method_explorer_type method_explorer
6121 int argc = vm_ci_argc(ci);
6122 VALUE recv = TOPN(argc);
6124 .block_handler = block_handler,
6125 .kw_splat = IS_ARGS_KW_SPLAT(ci) > 0,
6131 switch (method_explorer) {
6132 case mexp_search_method:
6133 calling.cc = cc = vm_search_method_fastpath((
VALUE)reg_cfp->iseq, cd,
CLASS_OF(recv));
6134 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6136 case mexp_search_super:
6137 calling.cc = cc = vm_search_super_method(reg_cfp, cd, recv);
6138 val = vm_cc_call(cc)(ec, GET_CFP(), &calling);
6140 case mexp_search_invokeblock:
6141 val = vm_invokeblock_i(ec, GET_CFP(), &calling);
6148rb_vm_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6151 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq,
false);
6152 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6158rb_vm_sendforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6165 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
false, &adjusted_cd, &adjusted_ci);
6167 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
6169 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6178rb_vm_opt_send_without_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6181 VALUE bh = VM_BLOCK_HANDLER_NONE;
6182 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
6188rb_vm_invokesuper(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6192 struct rb_callinfo adjusted_ci = VM_CI_ON_STACK(vm_ci_mid(cd->ci),
6195 vm_ci_kwarg(cd->ci));
6196 const struct rb_callcache *original_cc = rbimpl_atomic_ptr_load((
void **)&cd->cc, RBIMPL_ATOMIC_ACQUIRE);
6202 VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), adjusted_cd.ci, blockiseq,
true);
6203 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd, bh, mexp_search_super);
6205 if (original_cc != adjusted_cd.cc && vm_cc_markable(adjusted_cd.cc)) {
6206 rbimpl_atomic_ptr_store((
volatile void **)&cd->cc, (
void *)adjusted_cd.cc, RBIMPL_ATOMIC_RELEASE);
6215rb_vm_invokesuperforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
6221 VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq,
true, &adjusted_cd, &adjusted_ci);
6223 VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
6225 if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
6234rb_vm_invokeblock(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd)
6237 VALUE bh = VM_BLOCK_HANDLER_NONE;
6238 VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
6255vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6266 if (check_method_basic_definition(cme)) {
6275 if (check_cfunc(cme, rb_mod_to_s)) {
6281 val = rb_mod_to_s(recv);
6287 if (check_cfunc(cme, rb_nil_to_s)) {
6288 return rb_nil_to_s(recv);
6292 if (check_cfunc(cme, rb_true_to_s)) {
6293 return rb_true_to_s(recv);
6297 if (check_cfunc(cme, rb_false_to_s)) {
6298 return rb_false_to_s(recv);
6302 if (check_cfunc(cme, rb_int_to_s)) {
6303 return rb_fix_to_s(recv);
6313rb_vm_objtostring(
const rb_iseq_t *iseq,
VALUE recv, CALL_DATA cd)
6315 return vm_objtostring(iseq, recv, cd);
6319vm_opt_ary_freeze(
VALUE ary,
int bop,
ID id)
6321 if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
6330vm_opt_hash_freeze(
VALUE hash,
int bop,
ID id)
6332 if (BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
6341vm_opt_str_freeze(
VALUE str,
int bop,
ID id)
6343 if (BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
6355vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6357 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6361 VALUE args[1] = {target};
6364 RUBY_DTRACE_CREATE_HOOK(ARRAY,
RARRAY_LEN(ary));
6367 return rb_vm_call_with_refinements(ec, dupary, idIncludeP, 1, args,
RB_NO_KEYWORDS);
6372rb_vm_opt_duparray_include_p(rb_execution_context_t *ec,
const VALUE ary,
VALUE target)
6374 return vm_opt_duparray_include_p(ec, ary, target);
6378vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6380 if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
6381 if (array_len == 0) {
6385 VALUE result = *ptr;
6386 rb_snum_t i = array_len - 1;
6388 const VALUE v = *++ptr;
6389 if (OPTIMIZED_CMP(v, result) > 0) {
6402rb_vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6404 return vm_opt_newarray_max(ec, array_len, ptr);
6408vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6410 if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
6411 if (array_len == 0) {
6415 VALUE result = *ptr;
6416 rb_snum_t i = array_len - 1;
6418 const VALUE v = *++ptr;
6419 if (OPTIMIZED_CMP(v, result) < 0) {
6432rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6434 return vm_opt_newarray_min(ec, array_len, ptr);
6438vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6441 if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
6442 return rb_ary_hash_values(array_len, ptr);
6450rb_vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr)
6452 return vm_opt_newarray_hash(ec, array_len, ptr);
6459vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE target)
6461 if (BASIC_OP_UNREDEFINED_P(BOP_INCLUDE_P, ARRAY_REDEFINED_OP_FLAG)) {
6462 struct RArray fake_ary = {RBASIC_INIT};
6463 VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, array_len);
6467 VALUE args[1] = {target};
6473rb_vm_opt_newarray_include_p(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE target)
6475 return vm_opt_newarray_include_p(ec, array_len, ptr, target);
6479vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt,
VALUE buffer)
6481 if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) {
6482 struct RArray fake_ary = {RBASIC_INIT};
6483 VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, array_len);
6484 return rb_ec_pack_ary(ec,
ary, fmt, (UNDEF_P(buffer) ?
Qnil : buffer));
6494 if (!UNDEF_P(buffer)) {
6495 args[1] = rb_hash_new_with_size(1);
6496 rb_hash_aset(args[1],
ID2SYM(idBuffer), buffer);
6501 return rb_vm_call_with_refinements(ec,
rb_ary_new4(array_len, ptr), idPack, argc, args, kw_splat);
6506rb_vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt,
VALUE buffer)
6508 return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt, buffer);
6512rb_vm_opt_newarray_pack(rb_execution_context_t *ec, rb_num_t array_len,
const VALUE *ptr,
VALUE fmt)
6514 return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt,
Qundef);
6520vm_track_constant_cache(
ID id,
void *ic)
6522 rb_vm_t *vm = GET_VM();
6523 struct rb_id_table *const_cache = vm->constant_cache;
6524 VALUE lookup_result;
6527 if (rb_id_table_lookup(const_cache,
id, &lookup_result)) {
6531 ics = set_init_numtable();
6532 rb_id_table_insert(const_cache,
id, (
VALUE)ics);
6547 vm->inserting_constant_cache_id = id;
6549 set_insert(ics, (st_data_t)ic);
6551 vm->inserting_constant_cache_id = (
ID)0;
6555vm_ic_track_const_chain(rb_control_frame_t *cfp, IC ic,
const ID *segments)
6558 for (
int i = 0; segments[i]; i++) {
6559 ID id = segments[i];
6560 if (
id == idNULL)
continue;
6561 vm_track_constant_cache(
id, ic);
6568vm_inlined_ic_hit_p(
VALUE flags,
VALUE value,
const rb_cref_t *ic_cref,
const VALUE *reg_ep)
6570 if ((flags & IMEMO_CONST_CACHE_SHAREABLE) || rb_ractor_main_p()) {
6571 VM_ASSERT(ractor_incidental_shareable_p(flags & IMEMO_CONST_CACHE_SHAREABLE, value));
6573 return (ic_cref == NULL ||
6574 ic_cref == vm_get_cref(reg_ep));
6582 VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
6583 return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, reg_ep);
6588rb_vm_ic_hit_p(IC ic,
const VALUE *reg_ep)
6590 return ic->entry && vm_ic_hit_p(ic->entry, reg_ep);
6594vm_ic_update(
const rb_iseq_t *iseq, IC ic,
VALUE val,
const VALUE *reg_ep,
const VALUE *pc)
6596 if (ruby_vm_const_missing_count > 0) {
6597 ruby_vm_const_missing_count = 0;
6604 ice->ic_cref = vm_get_const_key_cref(reg_ep);
6608 ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
6612 unsigned pos = (unsigned)(pc - ISEQ_BODY(iseq)->iseq_encoded);
6613 rb_yjit_constant_ic_update(iseq, ic, pos);
6617rb_vm_opt_getconstant_path(rb_execution_context_t *ec, rb_control_frame_t *
const reg_cfp, IC ic)
6623 if (ice && vm_ic_hit_p(ice, GET_EP())) {
6626 VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
6629 ruby_vm_constant_cache_misses++;
6630 val = vm_get_ev_const_chain(ec, segments);
6631 vm_ic_track_const_chain(GET_CFP(), ic, segments);
6634 vm_ic_update(GET_ISEQ(), ic, val, GET_EP(), GET_PC() - 2);
6640vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, ISE is)
6642 rb_thread_t *th = rb_ec_thread_ptr(ec);
6643 rb_thread_t *
const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1);
6646 if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
6647 return is->once.value;
6649 else if (is->once.running_thread == NULL) {
6651 is->once.running_thread = th;
6656 RB_OBJ_SET_SHAREABLE(val);
6662 is->once.running_thread = RUNNING_THREAD_ONCE_DONE;
6665 else if (is->once.running_thread == th) {
6667 return vm_once_exec((
VALUE)iseq);
6671 RUBY_VM_CHECK_INTS(ec);
6678vm_case_dispatch(CDHASH hash, OFFSET else_offset,
VALUE key)
6680 switch (OBJ_BUILTIN_TYPE(key)) {
6686 if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
6687 SYMBOL_REDEFINED_OP_FLAG |
6688 INTEGER_REDEFINED_OP_FLAG |
6689 FLOAT_REDEFINED_OP_FLAG |
6690 NIL_REDEFINED_OP_FLAG |
6691 TRUE_REDEFINED_OP_FLAG |
6692 FALSE_REDEFINED_OP_FLAG |
6693 STRING_REDEFINED_OP_FLAG)) {
6697 if (!isinf(kval) && modf(kval, &kval) == 0.0) {
6701 if (rb_hash_stlike_lookup(hash, key, &val)) {
6713 vm_stack_consistency_error(
const rb_execution_context_t *ec,
6714 const rb_control_frame_t *,
6717vm_stack_consistency_error(
const rb_execution_context_t *ec,
6718 const rb_control_frame_t *cfp,
6721 const ptrdiff_t nsp = VM_SP_CNT(ec, cfp->sp);
6722 const ptrdiff_t nbp = VM_SP_CNT(ec, bp);
6723 static const char stack_consistency_error[] =
6724 "Stack consistency error (sp: %"PRIdPTRDIFF
", bp: %"PRIdPTRDIFF
")";
6725#if defined RUBY_DEVEL
6726 VALUE mesg = rb_sprintf(stack_consistency_error, nsp, nbp);
6731 rb_bug(stack_consistency_error, nsp, nbp);
6738 if (FIXNUM_2_P(recv, obj) &&
6739 BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
6740 return rb_fix_plus_fix(recv, obj);
6742 else if (FLONUM_2_P(recv, obj) &&
6743 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6751 BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
6756 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
6757 return rb_str_opt_plus(recv, obj);
6761 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
6772 if (FIXNUM_2_P(recv, obj) &&
6773 BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
6774 return rb_fix_minus_fix(recv, obj);
6776 else if (FLONUM_2_P(recv, obj) &&
6777 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6785 BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
6796 if (FIXNUM_2_P(recv, obj) &&
6797 BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
6798 return rb_fix_mul_fix(recv, obj);
6800 else if (FLONUM_2_P(recv, obj) &&
6801 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6809 BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
6820 if (FIXNUM_2_P(recv, obj) &&
6821 BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
6822 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_div_fix(recv, obj);
6824 else if (FLONUM_2_P(recv, obj) &&
6825 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6826 return rb_flo_div_flo(recv, obj);
6833 BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
6834 return rb_flo_div_flo(recv, obj);
6844 if (FIXNUM_2_P(recv, obj) &&
6845 BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
6846 return (
FIX2LONG(obj) == 0) ?
Qundef : rb_fix_mod_fix(recv, obj);
6848 else if (FLONUM_2_P(recv, obj) &&
6849 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6857 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
6866vm_opt_neq(
const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq,
VALUE recv,
VALUE obj)
6868 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not_equal)) {
6869 VALUE val = opt_equality(iseq, recv, obj, cd_eq);
6871 if (!UNDEF_P(val)) {
6872 return RBOOL(!
RTEST(val));
6882 if (FIXNUM_2_P(recv, obj) &&
6883 BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
6886 else if (FLONUM_2_P(recv, obj) &&
6887 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6895 BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
6906 if (FIXNUM_2_P(recv, obj) &&
6907 BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
6910 else if (FLONUM_2_P(recv, obj) &&
6911 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6919 BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
6930 if (FIXNUM_2_P(recv, obj) &&
6931 BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
6934 else if (FLONUM_2_P(recv, obj) &&
6935 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6943 BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
6954 if (FIXNUM_2_P(recv, obj) &&
6955 BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
6958 else if (FLONUM_2_P(recv, obj) &&
6959 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6967 BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
6983 BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
6992 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
7010 BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
7021 if (FIXNUM_2_P(recv, obj) &&
7022 BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
7034 if (FIXNUM_2_P(recv, obj) &&
7035 BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
7036 return rb_fix_aref(recv, obj);
7041 BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG)) {
7043 return rb_ary_entry_internal(recv,
FIX2LONG(obj));
7046 return rb_ary_aref1(recv, obj);
7050 BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
7051 return rb_hash_aref(recv, obj);
7065 BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
7071 BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
7072 rb_hash_aset(recv, obj, set);
7081vm_opt_length(
VALUE recv,
int bop)
7087 BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
7088 if (bop == BOP_EMPTY_P) {
7089 return LONG2NUM(RSTRING_LEN(recv));
7096 BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
7100 BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
7109vm_opt_empty_p(
VALUE recv)
7111 switch (vm_opt_length(recv, BOP_EMPTY_P)) {
7121vm_opt_nil_p(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7124 BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
7127 else if (vm_method_cfunc_is(iseq, cd, recv, rb_false)) {
7143 case RSHIFT(~0UL, 1):
7146 return rb_uint2big(1UL << (SIZEOF_LONG * CHAR_BIT - 2));
7164vm_opt_succ(
VALUE recv)
7167 BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
7168 return fix_succ(recv);
7174 BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
7183vm_opt_not(
const rb_iseq_t *iseq, CALL_DATA cd,
VALUE recv)
7185 if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not)) {
7186 return RBOOL(!
RTEST(recv));
7201 BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
7205 BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
7213rb_event_flag_t rb_iseq_event_flags(
const rb_iseq_t *iseq,
size_t pos);
7215NOINLINE(
static void vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp));
7218vm_trace_hook(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const VALUE *pc,
7220 rb_hook_list_t *global_hooks, rb_hook_list_t *local_hooks,
VALUE val)
7223 VALUE self = GET_SELF();
7225 VM_ASSERT(rb_popcount64((uint64_t)event) == 1);
7227 if (local_hooks) local_hooks->running++;
7229 if (event & global_hooks->events) {
7232 vm_dtrace(event, ec);
7233 rb_exec_event_hook_orig(ec, global_hooks, event, self, 0, 0, 0 , val, 0);
7237 if (local_hooks) local_hooks->running--;
7238 if (local_hooks != NULL) {
7239 if (event & local_hooks->events) {
7242 rb_exec_event_hook_orig(ec, local_hooks, event, self, 0, 0, 0 , val, 0);
7248#define VM_TRACE_HOOK(target_event, val) do { \
7249 if ((pc_events & (target_event)) & enabled_flags) { \
7250 vm_trace_hook(ec, reg_cfp, pc, pc_events, (target_event), global_hooks, local_hooks, (val)); \
7255rescue_errinfo(rb_execution_context_t *ec, rb_control_frame_t *cfp)
7257 VM_ASSERT(VM_FRAME_RUBYFRAME_P(cfp));
7258 VM_ASSERT(ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE);
7259 return cfp->ep[VM_ENV_INDEX_LAST_LVAR];
7263vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
7265 const VALUE *pc = reg_cfp->pc;
7266 rb_ractor_t *r = rb_ec_ractor_ptr(ec);
7267 rb_event_flag_t enabled_flags = r->pub.hooks.events & ISEQ_TRACE_EVENTS;
7270 if (enabled_flags == 0 && rb_ractor_targeted_hooks_cnt(r) == 0) {
7274 const rb_iseq_t *iseq = reg_cfp->iseq;
7275 size_t pos = pc - ISEQ_BODY(iseq)->iseq_encoded;
7277 unsigned int local_hooks_cnt = iseq->aux.exec.local_hooks_cnt;
7278 rb_hook_list_t *local_hooks = NULL;
7279 if (RB_UNLIKELY(local_hooks_cnt > 0)) {
7281 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
7282 local_hooks = (rb_hook_list_t*)val;
7285 rb_event_flag_t iseq_local_events = local_hooks != NULL ? local_hooks->events : 0;
7287 rb_hook_list_t *bmethod_local_hooks = NULL;
7289 const bool bmethod_frame = VM_FRAME_BMETHOD_P(reg_cfp);
7290 enabled_flags |= iseq_local_events;
7292 VM_ASSERT((iseq_local_events & ~ISEQ_TRACE_EVENTS) == 0);
7294 if (bmethod_frame) {
7295 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
7296 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
7297 unsigned int bmethod_hooks_cnt = me->def->body.bmethod.local_hooks_cnt;
7298 if (RB_UNLIKELY(bmethod_hooks_cnt > 0)) {
7300 if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)me->def, &val)) {
7301 bmethod_local_hooks = (rb_hook_list_t*)val;
7303 if (bmethod_local_hooks) {
7304 bmethod_local_events = bmethod_local_hooks->events;
7309 if ((pc_events & enabled_flags) == 0 && !bmethod_frame) {
7313 rb_iseq_trace_set(iseq, vm_event_flags & ISEQ_TRACE_EVENTS);
7321 else if (ec->trace_arg != NULL) {
7326 rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(ec);
7329 rb_event_flag_t bmethod_events = ractor_events | bmethod_local_events;
7332 ruby_debug_printf(
"vm_trace>>%4d (%4x) - %s:%d %s\n",
7335 RSTRING_PTR(rb_iseq_path(iseq)),
7336 (
int)rb_iseq_line_no(iseq, pos),
7337 RSTRING_PTR(rb_iseq_label(iseq)));
7339 VM_ASSERT(reg_cfp->pc == pc);
7340 VM_ASSERT(pc_events != 0);
7350 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_LINE,
Qundef);
7351 VM_TRACE_HOOK(RUBY_EVENT_COVERAGE_BRANCH,
Qundef);
7362#if VM_CHECK_MODE > 0
7363NORETURN( NOINLINE( COLDFUNC
7364void rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)));
7367Init_vm_stack_canary(
void)
7370 int n = ruby_fill_random_bytes(&vm_stack_canary,
sizeof vm_stack_canary,
false);
7371 vm_stack_canary |= 0x01;
7373 vm_stack_canary_was_born =
true;
7378rb_vm_canary_is_found_dead(
enum ruby_vminsn_type i,
VALUE c)
7382 const char *insn = rb_insns_name(i);
7386 rb_bug(
"dead canary found at %s: %s", insn, str);
7390void Init_vm_stack_canary(
void) { }
7419builtin_invoker0(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7421 typedef VALUE (*rb_invoke_funcptr0_t)(rb_execution_context_t *ec,
VALUE self);
7422 return (*(rb_invoke_funcptr0_t)funcptr)(ec, self);
7426builtin_invoker1(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7428 typedef VALUE (*rb_invoke_funcptr1_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1);
7429 return (*(rb_invoke_funcptr1_t)funcptr)(ec, self, argv[0]);
7433builtin_invoker2(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7435 typedef VALUE (*rb_invoke_funcptr2_t)(rb_execution_context_t *ec,
VALUE self,
VALUE v1,
VALUE v2);
7436 return (*(rb_invoke_funcptr2_t)funcptr)(ec, self, argv[0], argv[1]);
7440builtin_invoker3(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7443 return (*(rb_invoke_funcptr3_t)funcptr)(ec, self, argv[0], argv[1], argv[2]);
7447builtin_invoker4(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7450 return (*(rb_invoke_funcptr4_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3]);
7454builtin_invoker5(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7457 return (*(rb_invoke_funcptr5_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4]);
7461builtin_invoker6(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7464 return (*(rb_invoke_funcptr6_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
7468builtin_invoker7(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7471 return (*(rb_invoke_funcptr7_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
7475builtin_invoker8(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7478 return (*(rb_invoke_funcptr8_t)funcptr)(ec, self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
7482builtin_invoker9(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7484 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);
7485 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]);
7489builtin_invoker10(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7491 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);
7492 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]);
7496builtin_invoker11(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7498 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);
7499 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]);
7503builtin_invoker12(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7505 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);
7506 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]);
7510builtin_invoker13(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7512 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);
7513 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]);
7517builtin_invoker14(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7519 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);
7520 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]);
7524builtin_invoker15(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr)
7526 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);
7527 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]);
7530typedef VALUE (*builtin_invoker)(rb_execution_context_t *ec,
VALUE self,
const VALUE *argv, rb_insn_func_t funcptr);
7532static builtin_invoker
7533lookup_builtin_invoker(
int argc)
7535 static const builtin_invoker invokers[] = {
7554 return invokers[argc];
7558invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7560 const bool canary_p = ISEQ_BODY(reg_cfp->iseq)->builtin_attrs & BUILTIN_ATTR_LEAF;
7561 SETUP_CANARY(canary_p);
7562 rb_insn_func_t func_ptr = (rb_insn_func_t)(uintptr_t)bf->func_ptr;
7563 VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, func_ptr);
7564 CHECK_CANARY(canary_p, BIN(invokebuiltin));
7569vm_invoke_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function* bf,
const VALUE *argv)
7571 return invoke_bf(ec, cfp, bf, argv);
7575vm_invoke_builtin_delegate(rb_execution_context_t *ec, rb_control_frame_t *cfp,
const struct rb_builtin_function *bf,
unsigned int start_index)
7578 fputs(
"vm_invoke_builtin_delegate: passing -> ", stderr);
7579 for (
int i=0; i<bf->argc; i++) {
7580 ruby_debug_printf(
":%s ", rb_id2name(ISEQ_BODY(cfp->iseq)->local_table[i+start_index]));
7582 ruby_debug_printf(
"\n" "%s %s(%d):%p\n", RUBY_FUNCTION_NAME_STRING, bf->name, bf->argc,
7583 (
void *)(uintptr_t)bf->func_ptr);
7586 if (bf->argc == 0) {
7587 return invoke_bf(ec, cfp, bf, NULL);
7590 const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1 + start_index;
7591 return invoke_bf(ec, cfp, bf, argv);
7598rb_vm_lvar_exposed(rb_execution_context_t *ec,
int index)
7600 const rb_control_frame_t *cfp = ec->cfp;
7601 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.