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);
	}
    }
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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--;
    }
}
Esempio n. 4
0
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);
	}
    }
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}