summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog27
-rw-r--r--internal.h1
-rw-r--r--iseq.c18
-rw-r--r--proc.c1
-rw-r--r--test/-ext-/debug/test_profile_frames.rb8
-rw-r--r--test/ruby/test_method.rb6
-rw-r--r--vm.c6
-rw-r--r--vm_backtrace.c81
-rw-r--r--vm_core.h1
-rw-r--r--vm_insnhelper.c51
10 files changed, 106 insertions, 94 deletions
diff --git a/ChangeLog b/ChangeLog
index d2ac69160c..4931830434 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+Tue Jul 7 03:33:20 2015 Koichi Sasada <ko1@atdot.net>
+
+ * vm_core.h: remove rb_iseq_t::klass to reduce dynamic data.
+
+ * internal.h, iseq.c (rb_iseq_klass): remove it because
+ rb_iseq_t::klass is removed.
+
+ * vm_insnhelper.c (vm_super_outside): do not see cfp->iseq, but
+ check callable method entry on a frame.
+ This fix simplify the logic to search super class.
+
+ * test/ruby/test_method.rb: support super() from Proc.
+ Now, [Bug #4881] and [Bug #3136] was solved.
+
+ * proc.c (rb_mod_define_method): catch up this change.
+
+ * vm.c (vm_define_method): ditto.
+
+ * vm_backtrace.c (rb_profile_frames): now, each `frame' objects
+ are rb_callable_method_entry_t data or iseq VALUEs.
+
+ This fix introduce minor compatibility issue that
+ rb_profile_frame_label() always returns
+ rb_profile_frame_base_label().
+
+ * test/-ext-/debug/test_profile_frames.rb: catch up this change.
+
Tue Jul 7 01:52:14 2015 Koichi Sasada <ko1@atdot.net>
* cont.c (fiber_init): initialize control frame correctly.
diff --git a/internal.h b/internal.h
index 86bf5fd9cc..268d655c1c 100644
--- a/internal.h
+++ b/internal.h
@@ -853,7 +853,6 @@ VALUE rb_iseq_absolute_path(VALUE iseqval);
VALUE rb_iseq_label(VALUE iseqval);
VALUE rb_iseq_base_label(VALUE iseqval);
VALUE rb_iseq_first_lineno(VALUE iseqval);
-VALUE rb_iseq_klass(VALUE iseqval); /* completely temporary function */
VALUE rb_iseq_method_name(VALUE self);
/* load.c */
diff --git a/iseq.c b/iseq.c
index 48de119a32..1bdb5f7407 100644
--- a/iseq.c
+++ b/iseq.c
@@ -127,8 +127,6 @@ iseq_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(iseq->orig);
}
- RUBY_MARK_UNLESS_NULL(iseq->klass);
-
if (iseq->compile_data != 0) {
struct iseq_compile_data *const compile_data = iseq->compile_data;
RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
@@ -261,7 +259,6 @@ prepare_iseq_build(rb_iseq_t *iseq,
const rb_compile_option_t *option)
{
iseq->type = type;
- RB_OBJ_WRITE(iseq->self, &iseq->klass, 0);
set_relation(iseq, parent);
name = rb_fstring(name);
@@ -939,14 +936,6 @@ rb_iseq_first_lineno(VALUE self)
}
VALUE
-rb_iseq_klass(VALUE self)
-{
- rb_iseq_t *iseq;
- GetISeqPtr(self, iseq);
- return iseq->local_iseq->klass;
-}
-
-VALUE
rb_iseq_method_name(VALUE self)
{
rb_iseq_t *iseq, *local_iseq;
@@ -1961,13 +1950,6 @@ rb_iseq_clone(VALUE iseqval, VALUE newcbase)
iseq1->local_iseq = iseq1;
}
- if (newcbase) {
- RB_OBJ_WRITE(iseq1->self, &iseq1->klass, newcbase);
- }
- else {
- RB_OBJ_WRITTEN(iseq1->self, Qundef, iseq1->klass);
- }
-
RB_GC_GUARD(iseqval); /* seems necessary iff RGenGC is disabled */
return newiseq;
diff --git a/proc.c b/proc.c
index 387a7ba5e7..1b57b31792 100644
--- a/proc.c
+++ b/proc.c
@@ -1725,7 +1725,6 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
GetProcPtr(body, proc);
if (!RUBY_VM_IFUNC_P(proc->block.iseq)) {
proc->block.iseq->defined_method_id = id;
- RB_OBJ_WRITE(proc->block.iseq->self, &proc->block.iseq->klass, mod);
proc->is_lambda = TRUE;
proc->is_from_method = TRUE;
}
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index 1879c222c2..e257ef09b3 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -25,12 +25,12 @@ class TestProfileFrames < Test::Unit::TestCase
}.resume
labels = [
- "block (2 levels) in test_profile_frames",
+ "test_profile_frames",
"zab",
"baz",
"bar",
"foo",
- "block in test_profile_frames",
+ "test_profile_frames",
]
base_labels = [
"test_profile_frames",
@@ -41,12 +41,12 @@ class TestProfileFrames < Test::Unit::TestCase
"test_profile_frames",
]
full_labels = [
- "block (2 levels) in TestProfileFrames#test_profile_frames",
+ "TestProfileFrames#test_profile_frames",
"#{obj.inspect}.zab",
"SampleClassForTestProfileFrames::Sample2#baz",
"SampleClassForTestProfileFrames.bar",
"SampleClassForTestProfileFrames#foo",
- "block in TestProfileFrames#test_profile_frames",
+ "TestProfileFrames#test_profile_frames",
]
classes = [
TestProfileFrames,
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 5de28cbbec..71d3b30dbf 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -405,11 +405,7 @@ class TestMethod < Test::Unit::TestCase
end
}
c2 = Class.new(c1) { define_method(:m) { Proc.new { super() } } }
- # c2.new.m.call should return :m1, but currently it raise NoMethodError.
- # see [Bug #4881] and [Bug #3136]
- assert_raise(NoMethodError) {
- c2.new.m.call
- }
+ assert_equal(:m1, c2.new.m.call, 'see [Bug #4881] and [Bug #3136]')
end
def test_clone
diff --git a/vm.c b/vm.c
index 36d5c8b42a..0ae5c45f70 100644
--- a/vm.c
+++ b/vm.c
@@ -2278,11 +2278,6 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
rb_iseq_t *miseq;
GetISeqPtr(iseqval, miseq);
- if (miseq->klass) {
- iseqval = rb_iseq_clone(iseqval, 0);
- GetISeqPtr(iseqval, miseq);
- }
-
if (NIL_P(klass)) {
rb_raise(rb_eTypeError, "no class/module to add method");
}
@@ -2293,7 +2288,6 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
}
/* dup */
- RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
miseq->defined_method_id = id;
rb_add_method_iseq(klass, id, iseqval, cref, visi);
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 99d3e7f3d3..3d4322cd4d 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -9,6 +9,8 @@
**********************************************************************/
+#define VM_CHECK_MODE 2
+
#include "internal.h"
#include "ruby/debug.h"
@@ -1248,15 +1250,24 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
rb_control_frame_t *cfp = th->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
for (i=0; i<limit && cfp != end_cfp;) {
- if (cfp->iseq && cfp->pc) { /* should be NORMAL_ISEQ */
+ const rb_callable_method_entry_t *cme = rb_vm_frame_method_entry(cfp);
+
+ if ((cme && cme->def->type == VM_METHOD_TYPE_ISEQ) || (cfp->iseq && cfp->pc)) {
if (start > 0) {
start--;
continue;
}
/* record frame info */
- buff[i] = cfp->iseq->self;
- if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
+ if (cme) {
+ buff[i] = (VALUE)cme;
+ }
+ else {
+ buff[i] = cfp->iseq->self;
+ }
+
+ if (cfp->iseq && lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
+
i++;
}
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
@@ -1265,42 +1276,83 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
return i;
}
-#define frame2iseq(frame) frame
+static VALUE
+frame2iseq(VALUE frame)
+{
+ if (frame == Qnil) return Qnil;
+
+ if (RB_TYPE_P(frame, T_DATA)) {
+ VM_ASSERT(strcmp(rb_objspace_data_type_name(frame), "iseq") == 0);
+ return frame;
+ }
+
+ if (RB_TYPE_P(frame, T_IMEMO)) {
+ const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+ VM_ASSERT(imemo_type(frame) == imemo_ment);
+ switch (cme->def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ return cme->def->body.iseq.iseqptr->self;
+ default:
+ return Qnil;
+ }
+ }
+ rb_bug("frame2iseq: unreachable");
+}
VALUE
rb_profile_frame_path(VALUE frame)
{
- return rb_iseq_path(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_path(iseqv);
}
VALUE
rb_profile_frame_absolute_path(VALUE frame)
{
- return rb_iseq_absolute_path(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_absolute_path(iseqv);
}
VALUE
rb_profile_frame_label(VALUE frame)
{
- return rb_iseq_label(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_label(iseqv);
}
VALUE
rb_profile_frame_base_label(VALUE frame)
{
- return rb_iseq_base_label(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_base_label(iseqv);
}
VALUE
rb_profile_frame_first_lineno(VALUE frame)
{
- return rb_iseq_first_lineno(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_first_lineno(iseqv);
+}
+
+static VALUE
+frame2klass(VALUE frame)
+{
+ if (frame == Qnil) return Qnil;
+
+ if (RB_TYPE_P(frame, T_IMEMO)) {
+ const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+ VM_ASSERT(imemo_type(frame) == imemo_ment);
+ return cme->defined_class;
+ }
+ else {
+ return Qnil;
+ }
}
VALUE
rb_profile_frame_classpath(VALUE frame)
{
- VALUE klass = rb_iseq_klass(frame2iseq(frame));
+ VALUE klass = frame2klass(frame);
if (klass && !NIL_P(klass)) {
if (RB_TYPE_P(klass, T_ICLASS)) {
@@ -1321,7 +1373,8 @@ rb_profile_frame_classpath(VALUE frame)
VALUE
rb_profile_frame_singleton_method_p(VALUE frame)
{
- VALUE klass = rb_iseq_klass(frame2iseq(frame));
+ VALUE klass = frame2klass(frame);
+
if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
return Qtrue;
}
@@ -1333,13 +1386,15 @@ rb_profile_frame_singleton_method_p(VALUE frame)
VALUE
rb_profile_frame_method_name(VALUE frame)
{
- return rb_iseq_method_name(frame2iseq(frame));
+ VALUE iseqv = frame2iseq(frame);
+ return NIL_P(iseqv) ? Qnil : rb_iseq_method_name(iseqv);
}
VALUE
rb_profile_frame_qualified_method_name(VALUE frame)
{
- VALUE method_name = rb_iseq_method_name(frame2iseq(frame));
+ VALUE method_name = rb_profile_frame_method_name(frame);
+
if (method_name != Qnil) {
VALUE classpath = rb_profile_frame_classpath(frame);
VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
diff --git a/vm_core.h b/vm_core.h
index 58179ffbef..48bf223853 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -348,7 +348,6 @@ struct rb_iseq_struct {
VALUE self;
const VALUE orig; /* non-NULL if its data have origin */
- const VALUE klass;
/* misc */
ID defined_method_id; /* for define_method */
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 2c6e76ce6e..864a3dabc5 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2173,58 +2173,19 @@ vm_super_outside(void)
static int
vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq, VALUE sigval, rb_call_info_t *ci)
{
- const rb_callable_method_entry_t *me;
-
- while (iseq && !iseq->klass) {
- iseq = iseq->parent_iseq;
- }
+ const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
- if (iseq == 0) {
+ if (me == NULL) {
return -1;
}
-
- ci->mid = iseq->defined_method_id;
-
- if (iseq != iseq->local_iseq) {
- /* defined by Module#define_method() */
- rb_control_frame_t *lcfp = GET_CFP();
-
- if (!sigval) {
- /* zsuper */
- return -2;
- }
-
- while (lcfp->iseq != iseq) {
- rb_thread_t *th = GET_THREAD();
- VALUE *tep = VM_EP_PREV_EP(lcfp->ep);
- while (1) {
- lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
- return -1;
- }
- if (lcfp->ep == tep) {
- break;
- }
- }
- }
-
- me = rb_vm_frame_method_entry(lcfp);
-
- /* temporary measure for [Bug #2420] [Bug #3136] */
- if (!me) {
- fprintf(stderr, "kore?\n");
- return -1;
- }
-
- ci->mid = me->def->original_id;
- ci->klass = vm_search_normal_superclass(me->defined_class);
+ else if (me->def->type == VM_METHOD_TYPE_BMETHOD && !sigval) {
+ return -2;
}
else {
- me = rb_vm_frame_method_entry(reg_cfp);
+ ci->mid = me->def->original_id;
ci->klass = vm_search_normal_superclass(me->defined_class);
+ return 0;
}
-
- return 0;
}
static void