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)
28 static 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)
63 rb_class_clear_method_cache(
VALUE klass,
VALUE arg)
95 if (klass && klass !=
Qundef) {
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) {
158 if (
METHOD_DEBUG) fprintf(stderr,
"-%p-%s:%d,%d (remove)\n", (
void *)def,
159 rb_id2name(def->original_id), alias_count, complemented_count);
167 if (
METHOD_DEBUG) fprintf(stderr,
"-%p-%s:%d->%d,%d->%d (dec)\n", (
void *)def,
rb_id2name(def->original_id),
168 alias_count, def->alias_count, complemented_count, def->complemented_count);
183 lookup_method_table(
VALUE klass,
ID id)
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());
363 if (
METHOD_DEBUG) fprintf(stderr,
"+%p-%s:%d\n", (
void *)def,
rb_id2name(def->original_id), def->alias_count);
371 if (
METHOD_DEBUG) fprintf(stderr,
"+%p-%s:%d\n", (
void *)def,
rb_id2name(def->original_id), def->complemented_count);
383 filter_defined_class(
VALUE klass)
399 rb_method_entry_t *me = rb_method_entry_alloc(called_id, klass, filter_defined_class(klass), def);
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;
431 refined.owner = orig_me->owner;
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);
505 check_override_opt_method_i(
VALUE klass,
VALUE arg)
510 if (vm_redefinition_check_flag(klass)) {
514 if (newme != me) rb_vm_check_redefinition_opt_method(me, me->
owner);
521 check_override_opt_method(
VALUE klass,
VALUE mid)
524 check_override_opt_method_i(klass, mid);
541 int make_refined = 0;
551 case idInitialize_copy:
552 case idInitialize_clone:
553 case idInitialize_dup:
567 if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
580 rb_vm_check_redefinition_opt_method(old_me, klass);
594 switch (old_def->type) {
596 iseq = def_iseq_ptr(old_def);
607 "previous definition of %"PRIsVALUE" was here",
625 case idMethodMissing:
631 if (mid ==
object_id || mid == id__send__) {
638 make_method_entry_refined(klass, me);
648 check_override_opt_method(klass, (
VALUE)mid);
654 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
655 const VALUE arg = ID2SYM(mid); \
656 VALUE recv_class = (klass); \
657 ID hook_id = (hook); \
658 if (FL_TEST((klass), FL_SINGLETON)) { \
659 recv_class = rb_ivar_get((klass), attached); \
660 hook_id = singleton_##hook; \
662 rb_funcallv(recv_class, hook_id, 1, &arg); \
666 method_added(
VALUE klass,
ID mid)
676 rb_method_entry_make(klass, mid, klass, visi,
type,
NULL, mid, opts);
679 method_added(klass, mid);
691 iseq_body.iseqptr = iseq;
692 iseq_body.cref = cref;
701 me->
def->type, method_definition_addref(me->
def), 0,
NULL);
702 method_added(klass, mid);
709 return method_entry_set(klass, mid, me, visi, klass);
712 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
735 if (allocator)
return allocator;
741 search_method(
VALUE klass,
ID id,
VALUE *defined_class_ptr)
747 if ((me = lookup_method_table(klass,
id)) != 0)
break;
750 if (defined_class_ptr)
751 *defined_class_ptr = klass;
758 return lookup_method_table(klass,
id);
768 method_entry_get_without_cache(
VALUE klass,
ID id,
769 VALUE *defined_class_ptr)
798 if (defined_class_ptr)
807 VALUE actual_defined_class;
809 method_entry_get_without_cache(klass,
id, &actual_defined_class);
812 rb_bug(
"method cache verification failed");
817 method_entry_get(
VALUE klass,
ID id,
VALUE *defined_class_ptr)
826 if (defined_class_ptr) *defined_class_ptr = ent->
defined_class;
833 return method_entry_get_without_cache(klass,
id, defined_class_ptr);
839 return method_entry_get(klass,
id,
NULL);
882 return prepare_callable_method_entry(defined_class,
id, me);
888 method_entry_resolve_refinement(
VALUE klass,
ID id,
int with_refinement,
VALUE *defined_class_ptr)
894 if (with_refinement) {
896 VALUE refinements = cref ? CREF_REFINEMENTS(cref) :
Qnil;
897 me = resolve_refined_method(refinements, me, defined_class_ptr);
900 me = resolve_refined_method(
Qnil, me, defined_class_ptr);
913 return method_entry_resolve_refinement(klass,
id,
TRUE, defined_class_ptr);
919 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
921 return prepare_callable_method_entry(*dcp,
id, me);
927 return method_entry_resolve_refinement(klass,
id,
FALSE, defined_class_ptr);
933 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
935 return prepare_callable_method_entry(*dcp,
id, me);
946 refinement = find_refinement(refinements, me->
owner);
947 if (!
NIL_P(refinement)) {
948 tmp_me = method_entry_get(refinement, me->
called_id, defined_class_ptr);
957 if (defined_class_ptr) *defined_class_ptr = tmp_me->
defined_class;
966 me = method_entry_get(super, me->
called_id, defined_class_ptr);
974 return resolve_refined_method(refinements, me,
NULL);
993 remove_method(
VALUE klass,
ID mid)
1001 if (mid ==
object_id || mid == id__send__ || mid == idInitialize) {
1015 rb_vm_check_redefinition_opt_method(me, klass);
1028 remove_method(klass, mid);
1052 for (i = 0; i <
argc; i++) {
1059 remove_method(
mod,
id);
1068 VALUE defined_class;
1071 me = search_method(origin_class,
name, &defined_class);
1082 rb_vm_check_redefinition_opt_method(me, klass);
1084 if (klass == defined_class || origin_class == defined_class) {
1085 METHOD_ENTRY_VISI_SET(me, visi);
1098 #define BOUND_PRIVATE 0x01
1099 #define BOUND_RESPONDS 0x02
1107 me = method_entry_resolve_refinement(klass,
id,
TRUE,
NULL);
1133 scope_visi->method_visi = method_visi;
1140 vm_cref_set_visibility(visi,
FALSE);
1144 scope_visibility_check(
void)
1149 rb_warn(
"calling %s without arguments inside a method may not have the intended effect",
1155 rb_scope_module_func_set(
void)
1157 scope_visibility_check();
1174 switch (vm_scope_visibility_get(ec)) {
1176 if (vm_scope_module_func_check(ec)) {
1177 rb_warning(
"attribute accessor as module_function");
1208 if (
id ==
object_id ||
id == id__send__ ||
id == idInitialize) {
1212 me = search_method(klass,
id, 0);
1276 for (i = 0; i <
argc; i++) {
1291 VALUE mid, include_super, lookup_mod =
mod;
1303 inc_super =
RTEST(include_super);
1486 switch (def->type) {
1506 d1 = original_method_definition(
d1);
1507 d2 = original_method_definition(d2);
1509 if (
d1 == d2)
return 1;
1510 if (!
d1 || !d2)
return 0;
1511 if (
d1->type != d2->type)
return 0;
1537 rb_bug(
"rb_method_definition_eq: unsupported type: %d\n",
d1->type);
1544 def = original_method_definition(def);
1546 if (!def)
return hash;
1548 switch (def->type) {
1571 rb_bug(
"rb_hash_method_definition: unsupported method type (%d)\n", def->type);
1577 return rb_hash_method_definition(hash, me->
def);
1583 const VALUE target_klass = klass;
1584 VALUE defined_class;
1595 orig_me = search_method(klass, original_name, &defined_class);
1603 (orig_me = search_method(
rb_cObject, original_name, &defined_class),
1619 rb_method_entry_make(target_klass, alias_name, target_klass, visi,
1622 method_added(target_klass, alias_name);
1627 alias_me = method_entry_set(target_klass, alias_name, orig_me, visi, orig_me->
owner);
1678 for (i = 0; i <
argc; i++) {
1684 rb_export_method(
self,
id, visi);
1692 scope_visibility_check();
1696 set_method_visibility(module,
argc,
argv, visi);
1816 for (i = 0; i <
argc; i++) {
1820 VALUE defined_class;
1826 me = search_method(origin_class,
name, &defined_class);
1836 if (module == defined_class || origin_class == defined_class) {
1837 switch (me->
def->type) {
1846 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)",
rb_id2name(
name));
1852 procval = vm_proc_to_block_handler(VM_BH_TO_PROC(procval));
1865 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)",
rb_id2name(
name));
1872 rb_warn(
"Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)",
rb_id2name(
name));
1877 rb_warn(
"Skipping set of ruby2_keywords flag for %s (can only set in method defining module)",
rb_id2name(
name));
2026 rb_scope_module_func_set();
2032 for (i = 0; i <
argc; i++) {
2037 me = search_method(m,
id, 0);
2059 if (cd->
ci.
mid != mid) {
2063 vm_search_method_fastpath(cd, klass);
2068 #pragma push_macro("rb_method_basic_definition_p")
2069 #undef rb_method_basic_definition_p
2075 if (!klass)
return TRUE;
2080 #pragma pop_macro("rb_method_basic_definition_p")
2088 prepare_callable_method_entry(defined_class,
id, me);
2089 VALUE passed_block_handler = vm_passed_block_handler(ec);
2091 vm_passed_block_handler_set(ec, passed_block_handler);
2099 VALUE defined_class, args[2];
2102 method_entry_get(klass, rtmid, &defined_class);
2107 return call_method_entry(ec, defined_class, obj, rtmid, me, 2, args,
RB_NO_KEYWORDS);
2120 ret = basic_obj_respond_to_missing(ec, klass, obj,
ID2SYM(
id),
2131 VALUE defined_class;
2134 method_entry_get(klass, resid, &defined_class);
2151 "respond_to? must accept 1 or 2 arguments (requires %d)",
2160 " the deprecated method signature, which takes one parameter",
2164 if (!
NIL_P(location)) {
2169 "respond_to? is defined here");
2174 result = call_method_entry(ec, defined_class, obj, resid, me,
argc, args,
RB_NO_KEYWORDS);
2175 return RTEST(result);
2184 int ret = vm_respond_to(ec, klass, obj,
id, priv);
2185 if (ret == -1) ret = basic_obj_respond_to(ec, obj,
id, !priv);
2225 VALUE ret = basic_obj_respond_to_missing(ec,
CLASS_OF(obj), obj,
2230 if (basic_obj_respond_to(ec, obj,
id, !
RTEST(priv)))
2260 char *
ptr =
getenv(
"RUBY_GLOBAL_METHOD_CACHE_SIZE");
2264 if ((val & (val - 1)) == 0) {
2265 global_method_cache.size = val;
2266 global_method_cache.mask = val - 1;
2269 fprintf(stderr,
"RUBY_GLOBAL_METHOD_CACHE_SIZE was set to %d but ignored because the value is not a power of 2.\n", val);
2274 if (global_method_cache.entries ==
NULL) {
2275 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
2284 #define rb_intern(str) rb_intern_const(str)
2306 "public", top_public, -1);
2308 "private", top_private, -1);
2310 "ruby2_keywords", top_ruby2_keywords, -1);
2313 #define REPLICATE_METHOD(klass, id) do { \
2314 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
2315 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \