Ruby
2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
|
Go to the documentation of this file.
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 = {
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;
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);
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;
562 VALUE refined_class = rb_refinement_module_get_refined_class(
klass);
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",
638 make_method_entry_refined(
klass,
me);
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); \
679 method_added(
klass, mid);
691 iseq_body.iseqptr =
iseq;
692 iseq_body.cref = cref;
702 method_added(
klass, mid);
712 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
735 if (allocator)
return allocator;
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);
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");
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);
1015 rb_vm_check_redefinition_opt_method(
me,
klass);
1028 remove_method(
klass, mid);
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
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");
1212 me = search_method(
klass,
id, 0);
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);
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);
1684 rb_export_method(
self,
id, visi);
1692 scope_visibility_check();
1696 set_method_visibility(module,
argc,
argv, visi);
1820 VALUE defined_class;
1826 me = search_method(origin_class,
name, &defined_class);
1836 if (module == defined_class || origin_class == defined_class) {
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();
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
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);
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");
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);
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) {
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)); \
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc, rb_method_visibility_t visi)
#define REPLICATE_METHOD(klass, id)
rb_subclass_entry_t * next
int rb_method_entry_arity(const rb_method_entry_t *me)
const char * rb_id2name(ID)
int rb_method_basic_definition_p(VALUE klass, ID id)
void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_visibility_t visi)
@ block_handler_type_iseq
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
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_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
@ VM_METHOD_TYPE_REFINED
refinement
VALUE(* invoker)(VALUE recv, int argc, const VALUE *argv, VALUE(*func)(ANYARGS))
@ VM_METHOD_TYPE_OPTIMIZED
Kernel::send, Proc::call, etc.
#define PREV_CLASS_SERIAL()
void rb_warn(const char *fmt,...)
struct cache_entry * entries
void rb_warning(const char *fmt,...)
st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
void rb_undef(VALUE klass, ID id)
rb_cref_t * cref
class reference, should be marked
const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase)
int rb_vm_check_optimizable_mid(VALUE mid)
VALUE rb_to_symbol(VALUE name)
MJIT_FUNC_EXPORTED const char * rb_obj_info(VALUE obj)
void rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
const struct rb_callable_method_entry_struct * me
void rb_method_name_error(VALUE klass, VALUE str)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
#define GLOBAL_METHOD_CACHE(c, m)
rb_method_visibility_t method_visi
#define RB_TYPE_P(obj, type)
RUBY_EXTERN VALUE rb_cModule
@ block_handler_type_proc
struct rb_method_definition_struct *const def
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
VALUE rb_iseq_path(const rb_iseq_t *iseq)
rb_iseq_location_t location
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
enum method_optimized_type optimize_type
rb_method_refined_t refined
struct rb_method_entry_struct * orig_me
int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
int rb_respond_to(VALUE obj, ID id)
#define METHOD_ENTRY_COMPLEMENTED_SET(me)
rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
struct rb_iseq_constant_body::@3 param
parameter information
void rb_free_method_entry(const rb_method_entry_t *me)
#define INC_GLOBAL_METHOD_STATE()
const rb_method_entry_t * rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
rb_cref_t * rb_vm_cref(void)
rb_method_bmethod_t bmethod
@ VM_METHOD_TYPE_IVAR
attr_reader or attr_accessor
int rb_obj_respond_to(VALUE obj, ID id, int priv)
const rb_method_entry_t * rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me)
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_notimplement(void)
if((ID)(DISPID) nameid !=nameid)
VALUE rb_method_entry_location(const rb_method_entry_t *me)
void rb_undef_alloc_func(VALUE klass)
const rb_scope_visibility_t scope_visi
RUBY_EXTERN VALUE rb_cBasicObject
#define rb_check_frozen(obj)
const VALUE defined_class
#define METHOD_ENTRY_VISI(me)
ID rb_frame_this_func(void)
The original name of the current method.
void rb_remove_method_id(VALUE klass, ID mid)
void rb_attr(VALUE klass, ID id, int read, int write, int ex)
unsigned long rb_serial_t
VALUE rb_vm_top_self(void)
#define RB_OBJ_WRITTEN(a, oldv, b)
void rb_clear_constant_cache(void)
void Init_eval_method(void)
void rb_compile_warning(const char *file, int line, const char *fmt,...)
@ VM_METHOD_TYPE_CFUNC
C method.
const rb_method_entry_t * rb_method_entry_at(VALUE klass, ID id)
const rb_method_entry_t * rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
@ VM_METHOD_TYPE_NOTIMPLEMENTED
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)
rb_method_entry_t * rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def)
#define METHOD_ENTRY_BASIC(me)
#define RARRAY_AREF(a, i)
#define RCLASS_CALLABLE_M_TBL(c)
enum rb_iseq_constant_body::iseq_type type
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry(VALUE klass, ID id)
#define GET_GLOBAL_METHOD_STATE()
struct rb_method_entry_struct * original_me
MJIT_FUNC_EXPORTED void rb_gc_writebarrier_remember(VALUE obj)
const char * rb_class2name(VALUE)
#define RB_OBJ_WRITE(a, slot, b)
#define OPT_GLOBAL_METHOD_CACHE
VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
ID rb_frame_callee(void)
The name of the current method.
void rb_define_alloc_func(VALUE klass, VALUE(*func)(VALUE))
void rb_alias(VALUE klass, ID alias_name, ID original_name)
struct rb_hook_list_struct * hooks
#define CALL_METHOD_HOOK(klass, hook, mid)
RUBY_EXTERN VALUE rb_cObject
#define GLOBAL_METHOD_CACHE_SIZE
@ VM_METHOD_TYPE_MISSING
wrapper for method_missing(id)
void rb_bug(const char *fmt,...)
MJIT_FUNC_EXPORTED const rb_method_entry_t * rb_method_entry(VALUE klass, ID id)
RUBY_EXTERN VALUE rb_mKernel
bool rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid)
#define rb_hash_uint(h, i)
MJIT_FUNC_EXPORTED rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
@ VM_METHOD_TYPE_ATTRSET
attr_writer or attr_accessor
VALUE rb_sprintf(const char *format,...)
rb_serial_t rb_next_class_serial(void)
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)
union rb_method_definition_struct::@0 body
void rb_print_undef_str(VALUE klass, VALUE name)
void rb_class_foreach_subclass(VALUE klass, void(*f)(VALUE, VALUE), VALUE arg)
rb_method_entry_t * rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi)
#define INC_GLOBAL_CONSTANT_STATE()
VALUE(* rb_alloc_func_t)(VALUE)
struct rb_id_table * rb_id_table_create(size_t capa)
@ VM_METHOD_TYPE_ISEQ
Ruby method.
union rb_captured_block::@11 code
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
struct rb_iseq_constant_body::@3::@5 flags
void rb_clear_method_cache_by_class(VALUE klass)
VALUE rb_ary_freeze(VALUE ary)
#define RUBY_DTRACE_HOOK(name, arg)
const rb_iseq_t * rb_proc_get_iseq(VALUE proc, int *is_proc)
#define MJIT_FUNC_EXPORTED
#define GLOBAL_METHOD_CACHE_MASK
void rb_compile_warn(const char *file, int line, const char *fmt,...)
struct rb_method_definition_struct *const def
#define RB_DEBUG_COUNTER_INC(type)
struct rb_iseq_constant_body * body
st_index_t rb_hash_proc(st_index_t hash, VALUE proc)
#define UNDEFINED_REFINED_METHOD_P(def)
#define rb_intern_str(string)
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)
MJIT_FUNC_EXPORTED void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
rb_alloc_func_t rb_get_alloc_func(VALUE klass)
void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src)
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
int rb_id_table_delete(struct rb_id_table *tbl, ID id)
void rb_add_refined_method_entry(VALUE refined_class, ID mid)
VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
void rb_scope_visibility_set(rb_method_visibility_t visi)
#define rb_name_err_raise(mesg, recv, name)
#define UNALIGNED_MEMBER_PTR(ptr, mem)
#define UNREACHABLE_RETURN(val)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
#define METHOD_ENTRY_COMPLEMENTED(me)
#define VM_DEBUG_VERIFY_METHOD_CACHE
const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me)
void rb_id_table_clear(struct rb_id_table *tbl)
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define UNDEFINED_METHOD_ENTRY_P(me)
int rb_method_boundp(VALUE klass, ID id, int ex)