* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51166 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2015-07-06 18:44:54 +00:00
Родитель 202643de00
Коммит 02d5868962
10 изменённых файлов: 106 добавлений и 94 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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 */

18
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);
@ -938,14 +935,6 @@ rb_iseq_first_lineno(VALUE self)
return iseq->location.first_lineno;
}
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)
{
@ -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;

1
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;
}

Просмотреть файл

@ -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,

Просмотреть файл

@ -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

6
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);

Просмотреть файл

@ -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);

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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;
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
while (iseq && !iseq->klass) {
iseq = iseq->parent_iseq;
}
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