1#ifndef RUBY_VM_CALLINFO_H
2#define RUBY_VM_CALLINFO_H
11#include "debug_counter.h"
13enum vm_call_flag_bits {
14 VM_CALL_ARGS_SPLAT_bit,
15 VM_CALL_ARGS_BLOCKARG_bit,
18 VM_CALL_ARGS_SIMPLE_bit,
19 VM_CALL_BLOCKISEQ_bit,
26 VM_CALL_KW_SPLAT_MUT_bit,
30#define VM_CALL_ARGS_SPLAT (0x01 << VM_CALL_ARGS_SPLAT_bit)
31#define VM_CALL_ARGS_BLOCKARG (0x01 << VM_CALL_ARGS_BLOCKARG_bit)
32#define VM_CALL_FCALL (0x01 << VM_CALL_FCALL_bit)
33#define VM_CALL_VCALL (0x01 << VM_CALL_VCALL_bit)
34#define VM_CALL_ARGS_SIMPLE (0x01 << VM_CALL_ARGS_SIMPLE_bit)
35#define VM_CALL_BLOCKISEQ (0x01 << VM_CALL_BLOCKISEQ_bit)
36#define VM_CALL_KWARG (0x01 << VM_CALL_KWARG_bit)
37#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit)
38#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit)
39#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit)
40#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
41#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
42#define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit)
50rb_callinfo_kwarg_bytes(
int keyword_len)
52 return rb_size_mul_add_or_raise(
73#define CI_EMBED_TAG_bits 1
74#define CI_EMBED_ARGC_bits 15
75#define CI_EMBED_FLAG_bits 16
76#define CI_EMBED_ID_bits 32
77#elif SIZEOF_VALUE == 4
78#define CI_EMBED_TAG_bits 1
79#define CI_EMBED_ARGC_bits 3
80#define CI_EMBED_FLAG_bits 13
81#define CI_EMBED_ID_bits 15
84#if (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits + CI_EMBED_FLAG_bits + CI_EMBED_ID_bits) != (SIZEOF_VALUE * 8)
88#define CI_EMBED_FLAG 0x01
89#define CI_EMBED_ARGC_SHFT (CI_EMBED_TAG_bits)
90#define CI_EMBED_ARGC_MASK ((((VALUE)1)<<CI_EMBED_ARGC_bits) - 1)
91#define CI_EMBED_FLAG_SHFT (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits)
92#define CI_EMBED_FLAG_MASK ((((VALUE)1)<<CI_EMBED_FLAG_bits) - 1)
93#define CI_EMBED_ID_SHFT (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits + CI_EMBED_FLAG_bits)
94#define CI_EMBED_ID_MASK ((((VALUE)1)<<CI_EMBED_ID_bits) - 1)
100 if (LIKELY(((VALUE)ci) & 0x01)) {
104 VM_ASSERT(IMEMO_TYPE_P(ci, imemo_callinfo));
115 if (vm_ci_packed_p(ci) || IMEMO_TYPE_P(ci, imemo_callinfo)) {
126 if (vm_ci_packed_p(ci)) {
127 return (((VALUE)ci) >> CI_EMBED_ID_SHFT) & CI_EMBED_ID_MASK;
134static inline unsigned int
137 if (vm_ci_packed_p(ci)) {
138 return (
unsigned int)((((
VALUE)ci) >> CI_EMBED_FLAG_SHFT) & CI_EMBED_FLAG_MASK);
141 return (
unsigned int)ci->flag;
145static inline unsigned int
148 if (vm_ci_packed_p(ci)) {
149 return (
unsigned int)((((
VALUE)ci) >> CI_EMBED_ARGC_SHFT) & CI_EMBED_ARGC_MASK);
152 return (
unsigned int)ci->argc;
159 if (vm_ci_packed_p(ci)) {
170 if (vm_ci_packed_p(ci)) {
171 ruby_debug_printf(
"packed_ci ID:%s flag:%x argc:%u\n",
172 rb_id2name(vm_ci_mid(ci)), vm_ci_flag(ci), vm_ci_argc(ci));
179#define vm_ci_new(mid, flag, argc, kwarg) vm_ci_new_(mid, flag, argc, kwarg, __FILE__, __LINE__)
180#define vm_ci_new_runtime(mid, flag, argc, kwarg) vm_ci_new_runtime_(mid, flag, argc, kwarg, __FILE__, __LINE__)
183#define VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg) \
184 (((mid ) & ~CI_EMBED_ID_MASK) ? false : \
185 ((flag) & ~CI_EMBED_FLAG_MASK) ? false : \
186 ((argc) & ~CI_EMBED_ARGC_MASK) ? false : \
187 (kwarg) ? false : true)
189#define vm_ci_new_id(mid, flag, argc, must_zero) \
190 ((const struct rb_callinfo *) \
191 ((((VALUE)(mid )) << CI_EMBED_ID_SHFT) | \
192 (((VALUE)(flag)) << CI_EMBED_FLAG_SHFT) | \
193 (((VALUE)(argc)) << CI_EMBED_ARGC_SHFT) | \
197vm_ci_new_(ID mid,
unsigned int flag,
unsigned int argc,
const struct rb_callinfo_kwarg *kwarg,
const char *file,
int line)
200 if (VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg)) {
201 RB_DEBUG_COUNTER_INC(ci_packed);
202 return vm_ci_new_id(mid, flag, argc, kwarg);
206 const bool debug = 0;
207 if (debug) ruby_debug_printf(
"%s:%d ", file, line);
211 rb_imemo_new(imemo_callinfo,
218 RB_DEBUG_COUNTER_INC(ci_kw);
221 RB_DEBUG_COUNTER_INC(ci_nokw);
224 VM_ASSERT(vm_ci_flag(ci) == flag);
225 VM_ASSERT(vm_ci_argc(ci) == argc);
232vm_ci_new_runtime_(ID mid,
unsigned int flag,
unsigned int argc,
const struct rb_callinfo_kwarg *kwarg,
const char *file,
int line)
234 RB_DEBUG_COUNTER_INC(ci_runtime);
235 return vm_ci_new_(mid, flag, argc, kwarg, file, line);
238#define VM_CALLINFO_NOT_UNDER_GC IMEMO_FL_USER0
246 else if (vm_ci_packed_p(ci)) {
250 VM_ASSERT(IMEMO_TYPE_P(ci, imemo_callinfo));
251 return !
FL_ANY_RAW((VALUE)ci, VM_CALLINFO_NOT_UNDER_GC);
255#define VM_CI_ON_STACK(mid_, flags_, argc_, kwarg_) \
256 (struct rb_callinfo) { \
258 (imemo_callinfo << FL_USHIFT) | \
259 VM_CALLINFO_NOT_UNDER_GC, \
266typedef VALUE (*vm_call_handler)(
283 const vm_call_handler call_;
286 const unsigned int attr_index;
287 const enum method_missing_reason method_missing_reason;
292#define VM_CALLCACHE_UNMARKABLE IMEMO_FL_USER0
293#define VM_CALLCACHE_ON_STACK IMEMO_FL_USER1
296vm_cc_new(VALUE klass,
298 vm_call_handler call)
301 RB_DEBUG_COUNTER_INC(cc_new);
305#define VM_CC_ON_STACK(clazz, call, aux, cme) \
306 (struct rb_callcache) { \
308 (imemo_callcache << FL_USHIFT) | \
309 VM_CALLCACHE_UNMARKABLE | \
310 VM_CALLCACHE_ON_STACK, \
318vm_cc_class_check(
const struct rb_callcache *cc, VALUE klass)
320 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
321 VM_ASSERT(cc->klass == 0 ||
323 return cc->klass == klass;
329 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
330 return FL_TEST_RAW((VALUE)cc, VM_CALLCACHE_UNMARKABLE) == 0;
336 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
337 VM_ASSERT(cc->call_ == NULL ||
338 !vm_cc_markable(cc) ||
344static inline vm_call_handler
347 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
348 VM_ASSERT(cc->call_ != NULL);
352static inline unsigned int
355 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
356 return cc->aux_.attr_index;
359static inline unsigned int
360vm_cc_cmethod_missing_reason(
const struct rb_callcache *cc)
362 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
363 return cc->aux_.method_missing_reason;
369 if (cc->klass && !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc))) {
381 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
382 if (cc->klass == klass && !METHOD_ENTRY_INVALIDATED(cc_cme)) {
391extern const struct rb_callcache *rb_vm_empty_cc_for_super(
void);
392#define vm_cc_empty() rb_vm_empty_cc()
397vm_cc_call_set(
const struct rb_callcache *cc, vm_call_handler call)
399 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
400 VM_ASSERT(cc != vm_cc_empty());
401 *(vm_call_handler *)&cc->call_ = call;
405vm_cc_attr_index_set(
const struct rb_callcache *cc,
int index)
407 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
408 VM_ASSERT(cc != vm_cc_empty());
409 *(
int *)&cc->aux_.attr_index = index;
413vm_cc_method_missing_reason_set(
const struct rb_callcache *cc,
enum method_missing_reason reason)
415 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
416 VM_ASSERT(cc != vm_cc_empty());
417 *(
enum method_missing_reason *)&cc->aux_.method_missing_reason = reason;
423 VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
424 VM_ASSERT(cc != vm_cc_empty());
425 VM_ASSERT(cc->klass != 0);
427 *(VALUE *)&cc->klass = 0;
428 RB_DEBUG_COUNTER_INC(cc_ent_invalidate);
445 struct rb_class_cc_entries_entry {
454void rb_vm_dump_overloaded_cme_table(
void);
459 return ccs->debug_sig == ~(
VALUE)ccs;
465 if (vm_cc_cme(cc) == cme ||
466 (cme->def->iseq_overload && vm_cc_cme(cc) == rb_vm_lookup_overloaded_cme(cme))) {
473 fprintf(stderr,
"iseq_overload:%d\n", (
int)cme->def->iseq_overload);
476 rb_vm_lookup_overloaded_cme(cme);
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define FL_ANY_RAW
Old name of RB_FL_ANY_RAW.
#define T_CLASS
Old name of RUBY_T_CLASS.
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.