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 fprintf(stderr
, " | [%d]\t", i
); vm_ci_dump(ccs
->entries
[i
].ci
);
35 rp_m( " | \t", ccs
->entries
[i
].cc
);
38 return ID_TABLE_CONTINUE
;
42 vm_ccs_dump(VALUE klass
, ID target_mid
)
44 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
48 if (rb_id_table_lookup(cc_tbl
, target_mid
, &ccs
)) {
49 fprintf(stderr
, " [CCTB] %p\n", (void *)cc_tbl
);
50 vm_ccs_dump_i(target_mid
, ccs
, NULL
);
54 fprintf(stderr
, " [CCTB] %p\n", (void *)cc_tbl
);
55 rb_id_table_foreach(cc_tbl
, vm_ccs_dump_i
, (void *)target_mid
);
60 static enum rb_id_table_iterator_result
61 vm_cme_dump_i(ID mid
, VALUE val
, void *data
)
63 ID target_mid
= (ID
)data
;
64 if (target_mid
== 0 || mid
== target_mid
) {
67 return ID_TABLE_CONTINUE
;
71 vm_mtbl_dump(VALUE klass
, ID target_mid
)
73 fprintf(stderr
, "# vm_mtbl\n");
78 if (RCLASS_M_TBL(klass
)) {
79 if (target_mid
!= 0) {
80 if (rb_id_table_lookup(RCLASS_M_TBL(klass
), target_mid
, &me
)) {
85 fprintf(stderr
, " ## RCLASS_M_TBL (%p)\n", (void *)RCLASS_M_TBL(klass
));
86 rb_id_table_foreach(RCLASS_M_TBL(klass
), vm_cme_dump_i
, NULL
);
90 fprintf(stderr
, " MTBL: NULL\n");
92 if (RCLASS_CALLABLE_M_TBL(klass
)) {
93 if (target_mid
!= 0) {
94 if (rb_id_table_lookup(RCLASS_CALLABLE_M_TBL(klass
), target_mid
, &me
)) {
99 fprintf(stderr
, " ## RCLASS_CALLABLE_M_TBL\n");
100 rb_id_table_foreach(RCLASS_CALLABLE_M_TBL(klass
), vm_cme_dump_i
, NULL
);
103 if (RCLASS_CC_TBL(klass
)) {
104 vm_ccs_dump(klass
, target_mid
);
106 klass
= RCLASS_SUPER(klass
);
112 rb_vm_mtbl_dump(const char *msg
, VALUE klass
, ID target_mid
)
114 fprintf(stderr
, "[%s] ", msg
);
115 vm_mtbl_dump(klass
, target_mid
);
119 vm_cme_invalidate(rb_callable_method_entry_t
*cme
)
121 VM_ASSERT(IMEMO_TYPE_P(cme
, imemo_ment
));
122 VM_ASSERT(callable_method_entry_p(cme
));
123 METHOD_ENTRY_INVALIDATED_SET(cme
);
124 RB_DEBUG_COUNTER_INC(cc_cme_invalidate
);
126 rb_yjit_cme_invalidate(cme
);
127 rb_mjit_cme_invalidate(cme
);
131 rb_clear_constant_cache_for_id_i(st_data_t ic
, st_data_t idx
, st_data_t arg
)
133 ((IC
) ic
)->entry
= NULL
;
137 // Here for backward compat.
138 void rb_clear_constant_cache(void) {}
141 rb_clear_constant_cache_for_id(ID id
)
144 rb_vm_t
*vm
= GET_VM();
146 if (rb_id_table_lookup(vm
->constant_cache
, id
, &lookup_result
)) {
147 st_table
*ics
= (st_table
*)lookup_result
;
148 st_foreach(ics
, rb_clear_constant_cache_for_id_i
, (st_data_t
) NULL
);
149 ruby_vm_constant_cache_invalidations
+= ics
->num_entries
;
152 rb_yjit_constant_state_changed(id
);
153 rb_mjit_constant_state_changed(id
);
157 invalidate_negative_cache(ID mid
)
160 rb_vm_t
*vm
= GET_VM();
162 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme
)) {
163 rb_id_table_delete(vm
->negative_cme_table
, mid
);
164 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
165 RB_DEBUG_COUNTER_INC(cc_invalidate_negative
);
169 static rb_method_entry_t
*rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
);
170 const rb_method_entry_t
* rb_method_entry_clone(const rb_method_entry_t
*src_me
);
171 static const rb_callable_method_entry_t
*complemented_callable_method_entry(VALUE klass
, ID id
);
172 static const rb_callable_method_entry_t
*lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
);
176 clear_method_cache_by_id_in_class(VALUE klass
, ID mid
)
178 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
179 if (rb_objspace_garbage_object_p(klass
)) return;
182 if (LIKELY(RCLASS_SUBCLASSES(klass
) == NULL
)) {
184 // check only current class
186 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
190 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
191 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
192 rb_yjit_cme_invalidate((rb_callable_method_entry_t
*)ccs
->cme
);
193 rb_mjit_cme_invalidate((rb_callable_method_entry_t
*)ccs
->cme
);
194 if (NIL_P(ccs
->cme
->owner
)) invalidate_negative_cache(mid
);
196 rb_id_table_delete(cc_tbl
, mid
);
197 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs
);
200 // remove from callable_m_tbl, if exists
201 struct rb_id_table
*cm_tbl
;
202 if ((cm_tbl
= RCLASS_CALLABLE_M_TBL(klass
)) != NULL
) {
204 if (rb_yjit_enabled_p() && rb_id_table_lookup(cm_tbl
, mid
, &cme
)) {
205 rb_yjit_cme_invalidate((rb_callable_method_entry_t
*)cme
);
207 if (mjit_enabled
&& rb_id_table_lookup(cm_tbl
, mid
, &cme
)) {
208 rb_mjit_cme_invalidate((rb_callable_method_entry_t
*)cme
);
210 rb_id_table_delete(cm_tbl
, mid
);
211 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_callable
);
213 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf
);
216 const rb_callable_method_entry_t
*cme
= complemented_callable_method_entry(klass
, mid
);
219 // invalidate cme if found to invalidate the inline method cache.
220 if (METHOD_ENTRY_CACHED(cme
)) {
221 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
225 // invalidate cc by invalidating cc->cme
226 VALUE owner
= cme
->owner
;
227 VM_ASSERT(BUILTIN_TYPE(owner
) == T_CLASS
);
228 VALUE klass_housing_cme
;
229 if (cme
->def
->type
== VM_METHOD_TYPE_REFINED
&& !cme
->def
->body
.refined
.orig_me
) {
230 klass_housing_cme
= owner
;
233 klass_housing_cme
= RCLASS_ORIGIN(owner
);
235 // replace the cme that will be invalid
236 VM_ASSERT(lookup_method_table(klass_housing_cme
, mid
) == (const rb_method_entry_t
*)cme
);
237 const rb_method_entry_t
*new_cme
= rb_method_entry_clone((const rb_method_entry_t
*)cme
);
238 rb_method_table_insert(klass_housing_cme
, RCLASS_M_TBL(klass_housing_cme
), mid
, new_cme
);
241 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
242 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme
);
244 if (cme
->def
->iseq_overload
) {
245 rb_callable_method_entry_t
*monly_cme
= (rb_callable_method_entry_t
*)lookup_overloaded_cme(cme
);
247 vm_cme_invalidate(monly_cme
);
252 // invalidate complement tbl
253 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
254 VALUE defined_class
= cme
->defined_class
;
255 struct rb_id_table
*cm_tbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
256 VM_ASSERT(cm_tbl
!= NULL
);
257 int r
= rb_id_table_delete(cm_tbl
, mid
);
258 VM_ASSERT(r
== TRUE
); (void)r
;
259 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_callable
);
262 RB_DEBUG_COUNTER_INC(cc_invalidate_tree
);
265 invalidate_negative_cache(mid
);
272 clear_iclass_method_cache_by_id(VALUE iclass
, VALUE d
)
274 VM_ASSERT(RB_TYPE_P(iclass
, T_ICLASS
));
276 clear_method_cache_by_id_in_class(iclass
, mid
);
280 clear_iclass_method_cache_by_id_for_refinements(VALUE klass
, VALUE d
)
282 if (RB_TYPE_P(klass
, T_ICLASS
)) {
284 clear_method_cache_by_id_in_class(klass
, mid
);
289 rb_clear_method_cache(VALUE klass_or_module
, ID mid
)
291 if (RB_TYPE_P(klass_or_module
, T_MODULE
)) {
292 VALUE module
= klass_or_module
; // alias
294 if (FL_TEST(module
, RMODULE_IS_REFINEMENT
)) {
295 VALUE refined_class
= rb_refinement_module_get_refined_class(module
);
296 rb_clear_method_cache(refined_class
, mid
);
297 rb_class_foreach_subclass(refined_class
, clear_iclass_method_cache_by_id_for_refinements
, mid
);
299 rb_class_foreach_subclass(module
, clear_iclass_method_cache_by_id
, mid
);
302 clear_method_cache_by_id_in_class(klass_or_module
, mid
);
307 void rb_cc_table_free(VALUE klass
);
310 invalidate_all_cc(void *vstart
, void *vend
, size_t stride
, void *data
)
312 VALUE v
= (VALUE
)vstart
;
313 for (; v
!= (VALUE
)vend
; v
+= stride
) {
314 void *ptr
= asan_poisoned_object_p(v
);
315 asan_unpoison_object(v
, false);
316 if (RBASIC(v
)->flags
) { // liveness check
317 if (RB_TYPE_P(v
, T_CLASS
) ||
318 RB_TYPE_P(v
, T_ICLASS
)) {
319 if (RCLASS_CC_TBL(v
)) {
322 RCLASS_CC_TBL(v
) = NULL
;
326 asan_poison_object(v
);
329 return 0; // continue to iteration
333 rb_clear_method_cache_all(void)
335 rb_objspace_each_objects(invalidate_all_cc
, NULL
);
337 rb_yjit_invalidate_all_method_lookup_assumptions();
341 rb_method_table_insert(VALUE klass
, struct rb_id_table
*table
, ID method_id
, const rb_method_entry_t
*me
)
343 VALUE table_owner
= klass
;
344 if (RB_TYPE_P(klass
, T_ICLASS
) && !RICLASS_OWNS_M_TBL_P(klass
)) {
345 table_owner
= RBASIC(table_owner
)->klass
;
347 VM_ASSERT(RB_TYPE_P(table_owner
, T_CLASS
) || RB_TYPE_P(table_owner
, T_ICLASS
) || RB_TYPE_P(table_owner
, T_MODULE
));
348 VM_ASSERT(table
== RCLASS_M_TBL(table_owner
));
349 rb_id_table_insert(table
, method_id
, (VALUE
)me
);
350 RB_OBJ_WRITTEN(table_owner
, Qundef
, (VALUE
)me
);
353 // rb_f_notimplement has an extra trailing argument to distinguish it from other methods
354 // at compile-time to override arity to be -1. But the trailing argument introduces a
355 // signature mismatch between caller and callee, so rb_define_method family inserts a
356 // method entry with rb_f_notimplement_internal, which has canonical arity=-1 signature,
357 // instead of rb_f_notimplement.
358 NORETURN(static VALUE
rb_f_notimplement_internal(int argc
, const VALUE
*argv
, VALUE obj
));
361 rb_f_notimplement_internal(int argc
, const VALUE
*argv
, VALUE obj
)
365 UNREACHABLE_RETURN(Qnil
);
369 rb_f_notimplement(int argc
, const VALUE
*argv
, VALUE obj
, VALUE marker
)
371 rb_f_notimplement_internal(argc
, argv
, obj
);
375 rb_define_notimplement_method_id(VALUE mod
, ID id
, rb_method_visibility_t visi
)
377 rb_add_method(mod
, id
, VM_METHOD_TYPE_NOTIMPLEMENTED
, (void *)1, visi
);
381 rb_add_method_cfunc(VALUE klass
, ID mid
, VALUE (*func
)(ANYARGS
), int argc
, rb_method_visibility_t visi
)
383 if (argc
< -2 || 15 < argc
) rb_raise(rb_eArgError
, "arity out of range: %d for -2..15", argc
);
384 if (func
!= (VALUE(*)(ANYARGS
))rb_f_notimplement
) {
385 rb_method_cfunc_t opt
;
388 rb_add_method(klass
, mid
, VM_METHOD_TYPE_CFUNC
, &opt
, visi
);
391 rb_define_notimplement_method_id(klass
, mid
, visi
);
396 rb_add_method_optimized(VALUE klass
, ID mid
, enum method_optimized_type opt_type
, unsigned int index
, rb_method_visibility_t visi
)
398 rb_method_optimized_t opt
= {
402 rb_add_method(klass
, mid
, VM_METHOD_TYPE_OPTIMIZED
, &opt
, visi
);
406 rb_method_definition_release(rb_method_definition_t
*def
, int complemented
)
409 const int alias_count
= def
->alias_count
;
410 const int complemented_count
= def
->complemented_count
;
411 VM_ASSERT(alias_count
>= 0);
412 VM_ASSERT(complemented_count
>= 0);
414 if (alias_count
+ complemented_count
== 0) {
415 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d,%d (remove)\n", (void *)def
,
416 rb_id2name(def
->original_id
), alias_count
, complemented_count
);
417 if (def
->type
== VM_METHOD_TYPE_BMETHOD
&& def
->body
.bmethod
.hooks
) {
418 xfree(def
->body
.bmethod
.hooks
);
424 VM_ASSERT(def
->complemented_count
> 0);
425 def
->complemented_count
--;
427 else if (def
->alias_count
> 0) {
431 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d->%d,%d->%d (dec)\n", (void *)def
, rb_id2name(def
->original_id
),
432 alias_count
, def
->alias_count
, complemented_count
, def
->complemented_count
);
437 static void delete_overloaded_cme(const rb_callable_method_entry_t
*cme
);
440 rb_free_method_entry(const rb_method_entry_t
*me
)
442 if (me
->def
&& me
->def
->iseq_overload
) {
443 delete_overloaded_cme((const rb_callable_method_entry_t
*)me
);
445 rb_method_definition_release(me
->def
, METHOD_ENTRY_COMPLEMENTED(me
));
448 static inline rb_method_entry_t
*search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
);
449 extern int rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
);
452 (*call_cfunc_invoker_func(int argc
))(VALUE recv
, int argc
, const VALUE
*, VALUE (*func
)(ANYARGS
))
454 if (!GET_THREAD()->ext_config
.ractor_safe
) {
456 case -2: return &call_cfunc_m2
;
457 case -1: return &call_cfunc_m1
;
458 case 0: return &call_cfunc_0
;
459 case 1: return &call_cfunc_1
;
460 case 2: return &call_cfunc_2
;
461 case 3: return &call_cfunc_3
;
462 case 4: return &call_cfunc_4
;
463 case 5: return &call_cfunc_5
;
464 case 6: return &call_cfunc_6
;
465 case 7: return &call_cfunc_7
;
466 case 8: return &call_cfunc_8
;
467 case 9: return &call_cfunc_9
;
468 case 10: return &call_cfunc_10
;
469 case 11: return &call_cfunc_11
;
470 case 12: return &call_cfunc_12
;
471 case 13: return &call_cfunc_13
;
472 case 14: return &call_cfunc_14
;
473 case 15: return &call_cfunc_15
;
475 rb_bug("unsupported length: %d", argc
);
480 case -2: return &ractor_safe_call_cfunc_m2
;
481 case -1: return &ractor_safe_call_cfunc_m1
;
482 case 0: return &ractor_safe_call_cfunc_0
;
483 case 1: return &ractor_safe_call_cfunc_1
;
484 case 2: return &ractor_safe_call_cfunc_2
;
485 case 3: return &ractor_safe_call_cfunc_3
;
486 case 4: return &ractor_safe_call_cfunc_4
;
487 case 5: return &ractor_safe_call_cfunc_5
;
488 case 6: return &ractor_safe_call_cfunc_6
;
489 case 7: return &ractor_safe_call_cfunc_7
;
490 case 8: return &ractor_safe_call_cfunc_8
;
491 case 9: return &ractor_safe_call_cfunc_9
;
492 case 10: return &ractor_safe_call_cfunc_10
;
493 case 11: return &ractor_safe_call_cfunc_11
;
494 case 12: return &ractor_safe_call_cfunc_12
;
495 case 13: return &ractor_safe_call_cfunc_13
;
496 case 14: return &ractor_safe_call_cfunc_14
;
497 case 15: return &ractor_safe_call_cfunc_15
;
499 rb_bug("unsupported length: %d", argc
);
505 setup_method_cfunc_struct(rb_method_cfunc_t
*cfunc
, VALUE (*func
)(ANYARGS
), int argc
)
509 cfunc
->invoker
= call_cfunc_invoker_func(argc
);
513 rb_method_definition_set(const rb_method_entry_t
*me
, rb_method_definition_t
*def
, void *opts
)
515 *(rb_method_definition_t
**)&me
->def
= def
;
519 case VM_METHOD_TYPE_ISEQ
:
521 rb_method_iseq_t
*iseq_body
= (rb_method_iseq_t
*)opts
;
522 const rb_iseq_t
*iseq
= iseq_body
->iseqptr
;
523 rb_cref_t
*method_cref
, *cref
= iseq_body
->cref
;
525 /* setup iseq first (before invoking GC) */
526 RB_OBJ_WRITE(me
, &def
->body
.iseq
.iseqptr
, iseq
);
528 if (ISEQ_BODY(iseq
)->mandatory_only_iseq
) def
->iseq_overload
= 1;
530 if (0) vm_cref_dump("rb_method_definition_create", cref
);
536 method_cref
= vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */
539 RB_OBJ_WRITE(me
, &def
->body
.iseq
.cref
, method_cref
);
542 case VM_METHOD_TYPE_CFUNC
:
544 rb_method_cfunc_t
*cfunc
= (rb_method_cfunc_t
*)opts
;
545 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), cfunc
->func
, cfunc
->argc
);
548 case VM_METHOD_TYPE_ATTRSET
:
549 case VM_METHOD_TYPE_IVAR
:
551 const rb_execution_context_t
*ec
= GET_EC();
552 rb_control_frame_t
*cfp
;
555 def
->body
.attr
.id
= (ID
)(VALUE
)opts
;
557 cfp
= rb_vm_get_ruby_level_next_cfp(ec
, ec
->cfp
);
559 if (cfp
&& (line
= rb_vm_get_sourceline(cfp
))) {
560 VALUE location
= rb_ary_new3(2, rb_iseq_path(cfp
->iseq
), INT2FIX(line
));
561 RB_OBJ_WRITE(me
, &def
->body
.attr
.location
, rb_ary_freeze(location
));
564 VM_ASSERT(def
->body
.attr
.location
== 0);
568 case VM_METHOD_TYPE_BMETHOD
:
569 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.proc
, (VALUE
)opts
);
570 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.defined_ractor
, rb_ractor_self(GET_RACTOR()));
572 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
573 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), (VALUE(*)(ANYARGS
))rb_f_notimplement_internal
, -1);
575 case VM_METHOD_TYPE_OPTIMIZED
:
576 def
->body
.optimized
= *(rb_method_optimized_t
*)opts
;
578 case VM_METHOD_TYPE_REFINED
:
580 const rb_method_refined_t
*refined
= (rb_method_refined_t
*)opts
;
581 RB_OBJ_WRITE(me
, &def
->body
.refined
.orig_me
, refined
->orig_me
);
582 RB_OBJ_WRITE(me
, &def
->body
.refined
.owner
, refined
->owner
);
585 case VM_METHOD_TYPE_ALIAS
:
586 RB_OBJ_WRITE(me
, &def
->body
.alias
.original_me
, (rb_method_entry_t
*)opts
);
588 case VM_METHOD_TYPE_ZSUPER
:
589 case VM_METHOD_TYPE_UNDEF
:
590 case VM_METHOD_TYPE_MISSING
:
597 method_definition_reset(const rb_method_entry_t
*me
)
599 rb_method_definition_t
*def
= me
->def
;
602 case VM_METHOD_TYPE_ISEQ
:
603 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.iseqptr
);
604 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.cref
);
606 case VM_METHOD_TYPE_ATTRSET
:
607 case VM_METHOD_TYPE_IVAR
:
608 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.attr
.location
);
610 case VM_METHOD_TYPE_BMETHOD
:
611 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.proc
);
612 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.defined_ractor
);
613 /* give up to check all in a list */
614 if (def
->body
.bmethod
.hooks
) rb_gc_writebarrier_remember((VALUE
)me
);
616 case VM_METHOD_TYPE_REFINED
:
617 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.refined
.orig_me
);
618 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.refined
.owner
);
620 case VM_METHOD_TYPE_ALIAS
:
621 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.alias
.original_me
);
623 case VM_METHOD_TYPE_CFUNC
:
624 case VM_METHOD_TYPE_ZSUPER
:
625 case VM_METHOD_TYPE_MISSING
:
626 case VM_METHOD_TYPE_OPTIMIZED
:
627 case VM_METHOD_TYPE_UNDEF
:
628 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
633 rb_method_definition_t
*
634 rb_method_definition_create(rb_method_type_t type
, ID mid
)
636 rb_method_definition_t
*def
;
637 def
= ZALLOC(rb_method_definition_t
);
639 def
->original_id
= mid
;
640 static uintptr_t method_serial
= 1;
641 def
->method_serial
= method_serial
++;
645 static rb_method_definition_t
*
646 method_definition_addref(rb_method_definition_t
*def
)
649 if (METHOD_DEBUG
) fprintf(stderr
, "+%p-%s:%d\n", (void *)def
, rb_id2name(def
->original_id
), def
->alias_count
);
653 static rb_method_definition_t
*
654 method_definition_addref_complement(rb_method_definition_t
*def
)
656 def
->complemented_count
++;
657 if (METHOD_DEBUG
) fprintf(stderr
, "+%p-%s:%d\n", (void *)def
, rb_id2name(def
->original_id
), def
->complemented_count
);
661 static rb_method_entry_t
*
662 rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
)
664 rb_method_entry_t
*me
= (rb_method_entry_t
*)rb_imemo_new(imemo_ment
, (VALUE
)def
, (VALUE
)called_id
, owner
, defined_class
);
669 filter_defined_class(VALUE klass
)
671 switch (BUILTIN_TYPE(klass
)) {
681 rb_bug("filter_defined_class: %s", rb_obj_info(klass
));
685 rb_method_entry_create(ID called_id
, VALUE klass
, rb_method_visibility_t visi
, const rb_method_definition_t
*def
)
687 rb_method_entry_t
*me
= rb_method_entry_alloc(called_id
, klass
, filter_defined_class(klass
), def
);
688 METHOD_ENTRY_FLAGS_SET(me
, visi
, ruby_running
? FALSE
: TRUE
);
689 if (def
!= NULL
) method_definition_reset(me
);
693 const rb_method_entry_t
*
694 rb_method_entry_clone(const rb_method_entry_t
*src_me
)
696 rb_method_entry_t
*me
= rb_method_entry_alloc(src_me
->called_id
, src_me
->owner
, src_me
->defined_class
,
697 method_definition_addref(src_me
->def
));
698 if (METHOD_ENTRY_COMPLEMENTED(src_me
)) {
699 method_definition_addref_complement(src_me
->def
);
702 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
706 const rb_callable_method_entry_t
*
707 rb_method_entry_complement_defined_class(const rb_method_entry_t
*src_me
, ID called_id
, VALUE defined_class
)
709 rb_method_definition_t
*def
= src_me
->def
;
710 rb_method_entry_t
*me
;
712 const struct rb_method_entry_struct
*orig_me
;
716 if (!src_me
->defined_class
&&
717 def
->type
== VM_METHOD_TYPE_REFINED
&&
718 def
->body
.refined
.orig_me
) {
719 const rb_method_entry_t
*orig_me
=
720 rb_method_entry_clone(def
->body
.refined
.orig_me
);
721 RB_OBJ_WRITE((VALUE
)orig_me
, &orig_me
->defined_class
, defined_class
);
722 refined
.orig_me
= orig_me
;
723 refined
.owner
= orig_me
->owner
;
727 def
= method_definition_addref_complement(def
);
729 me
= rb_method_entry_alloc(called_id
, src_me
->owner
, defined_class
, def
);
730 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
731 METHOD_ENTRY_COMPLEMENTED_SET(me
);
733 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, called_id
);
734 rb_method_definition_set(me
, def
, &refined
);
737 VM_ASSERT(RB_TYPE_P(me
->owner
, T_MODULE
));
739 return (rb_callable_method_entry_t
*)me
;
743 rb_method_entry_copy(rb_method_entry_t
*dst
, const rb_method_entry_t
*src
)
745 *(rb_method_definition_t
**)&dst
->def
= method_definition_addref(src
->def
);
746 method_definition_reset(dst
);
747 dst
->called_id
= src
->called_id
;
748 RB_OBJ_WRITE((VALUE
)dst
, &dst
->owner
, src
->owner
);
749 RB_OBJ_WRITE((VALUE
)dst
, &dst
->defined_class
, src
->defined_class
);
750 METHOD_ENTRY_FLAGS_COPY(dst
, src
);
754 make_method_entry_refined(VALUE owner
, rb_method_entry_t
*me
)
756 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
761 struct rb_method_entry_struct
*orig_me
;
764 rb_method_definition_t
*def
;
766 rb_vm_check_redefinition_opt_method(me
, me
->owner
);
769 rb_method_entry_alloc(me
->called_id
, me
->owner
,
771 me
->defined_class
: owner
,
772 method_definition_addref(me
->def
));
773 METHOD_ENTRY_FLAGS_COPY(refined
.orig_me
, me
);
774 refined
.owner
= owner
;
776 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, me
->called_id
);
777 rb_method_definition_set(me
, def
, (void *)&refined
);
778 METHOD_ENTRY_VISI_SET(me
, METHOD_VISI_PUBLIC
);
782 static inline rb_method_entry_t
*
783 lookup_method_table(VALUE klass
, ID id
)
786 struct rb_id_table
*m_tbl
= RCLASS_M_TBL(klass
);
788 if (rb_id_table_lookup(m_tbl
, id
, &body
)) {
789 return (rb_method_entry_t
*) body
;
797 rb_add_refined_method_entry(VALUE refined_class
, ID mid
)
799 rb_method_entry_t
*me
= lookup_method_table(refined_class
, mid
);
802 make_method_entry_refined(refined_class
, me
);
803 rb_clear_method_cache(refined_class
, mid
);
806 rb_add_method(refined_class
, mid
, VM_METHOD_TYPE_REFINED
, 0, METHOD_VISI_PUBLIC
);
811 check_override_opt_method_i(VALUE klass
, VALUE arg
)
814 const rb_method_entry_t
*me
, *newme
;
816 if (vm_redefinition_check_flag(klass
)) {
817 me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
819 newme
= rb_method_entry(klass
, mid
);
820 if (newme
!= me
) rb_vm_check_redefinition_opt_method(me
, me
->owner
);
823 rb_class_foreach_subclass(klass
, check_override_opt_method_i
, (VALUE
)mid
);
827 check_override_opt_method(VALUE klass
, VALUE mid
)
829 if (rb_vm_check_optimizable_mid(mid
)) {
830 check_override_opt_method_i(klass
, mid
);
835 * klass->method_table[mid] = method_entry(defined_class, visi, def)
837 * If def is given (!= NULL), then just use it and ignore original_id and otps.
838 * If not given, then make a new def with original_id and opts.
840 static rb_method_entry_t
*
841 rb_method_entry_make(VALUE klass
, ID mid
, VALUE defined_class
, rb_method_visibility_t visi
,
842 rb_method_type_t type
, rb_method_definition_t
*def
, ID original_id
, void *opts
)
844 rb_method_entry_t
*me
;
845 struct rb_id_table
*mtbl
;
847 int make_refined
= 0;
855 if (!FL_TEST(klass
, FL_SINGLETON
) &&
856 type
!= VM_METHOD_TYPE_NOTIMPLEMENTED
&&
857 type
!= VM_METHOD_TYPE_ZSUPER
) {
860 case idInitialize_copy
:
861 case idInitialize_clone
:
862 case idInitialize_dup
:
863 case idRespond_to_missing
:
864 visi
= METHOD_VISI_PRIVATE
;
868 if (type
!= VM_METHOD_TYPE_REFINED
) {
869 rb_class_modify_check(klass
);
872 if (RB_TYPE_P(klass
, T_MODULE
) && FL_TEST(klass
, RMODULE_IS_REFINEMENT
)) {
873 VALUE refined_class
= rb_refinement_module_get_refined_class(klass
);
874 rb_add_refined_method_entry(refined_class
, mid
);
876 if (type
== VM_METHOD_TYPE_REFINED
) {
877 rb_method_entry_t
*old_me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
878 if (old_me
) rb_vm_check_redefinition_opt_method(old_me
, klass
);
881 klass
= RCLASS_ORIGIN(klass
);
882 if (klass
!= orig_klass
) {
883 rb_clear_method_cache(orig_klass
, mid
);
886 mtbl
= RCLASS_M_TBL(klass
);
888 /* check re-definition */
889 if (rb_id_table_lookup(mtbl
, mid
, &data
)) {
890 rb_method_entry_t
*old_me
= (rb_method_entry_t
*)data
;
891 rb_method_definition_t
*old_def
= old_me
->def
;
893 if (rb_method_definition_eq(old_def
, def
)) return old_me
;
894 rb_vm_check_redefinition_opt_method(old_me
, klass
);
896 if (old_def
->type
== VM_METHOD_TYPE_REFINED
) make_refined
= 1;
898 if (RTEST(ruby_verbose
) &&
899 type
!= VM_METHOD_TYPE_UNDEF
&&
900 (old_def
->alias_count
== 0) &&
901 (!old_def
->no_redef_warning
) &&
903 old_def
->type
!= VM_METHOD_TYPE_UNDEF
&&
904 old_def
->type
!= VM_METHOD_TYPE_ZSUPER
&&
905 old_def
->type
!= VM_METHOD_TYPE_ALIAS
) {
906 const rb_iseq_t
*iseq
= 0;
908 rb_warning("method redefined; discarding old %"PRIsVALUE
, rb_id2str(mid
));
909 switch (old_def
->type
) {
910 case VM_METHOD_TYPE_ISEQ
:
911 iseq
= def_iseq_ptr(old_def
);
913 case VM_METHOD_TYPE_BMETHOD
:
914 iseq
= rb_proc_get_iseq(old_def
->body
.bmethod
.proc
, 0);
920 rb_compile_warning(RSTRING_PTR(rb_iseq_path(iseq
)),
921 ISEQ_BODY(iseq
)->location
.first_lineno
,
922 "previous definition of %"PRIsVALUE
" was here",
923 rb_id2str(old_def
->original_id
));
928 /* create method entry */
929 me
= rb_method_entry_create(mid
, defined_class
, visi
, NULL
);
930 if (def
== NULL
) def
= rb_method_definition_create(type
, original_id
);
931 rb_method_definition_set(me
, def
, opts
);
933 rb_clear_method_cache(klass
, mid
);
936 if (klass
== rb_cObject
) {
939 case idRespond_to_missing
:
940 case idMethodMissing
:
942 rb_warn("redefining Object#%s may cause infinite loop", rb_id2name(mid
));
946 if (mid
== object_id
|| mid
== id__send__
) {
947 if (type
== VM_METHOD_TYPE_ISEQ
&& search_method(klass
, mid
, 0)) {
948 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid
));
953 make_method_entry_refined(klass
, me
);
956 rb_method_table_insert(klass
, mtbl
, mid
, me
);
958 VM_ASSERT(me
->def
!= NULL
);
960 /* check optimized method override by a prepended module */
961 if (RB_TYPE_P(orig_klass
, T_MODULE
)) {
962 check_override_opt_method(klass
, (VALUE
)mid
);
968 static rb_method_entry_t
*rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
);
971 overloaded_cme_table(void)
973 VM_ASSERT(GET_VM()->overloaded_cme_table
!= NULL
);
974 return GET_VM()->overloaded_cme_table
;
977 #if VM_CHECK_MODE > 0
979 vm_dump_overloaded_cme_table(st_data_t key
, st_data_t val
, st_data_t dmy
)
981 fprintf(stderr
, "key: "); rp(key
);
982 fprintf(stderr
, "val: "); rp(val
);
987 rb_vm_dump_overloaded_cme_table(void)
989 fprintf(stderr
, "== rb_vm_dump_overloaded_cme_table\n");
990 st_foreach(overloaded_cme_table(), vm_dump_overloaded_cme_table
, 0);
995 lookup_overloaded_cme_i(st_data_t
*key
, st_data_t
*value
, st_data_t data
, int existing
)
998 const rb_callable_method_entry_t
*cme
= (const rb_callable_method_entry_t
*)*key
;
999 const rb_callable_method_entry_t
*monly_cme
= (const rb_callable_method_entry_t
*)*value
;
1000 const rb_callable_method_entry_t
**ptr
= (const rb_callable_method_entry_t
**)data
;
1002 if (rb_objspace_garbage_object_p((VALUE
)cme
) ||
1003 rb_objspace_garbage_object_p((VALUE
)monly_cme
)) {
1015 static const rb_callable_method_entry_t
*
1016 lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1018 ASSERT_vm_locking();
1020 const rb_callable_method_entry_t
*monly_cme
= NULL
;
1021 st_update(overloaded_cme_table(), (st_data_t
)cme
, lookup_overloaded_cme_i
, (st_data_t
)&monly_cme
);
1025 #if VM_CHECK_MODE > 0
1026 const rb_callable_method_entry_t
*
1027 rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1029 return lookup_overloaded_cme(cme
);
1034 delete_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1036 st_data_t cme_data
= (st_data_t
)cme
;
1037 ASSERT_vm_locking();
1038 st_delete(overloaded_cme_table(), &cme_data
, NULL
);
1041 static const rb_callable_method_entry_t
*
1042 get_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1044 const rb_callable_method_entry_t
*monly_cme
= lookup_overloaded_cme(cme
);
1046 if (monly_cme
&& !METHOD_ENTRY_INVALIDATED(monly_cme
)) {
1051 rb_method_definition_t
*def
= rb_method_definition_create(VM_METHOD_TYPE_ISEQ
, cme
->def
->original_id
);
1052 def
->body
.iseq
.cref
= cme
->def
->body
.iseq
.cref
;
1053 def
->body
.iseq
.iseqptr
= ISEQ_BODY(cme
->def
->body
.iseq
.iseqptr
)->mandatory_only_iseq
;
1055 rb_method_entry_t
*me
= rb_method_entry_alloc(cme
->called_id
,
1060 ASSERT_vm_locking();
1061 st_insert(overloaded_cme_table(), (st_data_t
)cme
, (st_data_t
)me
);
1063 METHOD_ENTRY_VISI_SET(me
, METHOD_ENTRY_VISI(cme
));
1064 return (rb_callable_method_entry_t
*)me
;
1068 static const rb_callable_method_entry_t
*
1069 check_overloaded_cme(const rb_callable_method_entry_t
*cme
, const struct rb_callinfo
* const ci
)
1071 if (UNLIKELY(cme
->def
->iseq_overload
) &&
1072 (vm_ci_flag(ci
) & (VM_CALL_ARGS_SIMPLE
)) &&
1073 (int)vm_ci_argc(ci
) == ISEQ_BODY(method_entry_iseqptr(cme
))->param
.lead_num
) {
1074 VM_ASSERT(cme
->def
->type
== VM_METHOD_TYPE_ISEQ
); // iseq_overload is marked only on ISEQ methods
1076 cme
= get_overloaded_cme(cme
);
1078 VM_ASSERT(cme
!= NULL
);
1079 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct
*)cme
);
1085 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
1086 const VALUE arg = ID2SYM(mid); \
1087 VALUE recv_class = (klass); \
1088 ID hook_id = (hook); \
1089 if (FL_TEST((klass), FL_SINGLETON)) { \
1090 recv_class = RCLASS_ATTACHED_OBJECT((klass)); \
1091 hook_id = singleton_##hook; \
1093 rb_funcallv(recv_class, hook_id, 1, &arg); \
1097 method_added(VALUE klass
, ID mid
)
1100 CALL_METHOD_HOOK(klass
, added
, mid
);
1105 rb_add_method(VALUE klass
, ID mid
, rb_method_type_t type
, void *opts
, rb_method_visibility_t visi
)
1107 rb_method_entry_make(klass
, mid
, klass
, visi
, type
, NULL
, mid
, opts
);
1109 if (type
!= VM_METHOD_TYPE_UNDEF
&& type
!= VM_METHOD_TYPE_REFINED
) {
1110 method_added(klass
, mid
);
1115 rb_add_method_iseq(VALUE klass
, ID mid
, const rb_iseq_t
*iseq
, rb_cref_t
*cref
, rb_method_visibility_t visi
)
1117 struct { /* should be same fields with rb_method_iseq_struct */
1118 const rb_iseq_t
*iseqptr
;
1122 iseq_body
.iseqptr
= iseq
;
1123 iseq_body
.cref
= cref
;
1125 rb_add_method(klass
, mid
, VM_METHOD_TYPE_ISEQ
, &iseq_body
, visi
);
1128 static rb_method_entry_t
*
1129 method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
,
1130 rb_method_visibility_t visi
, VALUE defined_class
)
1132 rb_method_entry_t
*newme
= rb_method_entry_make(klass
, mid
, defined_class
, visi
,
1133 me
->def
->type
, me
->def
, 0, NULL
);
1135 me
->def
->no_redef_warning
= TRUE
;
1138 method_definition_addref(me
->def
);
1140 method_added(klass
, mid
);
1145 rb_method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
, rb_method_visibility_t visi
)
1147 return method_entry_set(klass
, mid
, me
, visi
, klass
);
1150 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
1153 rb_define_alloc_func(VALUE klass
, VALUE (*func
)(VALUE
))
1155 Check_Type(klass
, T_CLASS
);
1156 if (FL_TEST_RAW(klass
, FL_SINGLETON
)) {
1157 rb_raise(rb_eTypeError
, "can't define an allocator for a singleton class");
1159 RCLASS_SET_ALLOCATOR(klass
, func
);
1163 rb_undef_alloc_func(VALUE klass
)
1165 rb_define_alloc_func(klass
, UNDEF_ALLOC_FUNC
);
1169 rb_get_alloc_func(VALUE klass
)
1171 Check_Type(klass
, T_CLASS
);
1173 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1174 rb_alloc_func_t allocator
= RCLASS_ALLOCATOR(klass
);
1175 if (allocator
== UNDEF_ALLOC_FUNC
) break;
1176 if (allocator
) return allocator
;
1181 const rb_method_entry_t
*
1182 rb_method_entry_at(VALUE klass
, ID id
)
1184 return lookup_method_table(klass
, id
);
1187 static inline rb_method_entry_t
*
1188 search_method0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool skip_refined
)
1190 rb_method_entry_t
*me
= NULL
;
1192 RB_DEBUG_COUNTER_INC(mc_search
);
1194 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1195 RB_DEBUG_COUNTER_INC(mc_search_super
);
1196 if ((me
= lookup_method_table(klass
, id
)) != 0) {
1197 if (!skip_refined
|| me
->def
->type
!= VM_METHOD_TYPE_REFINED
||
1198 me
->def
->body
.refined
.orig_me
) {
1204 if (defined_class_ptr
) *defined_class_ptr
= klass
;
1206 if (me
== NULL
) RB_DEBUG_COUNTER_INC(mc_search_notfound
);
1208 VM_ASSERT(me
== NULL
|| !METHOD_ENTRY_INVALIDATED(me
));
1212 static inline rb_method_entry_t
*
1213 search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1215 return search_method0(klass
, id
, defined_class_ptr
, false);
1218 static rb_method_entry_t
*
1219 search_method_protect(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1221 rb_method_entry_t
*me
= search_method(klass
, id
, defined_class_ptr
);
1223 if (!UNDEFINED_METHOD_ENTRY_P(me
)) {
1231 const rb_method_entry_t
*
1232 rb_method_entry(VALUE klass
, ID id
)
1234 return search_method_protect(klass
, id
, NULL
);
1237 static inline const rb_callable_method_entry_t
*
1238 prepare_callable_method_entry(VALUE defined_class
, ID id
, const rb_method_entry_t
* const me
, int create
)
1240 struct rb_id_table
*mtbl
;
1241 const rb_callable_method_entry_t
*cme
;
1245 if (me
->defined_class
== 0) {
1246 RB_DEBUG_COUNTER_INC(mc_cme_complement
);
1247 VM_ASSERT(RB_TYPE_P(defined_class
, T_ICLASS
) || RB_TYPE_P(defined_class
, T_MODULE
));
1248 VM_ASSERT(me
->defined_class
== 0);
1250 mtbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
1252 if (mtbl
&& rb_id_table_lookup(mtbl
, id
, &cme_data
)) {
1253 cme
= (rb_callable_method_entry_t
*)cme_data
;
1254 RB_DEBUG_COUNTER_INC(mc_cme_complement_hit
);
1255 VM_ASSERT(callable_method_entry_p(cme
));
1256 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1260 mtbl
= RCLASS_EXT(defined_class
)->callable_m_tbl
= rb_id_table_create(0);
1262 cme
= rb_method_entry_complement_defined_class(me
, me
->called_id
, defined_class
);
1263 rb_id_table_insert(mtbl
, id
, (VALUE
)cme
);
1264 RB_OBJ_WRITTEN(defined_class
, Qundef
, (VALUE
)cme
);
1265 VM_ASSERT(callable_method_entry_p(cme
));
1272 cme
= (const rb_callable_method_entry_t
*)me
;
1273 VM_ASSERT(callable_method_entry_p(cme
));
1274 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1283 static const rb_callable_method_entry_t
*
1284 complemented_callable_method_entry(VALUE klass
, ID id
)
1286 VALUE defined_class
;
1287 rb_method_entry_t
*me
= search_method(klass
, id
, &defined_class
);
1288 return prepare_callable_method_entry(defined_class
, id
, me
, FALSE
);
1291 static const rb_callable_method_entry_t
*
1292 cached_callable_method_entry(VALUE klass
, ID mid
)
1294 ASSERT_vm_locking();
1296 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1299 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1300 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1301 VM_ASSERT(vm_ccs_p(ccs
));
1303 if (LIKELY(!METHOD_ENTRY_INVALIDATED(ccs
->cme
))) {
1304 VM_ASSERT(ccs
->cme
->called_id
== mid
);
1305 RB_DEBUG_COUNTER_INC(ccs_found
);
1309 rb_vm_ccs_free(ccs
);
1310 rb_id_table_delete(cc_tbl
, mid
);
1314 RB_DEBUG_COUNTER_INC(ccs_not_found
);
1319 cache_callable_method_entry(VALUE klass
, ID mid
, const rb_callable_method_entry_t
*cme
)
1321 ASSERT_vm_locking();
1322 VM_ASSERT(cme
!= NULL
);
1324 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1328 cc_tbl
= RCLASS_CC_TBL(klass
) = rb_id_table_create(2);
1331 if (rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1332 #if VM_CHECK_MODE > 0
1333 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1334 VM_ASSERT(ccs
->cme
== cme
);
1338 vm_ccs_create(klass
, cc_tbl
, mid
, cme
);
1342 static const rb_callable_method_entry_t
*
1343 negative_cme(ID mid
)
1345 rb_vm_t
*vm
= GET_VM();
1346 const rb_callable_method_entry_t
*cme
;
1349 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme_data
)) {
1350 cme
= (rb_callable_method_entry_t
*)cme_data
;
1353 cme
= (rb_callable_method_entry_t
*)rb_method_entry_alloc(mid
, Qnil
, Qnil
, NULL
);
1354 rb_id_table_insert(vm
->negative_cme_table
, mid
, (VALUE
)cme
);
1357 VM_ASSERT(cme
!= NULL
);
1361 static const rb_callable_method_entry_t
*
1362 callable_method_entry_or_negative(VALUE klass
, ID mid
, VALUE
*defined_class_ptr
)
1364 const rb_callable_method_entry_t
*cme
;
1366 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1369 cme
= cached_callable_method_entry(klass
, mid
);
1372 if (defined_class_ptr
!= NULL
) *defined_class_ptr
= cme
->defined_class
;
1375 VALUE defined_class
;
1376 rb_method_entry_t
*me
= search_method(klass
, mid
, &defined_class
);
1377 if (defined_class_ptr
) *defined_class_ptr
= defined_class
;
1380 cme
= prepare_callable_method_entry(defined_class
, mid
, me
, TRUE
);
1383 cme
= negative_cme(mid
);
1386 cache_callable_method_entry(klass
, mid
, cme
);
1394 // This is exposed for YJIT so that we can make assumptions that methods are
1396 const rb_callable_method_entry_t
*
1397 rb_callable_method_entry_or_negative(VALUE klass
, ID mid
)
1399 return callable_method_entry_or_negative(klass
, mid
, NULL
);
1402 static const rb_callable_method_entry_t
*
1403 callable_method_entry(VALUE klass
, ID mid
, VALUE
*defined_class_ptr
)
1405 const rb_callable_method_entry_t
*cme
;
1406 cme
= callable_method_entry_or_negative(klass
, mid
, defined_class_ptr
);
1407 return !UNDEFINED_METHOD_ENTRY_P(cme
) ? cme
: NULL
;
1410 const rb_callable_method_entry_t
*
1411 rb_callable_method_entry(VALUE klass
, ID mid
)
1413 return callable_method_entry(klass
, mid
, NULL
);
1416 static const rb_method_entry_t
*resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
);
1418 static const rb_method_entry_t
*
1419 method_entry_resolve_refinement(VALUE klass
, ID id
, int with_refinement
, VALUE
*defined_class_ptr
)
1421 const rb_method_entry_t
*me
= search_method_protect(klass
, id
, defined_class_ptr
);
1424 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1425 if (with_refinement
) {
1426 const rb_cref_t
*cref
= rb_vm_cref();
1427 VALUE refinements
= cref
? CREF_REFINEMENTS(cref
) : Qnil
;
1428 me
= resolve_refined_method(refinements
, me
, defined_class_ptr
);
1431 me
= resolve_refined_method(Qnil
, me
, defined_class_ptr
);
1434 if (UNDEFINED_METHOD_ENTRY_P(me
)) me
= NULL
;
1441 const rb_method_entry_t
*
1442 rb_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1444 return method_entry_resolve_refinement(klass
, id
, TRUE
, defined_class_ptr
);
1447 static const rb_callable_method_entry_t
*
1448 callable_method_entry_refeinements0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
,
1449 const rb_callable_method_entry_t
*cme
)
1451 if (cme
== NULL
|| LIKELY(cme
->def
->type
!= VM_METHOD_TYPE_REFINED
)) {
1455 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1456 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, with_refinements
, dcp
);
1457 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1461 static const rb_callable_method_entry_t
*
1462 callable_method_entry_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
)
1464 const rb_callable_method_entry_t
*cme
= callable_method_entry(klass
, id
, defined_class_ptr
);
1465 return callable_method_entry_refeinements0(klass
, id
, defined_class_ptr
, with_refinements
, cme
);
1468 const rb_callable_method_entry_t
*
1469 rb_callable_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1471 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, true);
1474 static const rb_callable_method_entry_t
*
1475 callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1477 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, false);
1480 const rb_method_entry_t
*
1481 rb_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1483 return method_entry_resolve_refinement(klass
, id
, FALSE
, defined_class_ptr
);
1486 const rb_callable_method_entry_t
*
1487 rb_callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1489 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1490 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, FALSE
, dcp
);
1491 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1494 static const rb_method_entry_t
*
1495 resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
)
1497 while (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1499 const rb_method_entry_t
*tmp_me
;
1502 refinement
= find_refinement(refinements
, me
->owner
);
1503 if (!NIL_P(refinement
)) {
1504 tmp_me
= search_method_protect(refinement
, me
->called_id
, defined_class_ptr
);
1506 if (tmp_me
&& tmp_me
->def
->type
!= VM_METHOD_TYPE_REFINED
) {
1511 tmp_me
= me
->def
->body
.refined
.orig_me
;
1513 if (defined_class_ptr
) *defined_class_ptr
= tmp_me
->defined_class
;
1517 super
= RCLASS_SUPER(me
->owner
);
1522 me
= search_method_protect(super
, me
->called_id
, defined_class_ptr
);
1527 const rb_method_entry_t
*
1528 rb_resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
)
1530 return resolve_refined_method(refinements
, me
, NULL
);
1533 const rb_callable_method_entry_t
*
1534 rb_resolve_refined_method_callable(VALUE refinements
, const rb_callable_method_entry_t
*me
)
1536 VALUE defined_class
= me
->defined_class
;
1537 const rb_method_entry_t
*resolved_me
= resolve_refined_method(refinements
, (const rb_method_entry_t
*)me
, &defined_class
);
1539 if (resolved_me
&& resolved_me
->defined_class
== 0) {
1540 return rb_method_entry_complement_defined_class(resolved_me
, me
->called_id
, defined_class
);
1543 return (const rb_callable_method_entry_t
*)resolved_me
;
1548 remove_method(VALUE klass
, ID mid
)
1551 rb_method_entry_t
*me
= 0;
1554 rb_class_modify_check(klass
);
1555 klass
= RCLASS_ORIGIN(klass
);
1556 if (mid
== object_id
|| mid
== id__send__
|| mid
== idInitialize
) {
1557 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid
));
1560 if (!rb_id_table_lookup(RCLASS_M_TBL(klass
), mid
, &data
) ||
1561 !(me
= (rb_method_entry_t
*)data
) ||
1562 (!me
->def
|| me
->def
->type
== VM_METHOD_TYPE_UNDEF
) ||
1563 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1564 rb_name_err_raise("method `%1$s' not defined in %2$s",
1565 klass
, ID2SYM(mid
));
1568 if (klass
!= self
) {
1569 rb_clear_method_cache(self
, mid
);
1571 rb_clear_method_cache(klass
, mid
);
1572 rb_id_table_delete(RCLASS_M_TBL(klass
), mid
);
1574 rb_vm_check_redefinition_opt_method(me
, klass
);
1576 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1577 rb_add_refined_method_entry(klass
, mid
);
1580 CALL_METHOD_HOOK(self
, removed
, mid
);
1584 rb_remove_method_id(VALUE klass
, ID mid
)
1586 remove_method(klass
, mid
);
1590 rb_remove_method(VALUE klass
, const char *name
)
1592 remove_method(klass
, rb_intern(name
));
1597 * remove_method(symbol) -> self
1598 * remove_method(string) -> self
1600 * Removes the method identified by _symbol_ from the current
1601 * class. For an example, see Module#undef_method.
1602 * String arguments are converted to symbols.
1606 rb_mod_remove_method(int argc
, VALUE
*argv
, VALUE mod
)
1610 for (i
= 0; i
< argc
; i
++) {
1612 ID id
= rb_check_id(&v
);
1614 rb_name_err_raise("method `%1$s' not defined in %2$s",
1617 remove_method(mod
, id
);
1623 rb_export_method(VALUE klass
, ID name
, rb_method_visibility_t visi
)
1625 rb_method_entry_t
*me
;
1626 VALUE defined_class
;
1627 VALUE origin_class
= RCLASS_ORIGIN(klass
);
1629 me
= search_method0(origin_class
, name
, &defined_class
, true);
1631 if (!me
&& RB_TYPE_P(klass
, T_MODULE
)) {
1632 me
= search_method(rb_cObject
, name
, &defined_class
);
1635 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1636 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1637 rb_print_undef(klass
, name
, METHOD_VISI_UNDEF
);
1640 if (METHOD_ENTRY_VISI(me
) != visi
) {
1641 rb_vm_check_redefinition_opt_method(me
, klass
);
1643 if (klass
== defined_class
|| origin_class
== defined_class
) {
1644 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1645 // Refinement method entries should always be public because the refinement
1646 // search is always performed.
1647 if (me
->def
->body
.refined
.orig_me
) {
1648 METHOD_ENTRY_VISI_SET((rb_method_entry_t
*)me
->def
->body
.refined
.orig_me
, visi
);
1652 METHOD_ENTRY_VISI_SET(me
, visi
);
1654 rb_clear_method_cache(klass
, name
);
1657 rb_add_method(klass
, name
, VM_METHOD_TYPE_ZSUPER
, 0, visi
);
1662 #define BOUND_PRIVATE 0x01
1663 #define BOUND_RESPONDS 0x02
1666 method_boundp(VALUE klass
, ID id
, int ex
)
1668 const rb_callable_method_entry_t
*cme
;
1670 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1672 if (ex
& BOUND_RESPONDS
) {
1673 cme
= rb_callable_method_entry_with_refinements(klass
, id
, NULL
);
1676 cme
= callable_method_entry_without_refinements(klass
, id
, NULL
);
1680 if (ex
& ~BOUND_RESPONDS
) {
1681 switch (METHOD_ENTRY_VISI(cme
)) {
1682 case METHOD_VISI_PRIVATE
:
1684 case METHOD_VISI_PROTECTED
:
1685 if (ex
& BOUND_RESPONDS
) return 0;
1691 if (cme
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) {
1692 if (ex
& BOUND_RESPONDS
) return 2;
1702 rb_method_boundp(VALUE klass
, ID id
, int ex
)
1704 return method_boundp(klass
, id
, ex
);
1708 vm_cref_set_visibility(rb_method_visibility_t method_visi
, int module_func
)
1710 rb_scope_visibility_t
*scope_visi
= (rb_scope_visibility_t
*)&rb_vm_cref()->scope_visi
;
1711 scope_visi
->method_visi
= method_visi
;
1712 scope_visi
->module_func
= module_func
;
1716 rb_scope_visibility_set(rb_method_visibility_t visi
)
1718 vm_cref_set_visibility(visi
, FALSE
);
1722 scope_visibility_check(void)
1724 /* Check for public/protected/private/module_function called inside a method */
1725 rb_control_frame_t
*cfp
= GET_EC()->cfp
+1;
1726 if (cfp
&& cfp
->iseq
&& ISEQ_BODY(cfp
->iseq
)->type
== ISEQ_TYPE_METHOD
) {
1727 rb_warn("calling %s without arguments inside a method may not have the intended effect",
1728 rb_id2name(rb_frame_this_func()));
1733 rb_scope_module_func_set(void)
1735 scope_visibility_check();
1736 vm_cref_set_visibility(METHOD_VISI_PRIVATE
, TRUE
);
1739 const rb_cref_t
*rb_vm_cref_in_context(VALUE self
, VALUE cbase
);
1741 rb_attr(VALUE klass
, ID id
, int read
, int write
, int ex
)
1744 rb_method_visibility_t visi
;
1745 const rb_execution_context_t
*ec
= GET_EC();
1746 const rb_cref_t
*cref
= rb_vm_cref_in_context(klass
, klass
);
1749 visi
= METHOD_VISI_PUBLIC
;
1752 switch (vm_scope_visibility_get(ec
)) {
1753 case METHOD_VISI_PRIVATE
:
1754 if (vm_scope_module_func_check(ec
)) {
1755 rb_warning("attribute accessor as module_function");
1757 visi
= METHOD_VISI_PRIVATE
;
1759 case METHOD_VISI_PROTECTED
:
1760 visi
= METHOD_VISI_PROTECTED
;
1763 visi
= METHOD_VISI_PUBLIC
;
1768 attriv
= rb_intern_str(rb_sprintf("@%"PRIsVALUE
, rb_id2str(id
)));
1770 rb_add_method(klass
, id
, VM_METHOD_TYPE_IVAR
, (void *)attriv
, visi
);
1773 rb_add_method(klass
, rb_id_attrset(id
), VM_METHOD_TYPE_ATTRSET
, (void *)attriv
, visi
);
1778 rb_undef(VALUE klass
, ID id
)
1780 const rb_method_entry_t
*me
;
1783 rb_raise(rb_eTypeError
, "no class to undef method");
1785 rb_class_modify_check(klass
);
1786 if (id
== object_id
|| id
== id__send__
|| id
== idInitialize
) {
1787 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id
));
1790 me
= search_method(klass
, id
, 0);
1791 if (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1792 me
= rb_resolve_refined_method(Qnil
, me
);
1795 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1796 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1797 rb_method_name_error(klass
, rb_id2str(id
));
1800 rb_add_method(klass
, id
, VM_METHOD_TYPE_UNDEF
, 0, METHOD_VISI_PUBLIC
);
1802 CALL_METHOD_HOOK(klass
, undefined
, id
);
1807 * undef_method(symbol) -> self
1808 * undef_method(string) -> self
1810 * Prevents the current class from responding to calls to the named
1811 * method. Contrast this with <code>remove_method</code>, which deletes
1812 * the method from the particular class; Ruby will still search
1813 * superclasses and mixed-in modules for a possible receiver.
1814 * String arguments are converted to symbols.
1821 * class Child < Parent
1833 * remove_method :hello # remove from child, still in parent
1839 * undef_method :hello # prevent any calls to 'hello'
1843 * <em>produces:</em>
1847 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
1851 rb_mod_undef_method(int argc
, VALUE
*argv
, VALUE mod
)
1854 for (i
= 0; i
< argc
; i
++) {
1856 ID id
= rb_check_id(&v
);
1858 rb_method_name_error(mod
, v
);
1865 static rb_method_visibility_t
1866 check_definition_visibility(VALUE mod
, int argc
, VALUE
*argv
)
1868 const rb_method_entry_t
*me
;
1869 VALUE mid
, include_super
, lookup_mod
= mod
;
1873 rb_scan_args(argc
, argv
, "11", &mid
, &include_super
);
1874 id
= rb_check_id(&mid
);
1875 if (!id
) return METHOD_VISI_UNDEF
;
1881 inc_super
= RTEST(include_super
);
1883 lookup_mod
= RCLASS_ORIGIN(mod
);
1887 me
= rb_method_entry_without_refinements(lookup_mod
, id
, NULL
);
1889 if (me
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) return METHOD_VISI_UNDEF
;
1890 if (!inc_super
&& me
->owner
!= mod
) return METHOD_VISI_UNDEF
;
1891 return METHOD_ENTRY_VISI(me
);
1893 return METHOD_VISI_UNDEF
;
1898 * mod.method_defined?(symbol, inherit=true) -> true or false
1899 * mod.method_defined?(string, inherit=true) -> true or false
1901 * Returns +true+ if the named method is defined by
1902 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1903 * ancestors. Public and protected methods are matched.
1904 * String arguments are converted to symbols.
1908 * def protected_method1() end
1909 * protected :protected_method1
1913 * def private_method2() end
1914 * private :private_method2
1921 * A.method_defined? :method1 #=> true
1922 * C.method_defined? "method1" #=> true
1923 * C.method_defined? "method2" #=> true
1924 * C.method_defined? "method2", true #=> true
1925 * C.method_defined? "method2", false #=> false
1926 * C.method_defined? "method3" #=> true
1927 * C.method_defined? "protected_method1" #=> true
1928 * C.method_defined? "method4" #=> false
1929 * C.method_defined? "private_method2" #=> false
1933 rb_mod_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1935 rb_method_visibility_t visi
= check_definition_visibility(mod
, argc
, argv
);
1936 return RBOOL(visi
== METHOD_VISI_PUBLIC
|| visi
== METHOD_VISI_PROTECTED
);
1940 check_definition(VALUE mod
, int argc
, VALUE
*argv
, rb_method_visibility_t visi
)
1942 return RBOOL(check_definition_visibility(mod
, argc
, argv
) == visi
);
1947 * mod.public_method_defined?(symbol, inherit=true) -> true or false
1948 * mod.public_method_defined?(string, inherit=true) -> true or false
1950 * Returns +true+ if the named public method is defined by
1951 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1953 * String arguments are converted to symbols.
1967 * A.method_defined? :method1 #=> true
1968 * C.public_method_defined? "method1" #=> true
1969 * C.public_method_defined? "method1", true #=> true
1970 * C.public_method_defined? "method1", false #=> true
1971 * C.public_method_defined? "method2" #=> false
1972 * C.method_defined? "method2" #=> true
1976 rb_mod_public_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1978 return check_definition(mod
, argc
, argv
, METHOD_VISI_PUBLIC
);
1983 * mod.private_method_defined?(symbol, inherit=true) -> true or false
1984 * mod.private_method_defined?(string, inherit=true) -> true or false
1986 * Returns +true+ if the named private method is defined by
1987 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1989 * String arguments are converted to symbols.
2003 * A.method_defined? :method1 #=> true
2004 * C.private_method_defined? "method1" #=> false
2005 * C.private_method_defined? "method2" #=> true
2006 * C.private_method_defined? "method2", true #=> true
2007 * C.private_method_defined? "method2", false #=> false
2008 * C.method_defined? "method2" #=> false
2012 rb_mod_private_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2014 return check_definition(mod
, argc
, argv
, METHOD_VISI_PRIVATE
);
2019 * mod.protected_method_defined?(symbol, inherit=true) -> true or false
2020 * mod.protected_method_defined?(string, inherit=true) -> true or false
2022 * Returns +true+ if the named protected method is defined
2023 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
2025 * String arguments are converted to symbols.
2039 * A.method_defined? :method1 #=> true
2040 * C.protected_method_defined? "method1" #=> false
2041 * C.protected_method_defined? "method2" #=> true
2042 * C.protected_method_defined? "method2", true #=> true
2043 * C.protected_method_defined? "method2", false #=> false
2044 * C.method_defined? "method2" #=> true
2048 rb_mod_protected_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
2050 return check_definition(mod
, argc
, argv
, METHOD_VISI_PROTECTED
);
2054 rb_method_entry_eq(const rb_method_entry_t
*m1
, const rb_method_entry_t
*m2
)
2056 return rb_method_definition_eq(m1
->def
, m2
->def
);
2059 static const rb_method_definition_t
*
2060 original_method_definition(const rb_method_definition_t
*def
)
2064 switch (def
->type
) {
2065 case VM_METHOD_TYPE_REFINED
:
2066 if (def
->body
.refined
.orig_me
) {
2067 def
= def
->body
.refined
.orig_me
->def
;
2071 case VM_METHOD_TYPE_ALIAS
:
2072 def
= def
->body
.alias
.original_me
->def
;
2082 rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
)
2084 d1
= original_method_definition(d1
);
2085 d2
= original_method_definition(d2
);
2087 if (d1
== d2
) return 1;
2088 if (!d1
|| !d2
) return 0;
2089 if (d1
->type
!= d2
->type
) return 0;
2092 case VM_METHOD_TYPE_ISEQ
:
2093 return d1
->body
.iseq
.iseqptr
== d2
->body
.iseq
.iseqptr
;
2094 case VM_METHOD_TYPE_CFUNC
:
2096 d1
->body
.cfunc
.func
== d2
->body
.cfunc
.func
&&
2097 d1
->body
.cfunc
.argc
== d2
->body
.cfunc
.argc
;
2098 case VM_METHOD_TYPE_ATTRSET
:
2099 case VM_METHOD_TYPE_IVAR
:
2100 return d1
->body
.attr
.id
== d2
->body
.attr
.id
;
2101 case VM_METHOD_TYPE_BMETHOD
:
2102 return RTEST(rb_equal(d1
->body
.bmethod
.proc
, d2
->body
.bmethod
.proc
));
2103 case VM_METHOD_TYPE_MISSING
:
2104 return d1
->original_id
== d2
->original_id
;
2105 case VM_METHOD_TYPE_ZSUPER
:
2106 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2107 case VM_METHOD_TYPE_UNDEF
:
2109 case VM_METHOD_TYPE_OPTIMIZED
:
2110 return (d1
->body
.optimized
.type
== d2
->body
.optimized
.type
) &&
2111 (d1
->body
.optimized
.index
== d2
->body
.optimized
.index
);
2112 case VM_METHOD_TYPE_REFINED
:
2113 case VM_METHOD_TYPE_ALIAS
:
2116 rb_bug("rb_method_definition_eq: unsupported type: %d\n", d1
->type
);
2120 rb_hash_method_definition(st_index_t hash
, const rb_method_definition_t
*def
)
2122 hash
= rb_hash_uint(hash
, def
->type
);
2123 def
= original_method_definition(def
);
2125 if (!def
) return hash
;
2127 switch (def
->type
) {
2128 case VM_METHOD_TYPE_ISEQ
:
2129 return rb_hash_uint(hash
, (st_index_t
)def
->body
.iseq
.iseqptr
);
2130 case VM_METHOD_TYPE_CFUNC
:
2131 hash
= rb_hash_uint(hash
, (st_index_t
)def
->body
.cfunc
.func
);
2132 return rb_hash_uint(hash
, def
->body
.cfunc
.argc
);
2133 case VM_METHOD_TYPE_ATTRSET
:
2134 case VM_METHOD_TYPE_IVAR
:
2135 return rb_hash_uint(hash
, def
->body
.attr
.id
);
2136 case VM_METHOD_TYPE_BMETHOD
:
2137 return rb_hash_proc(hash
, def
->body
.bmethod
.proc
);
2138 case VM_METHOD_TYPE_MISSING
:
2139 return rb_hash_uint(hash
, def
->original_id
);
2140 case VM_METHOD_TYPE_ZSUPER
:
2141 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2142 case VM_METHOD_TYPE_UNDEF
:
2144 case VM_METHOD_TYPE_OPTIMIZED
:
2145 hash
= rb_hash_uint(hash
, def
->body
.optimized
.index
);
2146 return rb_hash_uint(hash
, def
->body
.optimized
.type
);
2147 case VM_METHOD_TYPE_REFINED
:
2148 case VM_METHOD_TYPE_ALIAS
:
2149 break; /* unreachable */
2151 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def
->type
);
2155 rb_hash_method_entry(st_index_t hash
, const rb_method_entry_t
*me
)
2157 return rb_hash_method_definition(hash
, me
->def
);
2161 rb_alias(VALUE klass
, ID alias_name
, ID original_name
)
2163 const VALUE target_klass
= klass
;
2164 VALUE defined_class
;
2165 const rb_method_entry_t
*orig_me
;
2166 rb_method_visibility_t visi
= METHOD_VISI_UNDEF
;
2169 rb_raise(rb_eTypeError
, "no class to make alias");
2172 rb_class_modify_check(klass
);
2175 orig_me
= search_method(klass
, original_name
, &defined_class
);
2177 if (orig_me
&& orig_me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
2178 orig_me
= rb_resolve_refined_method(Qnil
, orig_me
);
2181 if (UNDEFINED_METHOD_ENTRY_P(orig_me
) ||
2182 UNDEFINED_REFINED_METHOD_P(orig_me
->def
)) {
2183 if ((!RB_TYPE_P(klass
, T_MODULE
)) ||
2184 (orig_me
= search_method(rb_cObject
, original_name
, &defined_class
),
2185 UNDEFINED_METHOD_ENTRY_P(orig_me
))) {
2186 rb_print_undef(klass
, original_name
, METHOD_VISI_UNDEF
);
2190 switch (orig_me
->def
->type
) {
2191 case VM_METHOD_TYPE_ZSUPER
:
2192 klass
= RCLASS_SUPER(klass
);
2193 original_name
= orig_me
->def
->original_id
;
2194 visi
= METHOD_ENTRY_VISI(orig_me
);
2196 case VM_METHOD_TYPE_ALIAS
:
2197 visi
= METHOD_ENTRY_VISI(orig_me
);
2198 orig_me
= orig_me
->def
->body
.alias
.original_me
;
2199 VM_ASSERT(orig_me
->def
->type
!= VM_METHOD_TYPE_ALIAS
);
2204 if (visi
== METHOD_VISI_UNDEF
) visi
= METHOD_ENTRY_VISI(orig_me
);
2206 if (orig_me
->defined_class
== 0) {
2207 rb_method_entry_make(target_klass
, alias_name
, target_klass
, visi
,
2208 VM_METHOD_TYPE_ALIAS
, NULL
, orig_me
->called_id
,
2209 (void *)rb_method_entry_clone(orig_me
));
2210 method_added(target_klass
, alias_name
);
2213 rb_method_entry_t
*alias_me
;
2215 alias_me
= method_entry_set(target_klass
, alias_name
, orig_me
, visi
, orig_me
->owner
);
2216 RB_OBJ_WRITE(alias_me
, &alias_me
->owner
, target_klass
);
2217 RB_OBJ_WRITE(alias_me
, &alias_me
->defined_class
, orig_me
->defined_class
);
2223 * alias_method(new_name, old_name) -> symbol
2225 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
2226 * be used to retain access to methods that are overridden.
2229 * alias_method :orig_exit, :exit #=> :orig_exit
2231 * puts "Exiting with code #{code}"
2238 * <em>produces:</em>
2240 * Exiting with code 99
2244 rb_mod_alias_method(VALUE mod
, VALUE newname
, VALUE oldname
)
2246 ID oldid
= rb_check_id(&oldname
);
2248 rb_print_undef_str(mod
, oldname
);
2250 VALUE id
= rb_to_id(newname
);
2251 rb_alias(mod
, id
, oldid
);
2256 check_and_export_method(VALUE self
, VALUE name
, rb_method_visibility_t visi
)
2258 ID id
= rb_check_id(&name
);
2260 rb_print_undef_str(self
, name
);
2262 rb_export_method(self
, id
, visi
);
2266 set_method_visibility(VALUE self
, int argc
, const VALUE
*argv
, rb_method_visibility_t visi
)
2270 rb_check_frozen(self
);
2272 rb_warning("%"PRIsVALUE
" with no argument is just ignored",
2273 QUOTE_ID(rb_frame_callee()));
2280 if (argc
== 1 && (v
= rb_check_array_type(argv
[0])) != Qnil
) {
2283 for (j
= 0; j
< RARRAY_LEN(v
); j
++) {
2284 check_and_export_method(self
, RARRAY_AREF(v
, j
), visi
);
2288 for (i
= 0; i
< argc
; i
++) {
2289 check_and_export_method(self
, argv
[i
], visi
);
2295 set_visibility(int argc
, const VALUE
*argv
, VALUE module
, rb_method_visibility_t visi
)
2298 scope_visibility_check();
2299 rb_scope_visibility_set(visi
);
2303 set_method_visibility(module
, argc
, argv
, visi
);
2307 return rb_ary_new_from_values(argc
, argv
);
2313 * public(method_name) -> method_name
2314 * public(method_name, method_name, ...) -> array
2315 * public(array) -> array
2317 * With no arguments, sets the default visibility for subsequently
2318 * defined methods to public. With arguments, sets the named methods to
2319 * have public visibility.
2320 * String arguments are converted to symbols.
2321 * An Array of Symbols and/or Strings is also accepted.
2322 * If a single argument is passed, it is returned.
2323 * If no argument is passed, nil is returned.
2324 * If multiple arguments are passed, the arguments are returned as an array.
2328 rb_mod_public(int argc
, VALUE
*argv
, VALUE module
)
2330 return set_visibility(argc
, argv
, module
, METHOD_VISI_PUBLIC
);
2336 * protected(method_name) -> method_name
2337 * protected(method_name, method_name, ...) -> array
2338 * protected(array) -> array
2340 * With no arguments, sets the default visibility for subsequently
2341 * defined methods to protected. With arguments, sets the named methods
2342 * to have protected visibility.
2343 * String arguments are converted to symbols.
2344 * An Array of Symbols and/or Strings is also accepted.
2345 * If a single argument is passed, it is returned.
2346 * If no argument is passed, nil is returned.
2347 * If multiple arguments are passed, the arguments are returned as an array.
2349 * If a method has protected visibility, it is callable only where
2350 * <code>self</code> of the context is the same as the method.
2351 * (method definition or instance_eval). This behavior is different from
2352 * Java's protected method. Usually <code>private</code> should be used.
2354 * Note that a protected method is slow because it can't use inline cache.
2356 * To show a private method on RDoc, use <code>:doc:</code> instead of this.
2360 rb_mod_protected(int argc
, VALUE
*argv
, VALUE module
)
2362 return set_visibility(argc
, argv
, module
, METHOD_VISI_PROTECTED
);
2368 * private(method_name) -> method_name
2369 * private(method_name, method_name, ...) -> array
2370 * private(array) -> array
2372 * With no arguments, sets the default visibility for subsequently
2373 * defined methods to private. With arguments, sets the named methods
2374 * to have private visibility.
2375 * String arguments are converted to symbols.
2376 * An Array of Symbols and/or Strings is also accepted.
2377 * If a single argument is passed, it is returned.
2378 * If no argument is passed, nil is returned.
2379 * If multiple arguments are passed, the arguments are returned as an array.
2388 * Mod.private_instance_methods #=> [:a, :c]
2390 * Note that to show a private method on RDoc, use <code>:doc:</code>.
2394 rb_mod_private(int argc
, VALUE
*argv
, VALUE module
)
2396 return set_visibility(argc
, argv
, module
, METHOD_VISI_PRIVATE
);
2401 * ruby2_keywords(method_name, ...) -> nil
2403 * For the given method names, marks the method as passing keywords through
2404 * a normal argument splat. This should only be called on methods that
2405 * accept an argument splat (<tt>*args</tt>) but not explicit keywords or
2406 * a keyword splat. It marks the method such that if the method is called
2407 * with keyword arguments, the final hash argument is marked with a special
2408 * flag such that if it is the final element of a normal argument splat to
2409 * another method call, and that method call does not include explicit
2410 * keywords or a keyword splat, the final element is interpreted as keywords.
2411 * In other words, keywords will be passed through the method to other
2414 * This should only be used for methods that delegate keywords to another
2415 * method, and only for backwards compatibility with Ruby versions before 3.0.
2416 * See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
2417 * for details on why +ruby2_keywords+ exists and when and how to use it.
2419 * This method will probably be removed at some point, as it exists only
2420 * for backwards compatibility. As it does not exist in Ruby versions before
2421 * 2.7, check that the module responds to this method before calling it:
2424 * def foo(meth, *args, &block)
2425 * send(:"do_#{meth}", *args, &block)
2427 * ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true)
2430 * However, be aware that if the +ruby2_keywords+ method is removed, the
2431 * behavior of the +foo+ method using the above approach will change so that
2432 * the method does not pass through keywords.
2436 rb_mod_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2439 VALUE origin_class
= RCLASS_ORIGIN(module
);
2441 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2442 rb_check_frozen(module
);
2444 for (i
= 0; i
< argc
; i
++) {
2446 ID name
= rb_check_id(&v
);
2447 rb_method_entry_t
*me
;
2448 VALUE defined_class
;
2451 rb_print_undef_str(module
, v
);
2454 me
= search_method(origin_class
, name
, &defined_class
);
2455 if (!me
&& RB_TYPE_P(module
, T_MODULE
)) {
2456 me
= search_method(rb_cObject
, name
, &defined_class
);
2459 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
2460 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
2461 rb_print_undef(module
, name
, METHOD_VISI_UNDEF
);
2464 if (module
== defined_class
|| origin_class
== defined_class
) {
2465 switch (me
->def
->type
) {
2466 case VM_METHOD_TYPE_ISEQ
:
2467 if (ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_rest
&&
2468 !ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_kw
&&
2469 !ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.has_kwrest
) {
2470 ISEQ_BODY(me
->def
->body
.iseq
.iseqptr
)->param
.flags
.ruby2_keywords
= 1;
2471 rb_clear_method_cache(module
, name
);
2474 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2477 case VM_METHOD_TYPE_BMETHOD
: {
2478 VALUE procval
= me
->def
->body
.bmethod
.proc
;
2479 if (vm_block_handler_type(procval
) == block_handler_type_proc
) {
2480 procval
= vm_proc_to_block_handler(VM_BH_TO_PROC(procval
));
2483 if (vm_block_handler_type(procval
) == block_handler_type_iseq
) {
2484 const struct rb_captured_block
*captured
= VM_BH_TO_ISEQ_BLOCK(procval
);
2485 const rb_iseq_t
*iseq
= rb_iseq_check(captured
->code
.iseq
);
2486 if (ISEQ_BODY(iseq
)->param
.flags
.has_rest
&&
2487 !ISEQ_BODY(iseq
)->param
.flags
.has_kw
&&
2488 !ISEQ_BODY(iseq
)->param
.flags
.has_kwrest
) {
2489 ISEQ_BODY(iseq
)->param
.flags
.ruby2_keywords
= 1;
2490 rb_clear_method_cache(module
, name
);
2493 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2500 rb_warn("Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)", rb_id2name(name
));
2505 rb_warn("Skipping set of ruby2_keywords flag for %s (can only set in method defining module)", rb_id2name(name
));
2513 * mod.public_class_method(symbol, ...) -> mod
2514 * mod.public_class_method(string, ...) -> mod
2515 * mod.public_class_method(array) -> mod
2517 * Makes a list of existing class methods public.
2519 * String arguments are converted to symbols.
2520 * An Array of Symbols and/or Strings is also accepted.
2524 rb_mod_public_method(int argc
, VALUE
*argv
, VALUE obj
)
2526 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PUBLIC
);
2532 * mod.private_class_method(symbol, ...) -> mod
2533 * mod.private_class_method(string, ...) -> mod
2534 * mod.private_class_method(array) -> mod
2536 * Makes existing class methods private. Often used to hide the default
2537 * constructor <code>new</code>.
2539 * String arguments are converted to symbols.
2540 * An Array of Symbols and/or Strings is also accepted.
2542 * class SimpleSingleton # Not thread safe
2543 * private_class_method :new
2544 * def SimpleSingleton.create(*args, &block)
2545 * @me = new(*args, &block) if ! @me
2552 rb_mod_private_method(int argc
, VALUE
*argv
, VALUE obj
)
2554 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PRIVATE
);
2561 * public(symbol, ...)
2562 * public(string, ...)
2565 * With no arguments, sets the default visibility for subsequently
2566 * defined methods to public. With arguments, sets the named methods to
2567 * have public visibility.
2569 * String arguments are converted to symbols.
2570 * An Array of Symbols and/or Strings is also accepted.
2574 top_public(int argc
, VALUE
*argv
, VALUE _
)
2576 return rb_mod_public(argc
, argv
, rb_cObject
);
2582 * private(symbol, ...)
2583 * private(string, ...)
2586 * With no arguments, sets the default visibility for subsequently
2587 * defined methods to private. With arguments, sets the named methods to
2588 * have private visibility.
2590 * String arguments are converted to symbols.
2591 * An Array of Symbols and/or Strings is also accepted.
2594 top_private(int argc
, VALUE
*argv
, VALUE _
)
2596 return rb_mod_private(argc
, argv
, rb_cObject
);
2601 * ruby2_keywords(method_name, ...) -> self
2603 * For the given method names, marks the method as passing keywords through
2604 * a normal argument splat. See Module#ruby2_keywords in detail.
2607 top_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2609 return rb_mod_ruby2_keywords(argc
, argv
, rb_cObject
);
2614 * module_function -> nil
2615 * module_function(method_name) -> method_name
2616 * module_function(method_name, method_name, ...) -> array
2618 * Creates module functions for the named methods. These functions may
2619 * be called with the module as a receiver, and also become available
2620 * as instance methods to classes that mix in the module. Module
2621 * functions are copies of the original, and so may be changed
2622 * independently. The instance-method versions are made private. If
2623 * used with no arguments, subsequently defined methods become module
2625 * String arguments are converted to symbols.
2626 * If a single argument is passed, it is returned.
2627 * If no argument is passed, nil is returned.
2628 * If multiple arguments are passed, the arguments are returned as an array.
2634 * module_function :one
2642 * Mod.one #=> "This is one"
2644 * c.call_one #=> "This is one"
2647 * "This is the new one"
2650 * Mod.one #=> "This is one"
2651 * c.call_one #=> "This is the new one"
2655 rb_mod_modfunc(int argc
, VALUE
*argv
, VALUE module
)
2659 const rb_method_entry_t
*me
;
2661 if (!RB_TYPE_P(module
, T_MODULE
)) {
2662 rb_raise(rb_eTypeError
, "module_function must be called for modules");
2666 rb_scope_module_func_set();
2670 set_method_visibility(module
, argc
, argv
, METHOD_VISI_PRIVATE
);
2672 for (i
= 0; i
< argc
; i
++) {
2675 id
= rb_to_id(argv
[i
]);
2677 me
= search_method(m
, id
, 0);
2679 me
= search_method(rb_cObject
, id
, 0);
2681 if (UNDEFINED_METHOD_ENTRY_P(me
)) {
2682 rb_print_undef(module
, id
, METHOD_VISI_UNDEF
);
2684 if (me
->def
->type
!= VM_METHOD_TYPE_ZSUPER
) {
2685 break; /* normal case: need not to follow 'super' link */
2687 m
= RCLASS_SUPER(m
);
2691 rb_method_entry_set(rb_singleton_class(module
), id
, me
, METHOD_VISI_PUBLIC
);
2696 return rb_ary_new_from_values(argc
, argv
);
2700 #pragma push_macro("rb_method_basic_definition_p")
2701 #undef rb_method_basic_definition_p
2704 rb_method_basic_definition_p(VALUE klass
, ID id
)
2706 const rb_callable_method_entry_t
*cme
;
2707 if (!klass
) return TRUE
; /* hidden object cannot be overridden */
2708 cme
= rb_callable_method_entry(klass
, id
);
2709 return (cme
&& METHOD_ENTRY_BASIC(cme
)) ? TRUE
: FALSE
;
2712 #pragma pop_macro("rb_method_basic_definition_p")
2716 call_method_entry(rb_execution_context_t
*ec
, VALUE defined_class
, VALUE obj
, ID id
,
2717 const rb_callable_method_entry_t
*cme
, int argc
, const VALUE
*argv
, int kw_splat
)
2719 VALUE passed_block_handler
= vm_passed_block_handler(ec
);
2720 VALUE result
= rb_vm_call_kw(ec
, obj
, id
, argc
, argv
, cme
, kw_splat
);
2721 vm_passed_block_handler_set(ec
, passed_block_handler
);
2726 basic_obj_respond_to_missing(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
,
2727 VALUE mid
, VALUE priv
)
2729 VALUE defined_class
, args
[2];
2730 const ID rtmid
= idRespond_to_missing
;
2731 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, rtmid
, &defined_class
);
2733 if (!cme
|| METHOD_ENTRY_BASIC(cme
)) return Qundef
;
2736 return call_method_entry(ec
, defined_class
, obj
, rtmid
, cme
, 2, args
, RB_NO_KEYWORDS
);
2740 basic_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int pub
)
2742 VALUE klass
= CLASS_OF(obj
);
2745 switch (method_boundp(klass
, id
, pub
|BOUND_RESPONDS
)) {
2749 ret
= basic_obj_respond_to_missing(ec
, klass
, obj
, ID2SYM(id
),
2751 return RTEST(ret
) && !UNDEF_P(ret
);
2758 vm_respond_to(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
, ID id
, int priv
)
2760 VALUE defined_class
;
2761 const ID resid
= idRespond_to
;
2762 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, resid
, &defined_class
);
2764 if (!cme
) return -1;
2765 if (METHOD_ENTRY_BASIC(cme
)) {
2773 args
[0] = ID2SYM(id
);
2776 argc
= rb_method_entry_arity((const rb_method_entry_t
*)cme
);
2778 rb_raise(rb_eArgError
,
2779 "respond_to? must accept 1 or 2 arguments (requires %d)",
2785 else if (!NIL_P(ruby_verbose
)) {
2786 VALUE location
= rb_method_entry_location((const rb_method_entry_t
*)cme
);
2787 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
,
2788 "%"PRIsVALUE
"%c""respond_to?(:%"PRIsVALUE
") uses"
2789 " the deprecated method signature, which takes one parameter",
2790 (FL_TEST(klass
, FL_SINGLETON
) ? obj
: klass
),
2791 (FL_TEST(klass
, FL_SINGLETON
) ? '.' : '#'),
2793 if (!NIL_P(location
)) {
2794 VALUE path
= RARRAY_AREF(location
, 0);
2795 VALUE line
= RARRAY_AREF(location
, 1);
2797 rb_category_compile_warn(RB_WARN_CATEGORY_DEPRECATED
,
2798 RSTRING_PTR(path
), NUM2INT(line
),
2799 "respond_to? is defined here");
2804 result
= call_method_entry(ec
, defined_class
, obj
, resid
, cme
, argc
, args
, RB_NO_KEYWORDS
);
2805 return RTEST(result
);
2810 rb_obj_respond_to(VALUE obj
, ID id
, int priv
)
2812 rb_execution_context_t
*ec
= GET_EC();
2813 return rb_ec_obj_respond_to(ec
, obj
, id
, priv
);
2817 rb_ec_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int priv
)
2819 VALUE klass
= CLASS_OF(obj
);
2820 int ret
= vm_respond_to(ec
, klass
, obj
, id
, priv
);
2821 if (ret
== -1) ret
= basic_obj_respond_to(ec
, obj
, id
, !priv
);
2826 rb_respond_to(VALUE obj
, ID id
)
2828 return rb_obj_respond_to(obj
, id
, FALSE
);
2834 * obj.respond_to?(symbol, include_all=false) -> true or false
2835 * obj.respond_to?(string, include_all=false) -> true or false
2837 * Returns +true+ if _obj_ responds to the given method. Private and
2838 * protected methods are included in the search only if the optional
2839 * second parameter evaluates to +true+.
2841 * If the method is not implemented,
2842 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
2843 * false is returned.
2845 * If the method is not defined, <code>respond_to_missing?</code>
2846 * method is called and the result is returned.
2848 * When the method name parameter is given as a string, the string is
2849 * converted to a symbol.
2853 obj_respond_to(int argc
, VALUE
*argv
, VALUE obj
)
2857 rb_execution_context_t
*ec
= GET_EC();
2859 rb_scan_args(argc
, argv
, "11", &mid
, &priv
);
2860 if (!(id
= rb_check_id(&mid
))) {
2861 VALUE ret
= basic_obj_respond_to_missing(ec
, CLASS_OF(obj
), obj
,
2862 rb_to_symbol(mid
), priv
);
2863 if (UNDEF_P(ret
)) ret
= Qfalse
;
2866 return RBOOL(basic_obj_respond_to(ec
, obj
, id
, !RTEST(priv
)));
2871 * obj.respond_to_missing?(symbol, include_all) -> true or false
2872 * obj.respond_to_missing?(string, include_all) -> true or false
2874 * DO NOT USE THIS DIRECTLY.
2876 * Hook method to return whether the _obj_ can respond to _id_ method
2879 * When the method name parameter is given as a string, the string is
2880 * converted to a symbol.
2882 * See #respond_to?, and the example of BasicObject.
2885 obj_respond_to_missing(VALUE obj
, VALUE mid
, VALUE priv
)
2897 Init_eval_method(void)
2899 rb_define_method(rb_mKernel
, "respond_to?", obj_respond_to
, -1);
2900 rb_define_method(rb_mKernel
, "respond_to_missing?", obj_respond_to_missing
, 2);
2902 rb_define_method(rb_cModule
, "remove_method", rb_mod_remove_method
, -1);
2903 rb_define_method(rb_cModule
, "undef_method", rb_mod_undef_method
, -1);
2904 rb_define_method(rb_cModule
, "alias_method", rb_mod_alias_method
, 2);
2905 rb_define_private_method(rb_cModule
, "public", rb_mod_public
, -1);
2906 rb_define_private_method(rb_cModule
, "protected", rb_mod_protected
, -1);
2907 rb_define_private_method(rb_cModule
, "private", rb_mod_private
, -1);
2908 rb_define_private_method(rb_cModule
, "module_function", rb_mod_modfunc
, -1);
2909 rb_define_private_method(rb_cModule
, "ruby2_keywords", rb_mod_ruby2_keywords
, -1);
2911 rb_define_method(rb_cModule
, "method_defined?", rb_mod_method_defined
, -1);
2912 rb_define_method(rb_cModule
, "public_method_defined?", rb_mod_public_method_defined
, -1);
2913 rb_define_method(rb_cModule
, "private_method_defined?", rb_mod_private_method_defined
, -1);
2914 rb_define_method(rb_cModule
, "protected_method_defined?", rb_mod_protected_method_defined
, -1);
2915 rb_define_method(rb_cModule
, "public_class_method", rb_mod_public_method
, -1);
2916 rb_define_method(rb_cModule
, "private_class_method", rb_mod_private_method
, -1);
2918 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2919 "public", top_public
, -1);
2920 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2921 "private", top_private
, -1);
2922 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2923 "ruby2_keywords", top_ruby2_keywords
, -1);
2926 #define REPLICATE_METHOD(klass, id) do { \
2927 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
2928 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \
2931 REPLICATE_METHOD(rb_eException
, idMethodMissing
);
2932 REPLICATE_METHOD(rb_eException
, idRespond_to
);
2933 REPLICATE_METHOD(rb_eException
, idRespond_to_missing
);