void rb_sweep_method_entry(void *pvm) { rb_vm_t *vm = pvm; struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume; while (ume) { if (ume->me->mark) { ume->me->mark = 0; prev_ume = ume; ume = ume->next; } else { rb_free_method_entry(ume->me); if (prev_ume == 0) { vm->unlinked_method_entry_list = ume->next; } else { prev_ume->next = ume->next; } curr_ume = ume; ume = ume->next; xfree(curr_ume); } } }
static void remove_method(VALUE klass, ID mid) { st_data_t data; rb_method_entry_t *me = 0; if (klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't remove method"); } if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); if (mid == object_id || mid == id__send__ || mid == idInitialize) { rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); } if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || !(me = (rb_method_entry_t *)data) || (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { rb_name_error(mid, "method `%s' not defined in %s", rb_id2name(mid), rb_class2name(klass)); } st_delete(RCLASS_M_TBL(klass), &mid, &data); rb_vm_check_redefinition_opt_method(me); rb_clear_cache_for_undef(klass, mid); rb_free_method_entry(me); CALL_METHOD_HOOK(klass, removed, mid); }
static void release_method_definition(rb_method_definition_t *def) { if (def == 0) return; if (def->alias_count == 0) { if (def->type == VM_METHOD_TYPE_REFINED && def->body.orig_me) { rb_free_method_entry(def->body.orig_me); } xfree(def); } else if (def->alias_count > 0) { def->alias_count--; } }
void rb_sweep_method_entry(void *pvm) { rb_vm_t *vm = pvm; struct unlinked_method_entry_list_entry **prev_ume = &vm->unlinked_method_entry_list, *ume = *prev_ume, *curr_ume; while (ume) { if (ume->me->mark) { ume->me->mark = 0; prev_ume = &ume->next; ume = *prev_ume; } else { rb_free_method_entry(ume->me); curr_ume = ume; ume = ume->next; *prev_ume = ume; xfree(curr_ume); } } }
static int free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) { rb_free_method_entry(me); return ST_CONTINUE; }
static rb_method_entry_t * rb_add_method_def(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_flag_t noex) { rb_method_entry_t *me; st_table *mtbl; st_data_t data; if (NIL_P(klass)) { klass = rb_cObject; } if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_UNTRUSTED(klass))) { rb_raise(rb_eSecurityError, "Insecure: can't define method"); } if (!FL_TEST(klass, FL_SINGLETON) && type != VM_METHOD_TYPE_NOTIMPLEMENTED && type != VM_METHOD_TYPE_ZSUPER && (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { noex = NOEX_PRIVATE | noex; } else if (FL_TEST(klass, FL_SINGLETON) && type == VM_METHOD_TYPE_CFUNC && mid == rb_intern("allocate")) { rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()", rb_class2name(rb_ivar_get(klass, attached))); mid = ID_ALLOCATOR; } if (OBJ_FROZEN(klass)) { rb_error_frozen("class/module"); } mtbl = RCLASS_M_TBL(klass); /* check re-definition */ if (st_lookup(mtbl, mid, &data)) { rb_method_entry_t *old_me = (rb_method_entry_t *)data; rb_method_definition_t *old_def = old_me->def; if (rb_method_definition_eq(old_def, def)) return old_me; rb_vm_check_redefinition_opt_method(old_me); if (RTEST(ruby_verbose) && type != VM_METHOD_TYPE_UNDEF && old_def->alias_count == 0 && old_def->type != VM_METHOD_TYPE_UNDEF && old_def->type != VM_METHOD_TYPE_ZSUPER) { extern rb_iseq_t *rb_proc_get_iseq(VALUE proc, int *is_proc); rb_iseq_t *iseq = 0; rb_warning("method redefined; discarding old %s", rb_id2name(mid)); switch (old_def->type) { case VM_METHOD_TYPE_ISEQ: iseq = old_def->body.iseq; break; case VM_METHOD_TYPE_BMETHOD: iseq = rb_proc_get_iseq(old_def->body.proc, 0); break; default: break; } if (iseq && !NIL_P(iseq->filename)) { int line = iseq->insn_info_table ? rb_iseq_first_lineno(iseq) : 0; rb_compile_warning(RSTRING_PTR(iseq->filename), line, "previous definition of %s was here", rb_id2name(old_def->original_id)); } } rb_free_method_entry(old_me); } rb_clear_cache_by_id(mid); me = ALLOC(rb_method_entry_t); me->flag = NOEX_WITH_SAFE(noex); me->called_id = mid; me->klass = klass; me->def = def; if (def) def->alias_count++; /* check mid */ if (klass == rb_cObject && mid == idInitialize) { rb_warn("redefining Object#initialize may cause infinite loop"); } /* check mid */ if (mid == object_id || mid == id__send__) { if (type == VM_METHOD_TYPE_ISEQ) { rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid)); } } st_insert(mtbl, mid, (st_data_t) me); return me; }