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