9#if OPT_GLOBAL_METHOD_CACHE
10#ifndef GLOBAL_METHOD_CACHE_SIZE
11#define GLOBAL_METHOD_CACHE_SIZE 0x800
13#define LSB_ONLY(x) ((x) & ~((x) - 1))
14#define POWER_OF_2_P(x) ((x) == LSB_ONLY(x))
15#if !POWER_OF_2_P(GLOBAL_METHOD_CACHE_SIZE)
16# error GLOBAL_METHOD_CACHE_SIZE must be power of 2
18#ifndef GLOBAL_METHOD_CACHE_MASK
19#define GLOBAL_METHOD_CACHE_MASK (GLOBAL_METHOD_CACHE_SIZE-1)
22#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&(global_method_cache.mask))
23#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache.entries + GLOBAL_METHOD_CACHE_KEY(c,m))
25#define GLOBAL_METHOD_CACHE(c,m) (rb_bug("global method cache disabled improperly"), NULL)
28static int vm_redefinition_check_flag(
VALUE klass);
31#define object_id idObject_id
32#define added idMethod_added
33#define singleton_added idSingleton_method_added
34#define removed idMethod_removed
35#define singleton_removed idSingleton_method_removed
36#define undefined idMethod_undefined
37#define singleton_undefined idSingleton_method_undefined
38#define attached id__attached__
48#if OPT_GLOBAL_METHOD_CACHE
53} global_method_cache = {
54 GLOBAL_METHOD_CACHE_SIZE,
55 GLOBAL_METHOD_CACHE_MASK,
59#define ruby_running (GET_VM()->running)
105 rb_class_clear_method_cache(
klass, (
VALUE)&old_serial);
112 for (; entry !=
NULL; entry = entry->
next) {
144 rb_define_notimplement_method_id(
klass, mid, visi);
157 if (alias_count + complemented_count == 0) {
159 rb_id2name(def->original_id), alias_count, complemented_count);
168 alias_count, def->alias_count, complemented_count, def->complemented_count);
200 case -2:
return &call_cfunc_m2;
201 case -1:
return &call_cfunc_m1;
202 case 0:
return &call_cfunc_0;
203 case 1:
return &call_cfunc_1;
204 case 2:
return &call_cfunc_2;
205 case 3:
return &call_cfunc_3;
206 case 4:
return &call_cfunc_4;
207 case 5:
return &call_cfunc_5;
208 case 6:
return &call_cfunc_6;
209 case 7:
return &call_cfunc_7;
210 case 8:
return &call_cfunc_8;
211 case 9:
return &call_cfunc_9;
212 case 10:
return &call_cfunc_10;
213 case 11:
return &call_cfunc_11;
214 case 12:
return &call_cfunc_12;
215 case 13:
return &call_cfunc_13;
216 case 14:
return &call_cfunc_14;
217 case 15:
return &call_cfunc_15;
219 rb_bug(
"call_cfunc_func: unsupported length: %d",
argc);
246 if (0) vm_cref_dump(
"rb_method_definition_create", cref);
252 method_cref = vm_cref_new_toplevel(
GET_EC());
401 if (def !=
NULL) method_definition_reset(
me);
409 method_definition_addref(src_me->
def));
410 METHOD_ENTRY_FLAGS_COPY(
me, src_me);
430 refined.orig_me = orig_me;
435 def = method_definition_addref_complement(
def);
438 METHOD_ENTRY_FLAGS_COPY(
me, src_me);
454 method_definition_reset(dst);
458 METHOD_ENTRY_FLAGS_COPY(dst,
src);
474 rb_vm_check_redefinition_opt_method(
me,
me->
owner);
480 method_definition_addref(
me->
def));
481 METHOD_ENTRY_FLAGS_COPY(refined.orig_me,
me);
482 refined.owner =
owner;
496 make_method_entry_refined(refined_class,
me);
510 if (vm_redefinition_check_flag(
klass)) {
514 if (newme !=
me) rb_vm_check_redefinition_opt_method(
me,
me->
owner);
524 check_override_opt_method_i(
klass, mid);
541 int make_refined = 0;
567 if (old_me) rb_vm_check_redefinition_opt_method(old_me,
klass);
580 rb_vm_check_redefinition_opt_method(old_me,
klass);
595 switch (old_def->
type) {
597 iseq = def_iseq_ptr(old_def);
608 "previous definition of %"PRIsVALUE" was here",
639 make_method_entry_refined(
klass,
me);
655#define CALL_METHOD_HOOK(klass, hook, mid) do { \
656 const VALUE arg = ID2SYM(mid); \
657 VALUE recv_class = (klass); \
658 ID hook_id = (hook); \
659 if (FL_TEST((klass), FL_SINGLETON)) { \
660 recv_class = rb_ivar_get((klass), attached); \
661 hook_id = singleton_##hook; \
663 rb_funcallv(recv_class, hook_id, 1, &arg); \
680 method_added(
klass, mid);
692 iseq_body.iseqptr =
iseq;
693 iseq_body.cref = cref;
707 method_definition_addref(
me->
def);
709 method_added(
klass, mid);
719#define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
742 if (allocator)
return allocator;
754 if ((
me = lookup_method_table(
klass,
id)) != 0) {
761 if (defined_class_ptr)
762 *defined_class_ptr =
klass;
769 return lookup_method_table(
klass,
id);
780 VALUE *defined_class_ptr)
809 if (defined_class_ptr)
818 VALUE actual_defined_class;
820 method_entry_get_without_cache(
klass,
id, &actual_defined_class);
823 rb_bug(
"method cache verification failed");
830 return search_method0(
klass,
id, defined_class_ptr,
false);
843 if (defined_class_ptr) *defined_class_ptr = ent->
defined_class;
850 return method_entry_get_without_cache(
klass,
id, defined_class_ptr);
856 return method_entry_get(
klass,
id,
NULL);
899 return prepare_callable_method_entry(defined_class,
id,
me);
905method_entry_resolve_refinement(
VALUE klass,
ID id,
int with_refinement,
VALUE *defined_class_ptr)
911 if (with_refinement) {
913 VALUE refinements = cref ? CREF_REFINEMENTS(cref) :
Qnil;
914 me = resolve_refined_method(refinements,
me, defined_class_ptr);
917 me = resolve_refined_method(
Qnil,
me, defined_class_ptr);
930 return method_entry_resolve_refinement(
klass,
id,
TRUE, defined_class_ptr);
936 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
938 return prepare_callable_method_entry(*dcp,
id,
me);
944 return method_entry_resolve_refinement(
klass,
id,
FALSE, defined_class_ptr);
950 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
952 return prepare_callable_method_entry(*dcp,
id,
me);
963 refinement = find_refinement(refinements,
me->
owner);
964 if (!
NIL_P(refinement)) {
965 tmp_me = method_entry_get(refinement,
me->
called_id, defined_class_ptr);
974 if (defined_class_ptr) *defined_class_ptr = tmp_me->
defined_class;
983 me = method_entry_get(super,
me->
called_id, defined_class_ptr);
991 return resolve_refined_method(refinements,
me,
NULL);
1032 rb_vm_check_redefinition_opt_method(
me,
klass);
1045 remove_method(
klass, mid);
1076 remove_method(
mod,
id);
1085 VALUE defined_class;
1088 me = search_method0(origin_class,
name, &defined_class,
true);
1099 rb_vm_check_redefinition_opt_method(
me,
klass);
1101 if (
klass == defined_class || origin_class == defined_class) {
1102 METHOD_ENTRY_VISI_SET(
me, visi);
1115#define BOUND_PRIVATE 0x01
1116#define BOUND_RESPONDS 0x02
1157 vm_cref_set_visibility(visi,
FALSE);
1161scope_visibility_check(
void)
1166 rb_warn(
"calling %s without arguments inside a method may not have the intended effect",
1172rb_scope_module_func_set(
void)
1174 scope_visibility_check();
1191 switch (vm_scope_visibility_get(ec)) {
1193 if (vm_scope_module_func_check(ec)) {
1194 rb_warning(
"attribute accessor as module_function");
1229 me = search_method(
klass,
id, 0);
1308 VALUE mid, include_super, lookup_mod =
mod;
1320 inc_super =
RTEST(include_super);
1503 switch (def->
type) {
1523 d1 = original_method_definition(
d1);
1524 d2 = original_method_definition(d2);
1526 if (
d1 == d2)
return 1;
1527 if (!
d1 || !d2)
return 0;
1528 if (
d1->type != d2->
type)
return 0;
1554 rb_bug(
"rb_method_definition_eq: unsupported type: %d\n",
d1->type);
1561 def = original_method_definition(def);
1563 if (!def)
return hash;
1565 switch (def->
type) {
1588 rb_bug(
"rb_hash_method_definition: unsupported method type (%d)\n", def->
type);
1594 return rb_hash_method_definition(hash,
me->
def);
1601 VALUE defined_class;
1612 orig_me = search_method(
klass, original_name, &defined_class);
1620 (orig_me = search_method(
rb_cObject, original_name, &defined_class),
1636 rb_method_entry_make(target_klass, alias_name, target_klass, visi,
1639 method_added(target_klass, alias_name);
1644 alias_me = method_entry_set(target_klass, alias_name, orig_me, visi, orig_me->
owner);
1701 rb_export_method(
self,
id, visi);
1709 scope_visibility_check();
1713 set_method_visibility(module,
argc,
argv, visi);
1837 VALUE defined_class;
1843 me = search_method(origin_class,
name, &defined_class);
1853 if (module == defined_class || origin_class == defined_class) {
1863 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)",
rb_id2name(
name));
1869 procval = vm_proc_to_block_handler(VM_BH_TO_PROC(procval));
1882 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)",
rb_id2name(
name));
1889 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)",
rb_id2name(
name));
1894 rb_warn(
"Skipping set of ruby2_keywords flag for %s (can only set in method defining module)",
rb_id2name(
name));
2043 rb_scope_module_func_set();
2054 me = search_method(m,
id, 0);
2076 if (cd->
ci.
mid != mid) {
2080 vm_search_method_fastpath(cd,
klass);
2085#pragma push_macro("rb_method_basic_definition_p")
2086#undef rb_method_basic_definition_p
2097#pragma pop_macro("rb_method_basic_definition_p")
2105 prepare_callable_method_entry(defined_class,
id,
me);
2106 VALUE passed_block_handler = vm_passed_block_handler(ec);
2108 vm_passed_block_handler_set(ec, passed_block_handler);
2116 VALUE defined_class, args[2];
2119 method_entry_get(
klass, rtmid, &defined_class);
2148 VALUE defined_class;
2151 method_entry_get(
klass, resid, &defined_class);
2168 "respond_to? must accept 1 or 2 arguments (requires %d)",
2177 " the deprecated method signature, which takes one parameter",
2181 if (!
NIL_P(location)) {
2186 "respond_to? is defined here");
2192 return RTEST(result);
2201 int ret = vm_respond_to(ec,
klass,
obj,
id, priv);
2202 if (ret == -1) ret = basic_obj_respond_to(ec,
obj,
id, !priv);
2247 if (basic_obj_respond_to(ec,
obj,
id, !
RTEST(priv)))
2277 char *
ptr =
getenv(
"RUBY_GLOBAL_METHOD_CACHE_SIZE");
2281 if ((val & (val - 1)) == 0) {
2282 global_method_cache.size = val;
2283 global_method_cache.mask = val - 1;
2286 fprintf(
stderr,
"RUBY_GLOBAL_METHOD_CACHE_SIZE was set to %d but ignored because the value is not a power of 2.\n", val);
2291 if (global_method_cache.entries ==
NULL) {
2301#define rb_intern(str) rb_intern_const(str)
2323 "public", top_public, -1);
2325 "private", top_private, -1);
2327 "ruby2_keywords", top_ruby2_keywords, -1);
2330#define REPLICATE_METHOD(klass, id) do { \
2331 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
2332 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \
void rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
void rb_print_undef_str(VALUE klass, VALUE name)
#define rb_intern_str(string)
void rb_class_foreach_subclass(VALUE klass, void(*f)(VALUE, VALUE), VALUE)
VALUE rb_singleton_class(VALUE)
Returns the singleton class of obj.
void rb_class_modify_check(VALUE)
Asserts that klass is not a frozen class.
ID rb_frame_callee(void)
The name of the current method.
ID rb_frame_this_func(void)
The original name of the current method.
VALUE rb_mKernel
Kernel module.
VALUE rb_cBasicObject
BasicObject class.
VALUE rb_cObject
Object class.
VALUE rb_cModule
Module class.
void rb_notimplement(void)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_bug(const char *fmt,...)
void rb_warn(const char *fmt,...)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
void rb_id_table_clear(struct rb_id_table *tbl)
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
struct rb_id_table * rb_id_table_create(size_t capa)
int rb_id_table_delete(struct rb_id_table *tbl, ID id)
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_method_name_error(VALUE klass, VALUE str)
const struct rb_callable_method_entry_struct * me
struct rb_method_definition_struct *const def
const VALUE defined_class
union rb_captured_block::@53 code
const rb_scope_visibility_t scope_visi
unsigned int ruby2_keywords
enum rb_iseq_constant_body::iseq_type type
struct rb_iseq_constant_body::@45 param
rb_iseq_location_t location
struct rb_iseq_constant_body::@45::@47 flags
struct rb_iseq_constant_body * body
struct rb_method_entry_struct * original_me
struct rb_hook_list_struct * hooks
VALUE(* invoker)(VALUE recv, int argc, const VALUE *argv, VALUE(*func)())
unsigned int no_redef_warning
rb_method_bmethod_t bmethod
enum method_optimized_type optimize_type
union rb_method_definition_struct::@41 body
rb_method_refined_t refined
struct rb_method_definition_struct *const def
rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
rb_cref_t * cref
class reference, should be marked
struct rb_method_entry_struct * orig_me
rb_method_visibility_t method_visi
rb_subclass_entry_t * next
VALUE rb_vm_top_self(void)
int rb_method_basic_definition_p(VALUE klass, ID id)
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry(VALUE klass, ID id)
int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
#define CALL_METHOD_HOOK(klass, hook, mid)
void rb_attr(VALUE klass, ID id, int read, int write, int ex)
int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
MJIT_FUNC_EXPORTED const rb_method_entry_t * rb_method_entry(VALUE klass, ID id)
void rb_undef_alloc_func(VALUE klass)
void rb_clear_method_cache_by_class(VALUE klass)
const rb_method_entry_t * rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me)
void Init_eval_method(void)
void rb_clear_constant_cache(void)
void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src)
void rb_undef(VALUE klass, ID id)
void rb_add_refined_method_entry(VALUE refined_class, ID mid)
const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase)
bool rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid)
const rb_method_entry_t * rb_method_entry_at(VALUE klass, ID id)
const rb_method_entry_t * rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
void rb_remove_method(VALUE klass, const char *name)
MJIT_FUNC_EXPORTED rb_method_definition_t * rb_method_definition_create(rb_method_type_t type, ID mid)
void rb_free_method_entry(const rb_method_entry_t *me)
rb_alloc_func_t rb_get_alloc_func(VALUE klass)
void rb_alias(VALUE klass, ID alias_name, ID original_name)
#define REPLICATE_METHOD(klass, id)
const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me)
int rb_respond_to(VALUE obj, ID id)
rb_method_entry_t * rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi)
MJIT_FUNC_EXPORTED void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
int rb_obj_respond_to(VALUE obj, ID id, int priv)
void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_visibility_t visi)
void rb_remove_method_id(VALUE klass, ID mid)
MJIT_FUNC_EXPORTED void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
void rb_scope_visibility_set(rb_method_visibility_t visi)
#define GLOBAL_METHOD_CACHE(c, m)
const rb_method_entry_t * rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
void rb_define_alloc_func(VALUE klass, VALUE(*func)(VALUE))
VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class)
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me)
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc, rb_method_visibility_t visi)
st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
int rb_method_boundp(VALUE klass, ID id, int ex)
rb_method_entry_t * rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def)
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)