summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--NEWS5
-rw-r--r--gc.c4
-rw-r--r--method.h7
-rw-r--r--proc.c25
-rw-r--r--vm_eval.c4
-rw-r--r--vm_insnhelper.c4
-rw-r--r--vm_method.c15
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 <s.wanabe@gmail.com>
+
+ * 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 <tadf@dotrb.org>
* 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: