Navigation Menu

Skip to content

Commit

Permalink
* method.h (rb_method_definition_t): split from rb_method_entry_t
Browse files Browse the repository at this point in the history
  to deal aliases.  [ruby-dev:39165]

* proc.c (struct METHOD): contains rb_method_entry_t copy.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
nobu committed Aug 28, 2009
1 parent a2f3787 commit fcf88c1
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 193 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
@@ -1,3 +1,10 @@
Fri Aug 28 11:45:33 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>

* method.h (rb_method_definition_t): split from rb_method_entry_
to deal aliases. [ruby-dev:39165]

* proc.c (struct METHOD): contains rb_method_entry_t copy.

Fri Aug 28 10:21:30 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>

* iseq.c (iseq_mark): skip outdated cache entries.
Expand Down
19 changes: 8 additions & 11 deletions class.c
Expand Up @@ -126,17 +126,14 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
static int
clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data)
{
switch (me->type) {
case VM_METHOD_TYPE_ISEQ: {
VALUE newiseqval = rb_iseq_clone(me->body.iseq->self, data->klass);
rb_iseq_t *iseq;
GetISeqPtr(newiseqval, iseq);
rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
break;
}
default:
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
VALUE newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass);
rb_iseq_t *iseq;
GetISeqPtr(newiseqval, iseq);
rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
}
else {
rb_add_method_me(data->klass, mid, me, me->flag);
break;
}
return ST_CONTINUE;
}
Expand Down Expand Up @@ -683,7 +680,7 @@ method_entry(ID key, const rb_method_entry_t *me, st_table *list)
}

if (!st_lookup(list, key, 0)) {
if (!me || me->type == VM_METHOD_TYPE_UNDEF) {
if (UNDEFINED_METHOD_ENTRY_P(me)) {
type = -1; /* none */
}
else {
Expand Down
2 changes: 1 addition & 1 deletion eval.c
Expand Up @@ -693,7 +693,7 @@ frame_func_id(rb_control_frame_t *cfp)
{
rb_iseq_t *iseq = cfp->iseq;
if (!iseq) {
return cfp->me->original_id;
return cfp->me->def->original_id;
}
while (iseq) {
if (RUBY_VM_IFUNC_P(iseq)) {
Expand Down
11 changes: 7 additions & 4 deletions gc.c
Expand Up @@ -1377,13 +1377,16 @@ rb_mark_hash(st_table *tbl)
static void
mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me, int lev)
{
const rb_method_definition_t *def = me->def;

gc_mark(objspace, me->klass, lev);
switch (me->type) {
if (!def) return;
switch (def->type) {
case VM_METHOD_TYPE_ISEQ:
gc_mark(objspace, me->body.iseq->self, lev);
gc_mark(objspace, def->body.iseq->self, lev);
break;
case VM_METHOD_TYPE_BMETHOD:
gc_mark(objspace, me->body.proc, lev);
gc_mark(objspace, def->body.proc, lev);
break;
default:
break; /* ignore */
Expand Down Expand Up @@ -1417,7 +1420,7 @@ mark_m_tbl(rb_objspace_t *objspace, st_table *tbl, int lev)
static int
free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
{
xfree(me);
rb_free_method_entry(me);
return ST_CONTINUE;
}

Expand Down
17 changes: 12 additions & 5 deletions method.h
Expand Up @@ -49,12 +49,9 @@ typedef struct rb_method_cfunc_struct {

typedef struct rb_iseq_struct rb_iseq_t;

typedef struct rb_method_entry_struct {
rb_method_flag_t flag;
typedef struct rb_method_definition_struct {
rb_method_type_t type; /* method type */
ID called_id;
ID original_id;
VALUE klass; /* should be mark */
union {
rb_iseq_t *iseq; /* should be mark */
rb_method_cfunc_t cfunc;
Expand All @@ -66,13 +63,23 @@ typedef struct rb_method_entry_struct {
} optimize_type;
} body;
int alias_count;
} rb_method_definition_t;

typedef struct rb_method_entry_struct {
rb_method_flag_t flag;
rb_method_definition_t *def;
ID called_id;
VALUE klass; /* should be mark */
} rb_method_entry_t;

#define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF)

void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
void rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
rb_method_entry_t *rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
rb_method_entry_t *rb_method_entry(VALUE klass, ID id);
int rb_method_entry_arity(const rb_method_entry_t *me);
void rb_gc_mark_method_entry(const rb_method_entry_t *me);
void rb_free_method_entry(rb_method_entry_t *me);

#endif /* METHOD_H */
85 changes: 52 additions & 33 deletions proc.c
Expand Up @@ -16,7 +16,7 @@ struct METHOD {
VALUE recv;
VALUE rclass;
ID id;
rb_method_entry_t *me;
rb_method_entry_t me;
};

VALUE rb_cUnboundMethod;
Expand Down Expand Up @@ -843,7 +843,18 @@ bm_mark(void *ptr)
struct METHOD *data = ptr;
rb_gc_mark(data->rclass);
rb_gc_mark(data->recv);
rb_gc_mark_method_entry(data->me);
rb_gc_mark_method_entry(&data->me);
}

static void
bm_free(void *ptr)
{
struct METHOD *data = ptr;
rb_method_definition_t *def = data->me.def;
if (def->alias_count == 0)
xfree(def);
else if (def->alias_count > 0)
def->alias_count--;
}

static size_t
Expand All @@ -855,7 +866,7 @@ bm_memsize(void *ptr)
static const rb_data_type_t method_data_type = {
"method",
bm_mark,
RUBY_TYPED_DEFAULT_FREE,
bm_free,
bm_memsize,
};

Expand All @@ -873,18 +884,20 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
ID rid = id;
struct METHOD *data;
rb_method_entry_t *me;
rb_method_definition_t *def;

again:
me = rb_method_entry(klass, id);
if (!me) {
if (UNDEFINED_METHOD_ENTRY_P(me)) {
rb_print_undef(klass, id, 0);
}
def = me->def;
if (scope && (me->flag & NOEX_MASK) != NOEX_PUBLIC) {
rb_print_undef(rclass, me->original_id, (int)(me->flag & NOEX_MASK));
rb_print_undef(rclass, def->original_id, (int)(me->flag & NOEX_MASK));
}
if (me->type == VM_METHOD_TYPE_ZSUPER) {
if (def->type == VM_METHOD_TYPE_ZSUPER) {
klass = RCLASS_SUPER(me->klass);
id = me->original_id;
id = def->original_id;
goto again;
}

Expand All @@ -904,7 +917,8 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
data->recv = obj;
data->rclass = rclass;
data->id = rid;
data->me = me;
data->me = *me;
if (def) def->alias_count++;

OBJ_INFECT(method, klass);

Expand Down Expand Up @@ -959,7 +973,7 @@ method_eq(VALUE method, VALUE other)
m1 = (struct METHOD *)DATA_PTR(method);
m2 = (struct METHOD *)DATA_PTR(other);

if (!rb_method_entry_eq(m1->me, m2->me) ||
if (!rb_method_entry_eq(&m1->me, &m2->me) ||
m1->rclass != m2->rclass ||
m1->recv != m2->recv) {
return Qfalse;
Expand All @@ -984,7 +998,7 @@ method_hash(VALUE method)
TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
hash = (long)m->rclass;
hash ^= (long)m->recv;
hash ^= (long)m->me;
hash ^= (long)m->me.def;

return INT2FIX(hash);
}
Expand All @@ -1010,6 +1024,7 @@ method_unbind(VALUE obj)
data->recv = Qundef;
data->id = orig->id;
data->me = orig->me;
if (orig->me.def) orig->me.def->alias_count++;
data->rclass = orig->rclass;
OBJ_INFECT(method, obj);

Expand Down Expand Up @@ -1061,7 +1076,7 @@ method_owner(VALUE obj)
struct METHOD *data;

TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
return data->me->klass;
return data->me.klass;
}

/*
Expand Down Expand Up @@ -1223,7 +1238,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
rb_class2name(rclass));
}
}
rb_add_method_me(mod, id, method->me, noex);
rb_add_method_me(mod, id, &method->me, noex);
}
else if (rb_obj_is_proc(body)) {
rb_proc_t *proc;
Expand Down Expand Up @@ -1294,6 +1309,7 @@ method_clone(VALUE self)
clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
CLONESETUP(clone, self);
*data = *orig;
if (data->me.def) data->me.def->alias_count++;

return clone;
}
Expand Down Expand Up @@ -1336,7 +1352,7 @@ rb_method_call(int argc, VALUE *argv, VALUE method)
const rb_method_entry_t *me);

PASS_PASSED_BLOCK_TH(th);
result = rb_vm_call(th, data->recv, data->id, argc, argv, data->me);
result = rb_vm_call(th, data->recv, data->id, argc, argv, &data->me);
}
POP_TAG();
if (safe >= 0)
Expand Down Expand Up @@ -1456,6 +1472,7 @@ umethod_bind(VALUE method, VALUE recv)

method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
*bound = *data;
if (bound->me.def) bound->me.def->alias_count++;
bound->recv = recv;
bound->rclass = CLASS_OF(recv);

Expand All @@ -1465,21 +1482,23 @@ umethod_bind(VALUE method, VALUE recv)
int
rb_method_entry_arity(const rb_method_entry_t *me)
{
switch (me->type) {
const rb_method_definition_t *def = me->def;
if (!def) return 0;
switch (def->type) {
case VM_METHOD_TYPE_CFUNC:
if (me->body.cfunc.argc < 0)
if (def->body.cfunc.argc < 0)
return -1;
return check_argc(me->body.cfunc.argc);
return check_argc(def->body.cfunc.argc);
case VM_METHOD_TYPE_ZSUPER:
return -1;
case VM_METHOD_TYPE_ATTRSET:
return 1;
case VM_METHOD_TYPE_IVAR:
return 0;
case VM_METHOD_TYPE_BMETHOD:
return rb_proc_arity(me->body.proc);
return rb_proc_arity(def->body.proc);
case VM_METHOD_TYPE_ISEQ: {
rb_iseq_t *iseq = me->body.iseq;
rb_iseq_t *iseq = def->body.iseq;
if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
return iseq->argc;
}
Expand All @@ -1491,15 +1510,15 @@ rb_method_entry_arity(const rb_method_entry_t *me)
case VM_METHOD_TYPE_NOTIMPLEMENTED:
return 0;
case VM_METHOD_TYPE_OPTIMIZED: {
switch (me->body.optimize_type) {
switch (def->body.optimize_type) {
case OPTIMIZED_METHOD_TYPE_SEND:
return -1;
default:
break;
}
}
}
rb_bug("rb_method_entry_arity: invalid method entry type (%d)", me->type);
rb_bug("rb_method_entry_arity: invalid method entry type (%d)", def->type);
}

/*
Expand Down Expand Up @@ -1548,7 +1567,7 @@ method_arity(VALUE method)
struct METHOD *data;

TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
return rb_method_entry_arity(data->me);
return rb_method_entry_arity(&data->me);
}

int
Expand All @@ -1568,16 +1587,16 @@ rb_iseq_t *
rb_method_get_iseq(VALUE method)
{
struct METHOD *data;
rb_method_entry_t *me;
rb_method_definition_t *def;

TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
me = data->me;
def = data->me.def;

switch (me->type) {
switch (def->type) {
case VM_METHOD_TYPE_BMETHOD:
return get_proc_iseq(me->body.proc, 0);
return get_proc_iseq(def->body.proc, 0);
case VM_METHOD_TYPE_ISEQ:
return me->body.iseq;
return def->body.iseq;
default:
return 0;
}
Expand Down Expand Up @@ -1638,11 +1657,11 @@ method_inspect(VALUE method)
rb_str_buf_cat2(str, s);
rb_str_buf_cat2(str, ": ");

if (FL_TEST(data->me->klass, FL_SINGLETON)) {
VALUE v = rb_iv_get(data->me->klass, "__attached__");
if (FL_TEST(data->me.klass, FL_SINGLETON)) {
VALUE v = rb_iv_get(data->me.klass, "__attached__");

if (data->recv == Qundef) {
rb_str_buf_append(str, rb_inspect(data->me->klass));
rb_str_buf_append(str, rb_inspect(data->me.klass));
}
else if (data->recv == v) {
rb_str_buf_append(str, rb_inspect(v));
Expand All @@ -1658,15 +1677,15 @@ method_inspect(VALUE method)
}
else {
rb_str_buf_cat2(str, rb_class2name(data->rclass));
if (data->rclass != data->me->klass) {
if (data->rclass != data->me.klass) {
rb_str_buf_cat2(str, "(");
rb_str_buf_cat2(str, rb_class2name(data->me->klass));
rb_str_buf_cat2(str, rb_class2name(data->me.klass));
rb_str_buf_cat2(str, ")");
}
}
rb_str_buf_cat2(str, sharp);
rb_str_append(str, rb_id2str(data->me->original_id));
if (data->me->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
rb_str_append(str, rb_id2str(data->me.def->original_id));
if (data->me.def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
rb_str_buf_cat2(str, " (not-implemented)");
}
rb_str_buf_cat2(str, ">");
Expand Down

0 comments on commit fcf88c1

Please sign in to comment.