From c46f71399ae54967e7247ac4df0c26adeddbffd6 Mon Sep 17 00:00:00 2001 From: wanabe Date: Mon, 22 Mar 2010 11:44:01 +0000 Subject: * proc.c (rb_method_location): return attr's location if it is setup. [Feature #2084] * NEWS: follow above. * vm_method.c (rb_add_method): save attr's location. * gc.c (mark_method_entry): mark attr's location. * method.h (rb_method_definition_t): add member to save attr's location. * vm_eval.c (vm_call0): follow above. * vm_insnhelper.c (vm_call_method): ditto. * vm_method.c (rb_method_definition_eq): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27016 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 19 +++++++++++++++++++ NEWS | 5 +++++ gc.c | 4 ++++ method.h | 7 ++++++- proc.c | 25 ++++++++++++++++++++----- vm_eval.c | 4 ++-- vm_insnhelper.c | 4 ++-- vm_method.c | 15 +++++++++++++-- 8 files changed, 71 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index d9baf8564d..730a55d9a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +Mon Mar 22 20:32:22 2010 wanabe + + * proc.c (rb_method_location): return attr's location if it is setup. + [Feature #2084] + + * NEWS: follow above. + + * vm_method.c (rb_add_method): save attr's location. + + * gc.c (mark_method_entry): mark attr's location. + + * method.h (rb_method_definition_t): add member to save attr's location. + + * vm_eval.c (vm_call0): follow above. + + * vm_insnhelper.c (vm_call_method): ditto. + + * vm_method.c (rb_method_definition_eq): ditto. + Mon Mar 22 19:31:06 2010 Tadayoshi Funaba * lib/date.rb (Date#>>): fixed. [ruby-core:28011] diff --git a/NEWS b/NEWS index 04ddaf9719..4821eb6cf6 100644 --- a/NEWS +++ b/NEWS @@ -96,6 +96,11 @@ with all sufficient information, see the ChangeLog file. * New method: * MatchData#== + * Proc + * extended method: + * Proc#source_location returns location even if receiver is a method + defined by attr_reader / attr_writer / attr_accessor. + * Process * extended methods: * Process.spawn accepts [:child, FD] for a redirect target. diff --git a/gc.c b/gc.c index 768337d84f..9761a06a39 100644 --- a/gc.c +++ b/gc.c @@ -1423,6 +1423,10 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me, int lev) case VM_METHOD_TYPE_BMETHOD: gc_mark(objspace, def->body.proc, lev); break; + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + gc_mark(objspace, def->body.attr.location, lev); + break; default: break; /* ignore */ } diff --git a/method.h b/method.h index 177d7bc677..c67667d3d8 100644 --- a/method.h +++ b/method.h @@ -49,6 +49,11 @@ typedef struct rb_method_cfunc_struct { int argc; } rb_method_cfunc_t; +typedef struct rb_method_attr_struct { + ID id; + VALUE location; +} rb_method_attr_t; + typedef struct rb_iseq_struct rb_iseq_t; typedef struct rb_method_definition_struct { @@ -57,7 +62,7 @@ typedef struct rb_method_definition_struct { union { rb_iseq_t *iseq; /* should be mark */ rb_method_cfunc_t cfunc; - ID attr_id; + rb_method_attr_t attr; VALUE proc; /* should be mark */ enum method_optimized_type { OPTIMIZED_METHOD_TYPE_SEND, diff --git a/proc.c b/proc.c index 543ee95923..eff7a0bbbc 100644 --- a/proc.c +++ b/proc.c @@ -1634,15 +1634,18 @@ rb_obj_method_arity(VALUE obj, ID id) return rb_mod_method_arity(CLASS_OF(obj), id); } -rb_iseq_t * -rb_method_get_iseq(VALUE method) +static inline rb_method_definition_t * +method_get_def(VALUE method) { struct METHOD *data; - rb_method_definition_t *def; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - def = data->me.def; + return data->me.def; +} +static rb_iseq_t * +method_get_iseq(rb_method_definition_t *def) +{ switch (def->type) { case VM_METHOD_TYPE_BMETHOD: return get_proc_iseq(def->body.proc, 0); @@ -1653,6 +1656,12 @@ rb_method_get_iseq(VALUE method) } } +rb_iseq_t * +rb_method_get_iseq(VALUE method) +{ + return method_get_iseq(method_get_def(method)); +} + /* * call-seq: * meth.source_location => [String, Fixnum] @@ -1664,7 +1673,13 @@ rb_method_get_iseq(VALUE method) VALUE rb_method_location(VALUE method) { - return iseq_location(rb_method_get_iseq(method)); + rb_method_definition_t *def = method_get_def(method); + if (def->type == VM_METHOD_TYPE_ATTRSET || def->type == VM_METHOD_TYPE_IVAR) { + if (!def->body.attr.location) + return Qnil; + return rb_ary_dup(def->body.attr.location); + } + return iseq_location(method_get_iseq(def)); } /* diff --git a/vm_eval.c b/vm_eval.c index 0ce4b8f45d..ea72365d9d 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -89,14 +89,14 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, if (argc != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } - val = rb_ivar_set(recv, def->body.attr_id, argv[0]); + val = rb_ivar_set(recv, def->body.attr.id, argv[0]); break; } case VM_METHOD_TYPE_IVAR: { if (argc != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } - val = rb_attr_get(recv, def->body.attr_id); + val = rb_attr_get(recv, def->body.attr.id); break; } case VM_METHOD_TYPE_BMETHOD: { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 23b48506f5..cd74c8e18d 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -504,7 +504,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, if (num != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num); } - val = rb_ivar_set(recv, me->def->body.attr_id, *(cfp->sp - 1)); + val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1)); cfp->sp -= 2; break; } @@ -512,7 +512,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, if (num != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num); } - val = rb_attr_get(recv, me->def->body.attr_id); + val = rb_attr_get(recv, me->def->body.attr.id); cfp->sp -= 1; break; } diff --git a/vm_method.c b/vm_method.c index 5a78906a2e..4b5ab89e7c 100644 --- a/vm_method.c +++ b/vm_method.c @@ -260,6 +260,9 @@ method_added(VALUE klass, ID mid) rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) { + rb_thread_t *th; + rb_control_frame_t *cfp; + int line; rb_method_entry_t *me = rb_add_method_def(klass, mid, type, 0, noex); rb_method_definition_t *def = ALLOC(rb_method_definition_t); me->def = def; @@ -275,7 +278,15 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_ break; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: - def->body.attr_id = (ID)opts; + def->body.attr.id = (ID)opts; + th = GET_THREAD(); + cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); + if (cfp && (line = rb_vm_get_sourceline(cfp))) { + VALUE location = rb_ary_new3(2, cfp->iseq->filename, INT2FIX(line)); + def->body.attr.location = rb_ary_freeze(location); + } else { + def->body.attr.location = Qfalse; + } break; case VM_METHOD_TYPE_BMETHOD: def->body.proc = (VALUE)opts; @@ -838,7 +849,7 @@ rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_defini d1->body.cfunc.argc == d2->body.cfunc.argc; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: - return d1->body.attr_id == d2->body.attr_id; + return d1->body.attr.id == d2->body.attr.id; case VM_METHOD_TYPE_BMETHOD: return RTEST(rb_equal(d1->body.proc, d2->body.proc)); case VM_METHOD_TYPE_MISSING: -- cgit v1.2.3