2 * This file is included by vm.c
11 static int vm_redefinition_check_flag(VALUE klass
);
12 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t
*me
, VALUE klass
);
13 static inline rb_method_entry_t
*lookup_method_table(VALUE klass
, ID id
);
15 #define object_id idObject_id
16 #define added idMethod_added
17 #define singleton_added idSingleton_method_added
18 #define removed idMethod_removed
19 #define singleton_removed idSingleton_method_removed
20 #define undefined idMethod_undefined
21 #define singleton_undefined idSingleton_method_undefined
23 #define ruby_running (GET_VM()->running)
24 /* int ruby_running = 0; */
26 static enum rb_id_table_iterator_result
27 vm_ccs_dump_i(ID mid
, VALUE val
, void *data
)
29 const struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)val
;
30 fprintf(stderr
, " | %s (len:%d) ", rb_id2name(mid
), ccs
->len
);
33 for (int i
=0; i
<ccs
->len
; i
++) {
34 rp_m( " | \t", ccs
->entries
[i
].cc
);
37 return ID_TABLE_CONTINUE
;
41 vm_ccs_dump(VALUE klass
, ID target_mid
)
43 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
47 if (rb_id_table_lookup(cc_tbl
, target_mid
, &ccs
)) {
48 fprintf(stderr
, " [CCTB] %p\n", (void *)cc_tbl
);
49 vm_ccs_dump_i(target_mid
, ccs
, NULL
);
53 fprintf(stderr
, " [CCTB] %p\n", (void *)cc_tbl
);
54 rb_id_table_foreach(cc_tbl
, vm_ccs_dump_i
, (void *)target_mid
);
59 static enum rb_id_table_iterator_result
60 vm_cme_dump_i(ID mid
, VALUE val
, void *data
)
62 ID target_mid
= (ID
)data
;
63 if (target_mid
== 0 || mid
== target_mid
) {
66 return ID_TABLE_CONTINUE
;
70 vm_mtbl_dump(VALUE klass
, ID target_mid
)
72 fprintf(stderr
, "# vm_mtbl\n");
77 if (RCLASS_M_TBL(klass
)) {
78 if (target_mid
!= 0) {
79 if (rb_id_table_lookup(RCLASS_M_TBL(klass
), target_mid
, &me
)) {
84 fprintf(stderr
, " ## RCLASS_M_TBL (%p)\n", (void *)RCLASS_M_TBL(klass
));
85 rb_id_table_foreach(RCLASS_M_TBL(klass
), vm_cme_dump_i
, NULL
);
89 fprintf(stderr
, " MTBL: NULL\n");
91 if (RCLASS_CALLABLE_M_TBL(klass
)) {
92 if (target_mid
!= 0) {
93 if (rb_id_table_lookup(RCLASS_CALLABLE_M_TBL(klass
), target_mid
, &me
)) {
98 fprintf(stderr
, " ## RCLASS_CALLABLE_M_TBL\n");
99 rb_id_table_foreach(RCLASS_CALLABLE_M_TBL(klass
), vm_cme_dump_i
, NULL
);
102 if (RCLASS_CC_TBL(klass
)) {
103 vm_ccs_dump(klass
, target_mid
);
105 klass
= RCLASS_SUPER(klass
);
111 rb_vm_mtbl_dump(const char *msg
, VALUE klass
, ID target_mid
)
113 fprintf(stderr
, "[%s] ", msg
);
114 vm_mtbl_dump(klass
, target_mid
);
118 vm_cme_invalidate(rb_callable_method_entry_t
*cme
)
120 VM_ASSERT(IMEMO_TYPE_P(cme
, imemo_ment
), "cme: %d", imemo_type((VALUE
)cme
));
121 VM_ASSERT(callable_method_entry_p(cme
));
122 METHOD_ENTRY_INVALIDATED_SET(cme
);
123 RB_DEBUG_COUNTER_INC(cc_cme_invalidate
);
125 rb_yjit_cme_invalidate(cme
);
126 rb_rjit_cme_invalidate(cme
);
130 rb_clear_constant_cache_for_id_i(st_data_t ic
, st_data_t idx
, st_data_t arg
)
132 ((IC
) ic
)->entry
= NULL
;
136 // Here for backward compat.
137 void rb_clear_constant_cache(void) {}
140 rb_clear_constant_cache_for_id(ID id
)
143 rb_vm_t
*vm
= GET_VM();
145 if (rb_id_table_lookup(vm
->constant_cache
, id
, &lookup_result
)) {
146 st_table
*ics
= (st_table
*)lookup_result
;
147 st_foreach(ics
, rb_clear_constant_cache_for_id_i
, (st_data_t
) NULL
);
148 ruby_vm_constant_cache_invalidations
+= ics
->num_entries
;
151 rb_yjit_constant_state_changed(id
);
152 rb_rjit_constant_state_changed(id
);
156 invalidate_negative_cache(ID mid
)
159 rb_vm_t
*vm
= GET_VM();
161 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme
)) {
162 rb_id_table_delete(vm
->negative_cme_table
, mid
);
163 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
164 RB_DEBUG_COUNTER_INC(cc_invalidate_negative
);
168 const rb_method_entry_t
* rb_method_entry_clone(const rb_method_entry_t
*src_me
);
169 static const rb_callable_method_entry_t
*complemented_callable_method_entry(VALUE klass
, ID id
);
170 static const rb_callable_method_entry_t
*lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
);
174 clear_method_cache_by_id_in_class(VALUE klass
, ID mid
)
176 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
177 if (rb_objspace_garbage_object_p(klass
)) return;
180 if (LIKELY(RCLASS_SUBCLASSES(klass
) == NULL
)) {
182 // check only current class
184 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
188 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
189 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
190 rb_yjit_cme_invalidate((rb_callable_method_entry_t
*)ccs
->cme
);
191 rb_rjit_cme_invalidate((rb_callable_method_entry_t
*)ccs
->cme
);
192 if (NIL_P(ccs
->cme
->owner
)) invalidate_negative_cache(mid
);
194 rb_id_table_delete(cc_tbl
, mid
);
195 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs
);
198 // remove from callable_m_tbl, if exists
199 struct rb_id_table
*cm_tbl
;
200 if ((cm_tbl
= RCLASS_CALLABLE_M_TBL(klass
)) != NULL
) {
202 if (rb_yjit_enabled_p
&& rb_id_table_lookup(cm_tbl
, mid
, &cme
)) {
203 rb_yjit_cme_invalidate((rb_callable_method_entry_t
*)cme
);
205 if (rb_rjit_enabled
&& rb_id_table_lookup(cm_tbl
, mid
, &cme
)) {
206 rb_rjit_cme_invalidate((rb_callable_method_entry_t
*)cme
);
208 rb_id_table_delete(cm_tbl
, mid
);
209 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_callable
);
211 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf
);
214 const rb_callable_method_entry_t
*cme
= complemented_callable_method_entry(klass
, mid
);
217 // invalidate cme if found to invalidate the inline method cache.
218 if (METHOD_ENTRY_CACHED(cme
)) {
219 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
223 // invalidate cc by invalidating cc->cme
224 VALUE owner
= cme
->owner
;
225 VM_ASSERT(BUILTIN_TYPE(owner
) == T_CLASS
);
226 VALUE klass_housing_cme
;
227 if (cme
->def
->type
== VM_METHOD_TYPE_REFINED
&& !cme
->def
->body
.refined
.orig_me
) {
228 klass_housing_cme
= owner
;
231 klass_housing_cme
= RCLASS_ORIGIN(owner
);
233 // replace the cme that will be invalid
234 VM_ASSERT(lookup_method_table(klass_housing_cme
, mid
) == (const rb_method_entry_t
*)cme
);
235 const rb_method_entry_t
*new_cme
= rb_method_entry_clone((const rb_method_entry_t
*)cme
);
236 rb_method_table_insert(klass_housing_cme
, RCLASS_M_TBL(klass_housing_cme
), mid
, new_cme
);
239 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
240 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme
);
242 // In case of refinement ME, also invalidate the wrapped ME that
243 // could be cached at some callsite and is unreachable from any
245 if (cme
->def
->type
== VM_METHOD_TYPE_REFINED
&& cme
->def
->body
.refined
.orig_me
) {
246 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
->def
->body
.refined
.orig_me
);
249 if (cme
->def
->iseq_overload
) {
250 rb_callable_method_entry_t
*monly_cme
= (rb_callable_method_entry_t
*)lookup_overloaded_cme(cme
);
252 vm_cme_invalidate(monly_cme
);
257 // invalidate complement tbl
258 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
259 VALUE defined_class
= cme
->defined_class
;
260 struct rb_id_table
*cm_tbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
261 VM_ASSERT(cm_tbl
!= NULL
);
262 int r
= rb_id_table_delete(cm_tbl
, mid
);
263 VM_ASSERT(r
== TRUE
); (void)r
;
264 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_callable
);
267 RB_DEBUG_COUNTER_INC(cc_invalidate_tree
);
270 invalidate_negative_cache(mid
);
277 clear_iclass_method_cache_by_id(VALUE iclass
, VALUE d
)
279 VM_ASSERT(RB_TYPE_P(iclass
, T_ICLASS
));
281 clear_method_cache_by_id_in_class(iclass
, mid
);
285 clear_iclass_method_cache_by_id_for_refinements(VALUE klass
, VALUE d
)
287 if (RB_TYPE_P(klass
, T_ICLASS
)) {
289 clear_method_cache_by_id_in_class(klass
, mid
);
294 rb_clear_method_cache(VALUE klass_or_module
, ID mid
)
296 if (RB_TYPE_P(klass_or_module
, T_MODULE
)) {
297 VALUE module
= klass_or_module
; // alias
299 if (FL_TEST(module
, RMODULE_IS_REFINEMENT
)) {
300 VALUE refined_class
= rb_refinement_module_get_refined_class(module
);
301 rb_clear_method_cache(refined_class
, mid
);
302 rb_class_foreach_subclass(refined_class
, clear_iclass_method_cache_by_id_for_refinements
, mid
);
303 rb_clear_all_refinement_method_cache();
305 rb_class_foreach_subclass(module
, clear_iclass_method_cache_by_id
, mid
);
308 clear_method_cache_by_id_in_class(klass_or_module
, mid
);
313 invalidate_all_refinement_cc(void *vstart
, void *vend
, size_t stride
, void *data
)
315 VALUE v
= (VALUE
)vstart
;
316 for (; v
!= (VALUE
)vend
; v
+= stride
) {
317 void *ptr
= asan_poisoned_object_p(v
);
318 asan_unpoison_object(v
, false);
320 if (RBASIC(v
)->flags
) { // liveness check
321 if (imemo_type_p(v
, imemo_callcache
)) {
322 const struct rb_callcache
*cc
= (const struct rb_callcache
*)v
;
323 if (vm_cc_refinement_p(cc
) && cc
->klass
) {
324 vm_cc_invalidate(cc
);
330 asan_poison_object(v
);
333 return 0; // continue to iteration
339 const struct rb_callinfo
*ci
= (const struct rb_callinfo
*)v
;
341 h
= rb_hash_start(ci
->mid
);
342 h
= rb_hash_uint(h
, ci
->flag
);
343 h
= rb_hash_uint(h
, ci
->argc
);
345 for (int i
= 0; i
< ci
->kwarg
->keyword_len
; i
++) {
346 h
= rb_hash_uint(h
, ci
->kwarg
->keywords
[i
]);
353 vm_ci_hash_cmp(VALUE v1
, VALUE v2
)
355 const struct rb_callinfo
*ci1
= (const struct rb_callinfo
*)v1
;
356 const struct rb_callinfo
*ci2
= (const struct rb_callinfo
*)v2
;
357 if (ci1
->mid
!= ci2
->mid
) return 1;
358 if (ci1
->flag
!= ci2
->flag
) return 1;
359 if (ci1
->argc
!= ci2
->argc
) return 1;
360 if (ci1
->kwarg
!= NULL
) {
361 VM_ASSERT(ci2
->kwarg
!= NULL
); // implied by matching flags
363 if (ci1
->kwarg
->keyword_len
!= ci2
->kwarg
->keyword_len
)
366 for (int i
= 0; i
< ci1
->kwarg
->keyword_len
; i
++) {
367 if (ci1
->kwarg
->keywords
[i
] != ci2
->kwarg
->keywords
[i
]) {
372 VM_ASSERT(ci2
->kwarg
== NULL
); // implied by matching flags
377 static const struct st_hash_type vm_ci_hashtype
= {
383 ci_lookup_i(st_data_t
*key
, st_data_t
*value
, st_data_t data
, int existing
)
385 const struct rb_callinfo
*ci
= (const struct rb_callinfo
*)*key
;
386 st_data_t
*ret
= (st_data_t
*)data
;
389 if (rb_objspace_garbage_object_p((VALUE
)ci
)) {
390 *ret
= (st_data_t
)NULL
;
398 *key
= *value
= *ret
= (st_data_t
)ci
;
403 const struct rb_callinfo
*
404 rb_vm_ci_lookup(ID mid
, unsigned int flag
, unsigned int argc
, const struct rb_callinfo_kwarg
*kwarg
)
406 rb_vm_t
*vm
= GET_VM();
407 const struct rb_callinfo
*ci
= NULL
;
410 ((struct rb_callinfo_kwarg
*)kwarg
)->references
++;
413 struct rb_callinfo
*new_ci
= IMEMO_NEW(struct rb_callinfo
, imemo_callinfo
, (VALUE
)kwarg
);
420 st_table
*ci_table
= vm
->ci_table
;
424 st_update(ci_table
, (st_data_t
)new_ci
, ci_lookup_i
, (st_data_t
)&ci
);
425 } while (ci
== NULL
);
435 rb_vm_ci_free(const struct rb_callinfo
*ci
)
437 rb_vm_t
*vm
= GET_VM();
441 st_data_t key
= (st_data_t
)ci
;
442 st_delete(vm
->ci_table
, &key
, NULL
);
448 rb_clear_all_refinement_method_cache(void)
450 rb_objspace_each_objects(invalidate_all_refinement_cc
, NULL
);
451 rb_yjit_invalidate_all_method_lookup_assumptions();
455 rb_method_table_insert(VALUE klass
, struct rb_id_table
*table
, ID method_id
, const rb_method_entry_t
*me
)
457 VALUE table_owner
= klass
;
458 if (RB_TYPE_P(klass
, T_ICLASS
) && !RICLASS_OWNS_M_TBL_P(klass
)) {
459 table_owner
= RBASIC(table_owner
)->klass
;
461 VM_ASSERT(RB_TYPE_P(table_owner
, T_CLASS
) || RB_TYPE_P(table_owner
, T_ICLASS
) || RB_TYPE_P(table_owner
, T_MODULE
));
462 VM_ASSERT(table
== RCLASS_M_TBL(table_owner
));
463 rb_id_table_insert(table
, method_id
, (VALUE
)me
);
464 RB_OBJ_WRITTEN(table_owner
, Qundef
, (VALUE
)me
);
467 // rb_f_notimplement has an extra trailing argument to distinguish it from other methods
468 // at compile-time to override arity to be -1. But the trailing argument introduces a
469 // signature mismatch between caller and callee, so rb_define_method family inserts a
470 // method entry with rb_f_notimplement_internal, which has canonical arity=-1 signature,
471 // instead of rb_f_notimplement.
472 NORETURN(static VALUE
rb_f_notimplement_internal(int argc
, const VALUE
*argv
, VALUE obj
));
475 rb_f_notimplement_internal(int argc
, const VALUE
*argv
, VALUE obj
)
479 UNREACHABLE_RETURN(Qnil
);
483 rb_f_notimplement(int argc
, const VALUE
*argv
, VALUE obj
, VALUE marker
)
485 rb_f_notimplement_internal(argc
, argv
, obj
);
489 rb_define_notimplement_method_id(VALUE mod
, ID id
, rb_method_visibility_t visi
)
491 rb_add_method(mod
, id
, VM_METHOD_TYPE_NOTIMPLEMENTED
, (void *)1, visi
);
495 rb_add_method_cfunc(VALUE klass
, ID mid
, VALUE (*func
)(ANYARGS
), int argc
, rb_method_visibility_t visi
)
497 if (argc
< -2 || 15 < argc
) rb_raise(rb_eArgError
, "arity out of range: %d for -2..15", argc
);
498 if (func
!= (VALUE(*)(ANYARGS
))rb_f_notimplement
) {
499 rb_method_cfunc_t opt
;
502 rb_add_method(klass
, mid
, VM_METHOD_TYPE_CFUNC
, &opt
, visi
);
505 rb_define_notimplement_method_id(klass
, mid
, visi
);
510 rb_add_method_optimized(VALUE klass
, ID mid
, enum method_optimized_type opt_type
, unsigned int index
, rb_method_visibility_t visi
)
512 rb_method_optimized_t opt
= {
516 rb_add_method(klass
, mid
, VM_METHOD_TYPE_OPTIMIZED
, &opt
, visi
);
520 rb_method_definition_release(rb_method_definition_t
*def
)
523 const int reference_count
= def
->reference_count
;
524 def
->reference_count
--;
526 VM_ASSERT(reference_count
>= 0);
528 if (def
->reference_count
== 0) {
529 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d (remove)\n", (void *)def
,
530 rb_id2name(def
->original_id
), def
->reference_count
);
531 if (def
->type
== VM_METHOD_TYPE_BMETHOD
&& def
->body
.bmethod
.hooks
) {
532 xfree(def
->body
.bmethod
.hooks
);
537 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d->%d (dec)\n", (void *)def
, rb_id2name(def
->original_id
),
538 reference_count
, def
->reference_count
);
543 static void delete_overloaded_cme(const rb_callable_method_entry_t
*cme
);
546 rb_free_method_entry(const rb_method_entry_t
*me
)
548 if (me
->def
&& me
->def
->iseq_overload
) {
549 delete_overloaded_cme((const rb_callable_method_entry_t
*)me
);
551 rb_method_definition_release(me
->def
);
554 static inline rb_method_entry_t
*search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
);
555 extern int rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
);
558 (*call_cfunc_invoker_func(int argc
))(VALUE recv
, int argc
, const VALUE
*, VALUE (*func
)(ANYARGS
))
560 if (!GET_THREAD()->ext_config
.ractor_safe
) {
562 case -2: return &call_cfunc_m2
;
563 case -1: return &call_cfunc_m1
;
564 case 0: return &call_cfunc_0
;
565 case 1: return &call_cfunc_1
;
566 case 2: return &call_cfunc_2
;
567 case 3: return &call_cfunc_3
;
568 case 4: return &call_cfunc_4
;
569 case 5: return &call_cfunc_5
;
570 case 6: return &call_cfunc_6
;
571 case 7: return &call_cfunc_7
;
572 case 8: return &call_cfunc_8
;
573 case 9: return &call_cfunc_9
;
574 case 10: return &call_cfunc_10
;
575 case 11: return &call_cfunc_11
;
576 case 12: return &call_cfunc_12
;
577 case 13: return &call_cfunc_13
;
578 case 14: return &call_cfunc_14
;
579 case 15: return &call_cfunc_15
;
581 rb_bug("unsupported length: %d", argc
);
586 case -2: return &ractor_safe_call_cfunc_m2
;
587 case -1: return &ractor_safe_call_cfunc_m1
;
588 case 0: return &ractor_safe_call_cfunc_0
;
589 case 1: return &ractor_safe_call_cfunc_1
;
590 case 2: return &ractor_safe_call_cfunc_2
;
591 case 3: return &ractor_safe_call_cfunc_3
;
592 case 4: return &ractor_safe_call_cfunc_4
;
593 case 5: return &ractor_safe_call_cfunc_5
;
594 case 6: return &ractor_safe_call_cfunc_6
;
595 case 7: return &ractor_safe_call_cfunc_7
;
596 case 8: return &ractor_safe_call_cfunc_8
;
597 case 9: return &ractor_safe_call_cfunc_9
;
598 case 10: return &ractor_safe_call_cfunc_10
;
599 case 11: return &ractor_safe_call_cfunc_11
;
600 case 12: return &ractor_safe_call_cfunc_12
;
601 case 13: return &ractor_safe_call_cfunc_13
;
602 case 14: return &ractor_safe_call_cfunc_14
;
603 case 15: return &ractor_safe_call_cfunc_15
;
605 rb_bug("unsupported length: %d", argc
);
611 setup_method_cfunc_struct(rb_method_cfunc_t
*cfunc
, VALUE (*func
)(ANYARGS
), int argc
)
615 cfunc
->invoker
= call_cfunc_invoker_func(argc
);
618 static rb_method_definition_t
*
619 method_definition_addref(rb_method_definition_t
*def
, bool complemented
)
621 if (!complemented
&& def
->reference_count
> 0) def
->aliased
= true;
622 def
->reference_count
++;
623 if (METHOD_DEBUG
) fprintf(stderr
, "+%p-%s:%d\n", (void *)def
, rb_id2name(def
->original_id
), def
->reference_count
);
628 rb_method_definition_set(const rb_method_entry_t
*me
, rb_method_definition_t
*def
, void *opts
)
630 rb_method_definition_release(me
->def
);
631 *(rb_method_definition_t
**)&me
->def
= method_definition_addref(def
, METHOD_ENTRY_COMPLEMENTED(me
));
633 if (!ruby_running
) add_opt_method_entry(me
);
637 case VM_METHOD_TYPE_ISEQ
:
639 rb_method_iseq_t
*iseq_body
= (rb_method_iseq_t
*)opts
;
640 const rb_iseq_t
*iseq
= iseq_body
->iseqptr
;
641 rb_cref_t
*method_cref
, *cref
= iseq_body
->cref
;
643 /* setup iseq first (before invoking GC) */
644 RB_OBJ_WRITE(me
, &def
->body
.iseq
.iseqptr
, iseq
);
646 if (ISEQ_BODY(iseq
)->mandatory_only_iseq
) def
->iseq_overload
= 1;
648 if (0) vm_cref_dump("rb_method_definition_create", cref
);
654 method_cref
= vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */
657 RB_OBJ_WRITE(me
, &def
->body
.iseq
.cref
, method_cref
);
660 case VM_METHOD_TYPE_CFUNC
:
662 rb_method_cfunc_t
*cfunc
= (rb_method_cfunc_t
*)opts
;
663 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), cfunc
->func
, cfunc
->argc
);
666 case VM_METHOD_TYPE_ATTRSET
:
667 case VM_METHOD_TYPE_IVAR
:
669 const rb_execution_context_t
*ec
= GET_EC();
670 rb_control_frame_t
*cfp
;
673 def
->body
.attr
.id
= (ID
)(VALUE
)opts
;
675 cfp
= rb_vm_get_ruby_level_next_cfp(ec
, ec
->cfp
);
677 if (cfp
&& (line
= rb_vm_get_sourceline(cfp
))) {
678 VALUE location
= rb_ary_new3(2, rb_iseq_path(cfp
->iseq
), INT2FIX(line
));
679 RB_OBJ_WRITE(me
, &def
->body
.attr
.location
, rb_ary_freeze(location
));
682 VM_ASSERT(def
->body
.attr
.location
== 0);
686 case VM_METHOD_TYPE_BMETHOD
:
687 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.proc
, (VALUE
)opts
);
688 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.defined_ractor
, rb_ractor_self(GET_RACTOR()));
690 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
691 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), (VALUE(*)(ANYARGS
))rb_f_notimplement_internal
, -1);
693 case VM_METHOD_TYPE_OPTIMIZED
:
694 def
->body
.optimized
= *(rb_method_optimized_t
*)opts
;
696 case VM_METHOD_TYPE_REFINED
:
698 RB_OBJ_WRITE(me
, &def
->body
.refined
.orig_me
, (rb_method_entry_t
*)opts
);
701 case VM_METHOD_TYPE_ALIAS
:
702 RB_OBJ_WRITE(me
, &def
->body
.alias
.original_me
, (rb_method_entry_t
*)opts
);
704 case VM_METHOD_TYPE_ZSUPER
:
705 case VM_METHOD_TYPE_UNDEF
:
706 case VM_METHOD_TYPE_MISSING
:
713 method_definition_reset(const rb_method_entry_t
*me
)
715 rb_method_definition_t
*def
= me
->def
;
718 case VM_METHOD_TYPE_ISEQ
:
719 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.iseqptr
);
720 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.cref
);
722 case VM_METHOD_TYPE_ATTRSET
:
723 case VM_METHOD_TYPE_IVAR
:
724 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.attr
.location
);
726 case VM_METHOD_TYPE_BMETHOD
:
727 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.proc
);
728 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.defined_ractor
);
729 /* give up to check all in a list */
730 if (def
->body
.bmethod
.hooks
) rb_gc_writebarrier_remember((VALUE
)me
);
732 case VM_METHOD_TYPE_REFINED
:
733 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.refined
.orig_me
);
735 case VM_METHOD_TYPE_ALIAS
:
736 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.alias
.original_me
);
738 case VM_METHOD_TYPE_CFUNC
:
739 case VM_METHOD_TYPE_ZSUPER
:
740 case VM_METHOD_TYPE_MISSING
:
741 case VM_METHOD_TYPE_OPTIMIZED
:
742 case VM_METHOD_TYPE_UNDEF
:
743 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
748 rb_method_definition_t
*
749 rb_method_definition_create(rb_method_type_t type
, ID mid
)
751 rb_method_definition_t
*def
;
752 def
= ZALLOC(rb_method_definition_t
);
754 def
->original_id
= mid
;
755 static uintptr_t method_serial
= 1;
756 def
->method_serial
= method_serial
++;
760 static rb_method_entry_t
*
761 rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, rb_method_definition_t
*def
, bool complement
)
763 if (def
) method_definition_addref(def
, complement
);
764 rb_method_entry_t
*me
= IMEMO_NEW(rb_method_entry_t
, imemo_ment
, defined_class
);
765 *((rb_method_definition_t
**)&me
->def
) = def
;
766 me
->called_id
= called_id
;
773 filter_defined_class(VALUE klass
)
775 switch (BUILTIN_TYPE(klass
)) {
785 rb_bug("filter_defined_class: %s", rb_obj_info(klass
));
789 rb_method_entry_create(ID called_id
, VALUE klass
, rb_method_visibility_t visi
, rb_method_definition_t
*def
)
791 rb_method_entry_t
*me
= rb_method_entry_alloc(called_id
, klass
, filter_defined_class(klass
), def
, false);
792 METHOD_ENTRY_FLAGS_SET(me
, visi
, ruby_running
? FALSE
: TRUE
);
793 if (def
!= NULL
) method_definition_reset(me
);
797 // Return a cloned ME that's not invalidated (MEs are disposable for caching).
798 const rb_method_entry_t
*
799 rb_method_entry_clone(const rb_method_entry_t
*src_me
)
801 rb_method_entry_t
*me
= rb_method_entry_alloc(src_me
->called_id
, src_me
->owner
, src_me
->defined_class
, src_me
->def
, METHOD_ENTRY_COMPLEMENTED(src_me
));
803 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
805 // Also clone inner ME in case of refinement ME
807 src_me
->def
->type
== VM_METHOD_TYPE_REFINED
&&
808 src_me
->def
->body
.refined
.orig_me
) {
809 const rb_method_entry_t
*orig_me
= src_me
->def
->body
.refined
.orig_me
;
810 VM_ASSERT(orig_me
->def
->type
!= VM_METHOD_TYPE_REFINED
);
812 rb_method_entry_t
*orig_clone
= rb_method_entry_alloc(orig_me
->called_id
,
813 orig_me
->owner
, orig_me
->defined_class
, orig_me
->def
, METHOD_ENTRY_COMPLEMENTED(orig_me
));
814 METHOD_ENTRY_FLAGS_COPY(orig_clone
, orig_me
);
816 // Clone definition, since writing a VALUE to a shared definition
817 // can create reference edges we can't run WBs for.
818 rb_method_definition_t
*clone_def
=
819 rb_method_definition_create(VM_METHOD_TYPE_REFINED
, src_me
->called_id
);
820 rb_method_definition_set(me
, clone_def
, orig_clone
);
825 const rb_callable_method_entry_t
*
826 rb_method_entry_complement_defined_class(const rb_method_entry_t
*src_me
, ID called_id
, VALUE defined_class
)
828 rb_method_definition_t
*def
= src_me
->def
;
829 rb_method_entry_t
*me
;
830 const rb_method_entry_t
*refined_orig_me
= NULL
;
832 if (!src_me
->defined_class
&&
833 def
->type
== VM_METHOD_TYPE_REFINED
&&
834 def
->body
.refined
.orig_me
) {
835 const rb_method_entry_t
*orig_me
=
836 rb_method_entry_clone(def
->body
.refined
.orig_me
);
837 RB_OBJ_WRITE((VALUE
)orig_me
, &orig_me
->defined_class
, defined_class
);
838 refined_orig_me
= orig_me
;
842 me
= rb_method_entry_alloc(called_id
, src_me
->owner
, defined_class
, def
, true);
843 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
844 METHOD_ENTRY_COMPLEMENTED_SET(me
);
846 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, called_id
);
847 rb_method_definition_set(me
, def
, (void *)refined_orig_me
);
850 VM_ASSERT(RB_TYPE_P(me
->owner
, T_MODULE
));
852 return (rb_callable_method_entry_t
*)me
;
856 rb_method_entry_copy(rb_method_entry_t
*dst
, const rb_method_entry_t
*src
)
858 rb_method_definition_release(dst
->def
);
859 *(rb_method_definition_t
**)&dst
->def
= method_definition_addref(src
->def
, METHOD_ENTRY_COMPLEMENTED(src
));
860 method_definition_reset(dst
);
861 dst
->called_id
= src
->called_id
;
862 RB_OBJ_WRITE((VALUE
)dst
, &dst
->owner
, src
->owner
);
863 RB_OBJ_WRITE((VALUE
)dst
, &dst
->defined_class
, src
->defined_class
);
864 METHOD_ENTRY_FLAGS_COPY(dst
, src
);
868 make_method_entry_refined(VALUE owner
, rb_method_entry_t
*me
)
870 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
874 rb_method_definition_t
*def
;
876 rb_vm_check_redefinition_opt_method(me
, me
->owner
);
878 struct rb_method_entry_struct
*orig_me
=
879 rb_method_entry_alloc(me
->called_id
, me
->owner
,
880 me
->defined_class
? me
->defined_class
: owner
,
883 METHOD_ENTRY_FLAGS_COPY(orig_me
, me
);
885 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, me
->called_id
);
886 rb_method_definition_set(me
, def
, orig_me
);
887 METHOD_ENTRY_VISI_SET(me
, METHOD_VISI_PUBLIC
);
891 static inline rb_method_entry_t
*
892 lookup_method_table(VALUE klass
, ID id
)
895 struct rb_id_table
*m_tbl
= RCLASS_M_TBL(klass
);
897 if (rb_id_table_lookup(m_tbl
, id
, &body
)) {
898 return (rb_method_entry_t
*) body
;
906 rb_add_refined_method_entry(VALUE refined_class
, ID mid
)
908 rb_method_entry_t
*me
= lookup_method_table(refined_class
, mid
);
911 make_method_entry_refined(refined_class
, me
);
912 rb_clear_method_cache(refined_class
, mid
);
915 rb_add_method(refined_class
, mid
, VM_METHOD_TYPE_REFINED
, 0, METHOD_VISI_PUBLIC
);
920 check_override_opt_method_i(VALUE klass
, VALUE arg
)
923 const rb_method_entry_t
*me
, *newme
;
925 if (vm_redefinition_check_flag(klass
)) {
926 me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
928 newme
= rb_method_entry(klass
, mid
);
929 if (newme
!= me
) rb_vm_check_redefinition_opt_method(me
, me
->owner
);
932 rb_class_foreach_subclass(klass
, check_override_opt_method_i
, (VALUE
)mid
);
936 check_override_opt_method(VALUE klass
, VALUE mid
)
938 if (rb_vm_check_optimizable_mid(mid
)) {
939 check_override_opt_method_i(klass
, mid
);
944 * klass->method_table[mid] = method_entry(defined_class, visi, def)
946 * If def is given (!= NULL), then just use it and ignore original_id and otps.
947 * If not given, then make a new def with original_id and opts.
949 static rb_method_entry_t
*
950 rb_method_entry_make(VALUE klass
, ID mid
, VALUE defined_class
, rb_method_visibility_t visi
,
951 rb_method_type_t type
, rb_method_definition_t
*def
, ID original_id
, void *opts
)
953 rb_method_entry_t
*me
;
954 struct rb_id_table
*mtbl
;
956 int make_refined
= 0;
964 if (!RCLASS_SINGLETON_P(klass
) &&
965 type
!= VM_METHOD_TYPE_NOTIMPLEMENTED
&&
966 type
!= VM_METHOD_TYPE_ZSUPER
) {
969 case idInitialize_copy
:
970 case idInitialize_clone
:
971 case idInitialize_dup
:
972 case idRespond_to_missing
:
973 visi
= METHOD_VISI_PRIVATE
;
977 if (type
!= VM_METHOD_TYPE_REFINED
) {
978 rb_class_modify_check(klass
);
981 if (RB_TYPE_P(klass
, T_MODULE
) && FL_TEST(klass
, RMODULE_IS_REFINEMENT
)) {
982 VALUE refined_class
= rb_refinement_module_get_refined_class(klass
);
983 rb_add_refined_method_entry(refined_class
, mid
);
985 if (type
== VM_METHOD_TYPE_REFINED
) {
986 rb_method_entry_t
*old_me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
987 if (old_me
) rb_vm_check_redefinition_opt_method(old_me
, klass
);
990 klass
= RCLASS_ORIGIN(klass
);
991 if (klass
!= orig_klass
) {
992 rb_clear_method_cache(orig_klass
, mid
);
995 mtbl
= RCLASS_M_TBL(klass
);
997 /* check re-definition */
998 if (rb_id_table_lookup(mtbl
, mid
, &data
)) {
999 rb_method_entry_t
*old_me
= (rb_method_entry_t
*)data
;
1000 rb_method_definition_t
*old_def
= old_me
->def
;
1002 if (rb_method_definition_eq(old_def
, def
)) return old_me
;
1003 rb_vm_check_redefinition_opt_method(old_me
, klass
);
1005 if (old_def
->type
== VM_METHOD_TYPE_REFINED
) make_refined
= 1;
1007 if (RTEST(ruby_verbose
) &&
1008 type
!= VM_METHOD_TYPE_UNDEF
&&
1009 (old_def
->aliased
== false) &&
1010 (!old_def
->no_redef_warning
) &&
1012 old_def
->type
!= VM_METHOD_TYPE_UNDEF
&&
1013 old_def
->type
!= VM_METHOD_TYPE_ZSUPER
&&
1014 old_def
->type
!= VM_METHOD_TYPE_ALIAS
) {
1015 const rb_iseq_t
*iseq
= 0;
1017 switch (old_def
->type
) {
1018 case VM_METHOD_TYPE_ISEQ
:
1019 iseq
= def_iseq_ptr(old_def
);
1021 case VM_METHOD_TYPE_BMETHOD
:
1022 iseq
= rb_proc_get_iseq(old_def
->body
.bmethod
.proc
, 0);
1029 "method redefined; discarding old %"PRIsVALUE
"\n%s:%d: warning: previous definition of %"PRIsVALUE
" was here",
1031 RSTRING_PTR(rb_iseq_path(iseq
)),
1032 ISEQ_BODY(iseq
)->location
.first_lineno
,
1033 rb_id2str(old_def
->original_id
)
1037 rb_warning("method redefined; discarding old %"PRIsVALUE
, rb_id2str(mid
));
1042 /* create method entry */
1043 me
= rb_method_entry_create(mid
, defined_class
, visi
, NULL
);
1045 def
= rb_method_definition_create(type
, original_id
);
1047 rb_method_definition_set(me
, def
, opts
);
1049 rb_clear_method_cache(klass
, mid
);
1052 if (klass
== rb_cObject
) {
1055 case idRespond_to_missing
:
1056 case idMethodMissing
:
1058 rb_warn("redefining Object#%s may cause infinite loop", rb_id2name(mid
));
1062 if (mid
== object_id
|| mid
== id__send__
) {
1063 if (type
== VM_METHOD_TYPE_ISEQ
&& search_method(klass
, mid
, 0)) {
1064 rb_warn("redefining '%s' may cause serious problems", rb_id2name(mid
));
1069 make_method_entry_refined(klass
, me
);
1072 rb_method_table_insert(klass
, mtbl
, mid
, me
);
1074 VM_ASSERT(me
->def
!= NULL
);
1076 /* check optimized method override by a prepended module */
1077 if (RB_TYPE_P(orig_klass
, T_MODULE
)) {
1078 check_override_opt_method(klass
, (VALUE
)mid
);
1084 static rb_method_entry_t
*rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, rb_method_definition_t
*def
, bool refined
);
1087 overloaded_cme_table(void)
1089 VM_ASSERT(GET_VM()->overloaded_cme_table
!= NULL
);
1090 return GET_VM()->overloaded_cme_table
;
1093 #if VM_CHECK_MODE > 0
1095 vm_dump_overloaded_cme_table(st_data_t key
, st_data_t val
, st_data_t dmy
)
1097 fprintf(stderr
, "key: "); rp(key
);
1098 fprintf(stderr
, "val: "); rp(val
);
1103 rb_vm_dump_overloaded_cme_table(void)
1105 fprintf(stderr
, "== rb_vm_dump_overloaded_cme_table\n");
1106 st_foreach(overloaded_cme_table(), vm_dump_overloaded_cme_table
, 0);
1111 lookup_overloaded_cme_i(st_data_t
*key
, st_data_t
*value
, st_data_t data
, int existing
)
1114 const rb_callable_method_entry_t
*cme
= (const rb_callable_method_entry_t
*)*key
;
1115 const rb_callable_method_entry_t
*monly_cme
= (const rb_callable_method_entry_t
*)*value
;
1116 const rb_callable_method_entry_t
**ptr
= (const rb_callable_method_entry_t
**)data
;
1118 if (rb_objspace_garbage_object_p((VALUE
)cme
) ||
1119 rb_objspace_garbage_object_p((VALUE
)monly_cme
)) {
1131 static const rb_callable_method_entry_t
*
1132 lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1134 ASSERT_vm_locking();
1136 const rb_callable_method_entry_t
*monly_cme
= NULL
;
1137 st_update(overloaded_cme_table(), (st_data_t
)cme
, lookup_overloaded_cme_i
, (st_data_t
)&monly_cme
);
1141 #if VM_CHECK_MODE > 0
1142 const rb_callable_method_entry_t
*
1143 rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1145 return lookup_overloaded_cme(cme
);
1150 delete_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1152 st_data_t cme_data
= (st_data_t
)cme
;
1153 ASSERT_vm_locking();
1154 st_delete(overloaded_cme_table(), &cme_data
, NULL
);
1157 static const rb_callable_method_entry_t
*
1158 get_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1160 const rb_callable_method_entry_t
*monly_cme
= lookup_overloaded_cme(cme
);
1162 if (monly_cme
&& !METHOD_ENTRY_INVALIDATED(monly_cme
)) {
1167 rb_method_definition_t
*def
= rb_method_definition_create(VM_METHOD_TYPE_ISEQ
, cme
->def
->original_id
);
1168 rb_method_entry_t
*me
= rb_method_entry_alloc(cme
->called_id
,
1174 RB_OBJ_WRITE(me
, &def
->body
.iseq
.cref
, cme
->def
->body
.iseq
.cref
);
1175 RB_OBJ_WRITE(me
, &def
->body
.iseq
.iseqptr
, ISEQ_BODY(cme
->def
->body
.iseq
.iseqptr
)->mandatory_only_iseq
);
1177 ASSERT_vm_locking();
1178 st_insert(overloaded_cme_table(), (st_data_t
)cme
, (st_data_t
)me
);
1180 METHOD_ENTRY_VISI_SET(me
, METHOD_ENTRY_VISI(cme
));
1181 return (rb_callable_method_entry_t
*)me
;
1185 const rb_callable_method_entry_t
*
1186 rb_check_overloaded_cme(const rb_callable_method_entry_t
*cme
, const struct rb_callinfo
* const ci
)
1188 if (UNLIKELY(cme
->def
->iseq_overload
) &&
1189 (vm_ci_flag(ci
) & (VM_CALL_ARGS_SIMPLE
)) &&
1190 (int)vm_ci_argc(ci
) == ISEQ_BODY(method_entry_iseqptr(cme
))->param
.lead_num
) {
1191 VM_ASSERT(cme
->def
->type
== VM_METHOD_TYPE_ISEQ
); // iseq_overload is marked only on ISEQ methods
1193 cme
= get_overloaded_cme(cme
);
1195 VM_ASSERT(cme
!= NULL
);
1196 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct
*)cme
);
1202 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
1203 const VALUE arg = ID2SYM(mid); \
1204 VALUE recv_class = (klass); \
1205 ID hook_id = (hook); \
1206 if (RCLASS_SINGLETON_P((klass))) { \
1207 recv_class = RCLASS_ATTACHED_OBJECT((klass)); \
1208 hook_id = singleton_##hook; \
1210 rb_funcallv(recv_class, hook_id, 1, &arg); \
1214 method_added(VALUE klass
, ID mid
)
1217 CALL_METHOD_HOOK(klass
, added
, mid
);
1222 rb_add_method(VALUE klass
, ID mid
, rb_method_type_t type
, void *opts
, rb_method_visibility_t visi
)
1224 rb_method_entry_make(klass
, mid
, klass
, visi
, type
, NULL
, mid
, opts
);
1226 if (type
!= VM_METHOD_TYPE_UNDEF
&& type
!= VM_METHOD_TYPE_REFINED
) {
1227 method_added(klass
, mid
);
1232 rb_add_method_iseq(VALUE klass
, ID mid
, const rb_iseq_t
*iseq
, rb_cref_t
*cref
, rb_method_visibility_t visi
)
1234 struct { /* should be same fields with rb_method_iseq_struct */
1235 const rb_iseq_t
*iseqptr
;
1239 iseq_body
.iseqptr
= iseq
;
1240 iseq_body
.cref
= cref
;
1242 rb_add_method(klass
, mid
, VM_METHOD_TYPE_ISEQ
, &iseq_body
, visi
);
1245 static rb_method_entry_t
*
1246 method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
,
1247 rb_method_visibility_t visi
, VALUE defined_class
)
1249 rb_method_entry_t
*newme
= rb_method_entry_make(klass
, mid
, defined_class
, visi
,
1250 me
->def
->type
, me
->def
, 0, NULL
);
1252 me
->def
->no_redef_warning
= TRUE
;
1255 method_added(klass
, mid
);
1260 rb_method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
, rb_method_visibility_t visi
)
1262 return method_entry_set(klass
, mid
, me
, visi
, klass
);
1265 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
1268 rb_define_alloc_func(VALUE klass
, VALUE (*func
)(VALUE
))
1270 Check_Type(klass
, T_CLASS
);
1271 if (RCLASS_SINGLETON_P(klass
)) {
1272 rb_raise(rb_eTypeError
, "can't define an allocator for a singleton class");
1274 RCLASS_SET_ALLOCATOR(klass
, func
);
1278 rb_undef_alloc_func(VALUE klass
)
1280 rb_define_alloc_func(klass
, UNDEF_ALLOC_FUNC
);
1284 rb_get_alloc_func(VALUE klass
)
1286 Check_Type(klass
, T_CLASS
);
1288 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1289 rb_alloc_func_t allocator
= RCLASS_ALLOCATOR(klass
);
1290 if (allocator
== UNDEF_ALLOC_FUNC
) break;
1291 if (allocator
) return allocator
;
1296 const rb_method_entry_t
*
1297 rb_method_entry_at(VALUE klass
, ID id
)
1299 return lookup_method_table(klass
, id
);
1302 static inline rb_method_entry_t
*
1303 search_method0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool skip_refined
)
1305 rb_method_entry_t
*me
= NULL
;
1307 RB_DEBUG_COUNTER_INC(mc_search
);
1309 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1310 RB_DEBUG_COUNTER_INC(mc_search_super
);
1311 if ((me
= lookup_method_table(klass
, id
)) != 0) {
1312 if (!skip_refined
|| me
->def
->type
!= VM_METHOD_TYPE_REFINED
||
1313 me
->def
->body
.refined
.orig_me
) {
1319 if (defined_class_ptr
) *defined_class_ptr
= klass
;
1321 if (me
== NULL
) RB_DEBUG_COUNTER_INC(mc_search_notfound
);
1323 VM_ASSERT(me
== NULL
|| !METHOD_ENTRY_INVALIDATED(me
));
1327 static inline rb_method_entry_t
*
1328 search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1330 return search_method0(klass
, id
, defined_class_ptr
, false);
1333 static rb_method_entry_t
*
1334 search_method_protect(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1336 rb_method_entry_t
*me
= search_method(klass
, id
, defined_class_ptr
);
1338 if (!UNDEFINED_METHOD_ENTRY_P(me
)) {
1346 const rb_method_entry_t
*
1347 rb_method_entry(VALUE klass
, ID id
)
1349 return search_method_protect(klass
, id
, NULL
);
1352 static inline const rb_callable_method_entry_t
*
1353 prepare_callable_method_entry(VALUE defined_class
, ID id
, const rb_method_entry_t
* const me
, int create
)
1355 struct rb_id_table
*mtbl
;
1356 const rb_callable_method_entry_t
*cme
;
1360 if (me
->defined_class
== 0) {
1361 RB_DEBUG_COUNTER_INC(mc_cme_complement
);
1362 VM_ASSERT(RB_TYPE_P(defined_class
, T_ICLASS
) || RB_TYPE_P(defined_class
, T_MODULE
));
1363 VM_ASSERT(me
->defined_class
== 0);
1365 mtbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
1367 if (mtbl
&& rb_id_table_lookup(mtbl
, id
, &cme_data
)) {
1368 cme
= (rb_callable_method_entry_t
*)cme_data
;
1369 RB_DEBUG_COUNTER_INC(mc_cme_complement_hit
);
1370 VM_ASSERT(callable_method_entry_p(cme
));
1371 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1375 mtbl
= RCLASS_EXT(defined_class
)->callable_m_tbl
= rb_id_table_create(0);
1377 cme
= rb_method_entry_complement_defined_class(me
, me
->called_id
, defined_class
);
1378 rb_id_table_insert(mtbl
, id
, (VALUE
)cme
);
1379 RB_OBJ_WRITTEN(defined_class
, Qundef
, (VALUE
)cme
);
1380 VM_ASSERT(callable_method_entry_p(cme
));
1387 cme
= (const rb_callable_method_entry_t
*)me
;
1388 VM_ASSERT(callable_method_entry_p(cme
));
1389 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1398 static const rb_callable_method_entry_t
*
1399 complemented_callable_method_entry(VALUE klass
, ID id
)
1401 VALUE defined_class
;
1402 rb_method_entry_t
*me
= search_method(klass
, id
, &defined_class
);
1403 return prepare_callable_method_entry(defined_class
, id
, me
, FALSE
);
1406 static const rb_callable_method_entry_t
*
1407 cached_callable_method_entry(VALUE klass
, ID mid
)
1409 ASSERT_vm_locking();
1411 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1414 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1415 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1416 VM_ASSERT(vm_ccs_p(ccs
));
1418 if (LIKELY(!METHOD_ENTRY_INVALIDATED(ccs
->cme
))) {
1419 VM_ASSERT(ccs
->cme
->called_id
== mid
);
1420 RB_DEBUG_COUNTER_INC(ccs_found
);
1424 rb_vm_ccs_free(ccs
);
1425 rb_id_table_delete(cc_tbl
, mid
);
1429 RB_DEBUG_COUNTER_INC(ccs_not_found
);
1434 cache_callable_method_entry(VALUE klass
, ID mid
, const rb_callable_method_entry_t
*cme
)
1436 ASSERT_vm_locking();
1437 VM_ASSERT(cme
!= NULL
);
1439 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1443 cc_tbl
= RCLASS_CC_TBL(klass
) = rb_id_table_create(2);
1446 if (rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1447 #if VM_CHECK_MODE > 0
1448 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1449 VM_ASSERT(ccs
->cme
== cme
);
1453 vm_ccs_create(klass
, cc_tbl
, mid
, cme
);
1457 static const rb_callable_method_entry_t
*
1458 negative_cme(ID mid
)
1460 rb_vm_t
*vm
= GET_VM();
1461 const rb_callable_method_entry_t
*cme
;
1464 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme_data
)) {
1465 cme
= (rb_callable_method_entry_t
*)cme_data
;
1468 cme
= (rb_callable_method_entry_t
*)rb_method_entry_alloc(mid
, Qnil
, Qnil
, NULL
, false);
1469 rb_id_table_insert(vm
->negative_cme_table
, mid
, (VALUE
)cme
);
1472 VM_ASSERT(cme
!= NULL
);
1476 static const rb_callable_method_entry_t
*
1477 callable_method_entry_or_negative(VALUE klass
, ID mid
, VALUE
*defined_class_ptr
)
1479 const rb_callable_method_entry_t
*cme
;
1481 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1484 cme
= cached_callable_method_entry(klass
, mid
);
1487 if (defined_class_ptr
!= NULL
) *defined_class_ptr
= cme
->defined_class
;
1490 VALUE defined_class
;
1491 rb_method_entry_t
*me
= search_method(klass
, mid
, &defined_class
);
1492 if (defined_class_ptr
) *defined_class_ptr
= defined_class
;
1495 cme
= prepare_callable_method_entry(defined_class
, mid
, me
, TRUE
);
1498 cme
= negative_cme(mid
);
1501 cache_callable_method_entry(klass
, mid
, cme
);
1509 // This is exposed for YJIT so that we can make assumptions that methods are
1511 const rb_callable_method_entry_t
*
1512 rb_callable_method_entry_or_negative(VALUE klass
, ID mid
)
1514 return callable_method_entry_or_negative(klass
, mid
, NULL
);
1517 static const rb_callable_method_entry_t
*
1518 callable_method_entry(VALUE klass
, ID mid
, VALUE
*defined_class_ptr
)
1520 const rb_callable_method_entry_t
*cme
;
1521 cme
= callable_method_entry_or_negative(klass
, mid
, defined_class_ptr
);
1522 return !UNDEFINED_METHOD_ENTRY_P(cme
) ? cme
: NULL
;
1525 const rb_callable_method_entry_t
*
1526 rb_callable_method_entry(VALUE klass
, ID mid
)
1528 return callable_method_entry(klass
, mid
, NULL
);
1531 static const rb_method_entry_t
*resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
);
1533 static const rb_method_entry_t
*
1534 method_entry_resolve_refinement(VALUE klass
, ID id
, int with_refinement
, VALUE
*defined_class_ptr
)
1536 const rb_method_entry_t
*me
= search_method_protect(klass
, id
, defined_class_ptr
);
1539 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1540 if (with_refinement
) {
1541 const rb_cref_t
*cref
= rb_vm_cref();
1542 VALUE refinements
= cref
? CREF_REFINEMENTS(cref
) : Qnil
;
1543 me
= resolve_refined_method(refinements
, me
, defined_class_ptr
);
1546 me
= resolve_refined_method(Qnil
, me
, defined_class_ptr
);
1549 if (UNDEFINED_METHOD_ENTRY_P(me
)) me
= NULL
;
1556 const rb_method_entry_t
*
1557 rb_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1559 return method_entry_resolve_refinement(klass
, id
, TRUE
, defined_class_ptr
);
1562 static const rb_callable_method_entry_t
*
1563 callable_method_entry_refinements0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
,
1564 const rb_callable_method_entry_t
*cme
)
1566 if (cme
== NULL
|| LIKELY(cme
->def
->type
!= VM_METHOD_TYPE_REFINED
)) {
1570 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1571 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, with_refinements
, dcp
);
1572 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1576 static const rb_callable_method_entry_t
*
1577 callable_method_entry_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
)
1579 const rb_callable_method_entry_t
*cme
= callable_method_entry(klass
, id
, defined_class_ptr
);
1580 return callable_method_entry_refinements0(klass
, id
, defined_class_ptr
, with_refinements
, cme
);
1583 const rb_callable_method_entry_t
*
1584 rb_callable_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1586 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, true);
1589 static const rb_callable_method_entry_t
*
1590 callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1592 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, false);
1595 const rb_method_entry_t
*
1596 rb_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1598 return method_entry_resolve_refinement(klass
, id
, FALSE
, defined_class_ptr
);
1601 const rb_callable_method_entry_t
*
1602 rb_callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1604 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1605 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, FALSE
, dcp
);
1606 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1609 static const rb_method_entry_t
*
1610 resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
)
1612 while (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1614 const rb_method_entry_t
*tmp_me
;
1617 refinement
= find_refinement(refinements
, me
->owner
);
1618 if (!NIL_P(refinement
)) {
1619 tmp_me
= search_method_protect(refinement
, me
->called_id
, defined_class_ptr
);
1621 if (tmp_me
&& tmp_me
->def
->type
!= VM_METHOD_TYPE_REFINED
) {
1626 tmp_me
= me
->def
->body
.refined
.orig_me
;
1628 if (defined_class_ptr
) *defined_class_ptr
= tmp_me
->defined_class
;
1632 super
= RCLASS_SUPER(me
->owner
);
1637 me
= search_method_protect(super
, me
->called_id
, defined_class_ptr
);
1642 const rb_method_entry_t
*
1643 rb_resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
)
1645 return resolve_refined_method(refinements
, me
, NULL
);
1648 const rb_callable_method_entry_t
*
1649 rb_resolve_refined_method_callable(VALUE refinements
, const rb_callable_method_entry_t
*me
)
1651 VALUE defined_class
= me
->defined_class
;
1652 const rb_method_entry_t
*resolved_me
= resolve_refined_method(refinements
, (const rb_method_entry_t
*)me
, &defined_class
);
1654 if (resolved_me
&& resolved_me
->defined_class
== 0) {
1655 return rb_method_entry_complement_defined_class(resolved_me
, me
->called_id
, defined_class
);
1658 return (const rb_callable_method_entry_t
*)resolved_me
;
1663 remove_method(VALUE klass
, ID mid
)
1666 rb_method_entry_t
*me
= 0;
1669 rb_class_modify_check(klass
);
1670 klass
= RCLASS_ORIGIN(klass
);
1671 if (mid
== object_id
|| mid
== id__send__
|| mid
== idInitialize
) {
1672 rb_warn("removing '%s' may cause serious problems", rb_id2name(mid
));
1675 if (!rb_id_table_lookup(RCLASS_M_TBL(klass
), mid
, &data
) ||
1676 !(me
= (rb_method_entry_t
*)data
) ||
1677 (!me
->def
|| me
->def
->type
== VM_METHOD_TYPE_UNDEF
) ||
1678 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1679 rb_name_err_raise("method '%1$s' not defined in %2$s",
1680 klass
, ID2SYM(mid
));
1683 if (klass
!= self
) {
1684 rb_clear_method_cache(self
, mid
);
1686 rb_clear_method_cache(klass
, mid
);
1687 rb_id_table_delete(RCLASS_M_TBL(klass
), mid
);
1689 rb_vm_check_redefinition_opt_method(me
, klass
);
1691 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1692 rb_add_refined_method_entry(klass
, mid
);
1695 CALL_METHOD_HOOK(self
, removed
, mid
);
1699 rb_remove_method_id(VALUE klass
, ID mid
)
1701 remove_method(klass
, mid
);
1705 rb_remove_method(VALUE klass
, const char *name
)
1707 remove_method(klass
, rb_intern(name
));
1712 * remove_method(symbol) -> self
1713 * remove_method(string) -> self
1715 * Removes the method identified by _symbol_ from the current
1716 * class. For an example, see Module#undef_method.
1717 * String arguments are converted to symbols.
1721 rb_mod_remove_method(int argc
, VALUE
*argv
, VALUE mod
)
1725 for (i
= 0; i
< argc
; i
++) {
1727 ID id
= rb_check_id(&v
);
1729 rb_name_err_raise("method '%1$s' not defined in %2$s",
1732 remove_method(mod
, id
);
1738 rb_export_method(VALUE klass
, ID name
, rb_method_visibility_t visi
)
1740 rb_method_entry_t
*me
;
1741 VALUE defined_class
;
1742 VALUE origin_class
= RCLASS_ORIGIN(klass
);
1744 me
= search_method0(origin_class
, name
, &defined_class
, true);
1746 if (!me
&& RB_TYPE_P(klass
, T_MODULE
)) {
1747 me
= search_method(rb_cObject
, name
, &defined_class
);
1750 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1751 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1752 rb_print_undef(klass
, name
, METHOD_VISI_UNDEF
);
1755 if (METHOD_ENTRY_VISI(me
) != visi
) {
1756 rb_vm_check_redefinition_opt_method(me
, klass
);
1758 if (klass
== defined_class
|| origin_class
== defined_class
) {
1759 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1760 // Refinement method entries should always be public because the refinement
1761 // search is always performed.
1762 if (me
->def
->body
.refined
.orig_me
) {
1763 METHOD_ENTRY_VISI_SET((rb_method_entry_t
*)me
->def
->body
.refined
.orig_me
, visi
);
1767 METHOD_ENTRY_VISI_SET(me
, visi
);
1769 rb_clear_method_cache(klass
, name
);
1772 rb_add_method(klass
, name
, VM_METHOD_TYPE_ZSUPER
, 0, visi
);
1777 #define BOUND_PRIVATE 0x01
1778 #define BOUND_RESPONDS 0x02
1781 method_boundp(VALUE klass
, ID id
, int ex
)
1783 const rb_callable_method_entry_t
*cme
;
1785 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1787 if (ex
& BOUND_RESPONDS
) {
1788 cme
= rb_callable_method_entry_with_refinements(klass
, id
, NULL
);
1791 cme
= callable_method_entry_without_refinements(klass
, id
, NULL
);
1795 if (ex
& ~BOUND_RESPONDS
) {
1796 switch (METHOD_ENTRY_VISI(cme
)) {
1797 case METHOD_VISI_PRIVATE
:
1799 case METHOD_VISI_PROTECTED
:
1800 if (ex
& BOUND_RESPONDS
) return 0;
1806 if (cme
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) {
1807 if (ex
& BOUND_RESPONDS
) return 2;
1817 rb_method_boundp(VALUE klass
, ID id
, int ex
)
1819 return method_boundp(klass
, id
, ex
);
1823 vm_cref_set_visibility(rb_method_visibility_t method_visi
, int module_func
)
1825 rb_scope_visibility_t
*scope_visi
= (rb_scope_visibility_t
*)&rb_vm_cref()->scope_visi
;
1826 scope_visi
->method_visi
= method_visi
;
1827 scope_visi
->module_func
= module_func
;
1831 rb_scope_visibility_set(rb_method_visibility_t visi
)
1833 vm_cref_set_visibility(visi
, FALSE
);
1837 scope_visibility_check(void)
1839 /* Check for public/protected/private/module_function called inside a method */
1840 rb_control_frame_t
*cfp
= GET_EC()->cfp
+1;
1841 if (cfp
&& cfp
->iseq
&& ISEQ_BODY(cfp
->iseq
)->type
== ISEQ_TYPE_METHOD
) {
1842 rb_warn("calling %s without arguments inside a method may not have the intended effect",
1843 rb_id2name(rb_frame_this_func()));
1848 rb_scope_module_func_set(void)
1850 scope_visibility_check();
1851 vm_cref_set_visibility(METHOD_VISI_PRIVATE
, TRUE
);
1854 const rb_cref_t
*rb_vm_cref_in_context(VALUE self
, VALUE cbase
);
1856 rb_attr(VALUE klass
, ID id
, int read
, int write
, int ex
)
1859 rb_method_visibility_t visi
;
1860 const rb_execution_context_t
*ec
= GET_EC();
1861 const rb_cref_t
*cref
= rb_vm_cref_in_context(klass
, klass
);
1864 visi
= METHOD_VISI_PUBLIC
;
1867 switch (vm_scope_visibility_get(ec
)) {
1868 case METHOD_VISI_PRIVATE
:
1869 if (vm_scope_module_func_check(ec
)) {
1870 rb_warning("attribute accessor as module_function");
1872 visi
= METHOD_VISI_PRIVATE
;
1874 case METHOD_VISI_PROTECTED
:
1875 visi
= METHOD_VISI_PROTECTED
;
1878 visi
= METHOD_VISI_PUBLIC
;
1883 attriv
= rb_intern_str(rb_sprintf("@%"PRIsVALUE
, rb_id2str(id
)));
1885 rb_add_method(klass
, id
, VM_METHOD_TYPE_IVAR
, (void *)attriv
, visi
);
1888 rb_add_method(klass
, rb_id_attrset(id
), VM_METHOD_TYPE_ATTRSET
, (void *)attriv
, visi
);
1893 rb_undef(VALUE klass
, ID id
)
1895 const rb_method_entry_t
*me
;
1898 rb_raise(rb_eTypeError
, "no class to undef method");
1900 rb_class_modify_check(klass
);
1901 if (id
== object_id
|| id
== id__send__
|| id
== idInitialize
) {
1902 rb_warn("undefining '%s' may cause serious problems", rb_id2name(id
));
1905 me
= search_method(klass
, id
, 0);
1906 if (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1907 me
= rb_resolve_refined_method(Qnil
, me
);
1910 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1911 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1912 rb_method_name_error(klass
, rb_id2str(id
));
1915 rb_add_method(klass
, id
, VM_METHOD_TYPE_UNDEF
, 0, METHOD_VISI_PUBLIC
);
1917 CALL_METHOD_HOOK(klass
, undefined
, id
);
1922 * undef_method(symbol) -> self
1923 * undef_method(string) -> self
1925 * Prevents the current class from responding to calls to the named
1926 * method. Contrast this with <code>remove_method</code>, which deletes
1927 * the method from the particular class; Ruby will still search
1928 * superclasses and mixed-in modules for a possible receiver.
1929 * String arguments are converted to symbols.
1936 * class Child < Parent
1948 * remove_method :hello # remove from child, still in parent
1954 * undef_method :hello # prevent any calls to 'hello'
1958 * <em>produces:</em>
1962 * prog.rb:23: undefined method 'hello' for #<Child:0x401b3bb4> (NoMethodError)
1966 rb_mod_undef_method(int argc
, VALUE
*argv
, VALUE mod
)
1969 for (i
= 0; i
< argc
; i
++) {
1971 ID id
= rb_check_id(&v
);
1973 rb_method_name_error(mod
, v
);
1980 static rb_method_visibility_t
1981 check_definition_visibility(VALUE mod
, int argc
, VALUE
*argv
)
1983 const rb_method_entry_t
*me
;
1984 VALUE mid
, include_super
, lookup_mod
= mod
;
1988 rb_scan_args(argc
, argv
, "11", &mid
, &include_super
);
1989 id
= rb_check_id(&mid
);
1990 if (!id
) return METHOD_VISI_UNDEF
;
1996 inc_super
= RTEST(include_super
);
1998 lookup_mod
= RCLASS_ORIGIN(mod
);
2002 me
= rb_method_entry_without_refinements(lookup_mod
, id
, NULL
);
2004 if (me
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) return METHOD_VISI_UNDEF
;
2005 if (!inc_super
&& me
->owner
!= mod
) return METHOD_VISI_UNDEF
;
2006 return METHOD_ENTRY_VISI(me
);
2008 return METHOD_VISI_UNDEF
;
2013 * mod.method_defined?(symbol, inherit=true) -> true or false
2014 * mod.method_defined?(string, inherit=true) -> true or false
2016 * Returns +true+ if the named method is defined by
2017 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
2018 * ancestors. Public and protected methods are matched.
2019 * String arguments are converted to symbols.
2023 * def protected_method1() end
2024 * protected :protected_method1
2028 * def private_method2() end
2029 * private :private_method2
2036 * A.method_defined? :method1 #=> true
2037 * C.method_defined? "method1" #=> true
2038 * C.method_defined? "method2" #=> true
2039 * C.method_defined? "method2", true #=> true
2040 * C.method_defined? "method2", false #=> false
2041 * C.method_defined? "method3" #=> true
2042 * C.method_defined? "protected_method1" #=> true
2043 * C.method_defined? "method4" #=> false
2044 * C.method_defined? "private_method2" #=> false
2048 rb_mod_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2050 rb_method_visibility_t visi
= check_definition_visibility(mod
, argc
, argv
);
2051 return RBOOL(visi
== METHOD_VISI_PUBLIC
|| visi
== METHOD_VISI_PROTECTED
);
2055 check_definition(VALUE mod
, int argc
, VALUE
*argv
, rb_method_visibility_t visi
)
2057 return RBOOL(check_definition_visibility(mod
, argc
, argv
) == visi
);
2062 * mod.public_method_defined?(symbol, inherit=true) -> true or false
2063 * mod.public_method_defined?(string, inherit=true) -> true or false
2065 * Returns +true+ if the named public method is defined by
2066 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
2068 * String arguments are converted to symbols.
2082 * A.method_defined? :method1 #=> true
2083 * C.public_method_defined? "method1" #=> true
2084 * C.public_method_defined? "method1", true #=> true
2085 * C.public_method_defined? "method1", false #=> true
2086 * C.public_method_defined? "method2" #=> false
2087 * C.method_defined? "method2" #=> true
2091 rb_mod_public_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2093 return check_definition(mod
, argc
, argv
, METHOD_VISI_PUBLIC
);
2098 * mod.private_method_defined?(symbol, inherit=true) -> true or false
2099 * mod.private_method_defined?(string, inherit=true) -> true or false
2101 * Returns +true+ if the named private method is defined by
2102 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
2104 * String arguments are converted to symbols.
2118 * A.method_defined? :method1 #=> true
2119 * C.private_method_defined? "method1" #=> false
2120 * C.private_method_defined? "method2" #=> true
2121 * C.private_method_defined? "method2", true #=> true
2122 * C.private_method_defined? "method2", false #=> false
2123 * C.method_defined? "method2" #=> false
2127 rb_mod_private_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2129 return check_definition(mod
, argc
, argv
, METHOD_VISI_PRIVATE
);
2134 * mod.protected_method_defined?(symbol, inherit=true) -> true or false
2135 * mod.protected_method_defined?(string, inherit=true) -> true or false
2137 * Returns +true+ if the named protected method is defined
2138 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
2140 * String arguments are converted to symbols.
2154 * A.method_defined? :method1 #=> true
2155 * C.protected_method_defined? "method1" #=> false
2156 * C.protected_method_defined? "method2" #=> true
2157 * C.protected_method_defined? "method2", true #=> true
2158 * C.protected_method_defined? "method2", false #=> false
2159 * C.method_defined? "method2" #=> true
2163 rb_mod_protected_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2165 return check_definition(mod
, argc
, argv
, METHOD_VISI_PROTECTED
);
2169 rb_method_entry_eq(const rb_method_entry_t
*m1
, const rb_method_entry_t
*m2
)
2171 return rb_method_definition_eq(m1
->def
, m2
->def
);
2174 static const rb_method_definition_t
*
2175 original_method_definition(const rb_method_definition_t
*def
)
2179 switch (def
->type
) {
2180 case VM_METHOD_TYPE_REFINED
:
2181 if (def
->body
.refined
.orig_me
) {
2182 def
= def
->body
.refined
.orig_me
->def
;
2186 case VM_METHOD_TYPE_ALIAS
:
2187 def
= def
->body
.alias
.original_me
->def
;
2197 rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
)
2199 d1
= original_method_definition(d1
);
2200 d2
= original_method_definition(d2
);
2202 if (d1
== d2
) return 1;
2203 if (!d1
|| !d2
) return 0;
2204 if (d1
->type
!= d2
->type
) return 0;
2207 case VM_METHOD_TYPE_ISEQ
:
2208 return d1
->body
.iseq
.iseqptr
== d2
->body
.iseq
.iseqptr
;
2209 case VM_METHOD_TYPE_CFUNC
:
2211 d1
->body
.cfunc
.func
== d2
->body
.cfunc
.func
&&
2212 d1
->body
.cfunc
.argc
== d2
->body
.cfunc
.argc
;
2213 case VM_METHOD_TYPE_ATTRSET
:
2214 case VM_METHOD_TYPE_IVAR
:
2215 return d1
->body
.attr
.id
== d2
->body
.attr
.id
;
2216 case VM_METHOD_TYPE_BMETHOD
:
2217 return RTEST(rb_equal(d1
->body
.bmethod
.proc
, d2
->body
.bmethod
.proc
));
2218 case VM_METHOD_TYPE_MISSING
:
2219 return d1
->original_id
== d2
->original_id
;
2220 case VM_METHOD_TYPE_ZSUPER
:
2221 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2222 case VM_METHOD_TYPE_UNDEF
:
2224 case VM_METHOD_TYPE_OPTIMIZED
:
2225 return (d1
->body
.optimized
.type
== d2
->body
.optimized
.type
) &&
2226 (d1
->body
.optimized
.index
== d2
->body
.optimized
.index
);
2227 case VM_METHOD_TYPE_REFINED
:
2228 case VM_METHOD_TYPE_ALIAS
:
2231 rb_bug("rb_method_definition_eq: unsupported type: %d", d1
->type
);
2235 rb_hash_method_definition(st_index_t hash
, const rb_method_definition_t
*def
)
2237 hash
= rb_hash_uint(hash
, def
->type
);
2238 def
= original_method_definition(def
);
2240 if (!def
) return hash
;
2242 switch (def
->type
) {
2243 case VM_METHOD_TYPE_ISEQ
:
2244 return rb_hash_uint(hash
, (st_index_t
)def
->body
.iseq
.iseqptr
);
2245 case VM_METHOD_TYPE_CFUNC
:
2246 hash
= rb_hash_uint(hash
, (st_index_t
)def
->body
.cfunc
.func
);
2247 return rb_hash_uint(hash
, def
->body
.cfunc
.argc
);
2248 case VM_METHOD_TYPE_ATTRSET
:
2249 case VM_METHOD_TYPE_IVAR
:
2250 return rb_hash_uint(hash
, def
->body
.attr
.id
);
2251 case VM_METHOD_TYPE_BMETHOD
:
2252 return rb_hash_proc(hash
, def
->body
.bmethod
.proc
);
2253 case VM_METHOD_TYPE_MISSING
:
2254 return rb_hash_uint(hash
, def
->original_id
);
2255 case VM_METHOD_TYPE_ZSUPER
:
2256 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2257 case VM_METHOD_TYPE_UNDEF
:
2259 case VM_METHOD_TYPE_OPTIMIZED
:
2260 hash
= rb_hash_uint(hash
, def
->body
.optimized
.index
);
2261 return rb_hash_uint(hash
, def
->body
.optimized
.type
);
2262 case VM_METHOD_TYPE_REFINED
:
2263 case VM_METHOD_TYPE_ALIAS
:
2264 break; /* unreachable */
2266 rb_bug("rb_hash_method_definition: unsupported method type (%d)", def
->type
);
2270 rb_hash_method_entry(st_index_t hash
, const rb_method_entry_t
*me
)
2272 return rb_hash_method_definition(hash
, me
->def
);
2276 rb_alias(VALUE klass
, ID alias_name
, ID original_name
)
2278 const VALUE target_klass
= klass
;
2279 VALUE defined_class
;
2280 const rb_method_entry_t
*orig_me
;
2281 rb_method_visibility_t visi
= METHOD_VISI_UNDEF
;
2284 rb_raise(rb_eTypeError
, "no class to make alias");
2287 rb_class_modify_check(klass
);
2290 orig_me
= search_method(klass
, original_name
, &defined_class
);
2292 if (orig_me
&& orig_me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
2293 orig_me
= rb_resolve_refined_method(Qnil
, orig_me
);
2296 if (UNDEFINED_METHOD_ENTRY_P(orig_me
) ||
2297 UNDEFINED_REFINED_METHOD_P(orig_me
->def
)) {
2298 if ((!RB_TYPE_P(klass
, T_MODULE
)) ||
2299 (orig_me
= search_method(rb_cObject
, original_name
, &defined_class
),
2300 UNDEFINED_METHOD_ENTRY_P(orig_me
))) {
2301 rb_print_undef(klass
, original_name
, METHOD_VISI_UNDEF
);
2305 switch (orig_me
->def
->type
) {
2306 case VM_METHOD_TYPE_ZSUPER
:
2307 klass
= RCLASS_SUPER(klass
);
2308 original_name
= orig_me
->def
->original_id
;
2309 visi
= METHOD_ENTRY_VISI(orig_me
);
2311 case VM_METHOD_TYPE_ALIAS
:
2312 visi
= METHOD_ENTRY_VISI(orig_me
);
2313 orig_me
= orig_me
->def
->body
.alias
.original_me
;
2314 VM_ASSERT(orig_me
->def
->type
!= VM_METHOD_TYPE_ALIAS
);
2319 if (visi
== METHOD_VISI_UNDEF
) visi
= METHOD_ENTRY_VISI(orig_me
);
2321 if (orig_me
->defined_class
== 0) {
2322 rb_method_entry_make(target_klass
, alias_name
, target_klass
, visi
,
2323 VM_METHOD_TYPE_ALIAS
, NULL
, orig_me
->called_id
,
2324 (void *)rb_method_entry_clone(orig_me
));
2325 method_added(target_klass
, alias_name
);
2328 rb_method_entry_t
*alias_me
;
2330 alias_me
= method_entry_set(target_klass
, alias_name
, orig_me
, visi
, orig_me
->owner
);
2331 RB_OBJ_WRITE(alias_me
, &alias_me
->owner
, target_klass
);
2332 RB_OBJ_WRITE(alias_me
, &alias_me
->defined_class
, orig_me
->defined_class
);
2338 * alias_method(new_name, old_name) -> symbol
2340 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
2341 * be used to retain access to methods that are overridden.
2344 * alias_method :orig_exit, :exit #=> :orig_exit
2346 * puts "Exiting with code #{code}"
2353 * <em>produces:</em>
2355 * Exiting with code 99
2359 rb_mod_alias_method(VALUE mod
, VALUE newname
, VALUE oldname
)
2361 ID oldid
= rb_check_id(&oldname
);
2363 rb_print_undef_str(mod
, oldname
);
2365 VALUE id
= rb_to_id(newname
);
2366 rb_alias(mod
, id
, oldid
);
2371 check_and_export_method(VALUE self
, VALUE name
, rb_method_visibility_t visi
)
2373 ID id
= rb_check_id(&name
);
2375 rb_print_undef_str(self
, name
);
2377 rb_export_method(self
, id
, visi
);
2381 set_method_visibility(VALUE self
, int argc
, const VALUE
*argv
, rb_method_visibility_t visi
)
2385 rb_check_frozen(self
);
2387 rb_warning("%"PRIsVALUE
" with no argument is just ignored",
2388 QUOTE_ID(rb_frame_callee()));
2395 if (argc
== 1 && (v
= rb_check_array_type(argv
[0])) != Qnil
) {
2398 for (j
= 0; j
< RARRAY_LEN(v
); j
++) {
2399 check_and_export_method(self
, RARRAY_AREF(v
, j
), visi
);
2403 for (i
= 0; i
< argc
; i
++) {
2404 check_and_export_method(self
, argv
[i
], visi
);
2410 set_visibility(int argc
, const VALUE
*argv
, VALUE module
, rb_method_visibility_t visi
)
2413 scope_visibility_check();
2414 rb_scope_visibility_set(visi
);
2418 set_method_visibility(module
, argc
, argv
, visi
);
2422 return rb_ary_new_from_values(argc
, argv
);
2428 * public(method_name) -> method_name
2429 * public(method_name, method_name, ...) -> array
2430 * public(array) -> array
2432 * With no arguments, sets the default visibility for subsequently
2433 * defined methods to public. With arguments, sets the named methods to
2434 * have public visibility.
2435 * String arguments are converted to symbols.
2436 * An Array of Symbols and/or Strings is also accepted.
2437 * If a single argument is passed, it is returned.
2438 * If no argument is passed, nil is returned.
2439 * If multiple arguments are passed, the arguments are returned as an array.
2443 rb_mod_public(int argc
, VALUE
*argv
, VALUE module
)
2445 return set_visibility(argc
, argv
, module
, METHOD_VISI_PUBLIC
);
2451 * protected(method_name) -> method_name
2452 * protected(method_name, method_name, ...) -> array
2453 * protected(array) -> array
2455 * With no arguments, sets the default visibility for subsequently
2456 * defined methods to protected. With arguments, sets the named methods
2457 * to have protected visibility.
2458 * String arguments are converted to symbols.
2459 * An Array of Symbols and/or Strings is also accepted.
2460 * If a single argument is passed, it is returned.
2461 * If no argument is passed, nil is returned.
2462 * If multiple arguments are passed, the arguments are returned as an array.
2464 * If a method has protected visibility, it is callable only where
2465 * <code>self</code> of the context is the same as the method.
2466 * (method definition or instance_eval). This behavior is different from
2467 * Java's protected method. Usually <code>private</code> should be used.
2469 * Note that a protected method is slow because it can't use inline cache.
2471 * To show a private method on RDoc, use <code>:doc:</code> instead of this.
2475 rb_mod_protected(int argc
, VALUE
*argv
, VALUE module
)
2477 return set_visibility(argc
, argv
, module
, METHOD_VISI_PROTECTED
);
2483 * private(method_name) -> method_name
2484 * private(method_name, method_name, ...) -> array
2485 * private(array) -> array
2487 * With no arguments, sets the default visibility for subsequently
2488 * defined methods to private. With arguments, sets the named methods
2489 * to have private visibility.
2490 * String arguments are converted to symbols.
2491 * An Array of Symbols and/or Strings is also accepted.
2492 * If a single argument is passed, it is returned.
2493 * If no argument is passed, nil is returned.
2494 * If multiple arguments are passed, the arguments are returned as an array.
2503 * Mod.private_instance_methods #=> [:a, :c]
2505 * Note that to show a private method on RDoc, use <code>:doc:</code>.
2509 rb_mod_private(int argc
, VALUE
*argv
, VALUE module
)
2511 return set_visibility(argc
, argv
, module
, METHOD_VISI_PRIVATE
);
2516 * ruby2_keywords(method_name, ...) -> nil
2518 * For the given method names, marks the method as passing keywords through
2519 * a normal argument splat. This should only be called on methods that
2520 * accept an argument splat (<tt>*args</tt>) but not explicit keywords or
2521 * a keyword splat. It marks the method such that if the method is called
2522 * with keyword arguments, the final hash argument is marked with a special
2523 * flag such that if it is the final element of a normal argument splat to
2524 * another method call, and that method call does not include explicit
2525 * keywords or a keyword splat, the final element is interpreted as keywords.
2526 * In other words, keywords will be passed through the method to other
2529 * This should only be used for methods that delegate keywords to another
2530 * method, and only for backwards compatibility with Ruby versions before 3.0.
2531 * See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
2532 * for details on why +ruby2_keywords+ exists and when and how to use it.
2534 * This method will probably be removed at some point, as it exists only
2535 * for backwards compatibility. As it does not exist in Ruby versions before
2536 * 2.7, check that the module responds to this method before calling it:
2539 * def foo(meth, *args, &block)
2540 * send(:"do_#{meth}", *args, &block)
2542 * ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true)
2545 * However, be aware that if the +ruby2_keywords+ method is removed, the
2546 * behavior of the +foo+ method using the above approach will change so that
2547 * the method does not pass through keywords.
2551 rb_mod_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2554 VALUE origin_class
= RCLASS_ORIGIN(module
);
2556 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2557 rb_check_frozen(module
);
2559 for (i
= 0; i
< argc
; i
++) {
2561 ID name
= rb_check_id(&v
);
2562 rb_method_entry_t
*me
;
2563 VALUE defined_class
;
2566 rb_print_undef_str(module
, v
);
2569 me
= search_method(origin_class
, name
, &defined_class
);
2570 if (!me
&& RB_TYPE_P(module
, T_MODULE
)) {
2571 me
= search_method(rb_cObject
, name
, &defined_class
);
2574 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
2575 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
2576 rb_print_undef(module
, name
, METHOD_VISI_UNDEF
);
2579 if (module
== defined_class
|| origin_class
== defined_class
) {
2580 switch (me
->def
->type
) {
2581 case VM_METHOD_TYPE_ISEQ
:
2582 if (ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_rest
&&
2583 !ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_kw
&&
2584 !ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_kwrest
) {
2585 ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.ruby2_keywords
= 1;
2586 rb_clear_method_cache(module
, name
);
2589 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2592 case VM_METHOD_TYPE_BMETHOD
: {
2593 VALUE procval
= me
->def
->body
.bmethod
.proc
;
2594 if (vm_block_handler_type(procval
) == block_handler_type_proc
) {
2595 procval
= vm_proc_to_block_handler(VM_BH_TO_PROC(procval
));
2598 if (vm_block_handler_type(procval
) == block_handler_type_iseq
) {
2599 const struct rb_captured_block
*captured
= VM_BH_TO_ISEQ_BLOCK(procval
);
2600 const rb_iseq_t
*iseq
= rb_iseq_check(captured
->code
.iseq
);
2601 if (ISEQ_BODY(iseq
)->param
.flags
.has_rest
&&
2602 !ISEQ_BODY(iseq
)->param
.flags
.has_kw
&&
2603 !ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
2604 ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
= 1;
2605 rb_clear_method_cache(module
, name
);
2608 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2615 rb_warn("Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)", rb_id2name(name
));
2620 rb_warn("Skipping set of ruby2_keywords flag for %s (can only set in method defining module)", rb_id2name(name
));
2628 * mod.public_class_method(symbol, ...) -> mod
2629 * mod.public_class_method(string, ...) -> mod
2630 * mod.public_class_method(array) -> mod
2632 * Makes a list of existing class methods public.
2634 * String arguments are converted to symbols.
2635 * An Array of Symbols and/or Strings is also accepted.
2639 rb_mod_public_method(int argc
, VALUE
*argv
, VALUE obj
)
2641 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PUBLIC
);
2647 * mod.private_class_method(symbol, ...) -> mod
2648 * mod.private_class_method(string, ...) -> mod
2649 * mod.private_class_method(array) -> mod
2651 * Makes existing class methods private. Often used to hide the default
2652 * constructor <code>new</code>.
2654 * String arguments are converted to symbols.
2655 * An Array of Symbols and/or Strings is also accepted.
2657 * class SimpleSingleton # Not thread safe
2658 * private_class_method :new
2659 * def SimpleSingleton.create(*args, &block)
2660 * @me = new(*args, &block) if ! @me
2667 rb_mod_private_method(int argc
, VALUE
*argv
, VALUE obj
)
2669 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PRIVATE
);
2676 * public(symbol, ...)
2677 * public(string, ...)
2680 * With no arguments, sets the default visibility for subsequently
2681 * defined methods to public. With arguments, sets the named methods to
2682 * have public visibility.
2684 * String arguments are converted to symbols.
2685 * An Array of Symbols and/or Strings is also accepted.
2689 top_public(int argc
, VALUE
*argv
, VALUE _
)
2691 return rb_mod_public(argc
, argv
, rb_top_main_class("public"));
2697 * private(symbol, ...)
2698 * private(string, ...)
2701 * With no arguments, sets the default visibility for subsequently
2702 * defined methods to private. With arguments, sets the named methods to
2703 * have private visibility.
2705 * String arguments are converted to symbols.
2706 * An Array of Symbols and/or Strings is also accepted.
2709 top_private(int argc
, VALUE
*argv
, VALUE _
)
2711 return rb_mod_private(argc
, argv
, rb_top_main_class("private"));
2716 * ruby2_keywords(method_name, ...) -> self
2718 * For the given method names, marks the method as passing keywords through
2719 * a normal argument splat. See Module#ruby2_keywords in detail.
2722 top_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2724 return rb_mod_ruby2_keywords(argc
, argv
, rb_top_main_class("ruby2_keywords"));
2729 * module_function -> nil
2730 * module_function(method_name) -> method_name
2731 * module_function(method_name, method_name, ...) -> array
2733 * Creates module functions for the named methods. These functions may
2734 * be called with the module as a receiver, and also become available
2735 * as instance methods to classes that mix in the module. Module
2736 * functions are copies of the original, and so may be changed
2737 * independently. The instance-method versions are made private. If
2738 * used with no arguments, subsequently defined methods become module
2740 * String arguments are converted to symbols.
2741 * If a single argument is passed, it is returned.
2742 * If no argument is passed, nil is returned.
2743 * If multiple arguments are passed, the arguments are returned as an array.
2749 * module_function :one
2757 * Mod.one #=> "This is one"
2759 * c.call_one #=> "This is one"
2762 * "This is the new one"
2765 * Mod.one #=> "This is one"
2766 * c.call_one #=> "This is the new one"
2770 rb_mod_modfunc(int argc
, VALUE
*argv
, VALUE module
)
2774 const rb_method_entry_t
*me
;
2776 if (!RB_TYPE_P(module
, T_MODULE
)) {
2777 rb_raise(rb_eTypeError
, "module_function must be called for modules");
2781 rb_scope_module_func_set();
2785 set_method_visibility(module
, argc
, argv
, METHOD_VISI_PRIVATE
);
2787 for (i
= 0; i
< argc
; i
++) {
2790 id
= rb_to_id(argv
[i
]);
2792 me
= search_method(m
, id
, 0);
2794 me
= search_method(rb_cObject
, id
, 0);
2796 if (UNDEFINED_METHOD_ENTRY_P(me
)) {
2797 rb_print_undef(module
, id
, METHOD_VISI_UNDEF
);
2799 if (me
->def
->type
!= VM_METHOD_TYPE_ZSUPER
) {
2800 break; /* normal case: need not to follow 'super' link */
2802 m
= RCLASS_SUPER(m
);
2806 rb_method_entry_set(rb_singleton_class(module
), id
, me
, METHOD_VISI_PUBLIC
);
2811 return rb_ary_new_from_values(argc
, argv
);
2815 #pragma push_macro("rb_method_basic_definition_p")
2816 #undef rb_method_basic_definition_p
2819 rb_method_basic_definition_p(VALUE klass
, ID id
)
2821 const rb_callable_method_entry_t
*cme
;
2822 if (!klass
) return TRUE
; /* hidden object cannot be overridden */
2823 cme
= rb_callable_method_entry(klass
, id
);
2824 return (cme
&& METHOD_ENTRY_BASIC(cme
)) ? TRUE
: FALSE
;
2827 #pragma pop_macro("rb_method_basic_definition_p")
2831 call_method_entry(rb_execution_context_t
*ec
, VALUE defined_class
, VALUE obj
, ID id
,
2832 const rb_callable_method_entry_t
*cme
, int argc
, const VALUE
*argv
, int kw_splat
)
2834 VALUE passed_block_handler
= vm_passed_block_handler(ec
);
2835 VALUE result
= rb_vm_call_kw(ec
, obj
, id
, argc
, argv
, cme
, kw_splat
);
2836 vm_passed_block_handler_set(ec
, passed_block_handler
);
2841 basic_obj_respond_to_missing(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
,
2842 VALUE mid
, VALUE priv
)
2844 VALUE defined_class
, args
[2];
2845 const ID rtmid
= idRespond_to_missing
;
2846 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, rtmid
, &defined_class
);
2848 if (!cme
|| METHOD_ENTRY_BASIC(cme
)) return Qundef
;
2851 return call_method_entry(ec
, defined_class
, obj
, rtmid
, cme
, 2, args
, RB_NO_KEYWORDS
);
2855 basic_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int pub
)
2857 VALUE klass
= CLASS_OF(obj
);
2860 switch (method_boundp(klass
, id
, pub
|BOUND_RESPONDS
)) {
2864 ret
= basic_obj_respond_to_missing(ec
, klass
, obj
, ID2SYM(id
),
2866 return RTEST(ret
) && !UNDEF_P(ret
);
2873 vm_respond_to(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
, ID id
, int priv
)
2875 VALUE defined_class
;
2876 const ID resid
= idRespond_to
;
2877 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, resid
, &defined_class
);
2879 if (!cme
) return -1;
2880 if (METHOD_ENTRY_BASIC(cme
)) {
2888 args
[0] = ID2SYM(id
);
2891 argc
= rb_method_entry_arity((const rb_method_entry_t
*)cme
);
2893 rb_raise(rb_eArgError
,
2894 "respond_to? must accept 1 or 2 arguments (requires %d)",
2900 else if (!NIL_P(ruby_verbose
)) {
2901 VALUE location
= rb_method_entry_location((const rb_method_entry_t
*)cme
);
2902 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
,
2903 "%"PRIsVALUE
"%c""respond_to?(:%"PRIsVALUE
") uses"
2904 " the deprecated method signature, which takes one parameter",
2905 (RCLASS_SINGLETON_P(klass
) ? obj
: klass
),
2906 (RCLASS_SINGLETON_P(klass
) ? '.' : '#'),
2908 if (!NIL_P(location
)) {
2909 VALUE path
= RARRAY_AREF(location
, 0);
2910 VALUE line
= RARRAY_AREF(location
, 1);
2912 rb_category_compile_warn(RB_WARN_CATEGORY_DEPRECATED
,
2913 RSTRING_PTR(path
), NUM2INT(line
),
2914 "respond_to? is defined here");
2919 result
= call_method_entry(ec
, defined_class
, obj
, resid
, cme
, argc
, args
, RB_NO_KEYWORDS
);
2920 return RTEST(result
);
2925 rb_obj_respond_to(VALUE obj
, ID id
, int priv
)
2927 rb_execution_context_t
*ec
= GET_EC();
2928 return rb_ec_obj_respond_to(ec
, obj
, id
, priv
);
2932 rb_ec_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int priv
)
2934 VALUE klass
= CLASS_OF(obj
);
2935 int ret
= vm_respond_to(ec
, klass
, obj
, id
, priv
);
2936 if (ret
== -1) ret
= basic_obj_respond_to(ec
, obj
, id
, !priv
);
2941 rb_respond_to(VALUE obj
, ID id
)
2943 return rb_obj_respond_to(obj
, id
, FALSE
);
2949 * obj.respond_to?(symbol, include_all=false) -> true or false
2950 * obj.respond_to?(string, include_all=false) -> true or false
2952 * Returns +true+ if _obj_ responds to the given method. Private and
2953 * protected methods are included in the search only if the optional
2954 * second parameter evaluates to +true+.
2956 * If the method is not implemented,
2957 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
2958 * false is returned.
2960 * If the method is not defined, <code>respond_to_missing?</code>
2961 * method is called and the result is returned.
2963 * When the method name parameter is given as a string, the string is
2964 * converted to a symbol.
2968 obj_respond_to(int argc
, VALUE
*argv
, VALUE obj
)
2972 rb_execution_context_t
*ec
= GET_EC();
2974 rb_scan_args(argc
, argv
, "11", &mid
, &priv
);
2975 if (!(id
= rb_check_id(&mid
))) {
2976 VALUE ret
= basic_obj_respond_to_missing(ec
, CLASS_OF(obj
), obj
,
2977 rb_to_symbol(mid
), priv
);
2978 if (UNDEF_P(ret
)) ret
= Qfalse
;
2981 return RBOOL(basic_obj_respond_to(ec
, obj
, id
, !RTEST(priv
)));
2986 * obj.respond_to_missing?(symbol, include_all) -> true or false
2987 * obj.respond_to_missing?(string, include_all) -> true or false
2989 * DO NOT USE THIS DIRECTLY.
2991 * Hook method to return whether the _obj_ can respond to _id_ method
2994 * When the method name parameter is given as a string, the string is
2995 * converted to a symbol.
2997 * See #respond_to?, and the example of BasicObject.
3000 obj_respond_to_missing(VALUE obj
, VALUE mid
, VALUE priv
)
3006 Init_eval_method(void)
3008 rb_define_method(rb_mKernel
, "respond_to?", obj_respond_to
, -1);
3009 rb_define_method(rb_mKernel
, "respond_to_missing?", obj_respond_to_missing
, 2);
3011 rb_define_method(rb_cModule
, "remove_method", rb_mod_remove_method
, -1);
3012 rb_define_method(rb_cModule
, "undef_method", rb_mod_undef_method
, -1);
3013 rb_define_method(rb_cModule
, "alias_method", rb_mod_alias_method
, 2);
3014 rb_define_private_method(rb_cModule
, "public", rb_mod_public
, -1);
3015 rb_define_private_method(rb_cModule
, "protected", rb_mod_protected
, -1);
3016 rb_define_private_method(rb_cModule
, "private", rb_mod_private
, -1);
3017 rb_define_private_method(rb_cModule
, "module_function", rb_mod_modfunc
, -1);
3018 rb_define_private_method(rb_cModule
, "ruby2_keywords", rb_mod_ruby2_keywords
, -1);
3020 rb_define_method(rb_cModule
, "method_defined?", rb_mod_method_defined
, -1);
3021 rb_define_method(rb_cModule
, "public_method_defined?", rb_mod_public_method_defined
, -1);
3022 rb_define_method(rb_cModule
, "private_method_defined?", rb_mod_private_method_defined
, -1);
3023 rb_define_method(rb_cModule
, "protected_method_defined?", rb_mod_protected_method_defined
, -1);
3024 rb_define_method(rb_cModule
, "public_class_method", rb_mod_public_method
, -1);
3025 rb_define_method(rb_cModule
, "private_class_method", rb_mod_private_method
, -1);
3027 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
3028 "public", top_public
, -1);
3029 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
3030 "private", top_private
, -1);
3031 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
3032 "ruby2_keywords", top_ruby2_keywords
, -1);
3035 #define REPLICATE_METHOD(klass, id) do { \
3036 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
3037 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \
3040 REPLICATE_METHOD(rb_eException
, idMethodMissing
);
3041 REPLICATE_METHOD(rb_eException
, idRespond_to
);
3042 REPLICATE_METHOD(rb_eException
, idRespond_to_missing
);