2 * This file is included by vm.c
10 static int vm_redefinition_check_flag(VALUE klass
);
11 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t
*me
, VALUE klass
);
12 static inline rb_method_entry_t
*lookup_method_table(VALUE klass
, ID id
);
14 #define object_id idObject_id
15 #define added idMethod_added
16 #define singleton_added idSingleton_method_added
17 #define removed idMethod_removed
18 #define singleton_removed idSingleton_method_removed
19 #define undefined idMethod_undefined
20 #define singleton_undefined idSingleton_method_undefined
21 #define attached id__attached__
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((VALUE
)cme
);
130 rb_clear_constant_cache(void)
132 rb_yjit_constant_state_changed();
133 INC_GLOBAL_CONSTANT_STATE();
137 invalidate_negative_cache(ID mid
)
140 rb_vm_t
*vm
= GET_VM();
142 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme
)) {
143 rb_id_table_delete(vm
->negative_cme_table
, mid
);
144 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
145 RB_DEBUG_COUNTER_INC(cc_invalidate_negative
);
149 static rb_method_entry_t
*rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
);
150 const rb_method_entry_t
* rb_method_entry_clone(const rb_method_entry_t
*src_me
);
151 static const rb_callable_method_entry_t
*complemented_callable_method_entry(VALUE klass
, ID id
);
152 static const rb_callable_method_entry_t
*lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
);
156 clear_method_cache_by_id_in_class(VALUE klass
, ID mid
)
158 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
159 if (rb_objspace_garbage_object_p(klass
)) return;
162 if (LIKELY(RCLASS_SUBCLASSES(klass
) == NULL
)) {
164 // check only current class
166 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
170 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
171 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
172 if (NIL_P(ccs
->cme
->owner
)) invalidate_negative_cache(mid
);
174 rb_id_table_delete(cc_tbl
, mid
);
175 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs
);
178 // remove from callable_m_tbl, if exists
179 struct rb_id_table
*cm_tbl
;
180 if ((cm_tbl
= RCLASS_CALLABLE_M_TBL(klass
)) != NULL
) {
181 rb_id_table_delete(cm_tbl
, mid
);
182 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_callable
);
184 RB_DEBUG_COUNTER_INC(cc_invalidate_leaf
);
187 const rb_callable_method_entry_t
*cme
= complemented_callable_method_entry(klass
, mid
);
190 // invalidate cme if found to invalidate the inline method cache.
191 if (METHOD_ENTRY_CACHED(cme
)) {
192 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
196 // invalidate cc by invalidating cc->cme
197 VALUE owner
= cme
->owner
;
198 VM_ASSERT(BUILTIN_TYPE(owner
) == T_CLASS
);
199 VALUE klass_housing_cme
;
200 if (cme
->def
->type
== VM_METHOD_TYPE_REFINED
&& !cme
->def
->body
.refined
.orig_me
) {
201 klass_housing_cme
= owner
;
204 klass_housing_cme
= RCLASS_ORIGIN(owner
);
206 // replace the cme that will be invalid
207 VM_ASSERT(lookup_method_table(klass_housing_cme
, mid
) == (const rb_method_entry_t
*)cme
);
208 const rb_method_entry_t
*new_cme
= rb_method_entry_clone((const rb_method_entry_t
*)cme
);
209 rb_method_table_insert(klass_housing_cme
, RCLASS_M_TBL(klass_housing_cme
), mid
, new_cme
);
212 vm_cme_invalidate((rb_callable_method_entry_t
*)cme
);
213 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme
);
215 if (cme
->def
->iseq_overload
) {
216 rb_callable_method_entry_t
*monly_cme
= (rb_callable_method_entry_t
*)lookup_overloaded_cme(cme
);
218 vm_cme_invalidate(monly_cme
);
223 // invalidate complement tbl
224 if (METHOD_ENTRY_COMPLEMENTED(cme
)) {
225 VALUE defined_class
= cme
->defined_class
;
226 struct rb_id_table
*cm_tbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
227 VM_ASSERT(cm_tbl
!= NULL
);
228 int r
= rb_id_table_delete(cm_tbl
, mid
);
229 VM_ASSERT(r
== TRUE
); (void)r
;
230 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_callable
);
233 RB_DEBUG_COUNTER_INC(cc_invalidate_tree
);
236 invalidate_negative_cache(mid
);
241 rb_yjit_method_lookup_change(klass
, mid
);
245 clear_iclass_method_cache_by_id(VALUE iclass
, VALUE d
)
247 VM_ASSERT(RB_TYPE_P(iclass
, T_ICLASS
));
249 clear_method_cache_by_id_in_class(iclass
, mid
);
253 clear_iclass_method_cache_by_id_for_refinements(VALUE klass
, VALUE d
)
255 if (RB_TYPE_P(klass
, T_ICLASS
)) {
257 clear_method_cache_by_id_in_class(klass
, mid
);
262 rb_clear_method_cache(VALUE klass_or_module
, ID mid
)
264 if (RB_TYPE_P(klass_or_module
, T_MODULE
)) {
265 VALUE module
= klass_or_module
; // alias
267 if (FL_TEST(module
, RMODULE_IS_REFINEMENT
)) {
268 VALUE refined_class
= rb_refinement_module_get_refined_class(module
);
269 rb_clear_method_cache(refined_class
, mid
);
270 rb_class_foreach_subclass(refined_class
, clear_iclass_method_cache_by_id_for_refinements
, mid
);
272 rb_class_foreach_subclass(module
, clear_iclass_method_cache_by_id
, mid
);
275 clear_method_cache_by_id_in_class(klass_or_module
, mid
);
280 void rb_cc_table_free(VALUE klass
);
283 invalidate_all_cc(void *vstart
, void *vend
, size_t stride
, void *data
)
285 VALUE v
= (VALUE
)vstart
;
286 for (; v
!= (VALUE
)vend
; v
+= stride
) {
287 void *ptr
= asan_poisoned_object_p(v
);
288 asan_unpoison_object(v
, false);
289 if (RBASIC(v
)->flags
) { // liveness check
290 if (RB_TYPE_P(v
, T_CLASS
) ||
291 RB_TYPE_P(v
, T_ICLASS
)) {
292 if (RCLASS_CC_TBL(v
)) {
295 RCLASS_CC_TBL(v
) = NULL
;
299 asan_poison_object(v
);
302 return 0; // continue to iteration
306 rb_clear_method_cache_all(void)
308 rb_objspace_each_objects(invalidate_all_cc
, NULL
);
310 rb_yjit_invalidate_all_method_lookup_assumptions();
314 rb_method_table_insert(VALUE klass
, struct rb_id_table
*table
, ID method_id
, const rb_method_entry_t
*me
)
316 VALUE table_owner
= klass
;
317 if (RB_TYPE_P(klass
, T_ICLASS
) && !RICLASS_OWNS_M_TBL_P(klass
)) {
318 table_owner
= RBASIC(table_owner
)->klass
;
320 VM_ASSERT(RB_TYPE_P(table_owner
, T_CLASS
) || RB_TYPE_P(table_owner
, T_ICLASS
) || RB_TYPE_P(table_owner
, T_MODULE
));
321 VM_ASSERT(table
== RCLASS_M_TBL(table_owner
));
322 rb_id_table_insert(table
, method_id
, (VALUE
)me
);
323 RB_OBJ_WRITTEN(table_owner
, Qundef
, (VALUE
)me
);
327 rb_f_notimplement(int argc
, const VALUE
*argv
, VALUE obj
, VALUE marker
)
331 UNREACHABLE_RETURN(Qnil
);
335 rb_define_notimplement_method_id(VALUE mod
, ID id
, rb_method_visibility_t visi
)
337 rb_add_method(mod
, id
, VM_METHOD_TYPE_NOTIMPLEMENTED
, (void *)1, visi
);
341 rb_add_method_cfunc(VALUE klass
, ID mid
, VALUE (*func
)(ANYARGS
), int argc
, rb_method_visibility_t visi
)
343 if (argc
< -2 || 15 < argc
) rb_raise(rb_eArgError
, "arity out of range: %d for -2..15", argc
);
344 if (func
!= rb_f_notimplement
) {
345 rb_method_cfunc_t opt
;
348 rb_add_method(klass
, mid
, VM_METHOD_TYPE_CFUNC
, &opt
, visi
);
351 rb_define_notimplement_method_id(klass
, mid
, visi
);
356 rb_add_method_optimized(VALUE klass
, ID mid
, enum method_optimized_type opt_type
, unsigned int index
, rb_method_visibility_t visi
)
358 rb_method_optimized_t opt
= {
362 rb_add_method(klass
, mid
, VM_METHOD_TYPE_OPTIMIZED
, &opt
, visi
);
366 rb_method_definition_release(rb_method_definition_t
*def
, int complemented
)
369 const int alias_count
= def
->alias_count
;
370 const int complemented_count
= def
->complemented_count
;
371 VM_ASSERT(alias_count
>= 0);
372 VM_ASSERT(complemented_count
>= 0);
374 if (alias_count
+ complemented_count
== 0) {
375 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d,%d (remove)\n", (void *)def
,
376 rb_id2name(def
->original_id
), alias_count
, complemented_count
);
377 VM_ASSERT(def
->type
== VM_METHOD_TYPE_BMETHOD
? def
->body
.bmethod
.hooks
== NULL
: TRUE
);
382 VM_ASSERT(def
->complemented_count
> 0);
383 def
->complemented_count
--;
385 else if (def
->alias_count
> 0) {
389 if (METHOD_DEBUG
) fprintf(stderr
, "-%p-%s:%d->%d,%d->%d (dec)\n", (void *)def
, rb_id2name(def
->original_id
),
390 alias_count
, def
->alias_count
, complemented_count
, def
->complemented_count
);
395 static void delete_overloaded_cme(const rb_callable_method_entry_t
*cme
);
398 rb_free_method_entry(const rb_method_entry_t
*me
)
400 if (me
->def
&& me
->def
->iseq_overload
) {
401 delete_overloaded_cme((const rb_callable_method_entry_t
*)me
);
403 rb_method_definition_release(me
->def
, METHOD_ENTRY_COMPLEMENTED(me
));
406 static inline rb_method_entry_t
*search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
);
407 extern int rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
);
410 (*call_cfunc_invoker_func(int argc
))(VALUE recv
, int argc
, const VALUE
*, VALUE (*func
)(ANYARGS
))
412 if (!GET_THREAD()->ext_config
.ractor_safe
) {
414 case -2: return &call_cfunc_m2
;
415 case -1: return &call_cfunc_m1
;
416 case 0: return &call_cfunc_0
;
417 case 1: return &call_cfunc_1
;
418 case 2: return &call_cfunc_2
;
419 case 3: return &call_cfunc_3
;
420 case 4: return &call_cfunc_4
;
421 case 5: return &call_cfunc_5
;
422 case 6: return &call_cfunc_6
;
423 case 7: return &call_cfunc_7
;
424 case 8: return &call_cfunc_8
;
425 case 9: return &call_cfunc_9
;
426 case 10: return &call_cfunc_10
;
427 case 11: return &call_cfunc_11
;
428 case 12: return &call_cfunc_12
;
429 case 13: return &call_cfunc_13
;
430 case 14: return &call_cfunc_14
;
431 case 15: return &call_cfunc_15
;
433 rb_bug("unsupported length: %d", argc
);
438 case -2: return &ractor_safe_call_cfunc_m2
;
439 case -1: return &ractor_safe_call_cfunc_m1
;
440 case 0: return &ractor_safe_call_cfunc_0
;
441 case 1: return &ractor_safe_call_cfunc_1
;
442 case 2: return &ractor_safe_call_cfunc_2
;
443 case 3: return &ractor_safe_call_cfunc_3
;
444 case 4: return &ractor_safe_call_cfunc_4
;
445 case 5: return &ractor_safe_call_cfunc_5
;
446 case 6: return &ractor_safe_call_cfunc_6
;
447 case 7: return &ractor_safe_call_cfunc_7
;
448 case 8: return &ractor_safe_call_cfunc_8
;
449 case 9: return &ractor_safe_call_cfunc_9
;
450 case 10: return &ractor_safe_call_cfunc_10
;
451 case 11: return &ractor_safe_call_cfunc_11
;
452 case 12: return &ractor_safe_call_cfunc_12
;
453 case 13: return &ractor_safe_call_cfunc_13
;
454 case 14: return &ractor_safe_call_cfunc_14
;
455 case 15: return &ractor_safe_call_cfunc_15
;
457 rb_bug("unsupported length: %d", argc
);
463 setup_method_cfunc_struct(rb_method_cfunc_t
*cfunc
, VALUE (*func
)(ANYARGS
), int argc
)
467 cfunc
->invoker
= call_cfunc_invoker_func(argc
);
470 MJIT_FUNC_EXPORTED
void
471 rb_method_definition_set(const rb_method_entry_t
*me
, rb_method_definition_t
*def
, void *opts
)
473 *(rb_method_definition_t
**)&me
->def
= def
;
477 case VM_METHOD_TYPE_ISEQ
:
479 rb_method_iseq_t
*iseq_body
= (rb_method_iseq_t
*)opts
;
480 const rb_iseq_t
*iseq
= iseq_body
->iseqptr
;
481 rb_cref_t
*method_cref
, *cref
= iseq_body
->cref
;
483 /* setup iseq first (before invoking GC) */
484 RB_OBJ_WRITE(me
, &def
->body
.iseq
.iseqptr
, iseq
);
486 if (iseq
->body
->mandatory_only_iseq
) def
->iseq_overload
= 1;
488 if (0) vm_cref_dump("rb_method_definition_create", cref
);
494 method_cref
= vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */
497 RB_OBJ_WRITE(me
, &def
->body
.iseq
.cref
, method_cref
);
500 case VM_METHOD_TYPE_CFUNC
:
502 rb_method_cfunc_t
*cfunc
= (rb_method_cfunc_t
*)opts
;
503 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), cfunc
->func
, cfunc
->argc
);
506 case VM_METHOD_TYPE_ATTRSET
:
507 case VM_METHOD_TYPE_IVAR
:
509 const rb_execution_context_t
*ec
= GET_EC();
510 rb_control_frame_t
*cfp
;
513 def
->body
.attr
.id
= (ID
)(VALUE
)opts
;
515 cfp
= rb_vm_get_ruby_level_next_cfp(ec
, ec
->cfp
);
517 if (cfp
&& (line
= rb_vm_get_sourceline(cfp
))) {
518 VALUE location
= rb_ary_new3(2, rb_iseq_path(cfp
->iseq
), INT2FIX(line
));
519 RB_OBJ_WRITE(me
, &def
->body
.attr
.location
, rb_ary_freeze(location
));
522 VM_ASSERT(def
->body
.attr
.location
== 0);
526 case VM_METHOD_TYPE_BMETHOD
:
527 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.proc
, (VALUE
)opts
);
528 RB_OBJ_WRITE(me
, &def
->body
.bmethod
.defined_ractor
, rb_ractor_self(GET_RACTOR()));
530 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
531 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def
, body
.cfunc
), rb_f_notimplement
, -1);
533 case VM_METHOD_TYPE_OPTIMIZED
:
534 def
->body
.optimized
= *(rb_method_optimized_t
*)opts
;
536 case VM_METHOD_TYPE_REFINED
:
538 const rb_method_refined_t
*refined
= (rb_method_refined_t
*)opts
;
539 RB_OBJ_WRITE(me
, &def
->body
.refined
.orig_me
, refined
->orig_me
);
540 RB_OBJ_WRITE(me
, &def
->body
.refined
.owner
, refined
->owner
);
543 case VM_METHOD_TYPE_ALIAS
:
544 RB_OBJ_WRITE(me
, &def
->body
.alias
.original_me
, (rb_method_entry_t
*)opts
);
546 case VM_METHOD_TYPE_ZSUPER
:
547 case VM_METHOD_TYPE_UNDEF
:
548 case VM_METHOD_TYPE_MISSING
:
555 method_definition_reset(const rb_method_entry_t
*me
)
557 rb_method_definition_t
*def
= me
->def
;
560 case VM_METHOD_TYPE_ISEQ
:
561 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.iseqptr
);
562 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.iseq
.cref
);
564 case VM_METHOD_TYPE_ATTRSET
:
565 case VM_METHOD_TYPE_IVAR
:
566 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.attr
.location
);
568 case VM_METHOD_TYPE_BMETHOD
:
569 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.proc
);
570 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.bmethod
.defined_ractor
);
571 /* give up to check all in a list */
572 if (def
->body
.bmethod
.hooks
) rb_gc_writebarrier_remember((VALUE
)me
);
574 case VM_METHOD_TYPE_REFINED
:
575 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.refined
.orig_me
);
576 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.refined
.owner
);
578 case VM_METHOD_TYPE_ALIAS
:
579 RB_OBJ_WRITTEN(me
, Qundef
, def
->body
.alias
.original_me
);
581 case VM_METHOD_TYPE_CFUNC
:
582 case VM_METHOD_TYPE_ZSUPER
:
583 case VM_METHOD_TYPE_MISSING
:
584 case VM_METHOD_TYPE_OPTIMIZED
:
585 case VM_METHOD_TYPE_UNDEF
:
586 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
591 MJIT_FUNC_EXPORTED rb_method_definition_t
*
592 rb_method_definition_create(rb_method_type_t type
, ID mid
)
594 rb_method_definition_t
*def
;
595 def
= ZALLOC(rb_method_definition_t
);
597 def
->original_id
= mid
;
598 static uintptr_t method_serial
= 1;
599 def
->method_serial
= method_serial
++;
603 static rb_method_definition_t
*
604 method_definition_addref(rb_method_definition_t
*def
)
607 if (METHOD_DEBUG
) fprintf(stderr
, "+%p-%s:%d\n", (void *)def
, rb_id2name(def
->original_id
), def
->alias_count
);
611 static rb_method_definition_t
*
612 method_definition_addref_complement(rb_method_definition_t
*def
)
614 def
->complemented_count
++;
615 if (METHOD_DEBUG
) fprintf(stderr
, "+%p-%s:%d\n", (void *)def
, rb_id2name(def
->original_id
), def
->complemented_count
);
619 static rb_method_entry_t
*
620 rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
)
622 rb_method_entry_t
*me
= (rb_method_entry_t
*)rb_imemo_new(imemo_ment
, (VALUE
)def
, (VALUE
)called_id
, owner
, defined_class
);
627 filter_defined_class(VALUE klass
)
629 switch (BUILTIN_TYPE(klass
)) {
639 rb_bug("filter_defined_class: %s", rb_obj_info(klass
));
643 rb_method_entry_create(ID called_id
, VALUE klass
, rb_method_visibility_t visi
, const rb_method_definition_t
*def
)
645 rb_method_entry_t
*me
= rb_method_entry_alloc(called_id
, klass
, filter_defined_class(klass
), def
);
646 METHOD_ENTRY_FLAGS_SET(me
, visi
, ruby_running
? FALSE
: TRUE
);
647 if (def
!= NULL
) method_definition_reset(me
);
651 const rb_method_entry_t
*
652 rb_method_entry_clone(const rb_method_entry_t
*src_me
)
654 rb_method_entry_t
*me
= rb_method_entry_alloc(src_me
->called_id
, src_me
->owner
, src_me
->defined_class
,
655 method_definition_addref(src_me
->def
));
656 if (METHOD_ENTRY_COMPLEMENTED(src_me
)) {
657 method_definition_addref_complement(src_me
->def
);
660 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
664 MJIT_FUNC_EXPORTED
const rb_callable_method_entry_t
*
665 rb_method_entry_complement_defined_class(const rb_method_entry_t
*src_me
, ID called_id
, VALUE defined_class
)
667 rb_method_definition_t
*def
= src_me
->def
;
668 rb_method_entry_t
*me
;
670 const struct rb_method_entry_struct
*orig_me
;
674 if (!src_me
->defined_class
&&
675 def
->type
== VM_METHOD_TYPE_REFINED
&&
676 def
->body
.refined
.orig_me
) {
677 const rb_method_entry_t
*orig_me
=
678 rb_method_entry_clone(def
->body
.refined
.orig_me
);
679 RB_OBJ_WRITE((VALUE
)orig_me
, &orig_me
->defined_class
, defined_class
);
680 refined
.orig_me
= orig_me
;
681 refined
.owner
= orig_me
->owner
;
685 def
= method_definition_addref_complement(def
);
687 me
= rb_method_entry_alloc(called_id
, src_me
->owner
, defined_class
, def
);
688 METHOD_ENTRY_FLAGS_COPY(me
, src_me
);
689 METHOD_ENTRY_COMPLEMENTED_SET(me
);
691 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, called_id
);
692 rb_method_definition_set(me
, def
, &refined
);
695 VM_ASSERT(RB_TYPE_P(me
->owner
, T_MODULE
));
697 return (rb_callable_method_entry_t
*)me
;
701 rb_method_entry_copy(rb_method_entry_t
*dst
, const rb_method_entry_t
*src
)
703 *(rb_method_definition_t
**)&dst
->def
= method_definition_addref(src
->def
);
704 method_definition_reset(dst
);
705 dst
->called_id
= src
->called_id
;
706 RB_OBJ_WRITE((VALUE
)dst
, &dst
->owner
, src
->owner
);
707 RB_OBJ_WRITE((VALUE
)dst
, &dst
->defined_class
, src
->defined_class
);
708 METHOD_ENTRY_FLAGS_COPY(dst
, src
);
712 make_method_entry_refined(VALUE owner
, rb_method_entry_t
*me
)
714 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
719 struct rb_method_entry_struct
*orig_me
;
722 rb_method_definition_t
*def
;
724 rb_vm_check_redefinition_opt_method(me
, me
->owner
);
727 rb_method_entry_alloc(me
->called_id
, me
->owner
,
729 me
->defined_class
: owner
,
730 method_definition_addref(me
->def
));
731 METHOD_ENTRY_FLAGS_COPY(refined
.orig_me
, me
);
732 refined
.owner
= owner
;
734 def
= rb_method_definition_create(VM_METHOD_TYPE_REFINED
, me
->called_id
);
735 rb_method_definition_set(me
, def
, (void *)&refined
);
736 METHOD_ENTRY_VISI_SET(me
, METHOD_VISI_PUBLIC
);
740 static inline rb_method_entry_t
*
741 lookup_method_table(VALUE klass
, ID id
)
744 struct rb_id_table
*m_tbl
= RCLASS_M_TBL(klass
);
746 if (rb_id_table_lookup(m_tbl
, id
, &body
)) {
747 return (rb_method_entry_t
*) body
;
755 rb_add_refined_method_entry(VALUE refined_class
, ID mid
)
757 rb_method_entry_t
*me
= lookup_method_table(refined_class
, mid
);
760 make_method_entry_refined(refined_class
, me
);
761 rb_clear_method_cache(refined_class
, mid
);
764 rb_add_method(refined_class
, mid
, VM_METHOD_TYPE_REFINED
, 0, METHOD_VISI_PUBLIC
);
769 check_override_opt_method_i(VALUE klass
, VALUE arg
)
772 const rb_method_entry_t
*me
, *newme
;
774 if (vm_redefinition_check_flag(klass
)) {
775 me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
777 newme
= rb_method_entry(klass
, mid
);
778 if (newme
!= me
) rb_vm_check_redefinition_opt_method(me
, me
->owner
);
781 rb_class_foreach_subclass(klass
, check_override_opt_method_i
, (VALUE
)mid
);
785 check_override_opt_method(VALUE klass
, VALUE mid
)
787 if (rb_vm_check_optimizable_mid(mid
)) {
788 check_override_opt_method_i(klass
, mid
);
793 * klass->method_table[mid] = method_entry(defined_class, visi, def)
795 * If def is given (!= NULL), then just use it and ignore original_id and otps.
796 * If not given, then make a new def with original_id and opts.
798 static rb_method_entry_t
*
799 rb_method_entry_make(VALUE klass
, ID mid
, VALUE defined_class
, rb_method_visibility_t visi
,
800 rb_method_type_t type
, rb_method_definition_t
*def
, ID original_id
, void *opts
)
802 rb_method_entry_t
*me
;
803 struct rb_id_table
*mtbl
;
805 int make_refined
= 0;
813 if (!FL_TEST(klass
, FL_SINGLETON
) &&
814 type
!= VM_METHOD_TYPE_NOTIMPLEMENTED
&&
815 type
!= VM_METHOD_TYPE_ZSUPER
) {
818 case idInitialize_copy
:
819 case idInitialize_clone
:
820 case idInitialize_dup
:
821 case idRespond_to_missing
:
822 visi
= METHOD_VISI_PRIVATE
;
826 if (type
!= VM_METHOD_TYPE_REFINED
) {
827 rb_class_modify_check(klass
);
830 if (FL_TEST(klass
, RMODULE_IS_REFINEMENT
)) {
831 VALUE refined_class
= rb_refinement_module_get_refined_class(klass
);
832 rb_add_refined_method_entry(refined_class
, mid
);
834 if (type
== VM_METHOD_TYPE_REFINED
) {
835 rb_method_entry_t
*old_me
= lookup_method_table(RCLASS_ORIGIN(klass
), mid
);
836 if (old_me
) rb_vm_check_redefinition_opt_method(old_me
, klass
);
839 klass
= RCLASS_ORIGIN(klass
);
840 if (klass
!= orig_klass
) {
841 rb_clear_method_cache(orig_klass
, mid
);
844 mtbl
= RCLASS_M_TBL(klass
);
846 /* check re-definition */
847 if (rb_id_table_lookup(mtbl
, mid
, &data
)) {
848 rb_method_entry_t
*old_me
= (rb_method_entry_t
*)data
;
849 rb_method_definition_t
*old_def
= old_me
->def
;
851 if (rb_method_definition_eq(old_def
, def
)) return old_me
;
852 rb_vm_check_redefinition_opt_method(old_me
, klass
);
854 if (old_def
->type
== VM_METHOD_TYPE_REFINED
) make_refined
= 1;
856 if (RTEST(ruby_verbose
) &&
857 type
!= VM_METHOD_TYPE_UNDEF
&&
858 (old_def
->alias_count
== 0) &&
860 old_def
->type
!= VM_METHOD_TYPE_UNDEF
&&
861 old_def
->type
!= VM_METHOD_TYPE_ZSUPER
&&
862 old_def
->type
!= VM_METHOD_TYPE_ALIAS
) {
863 const rb_iseq_t
*iseq
= 0;
865 rb_warning("method redefined; discarding old %"PRIsVALUE
, rb_id2str(mid
));
866 switch (old_def
->type
) {
867 case VM_METHOD_TYPE_ISEQ
:
868 iseq
= def_iseq_ptr(old_def
);
870 case VM_METHOD_TYPE_BMETHOD
:
871 iseq
= rb_proc_get_iseq(old_def
->body
.bmethod
.proc
, 0);
877 rb_compile_warning(RSTRING_PTR(rb_iseq_path(iseq
)),
878 FIX2INT(iseq
->body
->location
.first_lineno
),
879 "previous definition of %"PRIsVALUE
" was here",
880 rb_id2str(old_def
->original_id
));
885 /* create method entry */
886 me
= rb_method_entry_create(mid
, defined_class
, visi
, NULL
);
887 if (def
== NULL
) def
= rb_method_definition_create(type
, original_id
);
888 rb_method_definition_set(me
, def
, opts
);
890 rb_clear_method_cache(klass
, mid
);
893 if (klass
== rb_cObject
) {
896 case idRespond_to_missing
:
897 case idMethodMissing
:
899 rb_warn("redefining Object#%s may cause infinite loop", rb_id2name(mid
));
903 if (mid
== object_id
|| mid
== id__send__
) {
904 if (type
== VM_METHOD_TYPE_ISEQ
&& search_method(klass
, mid
, 0)) {
905 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid
));
910 make_method_entry_refined(klass
, me
);
913 rb_method_table_insert(klass
, mtbl
, mid
, me
);
915 VM_ASSERT(me
->def
!= NULL
);
917 /* check optimized method override by a prepended module */
918 if (RB_TYPE_P(orig_klass
, T_MODULE
)) {
919 check_override_opt_method(klass
, (VALUE
)mid
);
925 static rb_method_entry_t
*rb_method_entry_alloc(ID called_id
, VALUE owner
, VALUE defined_class
, const rb_method_definition_t
*def
);
928 overloaded_cme_table(void)
930 VM_ASSERT(GET_VM()->overloaded_cme_table
!= NULL
);
931 return GET_VM()->overloaded_cme_table
;
934 #if VM_CHECK_MODE > 0
936 vm_dump_overloaded_cme_table(st_data_t key
, st_data_t val
, st_data_t dmy
)
938 fprintf(stderr
, "key: "); rp(key
);
939 fprintf(stderr
, "val: "); rp(val
);
944 rb_vm_dump_overloaded_cme_table(void)
946 fprintf(stderr
, "== rb_vm_dump_overloaded_cme_table\n");
947 st_foreach(overloaded_cme_table(), vm_dump_overloaded_cme_table
, 0);
952 lookup_overloaded_cme_i(st_data_t
*key
, st_data_t
*value
, st_data_t data
, int existing
)
955 const rb_callable_method_entry_t
*cme
= (const rb_callable_method_entry_t
*)*key
;
956 const rb_callable_method_entry_t
*monly_cme
= (const rb_callable_method_entry_t
*)*value
;
957 const rb_callable_method_entry_t
**ptr
= (const rb_callable_method_entry_t
**)data
;
959 if (rb_objspace_garbage_object_p((VALUE
)cme
) ||
960 rb_objspace_garbage_object_p((VALUE
)monly_cme
)) {
972 static const rb_callable_method_entry_t
*
973 lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
977 const rb_callable_method_entry_t
*monly_cme
= NULL
;
978 st_update(overloaded_cme_table(), (st_data_t
)cme
, lookup_overloaded_cme_i
, (st_data_t
)&monly_cme
);
982 #if VM_CHECK_MODE > 0
983 MJIT_FUNC_EXPORTED
const rb_callable_method_entry_t
*
984 rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t
*cme
)
986 return lookup_overloaded_cme(cme
);
991 delete_overloaded_cme(const rb_callable_method_entry_t
*cme
)
994 st_delete(overloaded_cme_table(), (st_data_t
*)&cme
, NULL
);
997 static const rb_callable_method_entry_t
*
998 get_overloaded_cme(const rb_callable_method_entry_t
*cme
)
1000 const rb_callable_method_entry_t
*monly_cme
= lookup_overloaded_cme(cme
);
1002 if (monly_cme
&& !METHOD_ENTRY_INVALIDATED(monly_cme
)) {
1007 rb_method_definition_t
*def
= rb_method_definition_create(VM_METHOD_TYPE_ISEQ
, cme
->def
->original_id
);
1008 def
->body
.iseq
.cref
= cme
->def
->body
.iseq
.cref
;
1009 def
->body
.iseq
.iseqptr
= cme
->def
->body
.iseq
.iseqptr
->body
->mandatory_only_iseq
;
1011 rb_method_entry_t
*me
= rb_method_entry_alloc(cme
->called_id
,
1016 ASSERT_vm_locking();
1017 st_insert(overloaded_cme_table(), (st_data_t
)cme
, (st_data_t
)me
);
1019 METHOD_ENTRY_VISI_SET(me
, METHOD_ENTRY_VISI(cme
));
1020 return (rb_callable_method_entry_t
*)me
;
1024 static const rb_callable_method_entry_t
*
1025 check_overloaded_cme(const rb_callable_method_entry_t
*cme
, const struct rb_callinfo
* const ci
)
1027 if (UNLIKELY(cme
->def
->iseq_overload
) &&
1028 (vm_ci_flag(ci
) & (VM_CALL_ARGS_SIMPLE
)) &&
1029 (int)vm_ci_argc(ci
) == method_entry_iseqptr(cme
)->body
->param
.lead_num
) {
1030 VM_ASSERT(cme
->def
->type
== VM_METHOD_TYPE_ISEQ
); // iseq_overload is marked only on ISEQ methods
1032 cme
= get_overloaded_cme(cme
);
1034 VM_ASSERT(cme
!= NULL
);
1035 METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct
*)cme
);
1041 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
1042 const VALUE arg = ID2SYM(mid); \
1043 VALUE recv_class = (klass); \
1044 ID hook_id = (hook); \
1045 if (FL_TEST((klass), FL_SINGLETON)) { \
1046 recv_class = rb_ivar_get((klass), attached); \
1047 hook_id = singleton_##hook; \
1049 rb_funcallv(recv_class, hook_id, 1, &arg); \
1053 method_added(VALUE klass
, ID mid
)
1056 CALL_METHOD_HOOK(klass
, added
, mid
);
1061 rb_add_method(VALUE klass
, ID mid
, rb_method_type_t type
, void *opts
, rb_method_visibility_t visi
)
1063 rb_method_entry_make(klass
, mid
, klass
, visi
, type
, NULL
, mid
, opts
);
1065 if (type
!= VM_METHOD_TYPE_UNDEF
&& type
!= VM_METHOD_TYPE_REFINED
) {
1066 method_added(klass
, mid
);
1070 MJIT_FUNC_EXPORTED
void
1071 rb_add_method_iseq(VALUE klass
, ID mid
, const rb_iseq_t
*iseq
, rb_cref_t
*cref
, rb_method_visibility_t visi
)
1073 struct { /* should be same fields with rb_method_iseq_struct */
1074 const rb_iseq_t
*iseqptr
;
1078 iseq_body
.iseqptr
= iseq
;
1079 iseq_body
.cref
= cref
;
1081 rb_add_method(klass
, mid
, VM_METHOD_TYPE_ISEQ
, &iseq_body
, visi
);
1084 static rb_method_entry_t
*
1085 method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
,
1086 rb_method_visibility_t visi
, VALUE defined_class
)
1088 rb_method_entry_t
*newme
= rb_method_entry_make(klass
, mid
, defined_class
, visi
,
1089 me
->def
->type
, method_definition_addref(me
->def
), 0, NULL
);
1090 method_added(klass
, mid
);
1095 rb_method_entry_set(VALUE klass
, ID mid
, const rb_method_entry_t
*me
, rb_method_visibility_t visi
)
1097 return method_entry_set(klass
, mid
, me
, visi
, klass
);
1100 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
1103 rb_define_alloc_func(VALUE klass
, VALUE (*func
)(VALUE
))
1105 Check_Type(klass
, T_CLASS
);
1106 RCLASS_ALLOCATOR(klass
) = func
;
1110 rb_undef_alloc_func(VALUE klass
)
1112 rb_define_alloc_func(klass
, UNDEF_ALLOC_FUNC
);
1116 rb_get_alloc_func(VALUE klass
)
1118 Check_Type(klass
, T_CLASS
);
1120 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1121 rb_alloc_func_t allocator
= RCLASS_ALLOCATOR(klass
);
1122 if (allocator
== UNDEF_ALLOC_FUNC
) break;
1123 if (allocator
) return allocator
;
1128 const rb_method_entry_t
*
1129 rb_method_entry_at(VALUE klass
, ID id
)
1131 return lookup_method_table(klass
, id
);
1134 static inline rb_method_entry_t
*
1135 search_method0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool skip_refined
)
1137 rb_method_entry_t
*me
= NULL
;
1139 RB_DEBUG_COUNTER_INC(mc_search
);
1141 for (; klass
; klass
= RCLASS_SUPER(klass
)) {
1142 RB_DEBUG_COUNTER_INC(mc_search_super
);
1143 if ((me
= lookup_method_table(klass
, id
)) != 0) {
1144 if (!skip_refined
|| me
->def
->type
!= VM_METHOD_TYPE_REFINED
||
1145 me
->def
->body
.refined
.orig_me
) {
1151 if (defined_class_ptr
) *defined_class_ptr
= klass
;
1153 if (me
== NULL
) RB_DEBUG_COUNTER_INC(mc_search_notfound
);
1155 VM_ASSERT(me
== NULL
|| !METHOD_ENTRY_INVALIDATED(me
));
1159 static inline rb_method_entry_t
*
1160 search_method(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1162 return search_method0(klass
, id
, defined_class_ptr
, false);
1165 static rb_method_entry_t
*
1166 search_method_protect(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1168 rb_method_entry_t
*me
= search_method(klass
, id
, defined_class_ptr
);
1170 if (!UNDEFINED_METHOD_ENTRY_P(me
)) {
1178 MJIT_FUNC_EXPORTED
const rb_method_entry_t
*
1179 rb_method_entry(VALUE klass
, ID id
)
1181 return search_method_protect(klass
, id
, NULL
);
1184 static inline const rb_callable_method_entry_t
*
1185 prepare_callable_method_entry(VALUE defined_class
, ID id
, const rb_method_entry_t
* const me
, int create
)
1187 struct rb_id_table
*mtbl
;
1188 const rb_callable_method_entry_t
*cme
;
1192 if (me
->defined_class
== 0) {
1193 RB_DEBUG_COUNTER_INC(mc_cme_complement
);
1194 VM_ASSERT(RB_TYPE_P(defined_class
, T_ICLASS
) || RB_TYPE_P(defined_class
, T_MODULE
));
1195 VM_ASSERT(me
->defined_class
== 0);
1197 mtbl
= RCLASS_CALLABLE_M_TBL(defined_class
);
1199 if (mtbl
&& rb_id_table_lookup(mtbl
, id
, &cme_data
)) {
1200 cme
= (rb_callable_method_entry_t
*)cme_data
;
1201 RB_DEBUG_COUNTER_INC(mc_cme_complement_hit
);
1202 VM_ASSERT(callable_method_entry_p(cme
));
1203 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1207 mtbl
= RCLASS_EXT(defined_class
)->callable_m_tbl
= rb_id_table_create(0);
1209 cme
= rb_method_entry_complement_defined_class(me
, me
->called_id
, defined_class
);
1210 rb_id_table_insert(mtbl
, id
, (VALUE
)cme
);
1211 RB_OBJ_WRITTEN(defined_class
, Qundef
, (VALUE
)cme
);
1212 VM_ASSERT(callable_method_entry_p(cme
));
1219 cme
= (const rb_callable_method_entry_t
*)me
;
1220 VM_ASSERT(callable_method_entry_p(cme
));
1221 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme
));
1230 static const rb_callable_method_entry_t
*
1231 complemented_callable_method_entry(VALUE klass
, ID id
)
1233 VALUE defined_class
;
1234 rb_method_entry_t
*me
= search_method(klass
, id
, &defined_class
);
1235 return prepare_callable_method_entry(defined_class
, id
, me
, FALSE
);
1238 static const rb_callable_method_entry_t
*
1239 cached_callable_method_entry(VALUE klass
, ID mid
)
1241 ASSERT_vm_locking();
1243 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1246 if (cc_tbl
&& rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1247 struct rb_class_cc_entries
*ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1248 VM_ASSERT(vm_ccs_p(ccs
));
1250 if (LIKELY(!METHOD_ENTRY_INVALIDATED(ccs
->cme
))) {
1251 VM_ASSERT(ccs
->cme
->called_id
== mid
);
1252 RB_DEBUG_COUNTER_INC(ccs_found
);
1256 rb_vm_ccs_free(ccs
);
1257 rb_id_table_delete(cc_tbl
, mid
);
1261 RB_DEBUG_COUNTER_INC(ccs_not_found
);
1266 cache_callable_method_entry(VALUE klass
, ID mid
, const rb_callable_method_entry_t
*cme
)
1268 ASSERT_vm_locking();
1269 VM_ASSERT(cme
!= NULL
);
1271 struct rb_id_table
*cc_tbl
= RCLASS_CC_TBL(klass
);
1272 struct rb_class_cc_entries
*ccs
;
1276 cc_tbl
= RCLASS_CC_TBL(klass
) = rb_id_table_create(2);
1279 if (rb_id_table_lookup(cc_tbl
, mid
, &ccs_data
)) {
1280 ccs
= (struct rb_class_cc_entries
*)ccs_data
;
1281 VM_ASSERT(ccs
->cme
== cme
);
1284 ccs
= vm_ccs_create(klass
, cme
);
1285 rb_id_table_insert(cc_tbl
, mid
, (VALUE
)ccs
);
1289 static const rb_callable_method_entry_t
*
1290 negative_cme(ID mid
)
1292 rb_vm_t
*vm
= GET_VM();
1293 const rb_callable_method_entry_t
*cme
;
1296 if (rb_id_table_lookup(vm
->negative_cme_table
, mid
, &cme_data
)) {
1297 cme
= (rb_callable_method_entry_t
*)cme_data
;
1300 cme
= (rb_callable_method_entry_t
*)rb_method_entry_alloc(mid
, Qnil
, Qnil
, NULL
);
1301 rb_id_table_insert(vm
->negative_cme_table
, mid
, (VALUE
)cme
);
1304 VM_ASSERT(cme
!= NULL
);
1308 static const rb_callable_method_entry_t
*
1309 callable_method_entry(VALUE klass
, ID mid
, VALUE
*defined_class_ptr
)
1311 const rb_callable_method_entry_t
*cme
;
1313 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1316 cme
= cached_callable_method_entry(klass
, mid
);
1319 if (defined_class_ptr
!= NULL
) *defined_class_ptr
= cme
->defined_class
;
1322 VALUE defined_class
;
1323 rb_method_entry_t
*me
= search_method(klass
, mid
, &defined_class
);
1324 if (defined_class_ptr
) *defined_class_ptr
= defined_class
;
1327 cme
= prepare_callable_method_entry(defined_class
, mid
, me
, TRUE
);
1330 cme
= negative_cme(mid
);
1333 cache_callable_method_entry(klass
, mid
, cme
);
1338 return !UNDEFINED_METHOD_ENTRY_P(cme
) ? cme
: NULL
;
1341 MJIT_FUNC_EXPORTED
const rb_callable_method_entry_t
*
1342 rb_callable_method_entry(VALUE klass
, ID mid
)
1344 return callable_method_entry(klass
, mid
, NULL
);
1347 static const rb_method_entry_t
*resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
);
1349 static const rb_method_entry_t
*
1350 method_entry_resolve_refinement(VALUE klass
, ID id
, int with_refinement
, VALUE
*defined_class_ptr
)
1352 const rb_method_entry_t
*me
= search_method_protect(klass
, id
, defined_class_ptr
);
1355 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1356 if (with_refinement
) {
1357 const rb_cref_t
*cref
= rb_vm_cref();
1358 VALUE refinements
= cref
? CREF_REFINEMENTS(cref
) : Qnil
;
1359 me
= resolve_refined_method(refinements
, me
, defined_class_ptr
);
1362 me
= resolve_refined_method(Qnil
, me
, defined_class_ptr
);
1365 if (UNDEFINED_METHOD_ENTRY_P(me
)) me
= NULL
;
1372 MJIT_FUNC_EXPORTED
const rb_method_entry_t
*
1373 rb_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1375 return method_entry_resolve_refinement(klass
, id
, TRUE
, defined_class_ptr
);
1378 static const rb_callable_method_entry_t
*
1379 callable_method_entry_refeinements0(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
,
1380 const rb_callable_method_entry_t
*cme
)
1382 if (cme
== NULL
|| LIKELY(cme
->def
->type
!= VM_METHOD_TYPE_REFINED
)) {
1386 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1387 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, with_refinements
, dcp
);
1388 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1392 static const rb_callable_method_entry_t
*
1393 callable_method_entry_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
, bool with_refinements
)
1395 const rb_callable_method_entry_t
*cme
= callable_method_entry(klass
, id
, defined_class_ptr
);
1396 return callable_method_entry_refeinements0(klass
, id
, defined_class_ptr
, with_refinements
, cme
);
1399 MJIT_FUNC_EXPORTED
const rb_callable_method_entry_t
*
1400 rb_callable_method_entry_with_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1402 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, true);
1405 static const rb_callable_method_entry_t
*
1406 callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1408 return callable_method_entry_refinements(klass
, id
, defined_class_ptr
, false);
1411 const rb_method_entry_t
*
1412 rb_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1414 return method_entry_resolve_refinement(klass
, id
, FALSE
, defined_class_ptr
);
1417 MJIT_FUNC_EXPORTED
const rb_callable_method_entry_t
*
1418 rb_callable_method_entry_without_refinements(VALUE klass
, ID id
, VALUE
*defined_class_ptr
)
1420 VALUE defined_class
, *dcp
= defined_class_ptr
? defined_class_ptr
: &defined_class
;
1421 const rb_method_entry_t
*me
= method_entry_resolve_refinement(klass
, id
, FALSE
, dcp
);
1422 return prepare_callable_method_entry(*dcp
, id
, me
, TRUE
);
1425 static const rb_method_entry_t
*
1426 resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
, VALUE
*defined_class_ptr
)
1428 while (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1430 const rb_method_entry_t
*tmp_me
;
1433 refinement
= find_refinement(refinements
, me
->owner
);
1434 if (!NIL_P(refinement
)) {
1435 tmp_me
= search_method_protect(refinement
, me
->called_id
, defined_class_ptr
);
1437 if (tmp_me
&& tmp_me
->def
->type
!= VM_METHOD_TYPE_REFINED
) {
1442 tmp_me
= me
->def
->body
.refined
.orig_me
;
1444 if (defined_class_ptr
) *defined_class_ptr
= tmp_me
->defined_class
;
1448 super
= RCLASS_SUPER(me
->owner
);
1453 me
= search_method_protect(super
, me
->called_id
, defined_class_ptr
);
1458 const rb_method_entry_t
*
1459 rb_resolve_refined_method(VALUE refinements
, const rb_method_entry_t
*me
)
1461 return resolve_refined_method(refinements
, me
, NULL
);
1465 const rb_callable_method_entry_t
*
1466 rb_resolve_refined_method_callable(VALUE refinements
, const rb_callable_method_entry_t
*me
)
1468 VALUE defined_class
= me
->defined_class
;
1469 const rb_method_entry_t
*resolved_me
= resolve_refined_method(refinements
, (const rb_method_entry_t
*)me
, &defined_class
);
1471 if (resolved_me
&& resolved_me
->defined_class
== 0) {
1472 return rb_method_entry_complement_defined_class(resolved_me
, me
->called_id
, defined_class
);
1475 return (const rb_callable_method_entry_t
*)resolved_me
;
1480 remove_method(VALUE klass
, ID mid
)
1483 rb_method_entry_t
*me
= 0;
1486 klass
= RCLASS_ORIGIN(klass
);
1487 rb_class_modify_check(klass
);
1488 if (mid
== object_id
|| mid
== id__send__
|| mid
== idInitialize
) {
1489 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid
));
1492 if (!rb_id_table_lookup(RCLASS_M_TBL(klass
), mid
, &data
) ||
1493 !(me
= (rb_method_entry_t
*)data
) ||
1494 (!me
->def
|| me
->def
->type
== VM_METHOD_TYPE_UNDEF
) ||
1495 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1496 rb_name_err_raise("method `%1$s' not defined in %2$s",
1497 klass
, ID2SYM(mid
));
1500 if (klass
!= self
) {
1501 rb_clear_method_cache(self
, mid
);
1503 rb_clear_method_cache(klass
, mid
);
1504 rb_id_table_delete(RCLASS_M_TBL(klass
), mid
);
1506 rb_vm_check_redefinition_opt_method(me
, klass
);
1508 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1509 rb_add_refined_method_entry(klass
, mid
);
1512 CALL_METHOD_HOOK(self
, removed
, mid
);
1516 rb_remove_method_id(VALUE klass
, ID mid
)
1518 remove_method(klass
, mid
);
1522 rb_remove_method(VALUE klass
, const char *name
)
1524 remove_method(klass
, rb_intern(name
));
1529 * remove_method(symbol) -> self
1530 * remove_method(string) -> self
1532 * Removes the method identified by _symbol_ from the current
1533 * class. For an example, see Module#undef_method.
1534 * String arguments are converted to symbols.
1538 rb_mod_remove_method(int argc
, VALUE
*argv
, VALUE mod
)
1542 for (i
= 0; i
< argc
; i
++) {
1544 ID id
= rb_check_id(&v
);
1546 rb_name_err_raise("method `%1$s' not defined in %2$s",
1549 remove_method(mod
, id
);
1555 rb_export_method(VALUE klass
, ID name
, rb_method_visibility_t visi
)
1557 rb_method_entry_t
*me
;
1558 VALUE defined_class
;
1559 VALUE origin_class
= RCLASS_ORIGIN(klass
);
1561 me
= search_method0(origin_class
, name
, &defined_class
, true);
1563 if (!me
&& RB_TYPE_P(klass
, T_MODULE
)) {
1564 me
= search_method(rb_cObject
, name
, &defined_class
);
1567 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1568 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1569 rb_print_undef(klass
, name
, METHOD_VISI_UNDEF
);
1572 if (METHOD_ENTRY_VISI(me
) != visi
) {
1573 rb_vm_check_redefinition_opt_method(me
, klass
);
1575 if (klass
== defined_class
|| origin_class
== defined_class
) {
1576 if (me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1577 // Refinement method entries should always be public because the refinement
1578 // search is always performed.
1579 if (me
->def
->body
.refined
.orig_me
) {
1580 METHOD_ENTRY_VISI_SET((rb_method_entry_t
*)me
->def
->body
.refined
.orig_me
, visi
);
1584 METHOD_ENTRY_VISI_SET(me
, visi
);
1586 rb_clear_method_cache(klass
, name
);
1589 rb_add_method(klass
, name
, VM_METHOD_TYPE_ZSUPER
, 0, visi
);
1594 #define BOUND_PRIVATE 0x01
1595 #define BOUND_RESPONDS 0x02
1598 method_boundp(VALUE klass
, ID id
, int ex
)
1600 const rb_callable_method_entry_t
*cme
;
1602 VM_ASSERT(RB_TYPE_P(klass
, T_CLASS
) || RB_TYPE_P(klass
, T_ICLASS
));
1604 if (ex
& BOUND_RESPONDS
) {
1605 cme
= rb_callable_method_entry_with_refinements(klass
, id
, NULL
);
1608 cme
= callable_method_entry_without_refinements(klass
, id
, NULL
);
1612 if (ex
& ~BOUND_RESPONDS
) {
1613 switch (METHOD_ENTRY_VISI(cme
)) {
1614 case METHOD_VISI_PRIVATE
:
1616 case METHOD_VISI_PROTECTED
:
1617 if (ex
& BOUND_RESPONDS
) return 0;
1623 if (cme
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) {
1624 if (ex
& BOUND_RESPONDS
) return 2;
1634 rb_method_boundp(VALUE klass
, ID id
, int ex
)
1636 return method_boundp(klass
, id
, ex
);
1640 vm_cref_set_visibility(rb_method_visibility_t method_visi
, int module_func
)
1642 rb_scope_visibility_t
*scope_visi
= (rb_scope_visibility_t
*)&rb_vm_cref()->scope_visi
;
1643 scope_visi
->method_visi
= method_visi
;
1644 scope_visi
->module_func
= module_func
;
1648 rb_scope_visibility_set(rb_method_visibility_t visi
)
1650 vm_cref_set_visibility(visi
, FALSE
);
1654 scope_visibility_check(void)
1656 /* Check for public/protected/private/module_function called inside a method */
1657 rb_control_frame_t
*cfp
= GET_EC()->cfp
+1;
1658 if (cfp
&& cfp
->iseq
&& cfp
->iseq
->body
->type
== ISEQ_TYPE_METHOD
) {
1659 rb_warn("calling %s without arguments inside a method may not have the intended effect",
1660 rb_id2name(rb_frame_this_func()));
1665 rb_scope_module_func_set(void)
1667 scope_visibility_check();
1668 vm_cref_set_visibility(METHOD_VISI_PRIVATE
, TRUE
);
1671 const rb_cref_t
*rb_vm_cref_in_context(VALUE self
, VALUE cbase
);
1673 rb_attr(VALUE klass
, ID id
, int read
, int write
, int ex
)
1676 rb_method_visibility_t visi
;
1677 const rb_execution_context_t
*ec
= GET_EC();
1678 const rb_cref_t
*cref
= rb_vm_cref_in_context(klass
, klass
);
1681 visi
= METHOD_VISI_PUBLIC
;
1684 switch (vm_scope_visibility_get(ec
)) {
1685 case METHOD_VISI_PRIVATE
:
1686 if (vm_scope_module_func_check(ec
)) {
1687 rb_warning("attribute accessor as module_function");
1689 visi
= METHOD_VISI_PRIVATE
;
1691 case METHOD_VISI_PROTECTED
:
1692 visi
= METHOD_VISI_PROTECTED
;
1695 visi
= METHOD_VISI_PUBLIC
;
1700 attriv
= rb_intern_str(rb_sprintf("@%"PRIsVALUE
, rb_id2str(id
)));
1702 rb_add_method(klass
, id
, VM_METHOD_TYPE_IVAR
, (void *)attriv
, visi
);
1705 rb_add_method(klass
, rb_id_attrset(id
), VM_METHOD_TYPE_ATTRSET
, (void *)attriv
, visi
);
1710 rb_undef(VALUE klass
, ID id
)
1712 const rb_method_entry_t
*me
;
1715 rb_raise(rb_eTypeError
, "no class to undef method");
1717 rb_class_modify_check(klass
);
1718 if (id
== object_id
|| id
== id__send__
|| id
== idInitialize
) {
1719 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id
));
1722 me
= search_method(klass
, id
, 0);
1723 if (me
&& me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
1724 me
= rb_resolve_refined_method(Qnil
, me
);
1727 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
1728 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
1729 rb_method_name_error(klass
, rb_id2str(id
));
1732 rb_add_method(klass
, id
, VM_METHOD_TYPE_UNDEF
, 0, METHOD_VISI_PUBLIC
);
1734 CALL_METHOD_HOOK(klass
, undefined
, id
);
1739 * undef_method(symbol) -> self
1740 * undef_method(string) -> self
1742 * Prevents the current class from responding to calls to the named
1743 * method. Contrast this with <code>remove_method</code>, which deletes
1744 * the method from the particular class; Ruby will still search
1745 * superclasses and mixed-in modules for a possible receiver.
1746 * String arguments are converted to symbols.
1753 * class Child < Parent
1765 * remove_method :hello # remove from child, still in parent
1771 * undef_method :hello # prevent any calls to 'hello'
1775 * <em>produces:</em>
1779 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
1783 rb_mod_undef_method(int argc
, VALUE
*argv
, VALUE mod
)
1786 for (i
= 0; i
< argc
; i
++) {
1788 ID id
= rb_check_id(&v
);
1790 rb_method_name_error(mod
, v
);
1797 static rb_method_visibility_t
1798 check_definition_visibility(VALUE mod
, int argc
, VALUE
*argv
)
1800 const rb_method_entry_t
*me
;
1801 VALUE mid
, include_super
, lookup_mod
= mod
;
1805 rb_scan_args(argc
, argv
, "11", &mid
, &include_super
);
1806 id
= rb_check_id(&mid
);
1807 if (!id
) return METHOD_VISI_UNDEF
;
1813 inc_super
= RTEST(include_super
);
1815 lookup_mod
= RCLASS_ORIGIN(mod
);
1819 me
= rb_method_entry_without_refinements(lookup_mod
, id
, NULL
);
1821 if (me
->def
->type
== VM_METHOD_TYPE_NOTIMPLEMENTED
) return METHOD_VISI_UNDEF
;
1822 if (!inc_super
&& me
->owner
!= mod
) return METHOD_VISI_UNDEF
;
1823 return METHOD_ENTRY_VISI(me
);
1825 return METHOD_VISI_UNDEF
;
1830 * mod.method_defined?(symbol, inherit=true) -> true or false
1831 * mod.method_defined?(string, inherit=true) -> true or false
1833 * Returns +true+ if the named method is defined by
1834 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1835 * ancestors. Public and protected methods are matched.
1836 * String arguments are converted to symbols.
1840 * def protected_method1() end
1841 * protected :protected_method1
1845 * def private_method2() end
1846 * private :private_method2
1853 * A.method_defined? :method1 #=> true
1854 * C.method_defined? "method1" #=> true
1855 * C.method_defined? "method2" #=> true
1856 * C.method_defined? "method2", true #=> true
1857 * C.method_defined? "method2", false #=> false
1858 * C.method_defined? "method3" #=> true
1859 * C.method_defined? "protected_method1" #=> true
1860 * C.method_defined? "method4" #=> false
1861 * C.method_defined? "private_method2" #=> false
1865 rb_mod_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1867 rb_method_visibility_t visi
= check_definition_visibility(mod
, argc
, argv
);
1868 return RBOOL(visi
== METHOD_VISI_PUBLIC
|| visi
== METHOD_VISI_PROTECTED
);
1872 check_definition(VALUE mod
, int argc
, VALUE
*argv
, rb_method_visibility_t visi
)
1874 return RBOOL(check_definition_visibility(mod
, argc
, argv
) == visi
);
1879 * mod.public_method_defined?(symbol, inherit=true) -> true or false
1880 * mod.public_method_defined?(string, inherit=true) -> true or false
1882 * Returns +true+ if the named public method is defined by
1883 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1885 * String arguments are converted to symbols.
1899 * A.method_defined? :method1 #=> true
1900 * C.public_method_defined? "method1" #=> true
1901 * C.public_method_defined? "method1", true #=> true
1902 * C.public_method_defined? "method1", false #=> true
1903 * C.public_method_defined? "method2" #=> false
1904 * C.method_defined? "method2" #=> true
1908 rb_mod_public_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1910 return check_definition(mod
, argc
, argv
, METHOD_VISI_PUBLIC
);
1915 * mod.private_method_defined?(symbol, inherit=true) -> true or false
1916 * mod.private_method_defined?(string, inherit=true) -> true or false
1918 * Returns +true+ if the named private method is defined by
1919 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1921 * String arguments are converted to symbols.
1935 * A.method_defined? :method1 #=> true
1936 * C.private_method_defined? "method1" #=> false
1937 * C.private_method_defined? "method2" #=> true
1938 * C.private_method_defined? "method2", true #=> true
1939 * C.private_method_defined? "method2", false #=> false
1940 * C.method_defined? "method2" #=> false
1944 rb_mod_private_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1946 return check_definition(mod
, argc
, argv
, METHOD_VISI_PRIVATE
);
1951 * mod.protected_method_defined?(symbol, inherit=true) -> true or false
1952 * mod.protected_method_defined?(string, inherit=true) -> true or false
1954 * Returns +true+ if the named protected method is defined
1955 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1957 * String arguments are converted to symbols.
1971 * A.method_defined? :method1 #=> true
1972 * C.protected_method_defined? "method1" #=> false
1973 * C.protected_method_defined? "method2" #=> true
1974 * C.protected_method_defined? "method2", true #=> true
1975 * C.protected_method_defined? "method2", false #=> false
1976 * C.method_defined? "method2" #=> true
1980 rb_mod_protected_method_defined(int argc
, VALUE
*argv
, VALUE mod
)
1982 return check_definition(mod
, argc
, argv
, METHOD_VISI_PROTECTED
);
1986 rb_method_entry_eq(const rb_method_entry_t
*m1
, const rb_method_entry_t
*m2
)
1988 return rb_method_definition_eq(m1
->def
, m2
->def
);
1991 static const rb_method_definition_t
*
1992 original_method_definition(const rb_method_definition_t
*def
)
1996 switch (def
->type
) {
1997 case VM_METHOD_TYPE_REFINED
:
1998 if (def
->body
.refined
.orig_me
) {
1999 def
= def
->body
.refined
.orig_me
->def
;
2003 case VM_METHOD_TYPE_ALIAS
:
2004 def
= def
->body
.alias
.original_me
->def
;
2013 MJIT_FUNC_EXPORTED
int
2014 rb_method_definition_eq(const rb_method_definition_t
*d1
, const rb_method_definition_t
*d2
)
2016 d1
= original_method_definition(d1
);
2017 d2
= original_method_definition(d2
);
2019 if (d1
== d2
) return 1;
2020 if (!d1
|| !d2
) return 0;
2021 if (d1
->type
!= d2
->type
) return 0;
2024 case VM_METHOD_TYPE_ISEQ
:
2025 return d1
->body
.iseq
.iseqptr
== d2
->body
.iseq
.iseqptr
;
2026 case VM_METHOD_TYPE_CFUNC
:
2028 d1
->body
.cfunc
.func
== d2
->body
.cfunc
.func
&&
2029 d1
->body
.cfunc
.argc
== d2
->body
.cfunc
.argc
;
2030 case VM_METHOD_TYPE_ATTRSET
:
2031 case VM_METHOD_TYPE_IVAR
:
2032 return d1
->body
.attr
.id
== d2
->body
.attr
.id
;
2033 case VM_METHOD_TYPE_BMETHOD
:
2034 return RTEST(rb_equal(d1
->body
.bmethod
.proc
, d2
->body
.bmethod
.proc
));
2035 case VM_METHOD_TYPE_MISSING
:
2036 return d1
->original_id
== d2
->original_id
;
2037 case VM_METHOD_TYPE_ZSUPER
:
2038 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2039 case VM_METHOD_TYPE_UNDEF
:
2041 case VM_METHOD_TYPE_OPTIMIZED
:
2042 return (d1
->body
.optimized
.type
== d2
->body
.optimized
.type
) &&
2043 (d1
->body
.optimized
.index
== d2
->body
.optimized
.index
);
2044 case VM_METHOD_TYPE_REFINED
:
2045 case VM_METHOD_TYPE_ALIAS
:
2048 rb_bug("rb_method_definition_eq: unsupported type: %d\n", d1
->type
);
2052 rb_hash_method_definition(st_index_t hash
, const rb_method_definition_t
*def
)
2054 hash
= rb_hash_uint(hash
, def
->type
);
2055 def
= original_method_definition(def
);
2057 if (!def
) return hash
;
2059 switch (def
->type
) {
2060 case VM_METHOD_TYPE_ISEQ
:
2061 return rb_hash_uint(hash
, (st_index_t
)def
->body
.iseq
.iseqptr
);
2062 case VM_METHOD_TYPE_CFUNC
:
2063 hash
= rb_hash_uint(hash
, (st_index_t
)def
->body
.cfunc
.func
);
2064 return rb_hash_uint(hash
, def
->body
.cfunc
.argc
);
2065 case VM_METHOD_TYPE_ATTRSET
:
2066 case VM_METHOD_TYPE_IVAR
:
2067 return rb_hash_uint(hash
, def
->body
.attr
.id
);
2068 case VM_METHOD_TYPE_BMETHOD
:
2069 return rb_hash_proc(hash
, def
->body
.bmethod
.proc
);
2070 case VM_METHOD_TYPE_MISSING
:
2071 return rb_hash_uint(hash
, def
->original_id
);
2072 case VM_METHOD_TYPE_ZSUPER
:
2073 case VM_METHOD_TYPE_NOTIMPLEMENTED
:
2074 case VM_METHOD_TYPE_UNDEF
:
2076 case VM_METHOD_TYPE_OPTIMIZED
:
2077 hash
= rb_hash_uint(hash
, def
->body
.optimized
.index
);
2078 return rb_hash_uint(hash
, def
->body
.optimized
.type
);
2079 case VM_METHOD_TYPE_REFINED
:
2080 case VM_METHOD_TYPE_ALIAS
:
2081 break; /* unreachable */
2083 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def
->type
);
2087 rb_hash_method_entry(st_index_t hash
, const rb_method_entry_t
*me
)
2089 return rb_hash_method_definition(hash
, me
->def
);
2093 rb_alias(VALUE klass
, ID alias_name
, ID original_name
)
2095 const VALUE target_klass
= klass
;
2096 VALUE defined_class
;
2097 const rb_method_entry_t
*orig_me
;
2098 rb_method_visibility_t visi
= METHOD_VISI_UNDEF
;
2101 rb_raise(rb_eTypeError
, "no class to make alias");
2104 rb_class_modify_check(klass
);
2107 orig_me
= search_method(klass
, original_name
, &defined_class
);
2109 if (orig_me
&& orig_me
->def
->type
== VM_METHOD_TYPE_REFINED
) {
2110 orig_me
= rb_resolve_refined_method(Qnil
, orig_me
);
2113 if (UNDEFINED_METHOD_ENTRY_P(orig_me
) ||
2114 UNDEFINED_REFINED_METHOD_P(orig_me
->def
)) {
2115 if ((!RB_TYPE_P(klass
, T_MODULE
)) ||
2116 (orig_me
= search_method(rb_cObject
, original_name
, &defined_class
),
2117 UNDEFINED_METHOD_ENTRY_P(orig_me
))) {
2118 rb_print_undef(klass
, original_name
, METHOD_VISI_UNDEF
);
2122 switch (orig_me
->def
->type
) {
2123 case VM_METHOD_TYPE_ZSUPER
:
2124 klass
= RCLASS_SUPER(klass
);
2125 original_name
= orig_me
->def
->original_id
;
2126 visi
= METHOD_ENTRY_VISI(orig_me
);
2128 case VM_METHOD_TYPE_ALIAS
:
2129 orig_me
= orig_me
->def
->body
.alias
.original_me
;
2130 VM_ASSERT(orig_me
->def
->type
!= VM_METHOD_TYPE_ALIAS
);
2135 if (visi
== METHOD_VISI_UNDEF
) visi
= METHOD_ENTRY_VISI(orig_me
);
2137 if (orig_me
->defined_class
== 0) {
2138 rb_method_entry_make(target_klass
, alias_name
, target_klass
, visi
,
2139 VM_METHOD_TYPE_ALIAS
, NULL
, orig_me
->called_id
,
2140 (void *)rb_method_entry_clone(orig_me
));
2141 method_added(target_klass
, alias_name
);
2144 rb_method_entry_t
*alias_me
;
2146 alias_me
= method_entry_set(target_klass
, alias_name
, orig_me
, visi
, orig_me
->owner
);
2147 RB_OBJ_WRITE(alias_me
, &alias_me
->owner
, target_klass
);
2148 RB_OBJ_WRITE(alias_me
, &alias_me
->defined_class
, orig_me
->defined_class
);
2154 * alias_method(new_name, old_name) -> symbol
2156 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
2157 * be used to retain access to methods that are overridden.
2160 * alias_method :orig_exit, :exit #=> :orig_exit
2162 * puts "Exiting with code #{code}"
2169 * <em>produces:</em>
2171 * Exiting with code 99
2175 rb_mod_alias_method(VALUE mod
, VALUE newname
, VALUE oldname
)
2177 ID oldid
= rb_check_id(&oldname
);
2179 rb_print_undef_str(mod
, oldname
);
2181 VALUE id
= rb_to_id(newname
);
2182 rb_alias(mod
, id
, oldid
);
2187 check_and_export_method(VALUE self
, VALUE name
, rb_method_visibility_t visi
)
2189 ID id
= rb_check_id(&name
);
2191 rb_print_undef_str(self
, name
);
2193 rb_export_method(self
, id
, visi
);
2197 set_method_visibility(VALUE self
, int argc
, const VALUE
*argv
, rb_method_visibility_t visi
)
2201 rb_check_frozen(self
);
2203 rb_warning("%"PRIsVALUE
" with no argument is just ignored",
2204 QUOTE_ID(rb_frame_callee()));
2211 if (argc
== 1 && (v
= rb_check_array_type(argv
[0])) != Qnil
) {
2214 for (j
= 0; j
< RARRAY_LEN(v
); j
++) {
2215 check_and_export_method(self
, RARRAY_AREF(v
, j
), visi
);
2219 for (i
= 0; i
< argc
; i
++) {
2220 check_and_export_method(self
, argv
[i
], visi
);
2226 set_visibility(int argc
, const VALUE
*argv
, VALUE module
, rb_method_visibility_t visi
)
2229 scope_visibility_check();
2230 rb_scope_visibility_set(visi
);
2234 set_method_visibility(module
, argc
, argv
, visi
);
2238 return rb_ary_new_from_values(argc
, argv
);
2244 * public(method_name) -> method_name
2245 * public(method_name, method_name, ...) -> array
2246 * public(array) -> array
2248 * With no arguments, sets the default visibility for subsequently
2249 * defined methods to public. With arguments, sets the named methods to
2250 * have public visibility.
2251 * String arguments are converted to symbols.
2252 * An Array of Symbols and/or Strings is also accepted.
2253 * If a single argument is passed, it is returned.
2254 * If no argument is passed, nil is returned.
2255 * If multiple arguments are passed, the arguments are returned as an array.
2259 rb_mod_public(int argc
, VALUE
*argv
, VALUE module
)
2261 return set_visibility(argc
, argv
, module
, METHOD_VISI_PUBLIC
);
2267 * protected(method_name) -> method_name
2268 * protected(method_name, method_name, ...) -> array
2269 * protected(array) -> array
2271 * With no arguments, sets the default visibility for subsequently
2272 * defined methods to protected. With arguments, sets the named methods
2273 * to have protected visibility.
2274 * String arguments are converted to symbols.
2275 * An Array of Symbols and/or Strings is also accepted.
2276 * If a single argument is passed, it is returned.
2277 * If no argument is passed, nil is returned.
2278 * If multiple arguments are passed, the arguments are returned as an array.
2280 * If a method has protected visibility, it is callable only where
2281 * <code>self</code> of the context is the same as the method.
2282 * (method definition or instance_eval). This behavior is different from
2283 * Java's protected method. Usually <code>private</code> should be used.
2285 * Note that a protected method is slow because it can't use inline cache.
2287 * To show a private method on RDoc, use <code>:doc:</code> instead of this.
2291 rb_mod_protected(int argc
, VALUE
*argv
, VALUE module
)
2293 return set_visibility(argc
, argv
, module
, METHOD_VISI_PROTECTED
);
2299 * private(method_name) -> method_name
2300 * private(method_name, method_name, ...) -> array
2301 * private(array) -> array
2303 * With no arguments, sets the default visibility for subsequently
2304 * defined methods to private. With arguments, sets the named methods
2305 * to have private visibility.
2306 * String arguments are converted to symbols.
2307 * An Array of Symbols and/or Strings is also accepted.
2308 * If a single argument is passed, it is returned.
2309 * If no argument is passed, nil is returned.
2310 * If multiple arguments are passed, the arguments are returned as an array.
2319 * Mod.private_instance_methods #=> [:a, :c]
2321 * Note that to show a private method on RDoc, use <code>:doc:</code>.
2325 rb_mod_private(int argc
, VALUE
*argv
, VALUE module
)
2327 return set_visibility(argc
, argv
, module
, METHOD_VISI_PRIVATE
);
2332 * ruby2_keywords(method_name, ...) -> nil
2334 * For the given method names, marks the method as passing keywords through
2335 * a normal argument splat. This should only be called on methods that
2336 * accept an argument splat (<tt>*args</tt>) but not explicit keywords or
2337 * a keyword splat. It marks the method such that if the method is called
2338 * with keyword arguments, the final hash argument is marked with a special
2339 * flag such that if it is the final element of a normal argument splat to
2340 * another method call, and that method call does not include explicit
2341 * keywords or a keyword splat, the final element is interpreted as keywords.
2342 * In other words, keywords will be passed through the method to other
2345 * This should only be used for methods that delegate keywords to another
2346 * method, and only for backwards compatibility with Ruby versions before 3.0.
2347 * See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
2348 * for details on why +ruby2_keywords+ exists and when and how to use it.
2350 * This method will probably be removed at some point, as it exists only
2351 * for backwards compatibility. As it does not exist in Ruby versions before
2352 * 2.7, check that the module responds to this method before calling it:
2355 * def foo(meth, *args, &block)
2356 * send(:"do_#{meth}", *args, &block)
2358 * ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true)
2361 * However, be aware that if the +ruby2_keywords+ method is removed, the
2362 * behavior of the +foo+ method using the above approach will change so that
2363 * the method does not pass through keywords.
2367 rb_mod_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2370 VALUE origin_class
= RCLASS_ORIGIN(module
);
2372 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2373 rb_check_frozen(module
);
2375 for (i
= 0; i
< argc
; i
++) {
2377 ID name
= rb_check_id(&v
);
2378 rb_method_entry_t
*me
;
2379 VALUE defined_class
;
2382 rb_print_undef_str(module
, v
);
2385 me
= search_method(origin_class
, name
, &defined_class
);
2386 if (!me
&& RB_TYPE_P(module
, T_MODULE
)) {
2387 me
= search_method(rb_cObject
, name
, &defined_class
);
2390 if (UNDEFINED_METHOD_ENTRY_P(me
) ||
2391 UNDEFINED_REFINED_METHOD_P(me
->def
)) {
2392 rb_print_undef(module
, name
, METHOD_VISI_UNDEF
);
2395 if (module
== defined_class
|| origin_class
== defined_class
) {
2396 switch (me
->def
->type
) {
2397 case VM_METHOD_TYPE_ISEQ
:
2398 if (me
->def
->body
.iseq
.iseqptr
->body
->param
.flags
.has_rest
&&
2399 !me
->def
->body
.iseq
.iseqptr
->body
->param
.flags
.has_kw
&&
2400 !me
->def
->body
.iseq
.iseqptr
->body
->param
.flags
.has_kwrest
) {
2401 me
->def
->body
.iseq
.iseqptr
->body
->param
.flags
.ruby2_keywords
= 1;
2402 rb_clear_method_cache(module
, name
);
2405 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2408 case VM_METHOD_TYPE_BMETHOD
: {
2409 VALUE procval
= me
->def
->body
.bmethod
.proc
;
2410 if (vm_block_handler_type(procval
) == block_handler_type_proc
) {
2411 procval
= vm_proc_to_block_handler(VM_BH_TO_PROC(procval
));
2414 if (vm_block_handler_type(procval
) == block_handler_type_iseq
) {
2415 const struct rb_captured_block
*captured
= VM_BH_TO_ISEQ_BLOCK(procval
);
2416 const rb_iseq_t
*iseq
= rb_iseq_check(captured
->code
.iseq
);
2417 if (iseq
->body
->param
.flags
.has_rest
&&
2418 !iseq
->body
->param
.flags
.has_kw
&&
2419 !iseq
->body
->param
.flags
.has_kwrest
) {
2420 iseq
->body
->param
.flags
.ruby2_keywords
= 1;
2421 rb_clear_method_cache(module
, name
);
2424 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name
));
2431 rb_warn("Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)", rb_id2name(name
));
2436 rb_warn("Skipping set of ruby2_keywords flag for %s (can only set in method defining module)", rb_id2name(name
));
2444 * mod.public_class_method(symbol, ...) -> mod
2445 * mod.public_class_method(string, ...) -> mod
2446 * mod.public_class_method(array) -> mod
2448 * Makes a list of existing class methods public.
2450 * String arguments are converted to symbols.
2451 * An Array of Symbols and/or Strings is also accepted.
2455 rb_mod_public_method(int argc
, VALUE
*argv
, VALUE obj
)
2457 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PUBLIC
);
2463 * mod.private_class_method(symbol, ...) -> mod
2464 * mod.private_class_method(string, ...) -> mod
2465 * mod.private_class_method(array) -> mod
2467 * Makes existing class methods private. Often used to hide the default
2468 * constructor <code>new</code>.
2470 * String arguments are converted to symbols.
2471 * An Array of Symbols and/or Strings is also accepted.
2473 * class SimpleSingleton # Not thread safe
2474 * private_class_method :new
2475 * def SimpleSingleton.create(*args, &block)
2476 * @me = new(*args, &block) if ! @me
2483 rb_mod_private_method(int argc
, VALUE
*argv
, VALUE obj
)
2485 set_method_visibility(rb_singleton_class(obj
), argc
, argv
, METHOD_VISI_PRIVATE
);
2492 * public(symbol, ...)
2493 * public(string, ...)
2496 * With no arguments, sets the default visibility for subsequently
2497 * defined methods to public. With arguments, sets the named methods to
2498 * have public visibility.
2500 * String arguments are converted to symbols.
2501 * An Array of Symbols and/or Strings is also accepted.
2505 top_public(int argc
, VALUE
*argv
, VALUE _
)
2507 return rb_mod_public(argc
, argv
, rb_cObject
);
2513 * private(symbol, ...)
2514 * private(string, ...)
2517 * With no arguments, sets the default visibility for subsequently
2518 * defined methods to private. With arguments, sets the named methods to
2519 * have private visibility.
2521 * String arguments are converted to symbols.
2522 * An Array of Symbols and/or Strings is also accepted.
2525 top_private(int argc
, VALUE
*argv
, VALUE _
)
2527 return rb_mod_private(argc
, argv
, rb_cObject
);
2532 * ruby2_keywords(method_name, ...) -> self
2534 * For the given method names, marks the method as passing keywords through
2535 * a normal argument splat. See Module#ruby2_keywords in detail.
2538 top_ruby2_keywords(int argc
, VALUE
*argv
, VALUE module
)
2540 return rb_mod_ruby2_keywords(argc
, argv
, rb_cObject
);
2545 * module_function -> nil
2546 * module_function(method_name) -> method_name
2547 * module_function(method_name, method_name, ...) -> array
2549 * Creates module functions for the named methods. These functions may
2550 * be called with the module as a receiver, and also become available
2551 * as instance methods to classes that mix in the module. Module
2552 * functions are copies of the original, and so may be changed
2553 * independently. The instance-method versions are made private. If
2554 * used with no arguments, subsequently defined methods become module
2556 * String arguments are converted to symbols.
2557 * If a single argument is passed, it is returned.
2558 * If no argument is passed, nil is returned.
2559 * If multiple arguments are passed, the arguments are returned as an array.
2565 * module_function :one
2573 * Mod.one #=> "This is one"
2575 * c.call_one #=> "This is one"
2578 * "This is the new one"
2581 * Mod.one #=> "This is one"
2582 * c.call_one #=> "This is the new one"
2586 rb_mod_modfunc(int argc
, VALUE
*argv
, VALUE module
)
2590 const rb_method_entry_t
*me
;
2592 if (!RB_TYPE_P(module
, T_MODULE
)) {
2593 rb_raise(rb_eTypeError
, "module_function must be called for modules");
2597 rb_scope_module_func_set();
2601 set_method_visibility(module
, argc
, argv
, METHOD_VISI_PRIVATE
);
2603 for (i
= 0; i
< argc
; i
++) {
2606 id
= rb_to_id(argv
[i
]);
2608 me
= search_method(m
, id
, 0);
2610 me
= search_method(rb_cObject
, id
, 0);
2612 if (UNDEFINED_METHOD_ENTRY_P(me
)) {
2613 rb_print_undef(module
, id
, METHOD_VISI_UNDEF
);
2615 if (me
->def
->type
!= VM_METHOD_TYPE_ZSUPER
) {
2616 break; /* normal case: need not to follow 'super' link */
2618 m
= RCLASS_SUPER(m
);
2622 rb_method_entry_set(rb_singleton_class(module
), id
, me
, METHOD_VISI_PUBLIC
);
2627 return rb_ary_new_from_values(argc
, argv
);
2631 #pragma push_macro("rb_method_basic_definition_p")
2632 #undef rb_method_basic_definition_p
2635 rb_method_basic_definition_p(VALUE klass
, ID id
)
2637 const rb_callable_method_entry_t
*cme
;
2638 if (!klass
) return TRUE
; /* hidden object cannot be overridden */
2639 cme
= rb_callable_method_entry(klass
, id
);
2640 return (cme
&& METHOD_ENTRY_BASIC(cme
)) ? TRUE
: FALSE
;
2643 #pragma pop_macro("rb_method_basic_definition_p")
2647 call_method_entry(rb_execution_context_t
*ec
, VALUE defined_class
, VALUE obj
, ID id
,
2648 const rb_callable_method_entry_t
*cme
, int argc
, const VALUE
*argv
, int kw_splat
)
2650 VALUE passed_block_handler
= vm_passed_block_handler(ec
);
2651 VALUE result
= rb_vm_call_kw(ec
, obj
, id
, argc
, argv
, cme
, kw_splat
);
2652 vm_passed_block_handler_set(ec
, passed_block_handler
);
2657 basic_obj_respond_to_missing(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
,
2658 VALUE mid
, VALUE priv
)
2660 VALUE defined_class
, args
[2];
2661 const ID rtmid
= idRespond_to_missing
;
2662 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, rtmid
, &defined_class
);
2664 if (!cme
|| METHOD_ENTRY_BASIC(cme
)) return Qundef
;
2667 return call_method_entry(ec
, defined_class
, obj
, rtmid
, cme
, 2, args
, RB_NO_KEYWORDS
);
2671 basic_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int pub
)
2673 VALUE klass
= CLASS_OF(obj
);
2676 switch (method_boundp(klass
, id
, pub
|BOUND_RESPONDS
)) {
2680 ret
= basic_obj_respond_to_missing(ec
, klass
, obj
, ID2SYM(id
),
2681 pub
? Qfalse
: Qtrue
);
2682 return RTEST(ret
) && ret
!= Qundef
;
2689 vm_respond_to(rb_execution_context_t
*ec
, VALUE klass
, VALUE obj
, ID id
, int priv
)
2691 VALUE defined_class
;
2692 const ID resid
= idRespond_to
;
2693 const rb_callable_method_entry_t
*const cme
= callable_method_entry(klass
, resid
, &defined_class
);
2695 if (!cme
) return -1;
2696 if (METHOD_ENTRY_BASIC(cme
)) {
2704 args
[0] = ID2SYM(id
);
2707 argc
= rb_method_entry_arity((const rb_method_entry_t
*)cme
);
2709 rb_raise(rb_eArgError
,
2710 "respond_to? must accept 1 or 2 arguments (requires %d)",
2716 else if (!NIL_P(ruby_verbose
)) {
2717 VALUE location
= rb_method_entry_location((const rb_method_entry_t
*)cme
);
2718 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
,
2719 "%"PRIsVALUE
"%c""respond_to?(:%"PRIsVALUE
") uses"
2720 " the deprecated method signature, which takes one parameter",
2721 (FL_TEST(klass
, FL_SINGLETON
) ? obj
: klass
),
2722 (FL_TEST(klass
, FL_SINGLETON
) ? '.' : '#'),
2724 if (!NIL_P(location
)) {
2725 VALUE path
= RARRAY_AREF(location
, 0);
2726 VALUE line
= RARRAY_AREF(location
, 1);
2728 rb_category_compile_warn(RB_WARN_CATEGORY_DEPRECATED
,
2729 RSTRING_PTR(path
), NUM2INT(line
),
2730 "respond_to? is defined here");
2735 result
= call_method_entry(ec
, defined_class
, obj
, resid
, cme
, argc
, args
, RB_NO_KEYWORDS
);
2736 return RTEST(result
);
2741 rb_obj_respond_to(VALUE obj
, ID id
, int priv
)
2743 rb_execution_context_t
*ec
= GET_EC();
2744 return rb_ec_obj_respond_to(ec
, obj
, id
, priv
);
2748 rb_ec_obj_respond_to(rb_execution_context_t
*ec
, VALUE obj
, ID id
, int priv
)
2750 VALUE klass
= CLASS_OF(obj
);
2751 int ret
= vm_respond_to(ec
, klass
, obj
, id
, priv
);
2752 if (ret
== -1) ret
= basic_obj_respond_to(ec
, obj
, id
, !priv
);
2757 rb_respond_to(VALUE obj
, ID id
)
2759 return rb_obj_respond_to(obj
, id
, FALSE
);
2765 * obj.respond_to?(symbol, include_all=false) -> true or false
2766 * obj.respond_to?(string, include_all=false) -> true or false
2768 * Returns +true+ if _obj_ responds to the given method. Private and
2769 * protected methods are included in the search only if the optional
2770 * second parameter evaluates to +true+.
2772 * If the method is not implemented,
2773 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
2774 * false is returned.
2776 * If the method is not defined, <code>respond_to_missing?</code>
2777 * method is called and the result is returned.
2779 * When the method name parameter is given as a string, the string is
2780 * converted to a symbol.
2784 obj_respond_to(int argc
, VALUE
*argv
, VALUE obj
)
2788 rb_execution_context_t
*ec
= GET_EC();
2790 rb_scan_args(argc
, argv
, "11", &mid
, &priv
);
2791 if (!(id
= rb_check_id(&mid
))) {
2792 VALUE ret
= basic_obj_respond_to_missing(ec
, CLASS_OF(obj
), obj
,
2793 rb_to_symbol(mid
), priv
);
2794 if (ret
== Qundef
) ret
= Qfalse
;
2797 return RBOOL(basic_obj_respond_to(ec
, obj
, id
, !RTEST(priv
)));
2802 * obj.respond_to_missing?(symbol, include_all) -> true or false
2803 * obj.respond_to_missing?(string, include_all) -> true or false
2805 * DO NOT USE THIS DIRECTLY.
2807 * Hook method to return whether the _obj_ can respond to _id_ method
2810 * When the method name parameter is given as a string, the string is
2811 * converted to a symbol.
2813 * See #respond_to?, and the example of BasicObject.
2816 obj_respond_to_missing(VALUE obj
, VALUE mid
, VALUE priv
)
2828 Init_eval_method(void)
2830 rb_define_method(rb_mKernel
, "respond_to?", obj_respond_to
, -1);
2831 rb_define_method(rb_mKernel
, "respond_to_missing?", obj_respond_to_missing
, 2);
2833 rb_define_method(rb_cModule
, "remove_method", rb_mod_remove_method
, -1);
2834 rb_define_method(rb_cModule
, "undef_method", rb_mod_undef_method
, -1);
2835 rb_define_method(rb_cModule
, "alias_method", rb_mod_alias_method
, 2);
2836 rb_define_private_method(rb_cModule
, "public", rb_mod_public
, -1);
2837 rb_define_private_method(rb_cModule
, "protected", rb_mod_protected
, -1);
2838 rb_define_private_method(rb_cModule
, "private", rb_mod_private
, -1);
2839 rb_define_private_method(rb_cModule
, "module_function", rb_mod_modfunc
, -1);
2840 rb_define_private_method(rb_cModule
, "ruby2_keywords", rb_mod_ruby2_keywords
, -1);
2842 rb_define_method(rb_cModule
, "method_defined?", rb_mod_method_defined
, -1);
2843 rb_define_method(rb_cModule
, "public_method_defined?", rb_mod_public_method_defined
, -1);
2844 rb_define_method(rb_cModule
, "private_method_defined?", rb_mod_private_method_defined
, -1);
2845 rb_define_method(rb_cModule
, "protected_method_defined?", rb_mod_protected_method_defined
, -1);
2846 rb_define_method(rb_cModule
, "public_class_method", rb_mod_public_method
, -1);
2847 rb_define_method(rb_cModule
, "private_class_method", rb_mod_private_method
, -1);
2849 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2850 "public", top_public
, -1);
2851 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2852 "private", top_private
, -1);
2853 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2854 "ruby2_keywords", top_ruby2_keywords
, -1);
2857 #define REPLICATE_METHOD(klass, id) do { \
2858 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
2859 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \
2862 REPLICATE_METHOD(rb_eException
, idMethodMissing
);
2863 REPLICATE_METHOD(rb_eException
, idRespond_to
);
2864 REPLICATE_METHOD(rb_eException
, idRespond_to_missing
);