Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

vm_method.c
Go to the documentation of this file.
1 /*
2 * This file is included by vm.c
3 */
4
5 #include "id_table.h"
6
7 #define METHOD_DEBUG 0
8
9 #if OPT_GLOBAL_METHOD_CACHE
10 #ifndef GLOBAL_METHOD_CACHE_SIZE
11 #define GLOBAL_METHOD_CACHE_SIZE 0x800
12 #endif
13 #define LSB_ONLY(x) ((x) & ~((x) - 1))
14 #define POWER_OF_2_P(x) ((x) == LSB_ONLY(x))
15 #if !POWER_OF_2_P(GLOBAL_METHOD_CACHE_SIZE)
16 # error GLOBAL_METHOD_CACHE_SIZE must be power of 2
17 #endif
18 #ifndef GLOBAL_METHOD_CACHE_MASK
19 #define GLOBAL_METHOD_CACHE_MASK (GLOBAL_METHOD_CACHE_SIZE-1)
20 #endif
21
22 #define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&(global_method_cache.mask))
23 #define GLOBAL_METHOD_CACHE(c,m) (global_method_cache.entries + GLOBAL_METHOD_CACHE_KEY(c,m))
24 #else
25 #define GLOBAL_METHOD_CACHE(c,m) (rb_bug("global method cache disabled improperly"), NULL)
26 #endif
27
28 static int vm_redefinition_check_flag(VALUE klass);
29 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass);
30
31 #define object_id idObject_id
32 #define added idMethod_added
33 #define singleton_added idSingleton_method_added
34 #define removed idMethod_removed
35 #define singleton_removed idSingleton_method_removed
36 #define undefined idMethod_undefined
37 #define singleton_undefined idSingleton_method_undefined
38 #define attached id__attached__
39
40 struct cache_entry {
41 rb_serial_t method_state;
42 rb_serial_t class_serial;
43 ID mid;
44 rb_method_entry_t* me;
45 VALUE defined_class;
46 };
47
48 #if OPT_GLOBAL_METHOD_CACHE
49 static struct {
50 unsigned int size;
51 unsigned int mask;
52 struct cache_entry *entries;
53 } global_method_cache = {
54 GLOBAL_METHOD_CACHE_SIZE,
55 GLOBAL_METHOD_CACHE_MASK,
56 };
57 #endif
58
59 #define ruby_running (GET_VM()->running)
60 /* int ruby_running = 0; */
61
62 static void
63 rb_class_clear_method_cache(VALUE klass, VALUE arg)
64 {
65 VALUE old_serial = *(rb_serial_t *)arg;
66 if (RCLASS_SERIAL(klass) > old_serial) {
67 return;
68 }
69
70 mjit_remove_class_serial(RCLASS_SERIAL(klass));
71 RCLASS_SERIAL(klass) = rb_next_class_serial();
72
73 if (BUILTIN_TYPE(klass) == T_ICLASS) {
74 struct rb_id_table *table = RCLASS_CALLABLE_M_TBL(klass);
75 if (table) {
76 rb_id_table_clear(table);
77 }
78 }
79 else {
80 VM_ASSERT(RCLASS_CALLABLE_M_TBL(klass) == 0);
81 }
82
83 rb_class_foreach_subclass(klass, rb_class_clear_method_cache, arg);
84 }
85
86 void
87 rb_clear_constant_cache(void)
88 {
89 INC_GLOBAL_CONSTANT_STATE();
90 }
91
92 void
93 rb_clear_method_cache_by_class(VALUE klass)
94 {
95 if (klass && klass != Qundef) {
96 int global = klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel;
97
98 RUBY_DTRACE_HOOK(METHOD_CACHE_CLEAR, (global ? "global" : rb_class2name(klass)));
99
100 if (global) {
101 INC_GLOBAL_METHOD_STATE();
102 }
103 else {
104 rb_serial_t old_serial = PREV_CLASS_SERIAL();
105 rb_class_clear_method_cache(klass, (VALUE)&old_serial);
106 }
107 }
108
109 if (klass == rb_mKernel) {
110 rb_subclass_entry_t *entry = RCLASS_EXT(klass)->subclasses;
111
112 for (; entry != NULL; entry = entry->next) {
113 struct rb_id_table *table = RCLASS_CALLABLE_M_TBL(entry->klass);
114 if (table)rb_id_table_clear(table);
115 }
116 }
117 }
118
119 VALUE
120 rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)
121 {
122 rb_notimplement();
123
124 UNREACHABLE_RETURN(Qnil);
125 }
126
127 static void
128 rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_visibility_t visi)
129 {
130 rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, (void *)1, visi);
131 }
132
133 void
134 rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi)
135 {
136 if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
137 if (func != rb_f_notimplement) {
138 rb_method_cfunc_t opt;
139 opt.func = func;
140 opt.argc = argc;
141 rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi);
142 }
143 else {
144 rb_define_notimplement_method_id(klass, mid, visi);
145 }
146 }
147
148 static void
149 rb_method_definition_release(rb_method_definition_t *def, int complemented)
150 {
151 if (def != NULL) {
152 const int alias_count = def->alias_count;
153 const int complemented_count = def->complemented_count;
154 VM_ASSERT(alias_count >= 0);
155 VM_ASSERT(complemented_count >= 0);
156
157 if (alias_count + complemented_count == 0) {
158 if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d,%d (remove)\n", (void *)def,
159 rb_id2name(def->original_id), alias_count, complemented_count);
160 VM_ASSERT(def->type == VM_METHOD_TYPE_BMETHOD ? def->body.bmethod.hooks == NULL : TRUE);
161 xfree(def);
162 }
163 else {
164 if (complemented) def->complemented_count--;
165 else if (def->alias_count > 0) def->alias_count--;
166
167 if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d->%d,%d->%d (dec)\n", (void *)def, rb_id2name(def->original_id),
168 alias_count, def->alias_count, complemented_count, def->complemented_count);
169 }
170 }
171 }
172
173 void
174 rb_free_method_entry(const rb_method_entry_t *me)
175 {
176 rb_method_definition_release(me->def, METHOD_ENTRY_COMPLEMENTED(me));
177 }
178
179 static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr);
180 extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
181
182 static inline rb_method_entry_t *
183 lookup_method_table(VALUE klass, ID id)
184 {
185 st_data_t body;
186 struct rb_id_table *m_tbl = RCLASS_M_TBL(klass);
187
188 if (rb_id_table_lookup(m_tbl, id, &body)) {
189 return (rb_method_entry_t *) body;
190 }
191 else {
192 return 0;
193 }
194 }
195
196 static VALUE
197 (*call_cfunc_invoker_func(int argc))(VALUE recv, int argc, const VALUE *, VALUE (*func)(ANYARGS))
198 {
199 switch (argc) {
200 case -2: return &call_cfunc_m2;
201 case -1: return &call_cfunc_m1;
202 case 0: return &call_cfunc_0;
203 case 1: return &call_cfunc_1;
204 case 2: return &call_cfunc_2;
205 case 3: return &call_cfunc_3;
206 case 4: return &call_cfunc_4;
207 case 5: return &call_cfunc_5;
208 case 6: return &call_cfunc_6;
209 case 7: return &call_cfunc_7;
210 case 8: return &call_cfunc_8;
211 case 9: return &call_cfunc_9;
212 case 10: return &call_cfunc_10;
213 case 11: return &call_cfunc_11;
214 case 12: return &call_cfunc_12;
215 case 13: return &call_cfunc_13;
216 case 14: return &call_cfunc_14;
217 case 15: return &call_cfunc_15;
218 default:
219 rb_bug("call_cfunc_func: unsupported length: %d", argc);
220 }
221 }
222
223 static void
224 setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
225 {
226 cfunc->func = func;
227 cfunc->argc = argc;
228 cfunc->invoker = call_cfunc_invoker_func(argc);
229 }
230
231 MJIT_FUNC_EXPORTED void
232 rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
233 {
234 *(rb_method_definition_t **)&me->def = def;
235
236 if (opts != NULL) {
237 switch (def->type) {
238 case VM_METHOD_TYPE_ISEQ:
239 {
240 rb_method_iseq_t *iseq_body = (rb_method_iseq_t *)opts;
241 rb_cref_t *method_cref, *cref = iseq_body->cref;
242
243 /* setup iseq first (before invoking GC) */
244 RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, iseq_body->iseqptr);
245
246 if (0) vm_cref_dump("rb_method_definition_create", cref);
247
248 if (cref) {
249 method_cref = cref;
250 }
251 else {
252 method_cref = vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */
253 }
254
255 RB_OBJ_WRITE(me, &def->body.iseq.cref, method_cref);
256 return;
257 }
258 case VM_METHOD_TYPE_CFUNC:
259 {
260 rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
261 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), cfunc->func, cfunc->argc);
262 return;
263 }
264 case VM_METHOD_TYPE_ATTRSET:
265 case VM_METHOD_TYPE_IVAR:
266 {
267 const rb_execution_context_t *ec = GET_EC();
268 rb_control_frame_t *cfp;
269 int line;
270
271 def->body.attr.id = (ID)(VALUE)opts;
272
273 cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
274
275 if (cfp && (line = rb_vm_get_sourceline(cfp))) {
276 VALUE location = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line));
277 RB_OBJ_WRITE(me, &def->body.attr.location, rb_ary_freeze(location));
278 }
279 else {
280 VM_ASSERT(def->body.attr.location == 0);
281 }
282 return;
283 }
284 case VM_METHOD_TYPE_BMETHOD:
285 RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts);
286 return;
287 case VM_METHOD_TYPE_NOTIMPLEMENTED:
288 setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1);
289 return;
290 case VM_METHOD_TYPE_OPTIMIZED:
291 def->body.optimize_type = (enum method_optimized_type)opts;
292 return;
293 case VM_METHOD_TYPE_REFINED:
294 {
295 const rb_method_refined_t *refined = (rb_method_refined_t *)opts;
296 RB_OBJ_WRITE(me, &def->body.refined.orig_me, refined->orig_me);
297 RB_OBJ_WRITE(me, &def->body.refined.owner, refined->owner);
298 return;
299 }
300 case VM_METHOD_TYPE_ALIAS:
301 RB_OBJ_WRITE(me, &def->body.alias.original_me, (rb_method_entry_t *)opts);
302 return;
303 case VM_METHOD_TYPE_ZSUPER:
304 case VM_METHOD_TYPE_UNDEF:
305 case VM_METHOD_TYPE_MISSING:
306 return;
307 }
308 }
309 }
310
311 static void
312 method_definition_reset(const rb_method_entry_t *me)
313 {
314 rb_method_definition_t *def = me->def;
315
316 switch(def->type) {
317 case VM_METHOD_TYPE_ISEQ:
318 RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.iseqptr);
319 RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.cref);
320 break;
321 case VM_METHOD_TYPE_ATTRSET:
322 case VM_METHOD_TYPE_IVAR:
323 RB_OBJ_WRITTEN(me, Qundef, def->body.attr.location);
324 break;
325 case VM_METHOD_TYPE_BMETHOD:
326 RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.proc);
327 /* give up to check all in a list */
328 if (def->body.bmethod.hooks) rb_gc_writebarrier_remember((VALUE)me);
329 break;
330 case VM_METHOD_TYPE_REFINED:
331 RB_OBJ_WRITTEN(me, Qundef, def->body.refined.orig_me);
332 RB_OBJ_WRITTEN(me, Qundef, def->body.refined.owner);
333 break;
334 case VM_METHOD_TYPE_ALIAS:
335 RB_OBJ_WRITTEN(me, Qundef, def->body.alias.original_me);
336 break;
337 case VM_METHOD_TYPE_CFUNC:
338 case VM_METHOD_TYPE_ZSUPER:
339 case VM_METHOD_TYPE_MISSING:
340 case VM_METHOD_TYPE_OPTIMIZED:
341 case VM_METHOD_TYPE_UNDEF:
342 case VM_METHOD_TYPE_NOTIMPLEMENTED:
343 break;
344 }
345 }
346
347 MJIT_FUNC_EXPORTED rb_method_definition_t *
348 rb_method_definition_create(rb_method_type_t type, ID mid)
349 {
350 rb_method_definition_t *def;
351 def = ZALLOC(rb_method_definition_t);
352 def->type = type;
353 def->original_id = mid;
354 static uintptr_t method_serial = 1;
355 def->method_serial = method_serial++;
356 return def;
357 }
358
359 static rb_method_definition_t *
360 method_definition_addref(rb_method_definition_t *def)
361 {
362 def->alias_count++;
363 if (METHOD_DEBUG) fprintf(stderr, "+%p-%s:%d\n", (void *)def, rb_id2name(def->original_id), def->alias_count);
364 return def;
365 }
366
367 static rb_method_definition_t *
368 method_definition_addref_complement(rb_method_definition_t *def)
369 {
370 def->complemented_count++;
371 if (METHOD_DEBUG) fprintf(stderr, "+%p-%s:%d\n", (void *)def, rb_id2name(def->original_id), def->complemented_count);
372 return def;
373 }
374
375 static rb_method_entry_t *
376 rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def)
377 {
378 rb_method_entry_t *me = (rb_method_entry_t *)rb_imemo_new(imemo_ment, (VALUE)def, (VALUE)called_id, owner, defined_class);
379 return me;
380 }
381
382 static VALUE
383 filter_defined_class(VALUE klass)
384 {
385 switch (BUILTIN_TYPE(klass)) {
386 case T_CLASS:
387 return klass;
388 case T_MODULE:
389 return 0;
390 case T_ICLASS:
391 break;
392 }
393 rb_bug("filter_defined_class: %s", rb_obj_info(klass));
394 }
395
396 rb_method_entry_t *
397 rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def)
398 {
399 rb_method_entry_t *me = rb_method_entry_alloc(called_id, klass, filter_defined_class(klass), def);
400 METHOD_ENTRY_FLAGS_SET(me, visi, ruby_running ? FALSE : TRUE);
401 if (def != NULL) method_definition_reset(me);
402 return me;
403 }
404
405 const rb_method_entry_t *
406 rb_method_entry_clone(const rb_method_entry_t *src_me)
407 {
408 rb_method_entry_t *me = rb_method_entry_alloc(src_me->called_id, src_me->owner, src_me->defined_class,
409 method_definition_addref(src_me->def));
410 METHOD_ENTRY_FLAGS_COPY(me, src_me);
411 return me;
412 }
413
414 MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
415 rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class)
416 {
417 rb_method_definition_t *def = src_me->def;
418 rb_method_entry_t *me;
419 struct {
420 const struct rb_method_entry_struct *orig_me;
421 VALUE owner;
422 } refined = {0};
423
424 if (!src_me->defined_class &&
425 def->type == VM_METHOD_TYPE_REFINED &&
426 def->body.refined.orig_me) {
427 const rb_method_entry_t *orig_me =
428 rb_method_entry_clone(def->body.refined.orig_me);
429 RB_OBJ_WRITE((VALUE)orig_me, &orig_me->defined_class, defined_class);
430 refined.orig_me = orig_me;
431 refined.owner = orig_me->owner;
432 def = NULL;
433 }
434 else {
435 def = method_definition_addref_complement(def);
436 }
437 me = rb_method_entry_alloc(called_id, src_me->owner, defined_class, def);
438 METHOD_ENTRY_FLAGS_COPY(me, src_me);
439 METHOD_ENTRY_COMPLEMENTED_SET(me);
440 if (!def) {
441 def = rb_method_definition_create(VM_METHOD_TYPE_REFINED, called_id);
442 rb_method_definition_set(me, def, &refined);
443 }
444
445 VM_ASSERT(RB_TYPE_P(me->owner, T_MODULE));
446
447 return (rb_callable_method_entry_t *)me;
448 }
449
450 void
451 rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src)
452 {
453 *(rb_method_definition_t **)&dst->def = method_definition_addref(src->def);
454 method_definition_reset(dst);
455 dst->called_id = src->called_id;
456 RB_OBJ_WRITE((VALUE)dst, &dst->owner, src->owner);
457 RB_OBJ_WRITE((VALUE)dst, &dst->defined_class, src->defined_class);
458 METHOD_ENTRY_FLAGS_COPY(dst, src);
459 }
460
461 static void
462 make_method_entry_refined(VALUE owner, rb_method_entry_t *me)
463 {
464 if (me->def->type == VM_METHOD_TYPE_REFINED) {
465 return;
466 }
467 else {
468 struct {
469 struct rb_method_entry_struct *orig_me;
470 VALUE owner;
471 } refined;
472 rb_method_definition_t *def;
473
474 rb_vm_check_redefinition_opt_method(me, me->owner);
475
476 refined.orig_me =
477 rb_method_entry_alloc(me->called_id, me->owner,
478 me->defined_class ?
479 me->defined_class : owner,
480 method_definition_addref(me->def));
481 METHOD_ENTRY_FLAGS_COPY(refined.orig_me, me);
482 refined.owner = owner;
483
484 def = rb_method_definition_create(VM_METHOD_TYPE_REFINED, me->called_id);
485 rb_method_definition_set(me, def, (void *)&refined);
486 METHOD_ENTRY_VISI_SET(me, METHOD_VISI_PUBLIC);
487 }
488 }
489
490 void
491 rb_add_refined_method_entry(VALUE refined_class, ID mid)
492 {
493 rb_method_entry_t *me = lookup_method_table(refined_class, mid);
494
495 if (me) {
496 make_method_entry_refined(refined_class, me);
497 rb_clear_method_cache_by_class(refined_class);
498 }
499 else {
500 rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, METHOD_VISI_PUBLIC);
501 }
502 }
503
504 static void
505 check_override_opt_method_i(VALUE klass, VALUE arg)
506 {
507 ID mid = (ID)arg;
508 const rb_method_entry_t *me, *newme;
509
510 if (vm_redefinition_check_flag(klass)) {
511 me = lookup_method_table(RCLASS_ORIGIN(klass), mid);
512 if (me) {
513 newme = rb_method_entry(klass, mid);
514 if (newme != me) rb_vm_check_redefinition_opt_method(me, me->owner);
515 }
516 }
517 rb_class_foreach_subclass(klass, check_override_opt_method_i, (VALUE)mid);
518 }
519
520 static void
521 check_override_opt_method(VALUE klass, VALUE mid)
522 {
523 if (rb_vm_check_optimizable_mid(mid)) {
524 check_override_opt_method_i(klass, mid);
525 }
526 }
527
528 /*
529 * klass->method_table[mid] = method_entry(defined_class, visi, def)
530 *
531 * If def is given (!= NULL), then just use it and ignore original_id and otps.
532 * If not given, then make a new def with original_id and opts.
533 */
534 static rb_method_entry_t *
535 rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibility_t visi,
536 rb_method_type_t type, rb_method_definition_t *def, ID original_id, void *opts)
537 {
538 rb_method_entry_t *me;
539 struct rb_id_table *mtbl;
540 st_data_t data;
541 int make_refined = 0;
542
543 if (NIL_P(klass)) {
544 klass = rb_cObject;
545 }
546 if (!FL_TEST(klass, FL_SINGLETON) &&
547 type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
548 type != VM_METHOD_TYPE_ZSUPER) {
549 switch (mid) {
550 case idInitialize:
551 case idInitialize_copy:
552 case idInitialize_clone:
553 case idInitialize_dup:
554 case idRespond_to_missing:
555 visi = METHOD_VISI_PRIVATE;
556 }
557 }
558
559 rb_class_modify_check(klass);
560
561 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
562 VALUE refined_class = rb_refinement_module_get_refined_class(klass);
563 rb_add_refined_method_entry(refined_class, mid);
564 }
565 if (type == VM_METHOD_TYPE_REFINED) {
566 rb_method_entry_t *old_me = lookup_method_table(RCLASS_ORIGIN(klass), mid);
567 if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
568 }
569 else {
570 klass = RCLASS_ORIGIN(klass);
571 }
572 mtbl = RCLASS_M_TBL(klass);
573
574 /* check re-definition */
575 if (rb_id_table_lookup(mtbl, mid, &data)) {
576 rb_method_entry_t *old_me = (rb_method_entry_t *)data;
577 rb_method_definition_t *old_def = old_me->def;
578
579 if (rb_method_definition_eq(old_def, def)) return old_me;
580 rb_vm_check_redefinition_opt_method(old_me, klass);
581
582 if (old_def->type == VM_METHOD_TYPE_REFINED) make_refined = 1;
583
584 if (RTEST(ruby_verbose) &&
585 type != VM_METHOD_TYPE_UNDEF &&
586 (old_def->alias_count == 0) &&
587 !make_refined &&
588 old_def->type != VM_METHOD_TYPE_UNDEF &&
589 old_def->type != VM_METHOD_TYPE_ZSUPER &&
590 old_def->type != VM_METHOD_TYPE_ALIAS) {
591 const rb_iseq_t *iseq = 0;
592
593 rb_warning("method redefined; discarding old %"PRIsVALUE, rb_id2str(mid));
594 switch (old_def->type) {
595 case VM_METHOD_TYPE_ISEQ:
596 iseq = def_iseq_ptr(old_def);
597 break;
598 case VM_METHOD_TYPE_BMETHOD:
599 iseq = rb_proc_get_iseq(old_def->body.bmethod.proc, 0);
600 break;
601 default:
602 break;
603 }
604 if (iseq) {
605 rb_compile_warning(RSTRING_PTR(rb_iseq_path(iseq)),
606 FIX2INT(iseq->body->location.first_lineno),
607 "previous definition of %"PRIsVALUE" was here",
608 rb_id2str(old_def->original_id));
609 }
610 }
611 }
612
613 /* create method entry */
614 me = rb_method_entry_create(mid, defined_class, visi, NULL);
615 if (def == NULL) def = rb_method_definition_create(type, original_id);
616 rb_method_definition_set(me, def, opts);
617
618 rb_clear_method_cache_by_class(klass);
619
620 /* check mid */
621 if (klass == rb_cObject) {
622 switch (mid) {
623 case idInitialize:
624 case idRespond_to_missing:
625 case idMethodMissing:
626 case idRespond_to:
627 rb_warn("redefining Object#%s may cause infinite loop", rb_id2name(mid));
628 }
629 }
630 /* check mid */
631 if (mid == object_id || mid == id__send__) {
632 if (type == VM_METHOD_TYPE_ISEQ && search_method(klass, mid, 0)) {
633 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
634 }
635 }
636
637 if (make_refined) {
638 make_method_entry_refined(klass, me);
639 }
640
641 rb_id_table_insert(mtbl, mid, (VALUE)me);
642 RB_OBJ_WRITTEN(klass, Qundef, (VALUE)me);
643
644 VM_ASSERT(me->def != NULL);
645
646 /* check optimized method override by a prepended module */
647 if (RB_TYPE_P(klass, T_MODULE)) {
648 check_override_opt_method(klass, (VALUE)mid);
649 }
650
651 return me;
652 }
653
654 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
655 const VALUE arg = ID2SYM(mid); \
656 VALUE recv_class = (klass); \
657 ID hook_id = (hook); \
658 if (FL_TEST((klass), FL_SINGLETON)) { \
659 recv_class = rb_ivar_get((klass), attached); \
660 hook_id = singleton_##hook; \
661 } \
662 rb_funcallv(recv_class, hook_id, 1, &arg); \
663 } while (0)
664
665 static void
666 method_added(VALUE klass, ID mid)
667 {
668 if (ruby_running) {
669 CALL_METHOD_HOOK(klass, added, mid);
670 }
671 }
672
673 void
674 rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_visibility_t visi)
675 {
676 rb_method_entry_make(klass, mid, klass, visi, type, NULL, mid, opts);
677
678 if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
679 method_added(klass, mid);
680 }
681 }
682
683 MJIT_FUNC_EXPORTED void
684 rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
685 {
686 struct { /* should be same fields with rb_method_iseq_struct */
687 const rb_iseq_t *iseqptr;
688 rb_cref_t *cref;
689 } iseq_body;
690
691 iseq_body.iseqptr = iseq;
692 iseq_body.cref = cref;
693 rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi);
694 }
695
696 static rb_method_entry_t *
697 method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
698 rb_method_visibility_t visi, VALUE defined_class)
699 {
700 rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi,
701 me->def->type, method_definition_addref(me->def), 0, NULL);
702 method_added(klass, mid);
703 return newme;
704 }
705
706 rb_method_entry_t *
707 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi)
708 {
709 return method_entry_set(klass, mid, me, visi, klass);
710 }
711
712 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
713
714 void
715 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
716 {
717 Check_Type(klass, T_CLASS);
718 RCLASS_EXT(klass)->allocator = func;
719 }
720
721 void
722 rb_undef_alloc_func(VALUE klass)
723 {
724 rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC);
725 }
726
727 rb_alloc_func_t
728 rb_get_alloc_func(VALUE klass)
729 {
730 Check_Type(klass, T_CLASS);
731
732 for (; klass; klass = RCLASS_SUPER(klass)) {
733 rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator;
734 if (allocator == UNDEF_ALLOC_FUNC) break;
735 if (allocator) return allocator;
736 }
737 return 0;
738 }
739
740 static inline rb_method_entry_t*
741 search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
742 {
743 rb_method_entry_t *me;
744
745 for (; klass; klass = RCLASS_SUPER(klass)) {
746 RB_DEBUG_COUNTER_INC(mc_search_super);
747 if ((me = lookup_method_table(klass, id)) != 0) break;
748 }
749
750 if (defined_class_ptr)
751 *defined_class_ptr = klass;
752 return me;
753 }
754
755 const rb_method_entry_t *
756 rb_method_entry_at(VALUE klass, ID id)
757 {
758 return lookup_method_table(klass, id);
759 }
760
761 /*
762 * search method entry without the method cache.
763 *
764 * if you need method entry with method cache (normal case), use
765 * rb_method_entry() simply.
766 */
767 static rb_method_entry_t *
768 method_entry_get_without_cache(VALUE klass, ID id,
769 VALUE *defined_class_ptr)
770 {
771 VALUE defined_class;
772 rb_method_entry_t *me = search_method(klass, id, &defined_class);
773
774 if (ruby_running) {
775 if (OPT_GLOBAL_METHOD_CACHE) {
776 struct cache_entry *ent;
777 ent = GLOBAL_METHOD_CACHE(klass, id);
778 ent->class_serial = RCLASS_SERIAL(klass);
779 ent->method_state = GET_GLOBAL_METHOD_STATE();
780 ent->defined_class = defined_class;
781 ent->mid = id;
782
783 if (UNDEFINED_METHOD_ENTRY_P(me)) {
784 me = ent->me = NULL;
785 }
786 else {
787 ent->me = me;
788 }
789 }
790 else if (UNDEFINED_METHOD_ENTRY_P(me)) {
791 me = NULL;
792 }
793 }
794 else if (UNDEFINED_METHOD_ENTRY_P(me)) {
795 me = NULL;
796 }
797
798 if (defined_class_ptr)
799 *defined_class_ptr = defined_class;
800 return me;
801 }
802
803 static void
804 verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me)
805 {
806 if (!VM_DEBUG_VERIFY_METHOD_CACHE) return;
807 VALUE actual_defined_class;
808 rb_method_entry_t *actual_me =
809 method_entry_get_without_cache(klass, id, &actual_defined_class);
810
811 if (me != actual_me || defined_class != actual_defined_class) {
812 rb_bug("method cache verification failed");
813 }
814 }
815
816 static rb_method_entry_t *
817 method_entry_get(VALUE klass, ID id, VALUE *defined_class_ptr)
818 {
819 struct cache_entry *ent;
820 if (!OPT_GLOBAL_METHOD_CACHE) goto nocache;
821 ent = GLOBAL_METHOD_CACHE(klass, id);
822 if (ent->method_state == GET_GLOBAL_METHOD_STATE() &&
823 ent->class_serial == RCLASS_SERIAL(klass) &&
824 ent->mid == id) {
825 verify_method_cache(klass, id, ent->defined_class, ent->me);
826 if (defined_class_ptr) *defined_class_ptr = ent->defined_class;
827 RB_DEBUG_COUNTER_INC(mc_global_hit);
828 return ent->me;
829 }
830
831 nocache:
832 RB_DEBUG_COUNTER_INC(mc_global_miss);
833 return method_entry_get_without_cache(klass, id, defined_class_ptr);
834 }
835
836 MJIT_FUNC_EXPORTED const rb_method_entry_t *
837 rb_method_entry(VALUE klass, ID id)
838 {
839 return method_entry_get(klass, id, NULL);
840 }
841
842 static const rb_callable_method_entry_t *
843 prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_t *me)
844 {
845 struct rb_id_table *mtbl;
846 const rb_callable_method_entry_t *cme;
847
848 if (me && me->defined_class == 0) {
849 RB_DEBUG_COUNTER_INC(mc_cme_complement);
850 VM_ASSERT(RB_TYPE_P(defined_class, T_ICLASS) || RB_TYPE_P(defined_class, T_MODULE));
851 VM_ASSERT(me->defined_class == 0);
852
853 mtbl = RCLASS_CALLABLE_M_TBL(defined_class);
854
855 if (mtbl && rb_id_table_lookup(mtbl, id, (VALUE *)&me)) {
856 RB_DEBUG_COUNTER_INC(mc_cme_complement_hit);
857 cme = (rb_callable_method_entry_t *)me;
858 VM_ASSERT(callable_method_entry_p(cme));
859 }
860 else {
861 if (!mtbl) {
862 mtbl = RCLASS_EXT(defined_class)->callable_m_tbl = rb_id_table_create(0);
863 }
864 cme = rb_method_entry_complement_defined_class(me, me->called_id, defined_class);
865 rb_id_table_insert(mtbl, id, (VALUE)cme);
866 VM_ASSERT(callable_method_entry_p(cme));
867 }
868 }
869 else {
870 cme = (const rb_callable_method_entry_t *)me;
871 VM_ASSERT(callable_method_entry_p(cme));
872 }
873
874 return cme;
875 }
876
877 MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
878 rb_callable_method_entry(VALUE klass, ID id)
879 {
880 VALUE defined_class;
881 rb_method_entry_t *me = method_entry_get(klass, id, &defined_class);
882 return prepare_callable_method_entry(defined_class, id, me);
883 }
884
885 static const rb_method_entry_t *resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *defined_class_ptr);
886
887 static const rb_method_entry_t *
888 method_entry_resolve_refinement(VALUE klass, ID id, int with_refinement, VALUE *defined_class_ptr)
889 {
890 const rb_method_entry_t *me = method_entry_get(klass, id, defined_class_ptr);
891
892 if (me) {
893 if (me->def->type == VM_METHOD_TYPE_REFINED) {
894 if (with_refinement) {
895 const rb_cref_t *cref = rb_vm_cref();
896 VALUE refinements = cref ? CREF_REFINEMENTS(cref) : Qnil;
897 me = resolve_refined_method(refinements, me, defined_class_ptr);
898 }
899 else {
900 me = resolve_refined_method(Qnil, me, defined_class_ptr);
901 }
902
903 if (UNDEFINED_METHOD_ENTRY_P(me)) me = NULL;
904 }
905 }
906
907 return me;
908 }
909
910 const rb_method_entry_t *
911 rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
912 {
913 return method_entry_resolve_refinement(klass, id, TRUE, defined_class_ptr);
914 }
915
916 MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
917 rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
918 {
919 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
920 const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, TRUE, dcp);
921 return prepare_callable_method_entry(*dcp, id, me);
922 }
923
924 const rb_method_entry_t *
925 rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
926 {
927 return method_entry_resolve_refinement(klass, id, FALSE, defined_class_ptr);
928 }
929
930 MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
931 rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
932 {
933 VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
934 const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, FALSE, dcp);
935 return prepare_callable_method_entry(*dcp, id, me);
936 }
937
938 static const rb_method_entry_t *
939 resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *defined_class_ptr)
940 {
941 while (me && me->def->type == VM_METHOD_TYPE_REFINED) {
942 VALUE refinement;
943 const rb_method_entry_t *tmp_me;
944 VALUE super;
945
946 refinement = find_refinement(refinements, me->owner);
947 if (!NIL_P(refinement)) {
948 tmp_me = method_entry_get(refinement, me->called_id, defined_class_ptr);
949
950 if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
951 return tmp_me;
952 }
953 }
954
955 tmp_me = me->def->body.refined.orig_me;
956 if (tmp_me) {
957 if (defined_class_ptr) *defined_class_ptr = tmp_me->defined_class;
958 return tmp_me;
959 }
960
961 super = RCLASS_SUPER(me->owner);
962 if (!super) {
963 return 0;
964 }
965
966 me = method_entry_get(super, me->called_id, defined_class_ptr);
967 }
968 return me;
969 }
970
971 const rb_method_entry_t *
972 rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me)
973 {
974 return resolve_refined_method(refinements, me, NULL);
975 }
976
977 MJIT_FUNC_EXPORTED
978 const rb_callable_method_entry_t *
979 rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me)
980 {
981 VALUE defined_class = me->defined_class;
982 const rb_method_entry_t *resolved_me = resolve_refined_method(refinements, (const rb_method_entry_t *)me, &defined_class);
983
984 if (resolved_me && resolved_me->defined_class == 0) {
985 return rb_method_entry_complement_defined_class(resolved_me, me->called_id, defined_class);
986 }
987 else {
988 return (const rb_callable_method_entry_t *)resolved_me;
989 }
990 }
991
992 static void
993 remove_method(VALUE klass, ID mid)
994 {
995 VALUE data;
996 rb_method_entry_t *me = 0;
997 VALUE self = klass;
998
999 klass = RCLASS_ORIGIN(klass);
1000 rb_class_modify_check(klass);
1001 if (mid == object_id || mid == id__send__ || mid == idInitialize) {
1002 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
1003 }
1004
1005 if (!rb_id_table_lookup(RCLASS_M_TBL(klass), mid, &data) ||
1006 !(me = (rb_method_entry_t *)data) ||
1007 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) ||
1008 UNDEFINED_REFINED_METHOD_P(me->def)) {
1009 rb_name_err_raise("method `%1$s' not defined in %2$s",
1010 klass, ID2SYM(mid));
1011 }
1012
1013 rb_id_table_delete(RCLASS_M_TBL(klass), mid);
1014
1015 rb_vm_check_redefinition_opt_method(me, klass);
1016 rb_clear_method_cache_by_class(klass);
1017
1018 if (me->def->type == VM_METHOD_TYPE_REFINED) {
1019 rb_add_refined_method_entry(klass, mid);
1020 }
1021
1022 CALL_METHOD_HOOK(self, removed, mid);
1023 }
1024
1025 void
1026 rb_remove_method_id(VALUE klass, ID mid)
1027 {
1028 remove_method(klass, mid);
1029 }
1030
1031 void
1032 rb_remove_method(VALUE klass, const char *name)
1033 {
1034 remove_method(klass, rb_intern(name));
1035 }
1036
1037 /*
1038 * call-seq:
1039 * remove_method(symbol) -> self
1040 * remove_method(string) -> self
1041 *
1042 * Removes the method identified by _symbol_ from the current
1043 * class. For an example, see Module#undef_method.
1044 * String arguments are converted to symbols.
1045 */
1046
1047 static VALUE
1048 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
1049 {
1050 int i;
1051
1052 for (i = 0; i < argc; i++) {
1053 VALUE v = argv[i];
1054 ID id = rb_check_id(&v);
1055 if (!id) {
1056 rb_name_err_raise("method `%1$s' not defined in %2$s",
1057 mod, v);
1058 }
1059 remove_method(mod, id);
1060 }
1061 return mod;
1062 }
1063
1064 static void
1065 rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi)
1066 {
1067 rb_method_entry_t *me;
1068 VALUE defined_class;
1069 VALUE origin_class = RCLASS_ORIGIN(klass);
1070
1071 me = search_method(origin_class, name, &defined_class);
1072 if (!me && RB_TYPE_P(klass, T_MODULE)) {
1073 me = search_method(rb_cObject, name, &defined_class);
1074 }
1075
1076 if (UNDEFINED_METHOD_ENTRY_P(me) ||
1077 UNDEFINED_REFINED_METHOD_P(me->def)) {
1078 rb_print_undef(klass, name, METHOD_VISI_UNDEF);
1079 }
1080
1081 if (METHOD_ENTRY_VISI(me) != visi) {
1082 rb_vm_check_redefinition_opt_method(me, klass);
1083
1084 if (klass == defined_class || origin_class == defined_class) {
1085 METHOD_ENTRY_VISI_SET(me, visi);
1086
1087 if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) {
1088 METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi);
1089 }
1090 rb_clear_method_cache_by_class(klass);
1091 }
1092 else {
1093 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, visi);
1094 }
1095 }
1096 }
1097
1098 #define BOUND_PRIVATE 0x01
1099 #define BOUND_RESPONDS 0x02
1100
1101 int
1102 rb_method_boundp(VALUE klass, ID id, int ex)
1103 {
1104 const rb_method_entry_t *me;
1105
1106 if (ex & BOUND_RESPONDS) {
1107 me = method_entry_resolve_refinement(klass, id, TRUE, NULL);
1108 }
1109 else {
1110 me = rb_method_entry_without_refinements(klass, id, NULL);
1111 }
1112
1113 if (me != 0) {
1114 if ((ex & ~BOUND_RESPONDS) &&
1115 ((METHOD_ENTRY_VISI(me) == METHOD_VISI_PRIVATE) ||
1116 ((ex & BOUND_RESPONDS) && (METHOD_ENTRY_VISI(me) == METHOD_VISI_PROTECTED)))) {
1117 return 0;
1118 }
1119
1120 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
1121 if (ex & BOUND_RESPONDS) return 2;
1122 return 0;
1123 }
1124 return 1;
1125 }
1126 return 0;
1127 }
1128
1129 static void
1130 vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func)
1131 {
1132 rb_scope_visibility_t *scope_visi = (rb_scope_visibility_t *)&rb_vm_cref()->scope_visi;
1133 scope_visi->method_visi = method_visi;
1134 scope_visi->module_func = module_func;
1135 }
1136
1137 void
1138 rb_scope_visibility_set(rb_method_visibility_t visi)
1139 {
1140 vm_cref_set_visibility(visi, FALSE);
1141 }
1142
1143 static void
1144 scope_visibility_check(void)
1145 {
1146 /* Check for public/protected/private/module_function called inside a method */
1147 rb_control_frame_t *cfp = rb_current_execution_context()->cfp+1;
1148 if (cfp && cfp->iseq && cfp->iseq->body->type == ISEQ_TYPE_METHOD) {
1149 rb_warn("calling %s without arguments inside a method may not have the intended effect",
1150 rb_id2name(rb_frame_this_func()));
1151 }
1152 }
1153
1154 static void
1155 rb_scope_module_func_set(void)
1156 {
1157 scope_visibility_check();
1158 vm_cref_set_visibility(METHOD_VISI_PRIVATE, TRUE);
1159 }
1160
1161 const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
1162 void
1163 rb_attr(VALUE klass, ID id, int read, int write, int ex)
1164 {
1165 ID attriv;
1166 rb_method_visibility_t visi;
1167 const rb_execution_context_t *ec = GET_EC();
1168 const rb_cref_t *cref = rb_vm_cref_in_context(klass, klass);
1169
1170 if (!ex || !cref) {
1171 visi = METHOD_VISI_PUBLIC;
1172 }
1173 else {
1174 switch (vm_scope_visibility_get(ec)) {
1175 case METHOD_VISI_PRIVATE:
1176 if (vm_scope_module_func_check(ec)) {
1177 rb_warning("attribute accessor as module_function");
1178 }
1179 visi = METHOD_VISI_PRIVATE;
1180 break;
1181 case METHOD_VISI_PROTECTED:
1182 visi = METHOD_VISI_PROTECTED;
1183 break;
1184 default:
1185 visi = METHOD_VISI_PUBLIC;
1186 break;
1187 }
1188 }
1189
1190 attriv = rb_intern_str(rb_sprintf("@%"PRIsVALUE, rb_id2str(id)));
1191 if (read) {
1192 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, visi);
1193 }
1194 if (write) {
1195 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, visi);
1196 }
1197 }
1198
1199 void
1200 rb_undef(VALUE klass, ID id)
1201 {
1202 const rb_method_entry_t *me;
1203
1204 if (NIL_P(klass)) {
1205 rb_raise(rb_eTypeError, "no class to undef method");
1206 }
1207 rb_class_modify_check(klass);
1208 if (id == object_id || id == id__send__ || id == idInitialize) {
1209 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
1210 }
1211
1212 me = search_method(klass, id, 0);
1213 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
1214 me = rb_resolve_refined_method(Qnil, me);
1215 }
1216
1217 if (UNDEFINED_METHOD_ENTRY_P(me) ||
1218 UNDEFINED_REFINED_METHOD_P(me->def)) {
1219 rb_method_name_error(klass, rb_id2str(id));
1220 }
1221
1222 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, METHOD_VISI_PUBLIC);
1223
1224 CALL_METHOD_HOOK(klass, undefined, id);
1225 }
1226
1227 /*
1228 * call-seq:
1229 * undef_method(symbol) -> self
1230 * undef_method(string) -> self
1231 *
1232 * Prevents the current class from responding to calls to the named
1233 * method. Contrast this with <code>remove_method</code>, which deletes
1234 * the method from the particular class; Ruby will still search
1235 * superclasses and mixed-in modules for a possible receiver.
1236 * String arguments are converted to symbols.
1237 *
1238 * class Parent
1239 * def hello
1240 * puts "In parent"
1241 * end
1242 * end
1243 * class Child < Parent
1244 * def hello
1245 * puts "In child"
1246 * end
1247 * end
1248 *
1249 *
1250 * c = Child.new
1251 * c.hello
1252 *
1253 *
1254 * class Child
1255 * remove_method :hello # remove from child, still in parent
1256 * end
1257 * c.hello
1258 *
1259 *
1260 * class Child
1261 * undef_method :hello # prevent any calls to 'hello'
1262 * end
1263 * c.hello
1264 *
1265 * <em>produces:</em>
1266 *
1267 * In child
1268 * In parent
1269 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
1270 */
1271
1272 static VALUE
1273 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
1274 {
1275 int i;
1276 for (i = 0; i < argc; i++) {
1277 VALUE v = argv[i];
1278 ID id = rb_check_id(&v);
1279 if (!id) {
1280 rb_method_name_error(mod, v);
1281 }
1282 rb_undef(mod, id);
1283 }
1284 return mod;
1285 }
1286
1287 static rb_method_visibility_t
1288 check_definition_visibility(VALUE mod, int argc, VALUE *argv)
1289 {
1290 const rb_method_entry_t *me;
1291 VALUE mid, include_super, lookup_mod = mod;
1292 int inc_super;
1293 ID id;
1294
1295 rb_scan_args(argc, argv, "11", &mid, &include_super);
1296 id = rb_check_id(&mid);
1297 if (!id) return METHOD_VISI_UNDEF;
1298
1299 if (argc == 1) {
1300 inc_super = 1;
1301 }
1302 else {
1303 inc_super = RTEST(include_super);
1304 if (!inc_super) {
1305 lookup_mod = RCLASS_ORIGIN(mod);
1306 }
1307 }
1308
1309 me = rb_method_entry_without_refinements(lookup_mod, id, NULL);
1310 if (me) {
1311 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) return METHOD_VISI_UNDEF;
1312 if (!inc_super && me->owner != mod) return METHOD_VISI_UNDEF;
1313 return METHOD_ENTRY_VISI(me);
1314 }
1315 return METHOD_VISI_UNDEF;
1316 }
1317
1318 /*
1319 * call-seq:
1320 * mod.method_defined?(symbol, inherit=true) -> true or false
1321 * mod.method_defined?(string, inherit=true) -> true or false
1322 *
1323 * Returns +true+ if the named method is defined by
1324 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1325 * ancestors. Public and protected methods are matched.
1326 * String arguments are converted to symbols.
1327 *
1328 * module A
1329 * def method1() end
1330 * def protected_method1() end
1331 * protected :protected_method1
1332 * end
1333 * class B
1334 * def method2() end
1335 * def private_method2() end
1336 * private :private_method2
1337 * end
1338 * class C < B
1339 * include A
1340 * def method3() end
1341 * end
1342 *
1343 * A.method_defined? :method1 #=> true
1344 * C.method_defined? "method1" #=> true
1345 * C.method_defined? "method2" #=> true
1346 * C.method_defined? "method2", true #=> true
1347 * C.method_defined? "method2", false #=> false
1348 * C.method_defined? "method3" #=> true
1349 * C.method_defined? "protected_method1" #=> true
1350 * C.method_defined? "method4" #=> false
1351 * C.method_defined? "private_method2" #=> false
1352 */
1353
1354 static VALUE
1355 rb_mod_method_defined(int argc, VALUE *argv, VALUE mod)
1356 {
1357 rb_method_visibility_t visi = check_definition_visibility(mod, argc, argv);
1358 return (visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED) ? Qtrue : Qfalse;
1359 }
1360
1361 static VALUE
1362 check_definition(VALUE mod, int argc, VALUE *argv, rb_method_visibility_t visi)
1363 {
1364 return (check_definition_visibility(mod, argc, argv) == visi) ? Qtrue : Qfalse;
1365 }
1366
1367 /*
1368 * call-seq:
1369 * mod.public_method_defined?(symbol, inherit=true) -> true or false
1370 * mod.public_method_defined?(string, inherit=true) -> true or false
1371 *
1372 * Returns +true+ if the named public method is defined by
1373 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1374 * ancestors.
1375 * String arguments are converted to symbols.
1376 *
1377 * module A
1378 * def method1() end
1379 * end
1380 * class B
1381 * protected
1382 * def method2() end
1383 * end
1384 * class C < B
1385 * include A
1386 * def method3() end
1387 * end
1388 *
1389 * A.method_defined? :method1 #=> true
1390 * C.public_method_defined? "method1" #=> true
1391 * C.public_method_defined? "method1", true #=> true
1392 * C.public_method_defined? "method1", false #=> true
1393 * C.public_method_defined? "method2" #=> false
1394 * C.method_defined? "method2" #=> true
1395 */
1396
1397 static VALUE
1398 rb_mod_public_method_defined(int argc, VALUE *argv, VALUE mod)
1399 {
1400 return check_definition(mod, argc, argv, METHOD_VISI_PUBLIC);
1401 }
1402
1403 /*
1404 * call-seq:
1405 * mod.private_method_defined?(symbol, inherit=true) -> true or false
1406 * mod.private_method_defined?(string, inherit=true) -> true or false
1407 *
1408 * Returns +true+ if the named private method is defined by
1409 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1410 * ancestors.
1411 * String arguments are converted to symbols.
1412 *
1413 * module A
1414 * def method1() end
1415 * end
1416 * class B
1417 * private
1418 * def method2() end
1419 * end
1420 * class C < B
1421 * include A
1422 * def method3() end
1423 * end
1424 *
1425 * A.method_defined? :method1 #=> true
1426 * C.private_method_defined? "method1" #=> false
1427 * C.private_method_defined? "method2" #=> true
1428 * C.private_method_defined? "method2", true #=> true
1429 * C.private_method_defined? "method2", false #=> false
1430 * C.method_defined? "method2" #=> false
1431 */
1432
1433 static VALUE
1434 rb_mod_private_method_defined(int argc, VALUE *argv, VALUE mod)
1435 {
1436 return check_definition(mod, argc, argv, METHOD_VISI_PRIVATE);
1437 }
1438
1439 /*
1440 * call-seq:
1441 * mod.protected_method_defined?(symbol, inherit=true) -> true or false
1442 * mod.protected_method_defined?(string, inherit=true) -> true or false
1443 *
1444 * Returns +true+ if the named protected method is defined
1445 * _mod_. If _inherit_ is set, the lookup will also search _mod_'s
1446 * ancestors.
1447 * String arguments are converted to symbols.
1448 *
1449 * module A
1450 * def method1() end
1451 * end
1452 * class B
1453 * protected
1454 * def method2() end
1455 * end
1456 * class C < B
1457 * include A
1458 * def method3() end
1459 * end
1460 *
1461 * A.method_defined? :method1 #=> true
1462 * C.protected_method_defined? "method1" #=> false
1463 * C.protected_method_defined? "method2" #=> true
1464 * C.protected_method_defined? "method2", true #=> true
1465 * C.protected_method_defined? "method2", false #=> false
1466 * C.method_defined? "method2" #=> true
1467 */
1468
1469 static VALUE
1470 rb_mod_protected_method_defined(int argc, VALUE *argv, VALUE mod)
1471 {
1472 return check_definition(mod, argc, argv, METHOD_VISI_PROTECTED);
1473 }
1474
1475 int
1476 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
1477 {
1478 return rb_method_definition_eq(m1->def, m2->def);
1479 }
1480
1481 static const rb_method_definition_t *
1482 original_method_definition(const rb_method_definition_t *def)
1483 {
1484 again:
1485 if (def) {
1486 switch (def->type) {
1487 case VM_METHOD_TYPE_REFINED:
1488 if (def->body.refined.orig_me) {
1489 def = def->body.refined.orig_me->def;
1490 goto again;
1491 }
1492 break;
1493 case VM_METHOD_TYPE_ALIAS:
1494 def = def->body.alias.original_me->def;
1495 goto again;
1496 default:
1497 break;
1498 }
1499 }
1500 return def;
1501 }
1502
1503 MJIT_FUNC_EXPORTED int
1504 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
1505 {
1506 d1 = original_method_definition(d1);
1507 d2 = original_method_definition(d2);
1508
1509 if (d1 == d2) return 1;
1510 if (!d1 || !d2) return 0;
1511 if (d1->type != d2->type) return 0;
1512
1513 switch (d1->type) {
1514 case VM_METHOD_TYPE_ISEQ:
1515 return d1->body.iseq.iseqptr == d2->body.iseq.iseqptr;
1516 case VM_METHOD_TYPE_CFUNC:
1517 return
1518 d1->body.cfunc.func == d2->body.cfunc.func &&
1519 d1->body.cfunc.argc == d2->body.cfunc.argc;
1520 case VM_METHOD_TYPE_ATTRSET:
1521 case VM_METHOD_TYPE_IVAR:
1522 return d1->body.attr.id == d2->body.attr.id;
1523 case VM_METHOD_TYPE_BMETHOD:
1524 return RTEST(rb_equal(d1->body.bmethod.proc, d2->body.bmethod.proc));
1525 case VM_METHOD_TYPE_MISSING:
1526 return d1->original_id == d2->original_id;
1527 case VM_METHOD_TYPE_ZSUPER:
1528 case VM_METHOD_TYPE_NOTIMPLEMENTED:
1529 case VM_METHOD_TYPE_UNDEF:
1530 return 1;
1531 case VM_METHOD_TYPE_OPTIMIZED:
1532 return d1->body.optimize_type == d2->body.optimize_type;
1533 case VM_METHOD_TYPE_REFINED:
1534 case VM_METHOD_TYPE_ALIAS:
1535 break;
1536 }
1537 rb_bug("rb_method_definition_eq: unsupported type: %d\n", d1->type);
1538 }
1539
1540 static st_index_t
1541 rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
1542 {
1543 hash = rb_hash_uint(hash, def->type);
1544 def = original_method_definition(def);
1545
1546 if (!def) return hash;
1547
1548 switch (def->type) {
1549 case VM_METHOD_TYPE_ISEQ:
1550 return rb_hash_uint(hash, (st_index_t)def->body.iseq.iseqptr);
1551 case VM_METHOD_TYPE_CFUNC:
1552 hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
1553 return rb_hash_uint(hash, def->body.cfunc.argc);
1554 case VM_METHOD_TYPE_ATTRSET:
1555 case VM_METHOD_TYPE_IVAR:
1556 return rb_hash_uint(hash, def->body.attr.id);
1557 case VM_METHOD_TYPE_BMETHOD:
1558 return rb_hash_proc(hash, def->body.bmethod.proc);
1559 case VM_METHOD_TYPE_MISSING:
1560 return rb_hash_uint(hash, def->original_id);
1561 case VM_METHOD_TYPE_ZSUPER:
1562 case VM_METHOD_TYPE_NOTIMPLEMENTED:
1563 case VM_METHOD_TYPE_UNDEF:
1564 return hash;
1565 case VM_METHOD_TYPE_OPTIMIZED:
1566 return rb_hash_uint(hash, def->body.optimize_type);
1567 case VM_METHOD_TYPE_REFINED:
1568 case VM_METHOD_TYPE_ALIAS:
1569 break; /* unreachable */
1570 }
1571 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type);
1572 }
1573
1574 st_index_t
1575 rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
1576 {
1577 return rb_hash_method_definition(hash, me->def);
1578 }
1579
1580 void
1581 rb_alias(VALUE klass, ID alias_name, ID original_name)
1582 {
1583 const VALUE target_klass = klass;
1584 VALUE defined_class;
1585 const rb_method_entry_t *orig_me;
1586 rb_method_visibility_t visi = METHOD_VISI_UNDEF;
1587
1588 if (NIL_P(klass)) {
1589 rb_raise(rb_eTypeError, "no class to make alias");
1590 }
1591
1592 rb_class_modify_check(klass);
1593
1594 again:
1595 orig_me = search_method(klass, original_name, &defined_class);
1596 if (orig_me && orig_me->def->type == VM_METHOD_TYPE_REFINED) {
1597 orig_me = rb_resolve_refined_method(Qnil, orig_me);
1598 }
1599
1600 if (UNDEFINED_METHOD_ENTRY_P(orig_me) ||
1601 UNDEFINED_REFINED_METHOD_P(orig_me->def)) {
1602 if ((!RB_TYPE_P(klass, T_MODULE)) ||
1603 (orig_me = search_method(rb_cObject, original_name, &defined_class),
1604 UNDEFINED_METHOD_ENTRY_P(orig_me))) {
1605 rb_print_undef(klass, original_name, METHOD_VISI_UNDEF);
1606 }
1607 }
1608
1609 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
1610 klass = RCLASS_SUPER(klass);
1611 original_name = orig_me->def->original_id;
1612 visi = METHOD_ENTRY_VISI(orig_me);
1613 goto again;
1614 }
1615
1616 if (visi == METHOD_VISI_UNDEF) visi = METHOD_ENTRY_VISI(orig_me);
1617
1618 if (orig_me->defined_class == 0) {
1619 rb_method_entry_make(target_klass, alias_name, target_klass, visi,
1620 VM_METHOD_TYPE_ALIAS, NULL, orig_me->called_id,
1621 (void *)rb_method_entry_clone(orig_me));
1622 method_added(target_klass, alias_name);
1623 }
1624 else {
1625 rb_method_entry_t *alias_me;
1626
1627 alias_me = method_entry_set(target_klass, alias_name, orig_me, visi, orig_me->owner);
1628 RB_OBJ_WRITE(alias_me, &alias_me->owner, target_klass);
1629 RB_OBJ_WRITE(alias_me, &alias_me->defined_class, defined_class);
1630 }
1631 }
1632
1633 /*
1634 * call-seq:
1635 * alias_method(new_name, old_name) -> self
1636 *
1637 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
1638 * be used to retain access to methods that are overridden.
1639 *
1640 * module Mod
1641 * alias_method :orig_exit, :exit
1642 * def exit(code=0)
1643 * puts "Exiting with code #{code}"
1644 * orig_exit(code)
1645 * end
1646 * end
1647 * include Mod
1648 * exit(99)
1649 *
1650 * <em>produces:</em>
1651 *
1652 * Exiting with code 99
1653 */
1654
1655 static VALUE
1656 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
1657 {
1658 ID oldid = rb_check_id(&oldname);
1659 if (!oldid) {
1660 rb_print_undef_str(mod, oldname);
1661 }
1662 rb_alias(mod, rb_to_id(newname), oldid);
1663 return mod;
1664 }
1665
1666 static void
1667 set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibility_t visi)
1668 {
1669 int i;
1670
1671 rb_check_frozen(self);
1672 if (argc == 0) {
1673 rb_warning("%"PRIsVALUE" with no argument is just ignored",
1674 QUOTE_ID(rb_frame_callee()));
1675 return;
1676 }
1677
1678 for (i = 0; i < argc; i++) {
1679 VALUE v = argv[i];
1680 ID id = rb_check_id(&v);
1681 if (!id) {
1682 rb_print_undef_str(self, v);
1683 }
1684 rb_export_method(self, id, visi);
1685 }
1686 }
1687
1688 static VALUE
1689 set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_visibility_t visi)
1690 {
1691 if (argc == 0) {
1692 scope_visibility_check();
1693 rb_scope_visibility_set(visi);
1694 }
1695 else {
1696 set_method_visibility(module, argc, argv, visi);
1697 }
1698 return module;
1699 }
1700
1701 /*
1702 * call-seq:
1703 * public -> self
1704 * public(symbol, ...) -> self
1705 * public(string, ...) -> self
1706 *
1707 * With no arguments, sets the default visibility for subsequently
1708 * defined methods to public. With arguments, sets the named methods to
1709 * have public visibility.
1710 * String arguments are converted to symbols.
1711 */
1712
1713 static VALUE
1714 rb_mod_public(int argc, VALUE *argv, VALUE module)
1715 {
1716 return set_visibility(argc, argv, module, METHOD_VISI_PUBLIC);
1717 }
1718
1719 /*
1720 * call-seq:
1721 * protected -> self
1722 * protected(symbol, ...) -> self
1723 * protected(string, ...) -> self
1724 *
1725 * With no arguments, sets the default visibility for subsequently
1726 * defined methods to protected. With arguments, sets the named methods
1727 * to have protected visibility.
1728 * String arguments are converted to symbols.
1729 *
1730 * If a method has protected visibility, it is callable only where
1731 * <code>self</code> of the context is the same as the method.
1732 * (method definition or instance_eval). This behavior is different from
1733 * Java's protected method. Usually <code>private</code> should be used.
1734 *
1735 * Note that a protected method is slow because it can't use inline cache.
1736 *
1737 * To show a private method on RDoc, use <code>:doc:</code> instead of this.
1738 */
1739
1740 static VALUE
1741 rb_mod_protected(int argc, VALUE *argv, VALUE module)
1742 {
1743 return set_visibility(argc, argv, module, METHOD_VISI_PROTECTED);
1744 }
1745
1746 /*
1747 * call-seq:
1748 * private -> self
1749 * private(symbol, ...) -> self
1750 * private(string, ...) -> self
1751 *
1752 * With no arguments, sets the default visibility for subsequently
1753 * defined methods to private. With arguments, sets the named methods
1754 * to have private visibility.
1755 * String arguments are converted to symbols.
1756 *
1757 * module Mod
1758 * def a() end
1759 * def b() end
1760 * private
1761 * def c() end
1762 * private :a
1763 * end
1764 * Mod.private_instance_methods #=> [:a, :c]
1765 *
1766 * Note that to show a private method on RDoc, use <code>:doc:</code>.
1767 */
1768
1769 static VALUE
1770 rb_mod_private(int argc, VALUE *argv, VALUE module)
1771 {
1772 return set_visibility(argc, argv, module, METHOD_VISI_PRIVATE);
1773 }
1774
1775 /*
1776 * call-seq:
1777 * ruby2_keywords(method_name, ...) -> self
1778 *
1779 * For the given method names, marks the method as passing keywords through
1780 * a normal argument splat. This should only be called on methods that
1781 * accept an argument splat (<tt>*args</tt>) but not explicit keywords or
1782 * a keyword splat. It marks the method such that if the method is called
1783 * with keyword arguments, the final hash argument is marked with a special
1784 * flag such that if it is the final element of a normal argument splat to
1785 * another method call, and that method call does not include explicit
1786 * keywords or a keyword splat, the final element is interpreted as keywords.
1787 * In other words, keywords will be passed through the method to other
1788 * methods.
1789 *
1790 * This should only be used for methods that delegate keywords to another
1791 * method, and only for backwards compatibility with Ruby versions before
1792 * 2.7.
1793 *
1794 * This method will probably be removed at some point, as it exists only
1795 * for backwards compatibility. As it does not exist in Ruby versions
1796 * before 2.7, check that the module responds to this method before calling
1797 * it. Also, be aware that if this method is removed, the behavior of the
1798 * method will change so that it does not pass through keywords.
1799 *
1800 * module Mod
1801 * def foo(meth, *args, &block)
1802 * send(:"do_#{meth}", *args, &block)
1803 * end
1804 * ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true)
1805 * end
1806 */
1807
1808 static VALUE
1809 rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module)
1810 {
1811 int i;
1812 VALUE origin_class = RCLASS_ORIGIN(module);
1813
1814 rb_check_frozen(module);
1815
1816 for (i = 0; i < argc; i++) {
1817 VALUE v = argv[i];
1818 ID name = rb_check_id(&v);
1819 rb_method_entry_t *me;
1820 VALUE defined_class;
1821
1822 if (!name) {
1823 rb_print_undef_str(module, v);
1824 }
1825
1826 me = search_method(origin_class, name, &defined_class);
1827 if (!me && RB_TYPE_P(module, T_MODULE)) {
1828 me = search_method(rb_cObject, name, &defined_class);
1829 }
1830
1831 if (UNDEFINED_METHOD_ENTRY_P(me) ||
1832 UNDEFINED_REFINED_METHOD_P(me->def)) {
1833 rb_print_undef(module, name, METHOD_VISI_UNDEF);
1834 }
1835
1836 if (module == defined_class || origin_class == defined_class) {
1837 switch (me->def->type) {
1838 case VM_METHOD_TYPE_ISEQ:
1839 if (me->def->body.iseq.iseqptr->body->param.flags.has_rest &&
1840 !me->def->body.iseq.iseqptr->body->param.flags.has_kw &&
1841 !me->def->body.iseq.iseqptr->body->param.flags.has_kwrest) {
1842 me->def->body.iseq.iseqptr->body->param.flags.ruby2_keywords = 1;
1843 rb_clear_method_cache_by_class(module);
1844 }
1845 else {
1846 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name));
1847 }
1848 break;
1849 case VM_METHOD_TYPE_BMETHOD: {
1850 VALUE procval = me->def->body.bmethod.proc;
1851 if (vm_block_handler_type(procval) == block_handler_type_proc) {
1852 procval = vm_proc_to_block_handler(VM_BH_TO_PROC(procval));
1853 }
1854
1855 if (vm_block_handler_type(procval) == block_handler_type_iseq) {
1856 const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(procval);
1857 const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
1858 if (iseq->body->param.flags.has_rest &&
1859 !iseq->body->param.flags.has_kw &&
1860 !iseq->body->param.flags.has_kwrest) {
1861 iseq->body->param.flags.ruby2_keywords = 1;
1862 rb_clear_method_cache_by_class(module);
1863 }
1864 else {
1865 rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name));
1866 }
1867 return Qnil;
1868 }
1869 }
1870 /* fallthrough */
1871 default:
1872 rb_warn("Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)", rb_id2name(name));
1873 break;
1874 }
1875 }
1876 else {
1877 rb_warn("Skipping set of ruby2_keywords flag for %s (can only set in method defining module)", rb_id2name(name));
1878 }
1879 }
1880 return Qnil;
1881 }
1882
1883 /*
1884 * call-seq:
1885 * mod.public_class_method(symbol, ...) -> mod
1886 * mod.public_class_method(string, ...) -> mod
1887 *
1888 * Makes a list of existing class methods public.
1889 *
1890 * String arguments are converted to symbols.
1891 */
1892
1893 static VALUE
1894 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
1895 {
1896 set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PUBLIC);
1897 return obj;
1898 }
1899
1900 /*
1901 * call-seq:
1902 * mod.private_class_method(symbol, ...) -> mod
1903 * mod.private_class_method(string, ...) -> mod
1904 *
1905 * Makes existing class methods private. Often used to hide the default
1906 * constructor <code>new</code>.
1907 *
1908 * String arguments are converted to symbols.
1909 *
1910 * class SimpleSingleton # Not thread safe
1911 * private_class_method :new
1912 * def SimpleSingleton.create(*args, &block)
1913 * @me = new(*args, &block) if ! @me
1914 * @me
1915 * end
1916 * end
1917 */
1918
1919 static VALUE
1920 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
1921 {
1922 set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PRIVATE);
1923 return obj;
1924 }
1925
1926 /*
1927 * call-seq:
1928 * public
1929 * public(symbol, ...)
1930 * public(string, ...)
1931 *
1932 * With no arguments, sets the default visibility for subsequently
1933 * defined methods to public. With arguments, sets the named methods to
1934 * have public visibility.
1935 *
1936 * String arguments are converted to symbols.
1937 */
1938
1939 static VALUE
1940 top_public(int argc, VALUE *argv, VALUE _)
1941 {
1942 return rb_mod_public(argc, argv, rb_cObject);
1943 }
1944
1945 /*
1946 * call-seq:
1947 * private
1948 * private(symbol, ...)
1949 * private(string, ...)
1950 *
1951 * With no arguments, sets the default visibility for subsequently
1952 * defined methods to private. With arguments, sets the named methods to
1953 * have private visibility.
1954 *
1955 * String arguments are converted to symbols.
1956 */
1957 static VALUE
1958 top_private(int argc, VALUE *argv, VALUE _)
1959 {
1960 return rb_mod_private(argc, argv, rb_cObject);
1961 }
1962
1963 /*
1964 * call-seq:
1965 * ruby2_keywords(method_name, ...) -> self
1966 *
1967 * For the given method names, marks the method as passing keywords through
1968 * a normal argument splat. See Module#ruby2_keywords in detail.
1969 */
1970 static VALUE
1971 top_ruby2_keywords(int argc, VALUE *argv, VALUE module)
1972 {
1973 return rb_mod_ruby2_keywords(argc, argv, rb_cObject);
1974 }
1975
1976 /*
1977 * call-seq:
1978 * module_function(symbol, ...) -> self
1979 * module_function(string, ...) -> self
1980 *
1981 * Creates module functions for the named methods. These functions may
1982 * be called with the module as a receiver, and also become available
1983 * as instance methods to classes that mix in the module. Module
1984 * functions are copies of the original, and so may be changed
1985 * independently. The instance-method versions are made private. If
1986 * used with no arguments, subsequently defined methods become module
1987 * functions.
1988 * String arguments are converted to symbols.
1989 *
1990 * module Mod
1991 * def one
1992 * "This is one"
1993 * end
1994 * module_function :one
1995 * end
1996 * class Cls
1997 * include Mod
1998 * def call_one
1999 * one
2000 * end
2001 * end
2002 * Mod.one #=> "This is one"
2003 * c = Cls.new
2004 * c.call_one #=> "This is one"
2005 * module Mod
2006 * def one
2007 * "This is the new one"
2008 * end
2009 * end
2010 * Mod.one #=> "This is one"
2011 * c.call_one #=> "This is the new one"
2012 */
2013
2014 static VALUE
2015 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
2016 {
2017 int i;
2018 ID id;
2019 const rb_method_entry_t *me;
2020
2021 if (!RB_TYPE_P(module, T_MODULE)) {
2022 rb_raise(rb_eTypeError, "module_function must be called for modules");
2023 }
2024
2025 if (argc == 0) {
2026 rb_scope_module_func_set();
2027 return module;
2028 }
2029
2030 set_method_visibility(module, argc, argv, METHOD_VISI_PRIVATE);
2031
2032 for (i = 0; i < argc; i++) {
2033 VALUE m = module;
2034
2035 id = rb_to_id(argv[i]);
2036 for (;;) {
2037 me = search_method(m, id, 0);
2038 if (me == 0) {
2039 me = search_method(rb_cObject, id, 0);
2040 }
2041 if (UNDEFINED_METHOD_ENTRY_P(me)) {
2042 rb_print_undef(module, id, METHOD_VISI_UNDEF);
2043 }
2044 if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
2045 break; /* normal case: need not to follow 'super' link */
2046 }
2047 m = RCLASS_SUPER(m);
2048 if (!m)
2049 break;
2050 }
2051 rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC);
2052 }
2053 return module;
2054 }
2055
2056 bool
2057 rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid)
2058 {
2059 if (cd->ci.mid != mid) {
2060 *cd = (struct rb_call_data) /* reset */ { .ci = { .mid = mid, }, };
2061 }
2062
2063 vm_search_method_fastpath(cd, klass);
2064 return cd->cc.me && METHOD_ENTRY_BASIC(cd->cc.me);
2065 }
2066
2067 #ifdef __GNUC__
2068 #pragma push_macro("rb_method_basic_definition_p")
2069 #undef rb_method_basic_definition_p
2070 #endif
2071 int
2072 rb_method_basic_definition_p(VALUE klass, ID id)
2073 {
2074 const rb_method_entry_t *me;
2075 if (!klass) return TRUE; /* hidden object cannot be overridden */
2076 me = rb_method_entry(klass, id);
2077 return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE;
2078 }
2079 #ifdef __GNUC__
2080 #pragma pop_macro("rb_method_basic_definition_p")
2081 #endif
2082
2083 static VALUE
2084 call_method_entry(rb_execution_context_t *ec, VALUE defined_class, VALUE obj, ID id,
2085 const rb_method_entry_t *me, int argc, const VALUE *argv, int kw_splat)
2086 {
2087 const rb_callable_method_entry_t *cme =
2088 prepare_callable_method_entry(defined_class, id, me);
2089 VALUE passed_block_handler = vm_passed_block_handler(ec);
2090 VALUE result = rb_vm_call_kw(ec, obj, id, argc, argv, cme, kw_splat);
2091 vm_passed_block_handler_set(ec, passed_block_handler);
2092 return result;
2093 }
2094
2095 static VALUE
2096 basic_obj_respond_to_missing(rb_execution_context_t *ec, VALUE klass, VALUE obj,
2097 VALUE mid, VALUE priv)
2098 {
2099 VALUE defined_class, args[2];
2100 const ID rtmid = idRespond_to_missing;
2101 const rb_method_entry_t *const me =
2102 method_entry_get(klass, rtmid, &defined_class);
2103
2104 if (!me || METHOD_ENTRY_BASIC(me)) return Qundef;
2105 args[0] = mid;
2106 args[1] = priv;
2107 return call_method_entry(ec, defined_class, obj, rtmid, me, 2, args, RB_NO_KEYWORDS);
2108 }
2109
2110 static inline int
2111 basic_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int pub)
2112 {
2113 VALUE klass = CLASS_OF(obj);
2114 VALUE ret;
2115
2116 switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
2117 case 2:
2118 return FALSE;
2119 case 0:
2120 ret = basic_obj_respond_to_missing(ec, klass, obj, ID2SYM(id),
2121 pub ? Qfalse : Qtrue);
2122 return RTEST(ret) && ret != Qundef;
2123 default:
2124 return TRUE;
2125 }
2126 }
2127
2128 static int
2129 vm_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int priv)
2130 {
2131 VALUE defined_class;
2132 const ID resid = idRespond_to;
2133 const rb_method_entry_t *const me =
2134 method_entry_get(klass, resid, &defined_class);
2135
2136 if (!me) return -1;
2137 if (METHOD_ENTRY_BASIC(me)) {
2138 return -1;
2139 }
2140 else {
2141 int argc = 1;
2142 VALUE args[2];
2143 VALUE result;
2144
2145 args[0] = ID2SYM(id);
2146 args[1] = Qtrue;
2147 if (priv) {
2148 argc = rb_method_entry_arity(me);
2149 if (argc > 2) {
2150 rb_raise(rb_eArgError,
2151 "respond_to? must accept 1 or 2 arguments (requires %d)",
2152 argc);
2153 }
2154 if (argc != 1) {
2155 argc = 2;
2156 }
2157 else if (!NIL_P(ruby_verbose)) {
2158 VALUE location = rb_method_entry_location(me);
2159 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") uses"
2160 " the deprecated method signature, which takes one parameter",
2161 (FL_TEST(klass, FL_SINGLETON) ? obj : klass),
2162 (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'),
2163 QUOTE_ID(id));
2164 if (!NIL_P(location)) {
2165 VALUE path = RARRAY_AREF(location, 0);
2166 VALUE line = RARRAY_AREF(location, 1);
2167 if (!NIL_P(path)) {
2168 rb_compile_warn(RSTRING_PTR(path), NUM2INT(line),
2169 "respond_to? is defined here");
2170 }
2171 }
2172 }
2173 }
2174 result = call_method_entry(ec, defined_class, obj, resid, me, argc, args, RB_NO_KEYWORDS);
2175 return RTEST(result);
2176 }
2177 }
2178
2179 int
2180 rb_obj_respond_to(VALUE obj, ID id, int priv)
2181 {
2182 rb_execution_context_t *ec = GET_EC();
2183 VALUE klass = CLASS_OF(obj);
2184 int ret = vm_respond_to(ec, klass, obj, id, priv);
2185 if (ret == -1) ret = basic_obj_respond_to(ec, obj, id, !priv);
2186 return ret;
2187 }
2188
2189 int
2190 rb_respond_to(VALUE obj, ID id)
2191 {
2192 return rb_obj_respond_to(obj, id, FALSE);
2193 }
2194
2195
2196 /*
2197 * call-seq:
2198 * obj.respond_to?(symbol, include_all=false) -> true or false
2199 * obj.respond_to?(string, include_all=false) -> true or false
2200 *
2201 * Returns +true+ if _obj_ responds to the given method. Private and
2202 * protected methods are included in the search only if the optional
2203 * second parameter evaluates to +true+.
2204 *
2205 * If the method is not implemented,
2206 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
2207 * false is returned.
2208 *
2209 * If the method is not defined, <code>respond_to_missing?</code>
2210 * method is called and the result is returned.
2211 *
2212 * When the method name parameter is given as a string, the string is
2213 * converted to a symbol.
2214 */
2215
2216 static VALUE
2217 obj_respond_to(int argc, VALUE *argv, VALUE obj)
2218 {
2219 VALUE mid, priv;
2220 ID id;
2221 rb_execution_context_t *ec = GET_EC();
2222
2223 rb_scan_args(argc, argv, "11", &mid, &priv);
2224 if (!(id = rb_check_id(&mid))) {
2225 VALUE ret = basic_obj_respond_to_missing(ec, CLASS_OF(obj), obj,
2226 rb_to_symbol(mid), priv);
2227 if (ret == Qundef) ret = Qfalse;
2228 return ret;
2229 }
2230 if (basic_obj_respond_to(ec, obj, id, !RTEST(priv)))
2231 return Qtrue;
2232 return Qfalse;
2233 }
2234
2235 /*
2236 * call-seq:
2237 * obj.respond_to_missing?(symbol, include_all) -> true or false
2238 * obj.respond_to_missing?(string, include_all) -> true or false
2239 *
2240 * DO NOT USE THIS DIRECTLY.
2241 *
2242 * Hook method to return whether the _obj_ can respond to _id_ method
2243 * or not.
2244 *
2245 * When the method name parameter is given as a string, the string is
2246 * converted to a symbol.
2247 *
2248 * See #respond_to?, and the example of BasicObject.
2249 */
2250 static VALUE
2251 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
2252 {
2253 return Qfalse;
2254 }
2255
2256 void
2257 Init_Method(void)
2258 {
2259 if (!OPT_GLOBAL_METHOD_CACHE) return;
2260 char *ptr = getenv("RUBY_GLOBAL_METHOD_CACHE_SIZE");
2261 int val;
2262
2263 if (ptr != NULL && (val = atoi(ptr)) > 0) {
2264 if ((val & (val - 1)) == 0) { /* ensure val is a power of 2 */
2265 global_method_cache.size = val;
2266 global_method_cache.mask = val - 1;
2267 }
2268 else {
2269 fprintf(stderr, "RUBY_GLOBAL_METHOD_CACHE_SIZE was set to %d but ignored because the value is not a power of 2.\n", val);
2270 }
2271 }
2272
2273 global_method_cache.entries = (struct cache_entry *)calloc(global_method_cache.size, sizeof(struct cache_entry));
2274 if (global_method_cache.entries == NULL) {
2275 fprintf(stderr, "[FATAL] failed to allocate memory\n");
2276 exit(EXIT_FAILURE);
2277 }
2278 }
2279
2280 void
2281 Init_eval_method(void)
2282 {
2283 #undef rb_intern
2284 #define rb_intern(str) rb_intern_const(str)
2285
2286 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
2287 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
2288
2289 rb_define_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
2290 rb_define_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
2291 rb_define_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
2292 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
2293 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
2294 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
2295 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
2296 rb_define_private_method(rb_cModule, "ruby2_keywords", rb_mod_ruby2_keywords, -1);
2297
2298 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, -1);
2299 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, -1);
2300 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, -1);
2301 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, -1);
2302 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
2303 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
2304
2305 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2306 "public", top_public, -1);
2307 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2308 "private", top_private, -1);
2309 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
2310 "ruby2_keywords", top_ruby2_keywords, -1);
2311
2312 {
2313 #define REPLICATE_METHOD(klass, id) do { \
2314 const rb_method_entry_t *me = rb_method_entry((klass), (id)); \
2315 rb_method_entry_set((klass), (id), me, METHOD_ENTRY_VISI(me)); \
2316 } while (0)
2317
2318 REPLICATE_METHOD(rb_eException, idMethodMissing);
2319 REPLICATE_METHOD(rb_eException, idRespond_to);
2320 REPLICATE_METHOD(rb_eException, idRespond_to_missing);
2321 }
2322 }
rb_add_method_cfunc
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc, rb_method_visibility_t visi)
Definition: vm_method.c:134
METHOD_VISI_PRIVATE
@ METHOD_VISI_PRIVATE
Definition: method.h:29
REPLICATE_METHOD
#define REPLICATE_METHOD(klass, id)
rb_subclass_entry::next
rb_subclass_entry_t * next
Definition: internal.h:1000
ID
unsigned long ID
Definition: ruby.h:103
rb_method_entry_arity
int rb_method_entry_arity(const rb_method_entry_t *me)
Definition: proc.c:2543
rb_id2name
const char * rb_id2name(ID)
Definition: symbol.c:801
rb_method_bmethod_struct::proc
VALUE proc
Definition: method.h:152
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE klass, ID id)
Definition: vm_method.c:2072
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
rb_add_method
void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_visibility_t visi)
Definition: vm_method.c:674
TRUE
#define TRUE
Definition: nkf.h:175
rb_callable_method_entry
const MJIT_FUNC_EXPORTED rb_callable_method_entry_t * rb_callable_method_entry(VALUE klass, ID id)
Definition: vm_method.c:878
block_handler_type_iseq
@ block_handler_type_iseq
Definition: vm_core.h:738
rb_check_id
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
rb_class_modify_check
void rb_class_modify_check(VALUE klass)
Asserts that klass is not a frozen class.
Definition: eval.c:437
id
const int id
Definition: nkf.c:209
VM_METHOD_TYPE_REFINED
@ VM_METHOD_TYPE_REFINED
refinement
Definition: method.h:113
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_iseq_struct
Definition: vm_core.h:456
rb_method_definition_struct::method_serial
uintptr_t method_serial
Definition: method.h:180
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
rb_method_cfunc_struct::invoker
VALUE(* invoker)(VALUE recv, int argc, const VALUE *argv, VALUE(*func)(ANYARGS))
Definition: method.h:133
VM_METHOD_TYPE_OPTIMIZED
@ VM_METHOD_TYPE_OPTIMIZED
Kernel::send, Proc::call, etc.
Definition: method.h:111
PREV_CLASS_SERIAL
#define PREV_CLASS_SERIAL()
Definition: vm_insnhelper.h:187
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
rb_method_definition_struct::attr
rb_method_attr_t attr
Definition: method.h:171
idInitialize_copy
@ idInitialize_copy
Definition: rb_mjit_min_header-2.7.0.h:8710
idRespond_to_missing
@ idRespond_to_missing
Definition: id.h:117
rb_hash_method_entry
st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
Definition: vm_method.c:1575
rb_undef
void rb_undef(VALUE klass, ID id)
Definition: vm_method.c:1200
cbase
VALUE cbase
Definition: rb_mjit_min_header-2.7.0.h:16133
rb_method_iseq_struct::cref
rb_cref_t * cref
class reference, should be marked
Definition: method.h:128
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
rb_vm_cref_in_context
const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase)
Definition: vm.c:1400
marker
const VALUE VALUE VALUE marker
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_vm_check_optimizable_mid
int rb_vm_check_optimizable_mid(VALUE mid)
Definition: vm.c:1581
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_to_symbol
VALUE rb_to_symbol(VALUE name)
Definition: string.c:11156
added
#define added
Definition: vm_method.c:32
rb_print_undef
void rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
Definition: eval_error.c:379
rb_call_cache::me
const struct rb_callable_method_entry_struct * me
Definition: internal.h:2373
mjit_remove_class_serial
void mjit_remove_class_serial(rb_serial_t class_serial)
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_callable_method_entry_struct::owner
const VALUE owner
Definition: method.h:64
rb_intern
#define rb_intern(str)
rb_method_name_error
void rb_method_name_error(VALUE klass, VALUE str)
Definition: proc.c:1778
rb_method_attr_struct::id
ID id
Definition: method.h:138
idInitialize_dup
@ idInitialize_dup
Definition: rb_mjit_min_header-2.7.0.h:8712
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
GLOBAL_METHOD_CACHE
#define GLOBAL_METHOD_CACHE(c, m)
Definition: vm_method.c:25
cache_entry::class_serial
rb_serial_t class_serial
Definition: vm_method.c:42
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_id_attrset
ID rb_id_attrset(ID)
Definition: symbol.c:98
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
rb_scope_visi_struct::method_visi
rb_method_visibility_t method_visi
Definition: rb_mjit_min_header-2.7.0.h:8771
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_callable_method_entry_struct
Definition: method.h:59
rb_cModule
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:2034
block_handler_type_proc
@ block_handler_type_proc
Definition: vm_core.h:741
rb_method_definition_struct::type
rb_method_type_t type
Definition: rb_mjit_min_header-2.7.0.h:8877
rb_method_entry_struct::def
struct rb_method_definition_struct *const def
Definition: method.h:54
rb_iseq_path
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:1027
getenv
#define getenv(name)
Definition: win32.c:73
rb_iseq_constant_body::location
rb_iseq_location_t location
Definition: vm_core.h:399
rb_id_table
Definition: id_table.c:40
rb_id_table_insert
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
Definition: id_table.c:256
rb_method_definition_struct::optimize_type
enum method_optimized_type optimize_type
Definition: method.h:176
rb_method_definition_struct::refined
rb_method_refined_t refined
Definition: method.h:173
rb_method_iseq_struct
Definition: method.h:126
rb_iseq_location_struct::first_lineno
VALUE first_lineno
Definition: vm_core.h:276
rb_method_visibility_t
rb_method_visibility_t
Definition: method.h:26
rb_method_refined_struct::orig_me
struct rb_method_entry_struct * orig_me
Definition: method.h:147
Qundef
#define Qundef
Definition: ruby.h:470
rb_method_definition_eq
int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
Definition: vm_method.c:1504
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:32
idInitialize
@ idInitialize
Definition: rb_mjit_min_header-2.7.0.h:8709
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
atoi
int atoi(const char *__nptr)
rb_respond_to
int rb_respond_to(VALUE obj, ID id)
Definition: vm_method.c:2190
ptr
struct RIMemo * ptr
Definition: debug.c:74
METHOD_ENTRY_COMPLEMENTED_SET
#define METHOD_ENTRY_COMPLEMENTED_SET(me)
Definition: method.h:70
rb_method_iseq_struct::iseqptr
rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
Definition: method.h:127
Qfalse
#define Qfalse
Definition: ruby.h:467
ruby_running
#define ruby_running
Definition: vm_method.c:59
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
rb_method_entry_struct::owner
VALUE owner
Definition: method.h:56
rb_method_definition_struct::alias_count
int alias_count
Definition: method.h:165
rb_free_method_entry
void rb_free_method_entry(const rb_method_entry_t *me)
Definition: vm_method.c:174
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
INC_GLOBAL_METHOD_STATE
#define INC_GLOBAL_METHOD_STATE()
Definition: vm_insnhelper.h:190
rb_method_entry_with_refinements
const rb_method_entry_t * rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:911
rb_callable_method_entry_with_refinements
const MJIT_FUNC_EXPORTED rb_callable_method_entry_t * rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:917
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:104
NULL
#define NULL
Definition: _sdbm.c:101
exit
void exit(int __status) __attribute__((__noreturn__))
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_vm_cref
rb_cref_t * rb_vm_cref(void)
Definition: vm.c:1384
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_method_definition_struct::bmethod
rb_method_bmethod_t bmethod
Definition: method.h:174
VM_METHOD_TYPE_IVAR
@ VM_METHOD_TYPE_IVAR
attr_reader or attr_accessor
Definition: method.h:105
rb_obj_respond_to
int rb_obj_respond_to(VALUE obj, ID id, int priv)
Definition: vm_method.c:2180
rb_resolve_refined_method
const rb_method_entry_t * rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me)
Definition: vm_method.c:972
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
rb_imemo_new
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
Definition: gc.c:2306
VM_METHOD_TYPE_UNDEF
@ VM_METHOD_TYPE_UNDEF
Definition: method.h:109
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
cache_entry::me
rb_method_entry_t * me
Definition: vm_method.c:44
rb_method_definition_struct::complemented_count
int complemented_count
Definition: method.h:166
cache_entry::mid
ID mid
Definition: vm_method.c:43
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
RCLASS_ORIGIN
#define RCLASS_ORIGIN(c)
Definition: internal.h:1075
rb_method_definition_struct::cfunc
rb_method_cfunc_t cfunc
Definition: method.h:170
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2712
idInitialize_clone
@ idInitialize_clone
Definition: rb_mjit_min_header-2.7.0.h:8711
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
rb_callable_method_entry_struct::called_id
ID called_id
Definition: method.h:63
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
RMODULE_IS_REFINEMENT
@ RMODULE_IS_REFINEMENT
Definition: ruby.h:956
read
_ssize_t read(int __fd, void *__buf, size_t __nbyte)
rb_method_definition_struct::body
union rb_method_definition_struct::@118 body
rb_method_entry_location
VALUE rb_method_entry_location(const rb_method_entry_t *me)
Definition: proc.c:2713
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE klass)
Definition: vm_method.c:722
rb_obj_info
const MJIT_FUNC_EXPORTED char * rb_obj_info(VALUE obj)
Definition: gc.c:11655
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
rb_scope_visi_struct::module_func
unsigned int module_func
Definition: method.h:37
rb_iseq_constant_body::param
struct rb_iseq_constant_body::@178 param
parameter information
rb_method_attr_struct::location
VALUE location
Definition: method.h:139
calloc
void * calloc(size_t, size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1
rb_cref_struct::scope_visi
const rb_scope_visibility_t scope_visi
Definition: method.h:46
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
undefined
#define undefined
Definition: vm_method.c:36
rb_cBasicObject
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ruby.h:2009
RCLASS_M_TBL
#define RCLASS_M_TBL(c)
Definition: internal.h:1069
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_callable_method_entry_struct::defined_class
const VALUE defined_class
Definition: method.h:61
rb_method_definition_struct::alias
rb_method_alias_t alias
Definition: method.h:172
rb_method_entry_complement_defined_class
const MJIT_FUNC_EXPORTED rb_callable_method_entry_t * rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class)
Definition: vm_method.c:415
METHOD_ENTRY_VISI
#define METHOD_ENTRY_VISI(me)
Definition: method.h:67
cache_entry
Definition: vm_method.c:40
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1182
rb_remove_method_id
void rb_remove_method_id(VALUE klass, ID mid)
Definition: vm_method.c:1026
rb_attr
void rb_attr(VALUE klass, ID id, int read, int write, int ex)
Definition: vm_method.c:1163
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3345
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
rb_clear_constant_cache
void rb_clear_constant_cache(void)
Definition: vm_method.c:87
Init_eval_method
void Init_eval_method(void)
Definition: vm_method.c:2281
rb_compile_warning
void rb_compile_warning(const char *file, int line, const char *fmt,...)
Definition: error.c:285
mask
enum @11::@13::@14 mask
VM_METHOD_TYPE_CFUNC
@ VM_METHOD_TYPE_CFUNC
C method.
Definition: method.h:103
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_method_entry_at
const rb_method_entry_t * rb_method_entry_at(VALUE klass, ID id)
Definition: vm_method.c:756
rb_method_entry_without_refinements
const rb_method_entry_t * rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:925
rb_method_cfunc_struct::func
VALUE(* func)(ANYARGS)
Definition: method.h:132
VM_METHOD_TYPE_NOTIMPLEMENTED
@ VM_METHOD_TYPE_NOTIMPLEMENTED
Definition: method.h:110
rb_cref_struct
CREF (Class REFerence)
Definition: method.h:41
RCLASS_SERIAL
#define RCLASS_SERIAL(c)
Definition: internal.h:1078
id__send__
@ id__send__
Definition: rb_mjit_min_header-2.7.0.h:8707
st_index_t
st_data_t st_index_t
Definition: st.h:50
METHOD_VISI_UNDEF
@ METHOD_VISI_UNDEF
Definition: method.h:27
VM_METHOD_TYPE_BMETHOD
@ VM_METHOD_TYPE_BMETHOD
Definition: method.h:106
rb_method_entry_create
rb_method_entry_t * rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def)
Definition: vm_method.c:397
METHOD_ENTRY_BASIC
#define METHOD_ENTRY_BASIC(me)
Definition: method.h:68
rb_method_definition_struct::iseq
rb_method_iseq_t iseq
Definition: method.h:169
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
RCLASS_CALLABLE_M_TBL
#define RCLASS_CALLABLE_M_TBL(c)
Definition: internal.h:1073
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
rb_call_data::cc
struct rb_call_cache cc
Definition: internal.h:2394
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
GET_GLOBAL_METHOD_STATE
#define GET_GLOBAL_METHOD_STATE()
Definition: vm_insnhelper.h:189
rb_call_info::mid
ID mid
Definition: internal.h:2389
entries
struct iseq_catch_table_entry entries[]
Definition: rb_mjit_min_header-2.7.0.h:10827
T_CLASS
#define T_CLASS
Definition: ruby.h:524
rb_method_alias_struct::original_me
struct rb_method_entry_struct * original_me
Definition: method.h:143
METHOD_DEBUG
#define METHOD_DEBUG
Definition: vm_method.c:7
METHOD_VISI_PROTECTED
@ METHOD_VISI_PROTECTED
Definition: method.h:30
mod
#define mod(x, y)
Definition: date_strftime.c:28
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
rb_control_frame_struct
Definition: vm_core.h:760
size
int size
Definition: encoding.c:58
FALSE
#define FALSE
Definition: nkf.h:174
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
cache_entry::defined_class
VALUE defined_class
Definition: vm_method.c:45
VM_METHOD_TYPE_ZSUPER
@ VM_METHOD_TYPE_ZSUPER
Definition: method.h:107
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_gc_writebarrier_remember
MJIT_FUNC_EXPORTED void rb_gc_writebarrier_remember(VALUE obj)
Definition: gc.c:6875
rb_iseq_constant_body::flags
struct rb_iseq_constant_body::@178::@180 flags
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:280
rb_method_refined_struct
Definition: method.h:146
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
rb_method_entry
const MJIT_FUNC_EXPORTED rb_method_entry_t * rb_method_entry(VALUE klass, ID id)
Definition: vm_method.c:837
OPT_GLOBAL_METHOD_CACHE
#define OPT_GLOBAL_METHOD_CACHE
Definition: vm_opts.h:50
me
const rb_callable_method_entry_t * me
Definition: rb_mjit_min_header-2.7.0.h:13226
rb_vm_call_kw
VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
Definition: vm_eval.c:265
RCLASS_EXT
#define RCLASS_EXT(c)
Definition: classext.h:15
rb_frame_callee
ID rb_frame_callee(void)
The name of the current method.
Definition: eval.c:1199
QUOTE_ID
#define QUOTE_ID(id)
Definition: internal.h:2143
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.0.h:2836
T_MODULE
#define T_MODULE
Definition: ruby.h:526
rb_define_alloc_func
void rb_define_alloc_func(VALUE klass, VALUE(*func)(VALUE))
Definition: vm_method.c:715
rb_alias
void rb_alias(VALUE klass, ID alias_name, ID original_name)
Definition: vm_method.c:1581
imemo_ment
@ imemo_ment
Definition: internal.h:1139
rb_method_bmethod_struct::hooks
struct rb_hook_list_struct * hooks
Definition: method.h:153
CALL_METHOD_HOOK
#define CALL_METHOD_HOOK(klass, hook, mid)
Definition: vm_method.c:654
rb_method_type_t
rb_method_type_t
Definition: method.h:101
rb_method_refined_struct::owner
VALUE owner
Definition: method.h:148
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
VM_METHOD_TYPE_MISSING
@ VM_METHOD_TYPE_MISSING
wrapper for method_missing(id)
Definition: method.h:112
rb_method_cfunc_struct::argc
int argc
Definition: method.h:134
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1998
argv
char ** argv
Definition: ruby.c:223
rb_method_basic_definition_p_with_cc
bool rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid)
Definition: vm_method.c:2057
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
rb_vm_get_ruby_level_next_cfp
MJIT_FUNC_EXPORTED rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
Definition: vm.c:553
VM_METHOD_TYPE_ATTRSET
@ VM_METHOD_TYPE_ATTRSET
attr_writer or attr_accessor
Definition: method.h:104
ANYARGS
#define ANYARGS
Definition: defines.h:201
rb_method_entry_struct::defined_class
VALUE defined_class
Definition: method.h:53
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
rb_next_class_serial
rb_serial_t rb_next_class_serial(void)
Definition: vm.c:358
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
rb_add_method_iseq
MJIT_FUNC_EXPORTED void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
Definition: vm_method.c:684
rb_captured_block::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:731
rb_subclass_entry::klass
VALUE klass
Definition: internal.h:999
rb_print_undef_str
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:394
rb_class_foreach_subclass
void rb_class_foreach_subclass(VALUE klass, void(*f)(VALUE, VALUE), VALUE arg)
Definition: class.c:113
BOUND_RESPONDS
#define BOUND_RESPONDS
Definition: vm_method.c:1099
rb_method_entry_set
rb_method_entry_t * rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi)
Definition: vm_method.c:707
rb_control_frame_struct::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:763
rb_captured_block::code
union rb_captured_block::@186 code
rb_captured_block
Definition: vm_core.h:727
cache_entry::method_state
rb_serial_t method_state
Definition: vm_method.c:41
INC_GLOBAL_CONSTANT_STATE
#define INC_GLOBAL_CONSTANT_STATE()
Definition: vm_insnhelper.h:192
rb_alloc_func_t
VALUE(* rb_alloc_func_t)(VALUE)
Definition: intern.h:427
removed
#define removed
Definition: vm_method.c:34
idMethodMissing
@ idMethodMissing
Definition: rb_mjit_min_header-2.7.0.h:8692
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_id_table_create
struct rb_id_table * rb_id_table_create(size_t capa)
Definition: id_table.c:95
rb_method_entry_struct::called_id
ID called_id
Definition: method.h:55
argc
int argc
Definition: ruby.c:222
VM_METHOD_TYPE_ISEQ
@ VM_METHOD_TYPE_ISEQ
Ruby method.
Definition: method.h:102
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1725
RB_NO_KEYWORDS
#define RB_NO_KEYWORDS
Definition: ruby.h:1977
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
rb_clear_method_cache_by_class
void rb_clear_method_cache_by_class(VALUE klass)
Definition: vm_method.c:93
rb_eException
VALUE rb_eException
Definition: error.c:914
xfree
#define xfree
Definition: defines.h:216
rb_ary_freeze
VALUE rb_ary_freeze(VALUE ary)
Definition: array.c:648
rb_method_definition_struct::original_id
ID original_id
Definition: method.h:179
rb_call_data::ci
struct rb_call_info ci
Definition: internal.h:2395
RUBY_DTRACE_HOOK
#define RUBY_DTRACE_HOOK(name, arg)
Definition: internal.h:2586
rb_proc_get_iseq
const rb_iseq_t * rb_proc_get_iseq(VALUE proc, int *is_proc)
Definition: proc.c:1194
rb_method_definition_struct
Definition: method.h:163
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
_
#define _(args)
Definition: dln.h:28
rb_compile_warn
void rb_compile_warn(const char *file, int line, const char *fmt,...)
Definition: error.c:270
rb_callable_method_entry_struct::def
struct rb_method_definition_struct *const def
Definition: method.h:62
Qtrue
#define Qtrue
Definition: ruby.h:468
Init_Method
void Init_Method(void)
Definition: vm_method.c:2257
rb_scope_visi_struct
Definition: method.h:35
UNDEF_ALLOC_FUNC
#define UNDEF_ALLOC_FUNC
Definition: vm_method.c:712
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition: debug_counter.h:375
method_optimized_type
method_optimized_type
Definition: method.h:156
rb_method_entry_struct
Definition: method.h:51
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition: vm_core.h:460
rb_subclass_entry
Definition: internal.h:998
rb_hash_proc
st_index_t rb_hash_proc(st_index_t hash, VALUE proc)
Definition: proc.c:1302
UNDEFINED_REFINED_METHOD_P
#define UNDEFINED_REFINED_METHOD_P(def)
Definition: method.h:187
rb_intern_str
#define rb_intern_str(string)
Definition: generator.h:16
rb_remove_method
void rb_remove_method(VALUE klass, const char *name)
Definition: vm_method.c:1032
rb_method_definition_create
MJIT_FUNC_EXPORTED rb_method_definition_t * rb_method_definition_create(rb_method_type_t type, ID mid)
Definition: vm_method.c:348
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
idRespond_to
@ idRespond_to
Definition: id.h:116
rb_method_definition_set
MJIT_FUNC_EXPORTED void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
Definition: vm_method.c:232
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_callable_method_entry_without_refinements
const MJIT_FUNC_EXPORTED rb_callable_method_entry_t * rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:931
rb_method_entry_eq
int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
Definition: vm_method.c:1476
rb_method_cfunc_struct
Definition: method.h:131
rb_get_alloc_func
rb_alloc_func_t rb_get_alloc_func(VALUE klass)
Definition: vm_method.c:728
rb_method_entry_copy
void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src)
Definition: vm_method.c:451
rb_vm_get_sourceline
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:68
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
rb_id_table_delete
int rb_id_table_delete(struct rb_id_table *tbl, ID id)
Definition: id_table.c:262
rb_add_refined_method_entry
void rb_add_refined_method_entry(VALUE refined_class, ID mid)
Definition: vm_method.c:491
rb_f_notimplement
VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)
Definition: vm_method.c:120
rb_id_table_lookup
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
Definition: id_table.c:226
rb_scope_visibility_set
void rb_scope_visibility_set(rb_method_visibility_t visi)
Definition: vm_method.c:1138
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1574
UNALIGNED_MEMBER_PTR
#define UNALIGNED_MEMBER_PTR(ptr, mem)
Definition: internal.h:2685
write
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN(val)
Definition: ruby.h:59
rb_call_data
Definition: internal.h:2393
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1569
METHOD_ENTRY_COMPLEMENTED
#define METHOD_ENTRY_COMPLEMENTED(me)
Definition: method.h:69
rb_resolve_refined_method_callable
const MJIT_FUNC_EXPORTED rb_callable_method_entry_t * rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me)
Definition: vm_method.c:979
id_table.h
VM_DEBUG_VERIFY_METHOD_CACHE
#define VM_DEBUG_VERIFY_METHOD_CACHE
Definition: vm_core.h:724
rb_method_entry_clone
const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me)
Definition: vm_method.c:406
RTEST
#define RTEST(v)
Definition: ruby.h:481
object_id
#define object_id
Definition: vm_method.c:31
rb_id_table_clear
void rb_id_table_clear(struct rb_id_table *tbl)
Definition: id_table.c:109
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
VM_METHOD_TYPE_ALIAS
@ VM_METHOD_TYPE_ALIAS
Definition: method.h:108
d1
#define d1
UNDEFINED_METHOD_ENTRY_P
#define UNDEFINED_METHOD_ENTRY_P(me)
Definition: method.h:186
cfp
rb_control_frame_t * cfp
Definition: rb_mjit_min_header-2.7.0.h:14544
rb_method_boundp
int rb_method_boundp(VALUE klass, ID id, int ex)
Definition: vm_method.c:1102
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843