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