00001
00002
00003
00004
00005 #ifndef GLOBAL_METHOD_CACHE_SIZE
00006 #define GLOBAL_METHOD_CACHE_SIZE 0x800
00007 #endif
00008 #ifndef GLOBAL_METHOD_CACHE_MASK
00009 #define GLOBAL_METHOD_CACHE_MASK 0x7ff
00010 #endif
00011
00012 #define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&GLOBAL_METHOD_CACHE_MASK)
00013 #define GLOBAL_METHOD_CACHE(c,m) (global_method_cache + GLOBAL_METHOD_CACHE_KEY(c,m))
00014 #include "method.h"
00015
00016 #define NOEX_NOREDEF 0
00017 #ifndef NOEX_NOREDEF
00018 #define NOEX_NOREDEF NOEX_RESPONDS
00019 #endif
00020
00021 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass);
00022
00023 #define object_id idObject_id
00024 #define added idMethod_added
00025 #define singleton_added idSingleton_method_added
00026 #define removed idMethod_removed
00027 #define singleton_removed idSingleton_method_removed
00028 #define undefined idMethod_undefined
00029 #define singleton_undefined idSingleton_method_undefined
00030 #define attached id__attached__
00031
00032 struct cache_entry {
00033 rb_serial_t method_state;
00034 rb_serial_t class_serial;
00035 ID mid;
00036 rb_method_entry_t* me;
00037 VALUE defined_class;
00038 };
00039
00040 static struct cache_entry global_method_cache[GLOBAL_METHOD_CACHE_SIZE];
00041 #define ruby_running (GET_VM()->running)
00042
00043
00044 static void
00045 rb_class_clear_method_cache(VALUE klass)
00046 {
00047 RCLASS_SERIAL(klass) = rb_next_class_serial();
00048 rb_class_foreach_subclass(klass, rb_class_clear_method_cache);
00049 }
00050
00051 void
00052 rb_clear_cache(void)
00053 {
00054 rb_warning("rb_clear_cache() is deprecated.");
00055 INC_GLOBAL_METHOD_STATE();
00056 INC_GLOBAL_CONSTANT_STATE();
00057 }
00058
00059 void
00060 rb_clear_constant_cache(void)
00061 {
00062 INC_GLOBAL_CONSTANT_STATE();
00063 }
00064
00065 void
00066 rb_clear_method_cache_by_class(VALUE klass)
00067 {
00068 if (klass && klass != Qundef) {
00069 int global = klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel;
00070
00071 if (RUBY_DTRACE_METHOD_CACHE_CLEAR_ENABLED()) {
00072 RUBY_DTRACE_METHOD_CACHE_CLEAR(global ? "global" : rb_class2name(klass), rb_sourcefile(), rb_sourceline());
00073 }
00074
00075 if (global) {
00076 INC_GLOBAL_METHOD_STATE();
00077 }
00078 else {
00079 rb_class_clear_method_cache(klass);
00080 }
00081 }
00082 }
00083
00084 VALUE
00085 rb_f_notimplement(int argc, VALUE *argv, VALUE obj)
00086 {
00087 rb_notimplement();
00088
00089 UNREACHABLE;
00090 }
00091
00092 static void
00093 rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex)
00094 {
00095 rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex);
00096 }
00097
00098 void
00099 rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
00100 {
00101 if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
00102 if (func != rb_f_notimplement) {
00103 rb_method_cfunc_t opt;
00104 opt.func = func;
00105 opt.argc = argc;
00106 rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
00107 }
00108 else {
00109 rb_define_notimplement_method_id(klass, mid, noex);
00110 }
00111 }
00112
00113 void
00114 rb_unlink_method_entry(rb_method_entry_t *me)
00115 {
00116 struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
00117 ume->me = me;
00118 ume->next = GET_VM()->unlinked_method_entry_list;
00119 GET_VM()->unlinked_method_entry_list = ume;
00120 }
00121
00122 void
00123 rb_gc_mark_unlinked_live_method_entries(void *pvm)
00124 {
00125 rb_vm_t *vm = pvm;
00126 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list;
00127
00128 while (ume) {
00129 if (ume->me->mark) {
00130 rb_mark_method_entry(ume->me);
00131 }
00132 ume = ume->next;
00133 }
00134 }
00135
00136 void
00137 rb_sweep_method_entry(void *pvm)
00138 {
00139 rb_vm_t *vm = pvm;
00140 struct unlinked_method_entry_list_entry **prev_ume = &vm->unlinked_method_entry_list, *ume = *prev_ume, *curr_ume;
00141
00142 while (ume) {
00143 if (ume->me->mark) {
00144 ume->me->mark = 0;
00145 prev_ume = &ume->next;
00146 ume = *prev_ume;
00147 }
00148 else {
00149 rb_free_method_entry(ume->me);
00150
00151 curr_ume = ume;
00152 ume = ume->next;
00153 *prev_ume = ume;
00154 xfree(curr_ume);
00155 }
00156 }
00157 }
00158
00159 static void
00160 release_method_definition(rb_method_definition_t *def)
00161 {
00162 if (def == 0)
00163 return;
00164 if (def->alias_count == 0) {
00165 if (def->type == VM_METHOD_TYPE_REFINED &&
00166 def->body.orig_me) {
00167 release_method_definition(def->body.orig_me->def);
00168 xfree(def->body.orig_me);
00169 }
00170 xfree(def);
00171 }
00172 else if (def->alias_count > 0) {
00173 def->alias_count--;
00174 }
00175 }
00176
00177 void
00178 rb_free_method_entry(rb_method_entry_t *me)
00179 {
00180 release_method_definition(me->def);
00181 xfree(me);
00182 }
00183
00184 static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr);
00185 static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
00186
00187 static inline rb_method_entry_t *
00188 lookup_method_table(VALUE klass, ID id)
00189 {
00190 st_data_t body;
00191 st_table *m_tbl = RCLASS_M_TBL(klass);
00192 if (st_lookup(m_tbl, id, &body)) {
00193 return (rb_method_entry_t *) body;
00194 }
00195 else {
00196 return 0;
00197 }
00198 }
00199
00200 static void
00201 make_method_entry_refined(rb_method_entry_t *me)
00202 {
00203 rb_method_definition_t *new_def;
00204
00205 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED)
00206 return;
00207
00208 new_def = ALLOC(rb_method_definition_t);
00209 new_def->type = VM_METHOD_TYPE_REFINED;
00210 new_def->original_id = me->called_id;
00211 new_def->alias_count = 0;
00212 new_def->body.orig_me = ALLOC(rb_method_entry_t);
00213 *new_def->body.orig_me = *me;
00214 rb_vm_check_redefinition_opt_method(me, me->klass);
00215 if (me->def) me->def->alias_count++;
00216 me->flag = NOEX_WITH_SAFE(NOEX_PUBLIC);
00217 me->def = new_def;
00218 }
00219
00220 void
00221 rb_add_refined_method_entry(VALUE refined_class, ID mid)
00222 {
00223 rb_method_entry_t *me = lookup_method_table(refined_class, mid);
00224
00225 if (me) {
00226 make_method_entry_refined(me);
00227 rb_clear_method_cache_by_class(refined_class);
00228 }
00229 else {
00230 rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
00231 NOEX_PUBLIC);
00232 }
00233 }
00234
00235 static rb_method_entry_t *
00236 rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
00237 rb_method_definition_t *def, rb_method_flag_t noex,
00238 VALUE defined_class)
00239 {
00240 rb_method_entry_t *me;
00241 #if NOEX_NOREDEF
00242 VALUE rklass;
00243 #endif
00244 st_table *mtbl;
00245 st_data_t data;
00246 int make_refined = 0;
00247
00248 if (NIL_P(klass)) {
00249 klass = rb_cObject;
00250 }
00251 if (!FL_TEST(klass, FL_SINGLETON) &&
00252 type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
00253 type != VM_METHOD_TYPE_ZSUPER &&
00254 (mid == idInitialize || mid == idInitialize_copy ||
00255 mid == idInitialize_clone || mid == idInitialize_dup ||
00256 mid == idRespond_to_missing)) {
00257 noex = NOEX_PRIVATE | noex;
00258 }
00259
00260 rb_check_frozen(klass);
00261 #if NOEX_NOREDEF
00262 rklass = klass;
00263 #endif
00264 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
00265 VALUE refined_class =
00266 rb_refinement_module_get_refined_class(klass);
00267
00268 rb_add_refined_method_entry(refined_class, mid);
00269 }
00270 if (type == VM_METHOD_TYPE_REFINED) {
00271 rb_method_entry_t *old_me =
00272 lookup_method_table(RCLASS_ORIGIN(klass), mid);
00273 if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
00274 }
00275 else {
00276 klass = RCLASS_ORIGIN(klass);
00277 }
00278 mtbl = RCLASS_M_TBL(klass);
00279
00280
00281 if (st_lookup(mtbl, mid, &data)) {
00282 rb_method_entry_t *old_me = (rb_method_entry_t *)data;
00283 rb_method_definition_t *old_def = old_me->def;
00284
00285 if (rb_method_definition_eq(old_def, def)) return old_me;
00286 #if NOEX_NOREDEF
00287 if (old_me->flag & NOEX_NOREDEF) {
00288 rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE,
00289 rb_class_name(rklass), rb_id2str(mid));
00290 }
00291 #endif
00292 rb_vm_check_redefinition_opt_method(old_me, klass);
00293 if (old_def->type == VM_METHOD_TYPE_REFINED)
00294 make_refined = 1;
00295
00296 if (RTEST(ruby_verbose) &&
00297 type != VM_METHOD_TYPE_UNDEF &&
00298 old_def->alias_count == 0 &&
00299 old_def->type != VM_METHOD_TYPE_UNDEF &&
00300 old_def->type != VM_METHOD_TYPE_ZSUPER) {
00301 rb_iseq_t *iseq = 0;
00302
00303 rb_warning("method redefined; discarding old %s", rb_id2name(mid));
00304 switch (old_def->type) {
00305 case VM_METHOD_TYPE_ISEQ:
00306 iseq = old_def->body.iseq;
00307 break;
00308 case VM_METHOD_TYPE_BMETHOD:
00309 iseq = rb_proc_get_iseq(old_def->body.proc, 0);
00310 break;
00311 default:
00312 break;
00313 }
00314 if (iseq && !NIL_P(iseq->location.path)) {
00315 int line = iseq->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq->self)) : 0;
00316 rb_compile_warning(RSTRING_PTR(iseq->location.path), line,
00317 "previous definition of %s was here",
00318 rb_id2name(old_def->original_id));
00319 }
00320 }
00321
00322 rb_unlink_method_entry(old_me);
00323 }
00324
00325 me = ALLOC(rb_method_entry_t);
00326
00327 rb_clear_method_cache_by_class(klass);
00328
00329 me->flag = NOEX_WITH_SAFE(noex);
00330 me->mark = 0;
00331 me->called_id = mid;
00332 RB_OBJ_WRITE(klass, &me->klass, defined_class);
00333 me->def = def;
00334
00335 if (def) {
00336 def->alias_count++;
00337
00338 switch(def->type) {
00339 case VM_METHOD_TYPE_ISEQ:
00340 RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq->self);
00341 break;
00342 case VM_METHOD_TYPE_IVAR:
00343 RB_OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
00344 break;
00345 case VM_METHOD_TYPE_BMETHOD:
00346 RB_OBJ_WRITTEN(klass, Qundef, def->body.proc);
00347 break;
00348 default:;
00349
00350 }
00351 }
00352
00353
00354 if (klass == rb_cObject && mid == idInitialize) {
00355 rb_warn("redefining Object#initialize may cause infinite loop");
00356 }
00357
00358 if (mid == object_id || mid == id__send__) {
00359 if (type == VM_METHOD_TYPE_ISEQ && search_method(klass, mid, 0)) {
00360 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
00361 }
00362 }
00363
00364 if (make_refined) {
00365 make_method_entry_refined(me);
00366 }
00367
00368 st_insert(mtbl, mid, (st_data_t) me);
00369
00370 return me;
00371 }
00372
00373 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
00374 const VALUE arg = ID2SYM(mid); \
00375 VALUE recv_class = (klass); \
00376 ID hook_id = (hook); \
00377 if (FL_TEST((klass), FL_SINGLETON)) { \
00378 recv_class = rb_ivar_get((klass), attached); \
00379 hook_id = singleton_##hook; \
00380 } \
00381 rb_funcall2(recv_class, hook_id, 1, &arg); \
00382 } while (0)
00383
00384 static void
00385 method_added(VALUE klass, ID mid)
00386 {
00387 if (ruby_running) {
00388 CALL_METHOD_HOOK(klass, added, mid);
00389 }
00390 }
00391
00392 static VALUE
00393 (*call_cfunc_invoker_func(int argc))(VALUE (*func)(ANYARGS), VALUE recv, int argc, const VALUE *)
00394 {
00395 switch (argc) {
00396 case -2: return &call_cfunc_m2;
00397 case -1: return &call_cfunc_m1;
00398 case 0: return &call_cfunc_0;
00399 case 1: return &call_cfunc_1;
00400 case 2: return &call_cfunc_2;
00401 case 3: return &call_cfunc_3;
00402 case 4: return &call_cfunc_4;
00403 case 5: return &call_cfunc_5;
00404 case 6: return &call_cfunc_6;
00405 case 7: return &call_cfunc_7;
00406 case 8: return &call_cfunc_8;
00407 case 9: return &call_cfunc_9;
00408 case 10: return &call_cfunc_10;
00409 case 11: return &call_cfunc_11;
00410 case 12: return &call_cfunc_12;
00411 case 13: return &call_cfunc_13;
00412 case 14: return &call_cfunc_14;
00413 case 15: return &call_cfunc_15;
00414 default:
00415 rb_bug("call_cfunc_func: unsupported length: %d", argc);
00416 }
00417 }
00418
00419 static void
00420 setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
00421 {
00422 cfunc->func = func;
00423 cfunc->argc = argc;
00424 cfunc->invoker = call_cfunc_invoker_func(argc);
00425 }
00426
00427 rb_method_entry_t *
00428 rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
00429 {
00430 rb_thread_t *th;
00431 rb_control_frame_t *cfp;
00432 int line;
00433 rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass);
00434 rb_method_definition_t *def = ALLOC(rb_method_definition_t);
00435 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
00436 me->def->body.orig_me->def = def;
00437 }
00438 else {
00439 me->def = def;
00440 }
00441 def->type = type;
00442 def->original_id = mid;
00443 def->alias_count = 0;
00444 switch (type) {
00445 case VM_METHOD_TYPE_ISEQ: {
00446 rb_iseq_t *iseq = (rb_iseq_t *)opts;
00447 *(rb_iseq_t **)&def->body.iseq = iseq;
00448 RB_OBJ_WRITTEN(klass, Qundef, iseq->self);
00449 break;
00450 }
00451 case VM_METHOD_TYPE_CFUNC:
00452 {
00453 rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
00454 setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc);
00455 }
00456 break;
00457 case VM_METHOD_TYPE_ATTRSET:
00458 case VM_METHOD_TYPE_IVAR:
00459 def->body.attr.id = (ID)opts;
00460 RB_OBJ_WRITE(klass, &def->body.attr.location, Qfalse);
00461 th = GET_THREAD();
00462 cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
00463 if (cfp && (line = rb_vm_get_sourceline(cfp))) {
00464 VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line));
00465 RB_OBJ_WRITE(klass, &def->body.attr.location, rb_ary_freeze(location));
00466 }
00467 break;
00468 case VM_METHOD_TYPE_BMETHOD:
00469 RB_OBJ_WRITE(klass, &def->body.proc, (VALUE)opts);
00470 break;
00471 case VM_METHOD_TYPE_NOTIMPLEMENTED:
00472 setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1);
00473 break;
00474 case VM_METHOD_TYPE_OPTIMIZED:
00475 def->body.optimize_type = (enum method_optimized_type)opts;
00476 break;
00477 case VM_METHOD_TYPE_ZSUPER:
00478 case VM_METHOD_TYPE_UNDEF:
00479 break;
00480 case VM_METHOD_TYPE_REFINED:
00481 def->body.orig_me = (rb_method_entry_t *) opts;
00482 break;
00483 default:
00484 rb_bug("rb_add_method: unsupported method type (%d)\n", type);
00485 }
00486 if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
00487 method_added(klass, mid);
00488 }
00489 return me;
00490 }
00491
00492 static rb_method_entry_t *
00493 method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
00494 rb_method_flag_t noex, VALUE defined_class)
00495 {
00496 rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
00497 rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex,
00498 defined_class);
00499 method_added(klass, mid);
00500 return newme;
00501 }
00502
00503 rb_method_entry_t *
00504 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
00505 {
00506 return method_entry_set(klass, mid, me, noex, klass);
00507 }
00508
00509 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
00510
00511 void
00512 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
00513 {
00514 Check_Type(klass, T_CLASS);
00515 RCLASS_EXT(klass)->allocator = func;
00516 }
00517
00518 void
00519 rb_undef_alloc_func(VALUE klass)
00520 {
00521 rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC);
00522 }
00523
00524 rb_alloc_func_t
00525 rb_get_alloc_func(VALUE klass)
00526 {
00527 Check_Type(klass, T_CLASS);
00528
00529 for (; klass; klass = RCLASS_SUPER(klass)) {
00530 rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator;
00531 if (allocator == UNDEF_ALLOC_FUNC) break;
00532 if (allocator) return allocator;
00533 }
00534 return 0;
00535 }
00536
00537 static inline rb_method_entry_t*
00538 search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
00539 {
00540 rb_method_entry_t *me;
00541
00542 for (me = 0; klass; klass = RCLASS_SUPER(klass)) {
00543 if ((me = lookup_method_table(klass, id)) != 0) break;
00544 }
00545
00546 if (defined_class_ptr)
00547 *defined_class_ptr = klass;
00548 return me;
00549 }
00550
00551 rb_method_entry_t *
00552 rb_method_entry_at(VALUE klass, ID id)
00553 {
00554 return lookup_method_table(klass, id);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 rb_method_entry_t *
00564 rb_method_entry_get_without_cache(VALUE klass, ID id,
00565 VALUE *defined_class_ptr)
00566 {
00567 VALUE defined_class;
00568 rb_method_entry_t *me = search_method(klass, id, &defined_class);
00569
00570 if (me && me->klass) {
00571 switch (BUILTIN_TYPE(me->klass)) {
00572 case T_CLASS:
00573 if (RBASIC(klass)->flags & FL_SINGLETON) break;
00574
00575 case T_ICLASS:
00576 defined_class = me->klass;
00577 }
00578 }
00579
00580 if (ruby_running) {
00581 struct cache_entry *ent;
00582 ent = GLOBAL_METHOD_CACHE(klass, id);
00583 ent->class_serial = RCLASS_EXT(klass)->class_serial;
00584 ent->method_state = GET_GLOBAL_METHOD_STATE();
00585 ent->defined_class = defined_class;
00586 ent->mid = id;
00587
00588 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00589 ent->me = 0;
00590 me = 0;
00591 }
00592 else {
00593 ent->me = me;
00594 }
00595 }
00596
00597 if (defined_class_ptr)
00598 *defined_class_ptr = defined_class;
00599 return me;
00600 }
00601
00602 #if VM_DEBUG_VERIFY_METHOD_CACHE
00603 static void
00604 verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me)
00605 {
00606 VALUE actual_defined_class;
00607 rb_method_entry_t *actual_me =
00608 rb_method_entry_get_without_cache(klass, id, &actual_defined_class);
00609
00610 if (me != actual_me || defined_class != actual_defined_class) {
00611 rb_bug("method cache verification failed");
00612 }
00613 }
00614 #endif
00615
00616 rb_method_entry_t *
00617 rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
00618 {
00619 #if OPT_GLOBAL_METHOD_CACHE
00620 struct cache_entry *ent;
00621 ent = GLOBAL_METHOD_CACHE(klass, id);
00622 if (ent->method_state == GET_GLOBAL_METHOD_STATE() &&
00623 ent->class_serial == RCLASS_EXT(klass)->class_serial &&
00624 ent->mid == id) {
00625 if (defined_class_ptr)
00626 *defined_class_ptr = ent->defined_class;
00627 #if VM_DEBUG_VERIFY_METHOD_CACHE
00628 verify_method_cache(klass, id, ent->defined_class, ent->me);
00629 #endif
00630 return ent->me;
00631 }
00632 #endif
00633
00634 return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
00635 }
00636
00637 static rb_method_entry_t *
00638 get_original_method_entry(VALUE refinements,
00639 const rb_method_entry_t *me,
00640 VALUE *defined_class_ptr)
00641 {
00642 if (me->def->body.orig_me) {
00643 return me->def->body.orig_me;
00644 }
00645 else {
00646 rb_method_entry_t *tmp_me;
00647 tmp_me = rb_method_entry(RCLASS_SUPER(me->klass), me->called_id,
00648 defined_class_ptr);
00649 return rb_resolve_refined_method(refinements, tmp_me,
00650 defined_class_ptr);
00651 }
00652 }
00653
00654 rb_method_entry_t *
00655 rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me,
00656 VALUE *defined_class_ptr)
00657 {
00658 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00659 VALUE refinement;
00660 rb_method_entry_t *tmp_me;
00661
00662 refinement = find_refinement(refinements, me->klass);
00663 if (NIL_P(refinement)) {
00664 return get_original_method_entry(refinements, me,
00665 defined_class_ptr);
00666 }
00667 tmp_me = rb_method_entry(refinement, me->called_id,
00668 defined_class_ptr);
00669 if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
00670 return tmp_me;
00671 }
00672 else {
00673 return get_original_method_entry(refinements, me,
00674 defined_class_ptr);
00675 }
00676 }
00677 else {
00678 return (rb_method_entry_t *)me;
00679 }
00680 }
00681
00682 rb_method_entry_t *
00683 rb_method_entry_with_refinements(VALUE klass, ID id,
00684 VALUE *defined_class_ptr)
00685 {
00686 VALUE defined_class;
00687 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
00688
00689 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00690 NODE *cref = rb_vm_cref();
00691 VALUE refinements = cref ? cref->nd_refinements : Qnil;
00692
00693 me = rb_resolve_refined_method(refinements, me, &defined_class);
00694 }
00695 if (defined_class_ptr)
00696 *defined_class_ptr = defined_class;
00697 return me;
00698 }
00699
00700 rb_method_entry_t *
00701 rb_method_entry_without_refinements(VALUE klass, ID id,
00702 VALUE *defined_class_ptr)
00703 {
00704 VALUE defined_class;
00705 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
00706
00707 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00708 me = rb_resolve_refined_method(Qnil, me, &defined_class);
00709 }
00710 if (defined_class_ptr)
00711 *defined_class_ptr = defined_class;
00712 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00713 return 0;
00714 }
00715 else {
00716 return me;
00717 }
00718 }
00719
00720 static void
00721 remove_method(VALUE klass, ID mid)
00722 {
00723 st_data_t key, data;
00724 rb_method_entry_t *me = 0;
00725 VALUE self = klass;
00726
00727 klass = RCLASS_ORIGIN(klass);
00728 rb_check_frozen(klass);
00729 if (mid == object_id || mid == id__send__ || mid == idInitialize) {
00730 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
00731 }
00732
00733 if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
00734 !(me = (rb_method_entry_t *)data) ||
00735 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
00736 rb_name_error(mid, "method `%s' not defined in %s",
00737 rb_id2name(mid), rb_class2name(klass));
00738 }
00739 key = (st_data_t)mid;
00740 st_delete(RCLASS_M_TBL(klass), &key, &data);
00741
00742 rb_vm_check_redefinition_opt_method(me, klass);
00743 rb_clear_method_cache_by_class(klass);
00744 rb_unlink_method_entry(me);
00745
00746 CALL_METHOD_HOOK(self, removed, mid);
00747 }
00748
00749 void
00750 rb_remove_method_id(VALUE klass, ID mid)
00751 {
00752 remove_method(klass, mid);
00753 }
00754
00755 void
00756 rb_remove_method(VALUE klass, const char *name)
00757 {
00758 remove_method(klass, rb_intern(name));
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 static VALUE
00772 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
00773 {
00774 int i;
00775
00776 for (i = 0; i < argc; i++) {
00777 VALUE v = argv[i];
00778 ID id = rb_check_id(&v);
00779 if (!id) {
00780 rb_name_error_str(v, "method `%s' not defined in %s",
00781 RSTRING_PTR(v), rb_class2name(mod));
00782 }
00783 remove_method(mod, id);
00784 }
00785 return mod;
00786 }
00787
00788 #undef rb_disable_super
00789 #undef rb_enable_super
00790
00791 void
00792 rb_disable_super(VALUE klass, const char *name)
00793 {
00794
00795 }
00796
00797 void
00798 rb_enable_super(VALUE klass, const char *name)
00799 {
00800 rb_warning("rb_enable_super() is obsolete");
00801 }
00802
00803 static void
00804 rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
00805 {
00806 rb_method_entry_t *me;
00807 VALUE defined_class;
00808
00809 me = search_method(klass, name, &defined_class);
00810 if (!me && RB_TYPE_P(klass, T_MODULE)) {
00811 me = search_method(rb_cObject, name, &defined_class);
00812 }
00813
00814 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00815 rb_print_undef(klass, name, 0);
00816 }
00817
00818 if (me->flag != noex) {
00819 rb_vm_check_redefinition_opt_method(me, klass);
00820
00821 if (klass == defined_class ||
00822 RCLASS_ORIGIN(klass) == defined_class) {
00823 me->flag = noex;
00824 if (me->def->type == VM_METHOD_TYPE_REFINED) {
00825 me->def->body.orig_me->flag = noex;
00826 }
00827 rb_clear_method_cache_by_class(klass);
00828 }
00829 else {
00830 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
00831 }
00832 }
00833 }
00834
00835 int
00836 rb_method_boundp(VALUE klass, ID id, int ex)
00837 {
00838 rb_method_entry_t *me =
00839 rb_method_entry_without_refinements(klass, id, 0);
00840
00841 if (me != 0) {
00842 if ((ex & ~NOEX_RESPONDS) &&
00843 ((me->flag & NOEX_PRIVATE) ||
00844 ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) {
00845 return 0;
00846 }
00847 if (!me->def) return 0;
00848 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
00849 if (ex & NOEX_RESPONDS) return 2;
00850 return 0;
00851 }
00852 return 1;
00853 }
00854 return 0;
00855 }
00856
00857 extern ID rb_check_attr_id(ID id);
00858
00859 void
00860 rb_attr(VALUE klass, ID id, int read, int write, int ex)
00861 {
00862 ID attriv;
00863 VALUE aname;
00864 rb_method_flag_t noex;
00865
00866 if (!ex) {
00867 noex = NOEX_PUBLIC;
00868 }
00869 else {
00870 if (SCOPE_TEST(NOEX_PRIVATE)) {
00871 noex = NOEX_PRIVATE;
00872 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
00873 "attribute accessor as module_function" :
00874 "private attribute?");
00875 }
00876 else if (SCOPE_TEST(NOEX_PROTECTED)) {
00877 noex = NOEX_PROTECTED;
00878 }
00879 else {
00880 noex = NOEX_PUBLIC;
00881 }
00882 }
00883
00884 aname = rb_id2str(rb_check_attr_id(id));
00885 if (NIL_P(aname)) {
00886 rb_raise(rb_eArgError, "argument needs to be symbol or string");
00887 }
00888 attriv = rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname));
00889 if (read) {
00890 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
00891 }
00892 if (write) {
00893 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
00894 }
00895 }
00896
00897 void
00898 rb_undef(VALUE klass, ID id)
00899 {
00900 rb_method_entry_t *me;
00901
00902 if (NIL_P(klass)) {
00903 rb_raise(rb_eTypeError, "no class to undef method");
00904 }
00905 rb_frozen_class_p(klass);
00906 if (id == object_id || id == id__send__ || id == idInitialize) {
00907 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
00908 }
00909
00910 me = search_method(klass, id, 0);
00911
00912 if (UNDEFINED_METHOD_ENTRY_P(me) ||
00913 (me->def->type == VM_METHOD_TYPE_REFINED &&
00914 UNDEFINED_METHOD_ENTRY_P(me->def->body.orig_me))) {
00915 const char *s0 = " class";
00916 VALUE c = klass;
00917
00918 if (FL_TEST(c, FL_SINGLETON)) {
00919 VALUE obj = rb_ivar_get(klass, attached);
00920
00921 if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
00922 c = obj;
00923 s0 = "";
00924 }
00925 }
00926 else if (RB_TYPE_P(c, T_MODULE)) {
00927 s0 = " module";
00928 }
00929 rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
00930 QUOTE_ID(id), s0, rb_class_name(c));
00931 }
00932
00933 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
00934
00935 CALL_METHOD_HOOK(klass, undefined, id);
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static VALUE
00984 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
00985 {
00986 int i;
00987 for (i = 0; i < argc; i++) {
00988 VALUE v = argv[i];
00989 ID id = rb_check_id(&v);
00990 if (!id) {
00991 rb_method_name_error(mod, v);
00992 }
00993 rb_undef(mod, id);
00994 }
00995 return mod;
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 static VALUE
01027 rb_mod_method_defined(VALUE mod, VALUE mid)
01028 {
01029 ID id = rb_check_id(&mid);
01030 if (!id || !rb_method_boundp(mod, id, 1)) {
01031 return Qfalse;
01032 }
01033 return Qtrue;
01034
01035 }
01036
01037 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
01038
01039 static VALUE
01040 check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
01041 {
01042 const rb_method_entry_t *me;
01043 ID id = rb_check_id(&mid);
01044 if (!id) return Qfalse;
01045 me = rb_method_entry(mod, id, 0);
01046 if (me) {
01047 if (VISI_CHECK(me->flag, noex))
01048 return Qtrue;
01049 }
01050 return Qfalse;
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 static VALUE
01082 rb_mod_public_method_defined(VALUE mod, VALUE mid)
01083 {
01084 return check_definition(mod, mid, NOEX_PUBLIC);
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 static VALUE
01116 rb_mod_private_method_defined(VALUE mod, VALUE mid)
01117 {
01118 return check_definition(mod, mid, NOEX_PRIVATE);
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 static VALUE
01150 rb_mod_protected_method_defined(VALUE mod, VALUE mid)
01151 {
01152 return check_definition(mod, mid, NOEX_PROTECTED);
01153 }
01154
01155 int
01156 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
01157 {
01158 return rb_method_definition_eq(m1->def, m2->def);
01159 }
01160
01161 static int
01162 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
01163 {
01164 if (d1 && d1->type == VM_METHOD_TYPE_REFINED && d1->body.orig_me)
01165 d1 = d1->body.orig_me->def;
01166 if (d2 && d2->type == VM_METHOD_TYPE_REFINED && d2->body.orig_me)
01167 d2 = d2->body.orig_me->def;
01168 if (d1 == d2) return 1;
01169 if (!d1 || !d2) return 0;
01170 if (d1->type != d2->type) {
01171 return 0;
01172 }
01173 switch (d1->type) {
01174 case VM_METHOD_TYPE_ISEQ:
01175 return d1->body.iseq == d2->body.iseq;
01176 case VM_METHOD_TYPE_CFUNC:
01177 return
01178 d1->body.cfunc.func == d2->body.cfunc.func &&
01179 d1->body.cfunc.argc == d2->body.cfunc.argc;
01180 case VM_METHOD_TYPE_ATTRSET:
01181 case VM_METHOD_TYPE_IVAR:
01182 return d1->body.attr.id == d2->body.attr.id;
01183 case VM_METHOD_TYPE_BMETHOD:
01184 return RTEST(rb_equal(d1->body.proc, d2->body.proc));
01185 case VM_METHOD_TYPE_MISSING:
01186 return d1->original_id == d2->original_id;
01187 case VM_METHOD_TYPE_ZSUPER:
01188 case VM_METHOD_TYPE_NOTIMPLEMENTED:
01189 case VM_METHOD_TYPE_UNDEF:
01190 return 1;
01191 case VM_METHOD_TYPE_OPTIMIZED:
01192 return d1->body.optimize_type == d2->body.optimize_type;
01193 default:
01194 rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type);
01195 return 0;
01196 }
01197 }
01198
01199 static st_index_t
01200 rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
01201 {
01202 again:
01203 hash = rb_hash_uint(hash, def->type);
01204 switch (def->type) {
01205 case VM_METHOD_TYPE_ISEQ:
01206 return rb_hash_uint(hash, (st_index_t)def->body.iseq);
01207 case VM_METHOD_TYPE_CFUNC:
01208 hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
01209 return rb_hash_uint(hash, def->body.cfunc.argc);
01210 case VM_METHOD_TYPE_ATTRSET:
01211 case VM_METHOD_TYPE_IVAR:
01212 return rb_hash_uint(hash, def->body.attr.id);
01213 case VM_METHOD_TYPE_BMETHOD:
01214 return rb_hash_proc(hash, def->body.proc);
01215 case VM_METHOD_TYPE_MISSING:
01216 return rb_hash_uint(hash, def->original_id);
01217 case VM_METHOD_TYPE_ZSUPER:
01218 case VM_METHOD_TYPE_NOTIMPLEMENTED:
01219 case VM_METHOD_TYPE_UNDEF:
01220 return hash;
01221 case VM_METHOD_TYPE_OPTIMIZED:
01222 return rb_hash_uint(hash, def->body.optimize_type);
01223 case VM_METHOD_TYPE_REFINED:
01224 if (def->body.orig_me) {
01225 def = def->body.orig_me->def;
01226 goto again;
01227 }
01228 else {
01229 return hash;
01230 }
01231 default:
01232 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type);
01233 }
01234 return hash;
01235 }
01236
01237 st_index_t
01238 rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
01239 {
01240 return rb_hash_method_definition(hash, me->def);
01241 }
01242
01243 void
01244 rb_alias(VALUE klass, ID name, ID def)
01245 {
01246 VALUE target_klass = klass;
01247 VALUE defined_class;
01248 rb_method_entry_t *orig_me;
01249 rb_method_flag_t flag = NOEX_UNDEF;
01250
01251 if (NIL_P(klass)) {
01252 rb_raise(rb_eTypeError, "no class to make alias");
01253 }
01254
01255 rb_frozen_class_p(klass);
01256
01257 again:
01258 orig_me = search_method(klass, def, &defined_class);
01259
01260 if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
01261 if ((!RB_TYPE_P(klass, T_MODULE)) ||
01262 (orig_me = search_method(rb_cObject, def, 0),
01263 UNDEFINED_METHOD_ENTRY_P(orig_me))) {
01264 rb_print_undef(klass, def, 0);
01265 }
01266 }
01267 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
01268 klass = RCLASS_SUPER(klass);
01269 def = orig_me->def->original_id;
01270 flag = orig_me->flag;
01271 goto again;
01272 }
01273 if (RB_TYPE_P(defined_class, T_ICLASS)) {
01274 VALUE real_class = RBASIC_CLASS(defined_class);
01275 if (real_class && RCLASS_ORIGIN(real_class) == defined_class)
01276 defined_class = real_class;
01277 }
01278
01279 if (flag == NOEX_UNDEF) flag = orig_me->flag;
01280 method_entry_set(target_klass, name, orig_me, flag, defined_class);
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 static VALUE
01306 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
01307 {
01308 ID oldid = rb_check_id(&oldname);
01309 if (!oldid) {
01310 rb_print_undef_str(mod, oldname);
01311 }
01312 rb_alias(mod, rb_to_id(newname), oldid);
01313 return mod;
01314 }
01315
01316 static void
01317 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
01318 {
01319 int i;
01320
01321 if (argc == 0) {
01322 rb_warning("%"PRIsVALUE" with no argument is just ignored",
01323 QUOTE_ID(rb_frame_callee()));
01324 return;
01325 }
01326
01327 for (i = 0; i < argc; i++) {
01328 VALUE v = argv[i];
01329 ID id = rb_check_id(&v);
01330 if (!id) {
01331 rb_print_undef_str(self, v);
01332 }
01333 rb_export_method(self, id, ex);
01334 }
01335 }
01336
01337 static VALUE
01338 set_visibility(int argc, VALUE *argv, VALUE module, rb_method_flag_t ex)
01339 {
01340 if (argc == 0) {
01341 SCOPE_SET(ex);
01342 }
01343 else {
01344 set_method_visibility(module, argc, argv, ex);
01345 }
01346 return module;
01347 }
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361 static VALUE
01362 rb_mod_public(int argc, VALUE *argv, VALUE module)
01363 {
01364 return set_visibility(argc, argv, module, NOEX_PUBLIC);
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379 static VALUE
01380 rb_mod_protected(int argc, VALUE *argv, VALUE module)
01381 {
01382 return set_visibility(argc, argv, module, NOEX_PROTECTED);
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 static VALUE
01407 rb_mod_private(int argc, VALUE *argv, VALUE module)
01408 {
01409 return set_visibility(argc, argv, module, NOEX_PRIVATE);
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 static VALUE
01423 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
01424 {
01425 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
01426 return obj;
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448 static VALUE
01449 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
01450 {
01451 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
01452 return obj;
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468 static VALUE
01469 top_public(int argc, VALUE *argv)
01470 {
01471 return rb_mod_public(argc, argv, rb_cObject);
01472 }
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 static VALUE
01487 top_private(int argc, VALUE *argv)
01488 {
01489 return rb_mod_private(argc, argv, rb_cObject);
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 static VALUE
01531 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
01532 {
01533 int i;
01534 ID id;
01535 const rb_method_entry_t *me;
01536
01537 if (!RB_TYPE_P(module, T_MODULE)) {
01538 rb_raise(rb_eTypeError, "module_function must be called for modules");
01539 }
01540
01541 if (argc == 0) {
01542 SCOPE_SET(NOEX_MODFUNC);
01543 return module;
01544 }
01545
01546 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
01547
01548 for (i = 0; i < argc; i++) {
01549 VALUE m = module;
01550
01551 id = rb_to_id(argv[i]);
01552 for (;;) {
01553 me = search_method(m, id, 0);
01554 if (me == 0) {
01555 me = search_method(rb_cObject, id, 0);
01556 }
01557 if (UNDEFINED_METHOD_ENTRY_P(me)) {
01558 rb_print_undef(module, id, 0);
01559 }
01560 if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
01561 break;
01562 }
01563 m = RCLASS_SUPER(m);
01564 if (!m)
01565 break;
01566 }
01567 rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC);
01568 }
01569 return module;
01570 }
01571
01572 int
01573 rb_method_basic_definition_p(VALUE klass, ID id)
01574 {
01575 const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
01576 if (me && (me->flag & NOEX_BASIC))
01577 return 1;
01578 return 0;
01579 }
01580
01581 static inline int
01582 basic_obj_respond_to(VALUE obj, ID id, int pub)
01583 {
01584 VALUE klass = CLASS_OF(obj);
01585 VALUE args[2];
01586
01587 switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
01588 case 2:
01589 return FALSE;
01590 case 0:
01591 args[0] = ID2SYM(id);
01592 args[1] = pub ? Qfalse : Qtrue;
01593 return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args));
01594 default:
01595 return TRUE;
01596 }
01597 }
01598
01599 int
01600 rb_obj_respond_to(VALUE obj, ID id, int priv)
01601 {
01602 VALUE klass = CLASS_OF(obj);
01603
01604 if (rb_method_basic_definition_p(klass, idRespond_to)) {
01605 return basic_obj_respond_to(obj, id, !RTEST(priv));
01606 }
01607 else {
01608 int argc = 1;
01609 VALUE args[2];
01610 args[0] = ID2SYM(id);
01611 args[1] = Qtrue;
01612 if (priv) {
01613 if (rb_obj_method_arity(obj, idRespond_to) != 1) {
01614 argc = 2;
01615 }
01616 else if (!NIL_P(ruby_verbose)) {
01617 VALUE klass = CLASS_OF(obj);
01618 VALUE location = rb_mod_method_location(klass, idRespond_to);
01619 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is"
01620 " old fashion which takes only one parameter",
01621 (FL_TEST(klass, FL_SINGLETON) ? obj : klass),
01622 (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'),
01623 QUOTE_ID(id));
01624 if (!NIL_P(location)) {
01625 VALUE path = RARRAY_AREF(location, 0);
01626 VALUE line = RARRAY_AREF(location, 1);
01627 if (!NIL_P(path)) {
01628 rb_compile_warn(RSTRING_PTR(path), NUM2INT(line),
01629 "respond_to? is defined here");
01630 }
01631 }
01632 }
01633 }
01634 return RTEST(rb_funcall2(obj, idRespond_to, argc, args));
01635 }
01636 }
01637
01638 int
01639 rb_respond_to(VALUE obj, ID id)
01640 {
01641 return rb_obj_respond_to(obj, id, FALSE);
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 static VALUE
01666 obj_respond_to(int argc, VALUE *argv, VALUE obj)
01667 {
01668 VALUE mid, priv;
01669 ID id;
01670
01671 rb_scan_args(argc, argv, "11", &mid, &priv);
01672 if (!(id = rb_check_id(&mid))) {
01673 if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
01674 VALUE args[2];
01675 args[0] = ID2SYM(rb_to_id(mid));
01676 args[1] = priv;
01677 return rb_funcall2(obj, idRespond_to_missing, 2, args);
01678 }
01679 return Qfalse;
01680 }
01681 if (basic_obj_respond_to(obj, id, !RTEST(priv)))
01682 return Qtrue;
01683 return Qfalse;
01684 }
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 static VALUE
01702 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
01703 {
01704 return Qfalse;
01705 }
01706
01707 void
01708 Init_eval_method(void)
01709 {
01710 #undef rb_intern
01711 #define rb_intern(str) rb_intern_const(str)
01712
01713 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
01714 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
01715
01716 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
01717 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
01718 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
01719 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
01720 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
01721 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
01722 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
01723
01724 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
01725 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
01726 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
01727 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
01728 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
01729 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
01730
01731 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01732 "public", top_public, -1);
01733 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01734 "private", top_private, -1);
01735
01736 {
01737 #define REPLICATE_METHOD(klass, id, noex) \
01738 rb_method_entry_set((klass), (id), \
01739 rb_method_entry((klass), (id), 0), \
01740 (rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF))
01741 REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE);
01742 REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC);
01743 REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
01744 }
01745 }
01746