[#38563] [Bug #1556] irb does not save history from 1.8.7-p83 and later — Nobuhiro IMAI <redmine@...>

Bug #1556: irb does not save history from 1.8.7-p83 and later

11 messages 2009/06/02

[#38571] [Bug #1582] IO.new Raises Other Errors between 1.8 and 1.9 — "ujihisa ." <redmine@...>

Bug #1582: IO.new Raises Other Errors between 1.8 and 1.9

15 messages 2009/06/05

[#38607] [Feature: trunk] GC.stat — SASADA Koichi <ko1@...>

 ささだです.

21 messages 2009/06/14

[#38608] Fixnum#fdiv — Tadayoshi Funaba <tadf@...>

Bignum#fdiv には大きな数である場合の配慮があるようですが、Fixnum ではな

23 messages 2009/06/14
[#38636] Re: Fixnum#fdiv — Tadayoshi Funaba <tadf@...> 2009/06/15

fdiv では2つの異る解釈が混在しているように見えます。

[#38638] Re: Fixnum#fdiv — Yukihiro Matsumoto <matz@...> 2009/06/15

まつもと ゆきひろです

[#38639] Re: Fixnum#fdiv — Tadayoshi Funaba <tadf@...> 2009/06/15

> えーと、設計者は「fdivは結果がfloatになるdiv」くらいしか考え

[#38640] Re: Fixnum#fdiv — Yukihiro Matsumoto <matz@...> 2009/06/15

まつもと ゆきひろです

[#38641] Re: Fixnum#fdiv — Tadayoshi Funaba <tadf@...> 2009/06/15

> ふむ。「中途半端」というのはfixnumとbignumで食い違うと言う意

[#38657] Re: Fixnum#fdiv — Tadayoshi Funaba <tadf@...> 2009/06/16

> > ふむ。「中途半端」というのはfixnumとbignumで食い違うと言う意

[#38659] Re: Fixnum#fdiv — Yukihiro Matsumoto <matz@...> 2009/06/16

まつもと ゆきひろです

[#38660] Re: Fixnum#fdiv — Tadayoshi Funaba <tadf@...> 2009/06/16

> 私が気にしているのは「挙動の理解しやすさ」ですね。

[#38701] [Bug #1676] only last "return" is traced by set_trace_func — _ wanabe <redmine@...>

Bug #1676: only last "return" is traced by set_trace_func

10 messages 2009/06/22

[ruby-dev:38705] Re: [Bug #1674] set_trace_func with 1line block

From: Yusuke ENDOH <mame@...>
Date: 2009-06-23 14:38:26 UTC
List: ruby-dev #38705
遠藤です。

2009/06/22 15:15 に _ wanabe<redmine@ruby-lang.org> さんは書きました:
> set_trace_funcだけでなく例外のバックトレース表示でも同様でした。
>
> $ ruby -e '1.upto(2) {
>  raise
> }'
> -e:1:in `block in <main>': unhandled exception
>        from -e:1:in `upto'
>        from -e:1:in `<main>'


カバレッジ測定機能にも影響があったので調べてみました。

r19592 で Proc#source_location などが導入されたとき、
brace_block で行番号をいじるようになったのが原因のようです。

  1: f = proc {
  2:  x
  3: }
  4: p f.source_location #=> 1

という挙動を実現するために、ブロックの先頭あたりのノードの
行番号を無理やり '{' のある行の番号に書き換えるようですが、
ちょっと ad-hoc だと思います。また、カバレッジの測定が変に
なるので実際問題としても困ります。


rb_iseq_struct に行番号を持たせるようにしてみました。
おまけの効果として、set_trace_func の class/end イベントや
call/return イベントの行番号をruby 1.8 と同じにできました。


Index: vm_core.h
===================================================================
--- vm_core.h	(revision 23832)
+++ vm_core.h	(working copy)
@@ -132,6 +132,7 @@
     unsigned long iseq_size;
     VALUE mark_ary;	/* Array: includes operands which should be GC marked */
     VALUE coverage;     /* coverage array */
+    unsigned short line_no;

     /* insn info, must be freed */
     struct iseq_insn_info_entry *insn_info_table;
@@ -433,8 +434,8 @@
 VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE);
 VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent);
 VALUE rb_iseq_new_main(NODE *node, VALUE filename);
-VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const
rb_compile_option_t*);
+VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE,
const rb_compile_option_t*);
 VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
 VALUE rb_iseq_disasm(VALUE self);
 VALUE rb_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos,
rb_iseq_t *iseq, VALUE child);
Index: iseq.c
===================================================================
--- iseq.c	(revision 23832)
+++ iseq.c	(working copy)
@@ -202,7 +202,7 @@

 static VALUE
 prepare_iseq_build(rb_iseq_t *iseq,
-		   VALUE name, VALUE filename,
+		   VALUE name, VALUE filename, VALUE line_no,
 		   VALUE parent, VALUE type, VALUE block_opt,
 		   const rb_compile_option_t *option)
 {
@@ -211,6 +211,7 @@

     iseq->name = name;
     iseq->filename = filename;
+    iseq->line_no = line_no;
     iseq->defined_method_id = 0;
     iseq->mark_ary = rb_ary_new();
     RBASIC(iseq->mark_ary)->klass = 0;
@@ -354,14 +355,14 @@
 rb_iseq_new(NODE *node, VALUE name, VALUE filename,
 	      VALUE parent, VALUE type)
 {
-    return rb_iseq_new_with_opt(node, name, filename, parent, type,
+    return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0), parent, type,
 				&COMPILE_OPTION_DEFAULT);
 }

 VALUE
 rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent)
 {
-    return rb_iseq_new_with_opt(node, name, filename, parent, ISEQ_TYPE_TOP,
+    return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0),
parent, ISEQ_TYPE_TOP,
 				&COMPILE_OPTION_DEFAULT);
 }

@@ -370,12 +371,12 @@
 {
     rb_thread_t *th = GET_THREAD();
     VALUE parent = th->base_block->iseq->self;
-    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename,
+    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"),
filename, INT2FIX(0),
 				parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
 }

 static VALUE
-rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename,
VALUE line_no,
 				VALUE parent, VALUE type, VALUE bopt,
 				const rb_compile_option_t *option)
 {
@@ -385,28 +386,28 @@
     GetISeqPtr(self, iseq);
     iseq->self = self;

-    prepare_iseq_build(iseq, name, filename, parent, type, bopt, option);
+    prepare_iseq_build(iseq, name, filename, line_no, parent, type,
bopt, option);
     rb_iseq_compile_node(self, node);
     cleanup_iseq_build(iseq);
     return self;
 }

 VALUE
-rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
 		     VALUE parent, VALUE type,
 		     const rb_compile_option_t *option)
 {
     /* TODO: argument check */
-    return rb_iseq_new_with_bopt_and_opt(node, name, filename, parent, type,
+    return rb_iseq_new_with_bopt_and_opt(node, name, filename,
line_no, parent, type,
 					   Qfalse, option);
 }

 VALUE
-rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
 		       VALUE parent, VALUE type, VALUE bopt)
 {
     /* TODO: argument check */
-    return rb_iseq_new_with_bopt_and_opt(node, name, filename, parent, type,
+    return rb_iseq_new_with_bopt_and_opt(node, name, filename,
line_no, parent, type,
 					   bopt, &COMPILE_OPTION_DEFAULT);
 }

@@ -420,7 +421,7 @@
     VALUE iseqval = iseq_alloc(self);

     VALUE magic, version1, version2, format_type, misc;
-    VALUE name, filename;
+    VALUE name, filename, line_no;
     VALUE type, body, locals, args, exception;

     VALUE iseq_type;
@@ -430,7 +431,7 @@
     int i = 0;

     /* [magic, major_version, minor_version, format_type, misc,
-     *  name, filename,
+     *  name, filename, line_no,
      *  type, locals, args, exception_table, body]
      */

@@ -444,6 +445,7 @@

     name        = CHECK_STRING(rb_ary_entry(data, i++));
     filename    = CHECK_STRING(rb_ary_entry(data, i++));
+    line_no     = CHECK_INTEGER(rb_ary_entry(data, i++));

     type        = CHECK_SYMBOL(rb_ary_entry(data, i++));
     locals      = CHECK_ARRAY(rb_ary_entry(data, i++));
@@ -485,7 +487,7 @@
     }

     make_compile_option(&option, opt);
-    prepare_iseq_build(iseq, name, filename,
+    prepare_iseq_build(iseq, name, filename, line_no,
 		       parent, iseq_type, 0, &option);

     rb_iseq_build_from_ary(iseq, locals, args, exception, body);
@@ -533,11 +535,11 @@

     if (th->base_block && th->base_block->iseq) {
 	return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
-				    file, th->base_block->iseq->self,
+				    file, line, th->base_block->iseq->self,
 				    ISEQ_TYPE_EVAL, &option);
     }
     else {
-	return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, Qfalse,
+	return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file,
line, Qfalse,
 				    ISEQ_TYPE_TOP, &option);
     }
 }
@@ -582,7 +584,7 @@
     parser = rb_parser_new();
     node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
     make_compile_option(&option, opt);
-    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, Qfalse,
+    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
line, Qfalse,
 				ISEQ_TYPE_TOP, &option);
 }

@@ -648,7 +650,7 @@
 int
 rb_iseq_first_lineno(rb_iseq_t *iseq)
 {
-    return iseq->insn_info_table[0].line_no;
+    return FIX2INT(iseq->line_no);
 }

 /* TODO: search algorithm is brute force.
@@ -1290,7 +1292,7 @@

     /*
      * [:magic, :major_version, :minor_version, :format_type, :misc,
-     *  :name, :filename, :type, :locals, :args,
+     *  :name, :filename, :line_no, :type, :locals, :args,
      *  :catch_table, :bytecode]
      */
     rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
@@ -1300,6 +1302,7 @@
     rb_ary_push(val, misc);
     rb_ary_push(val, iseq->name);
     rb_ary_push(val, iseq->filename);
+    rb_ary_push(val, iseq->line_no);
     rb_ary_push(val, type);
     rb_ary_push(val, locals);
     rb_ary_push(val, args);
@@ -1406,7 +1409,8 @@
     const VALUE *arg_opt_table,
     const struct iseq_catch_table_entry *catch_table,
     const char *name,
-    const char *filename)
+    const char *filename,
+    const unsigned short line_no)
 {
     int i;
     VALUE iseqval = iseq_alloc(rb_cISeq);
@@ -1417,6 +1421,7 @@
     *iseq = *iseq_template;
     iseq->name = rb_str_new2(name);
     iseq->filename = rb_str_new2(filename);
+    iseq->line_no = line_no;
     iseq->mark_ary = rb_ary_tmp_new(3);
     iseq->self = iseqval;

Index: compile.c
===================================================================
--- compile.c	(revision 23832)
+++ compile.c	(working copy)
@@ -167,15 +167,12 @@
 #define iseq_filename(iseq) \
   (((rb_iseq_t*)DATA_PTR(iseq))->filename)

-#define NEW_ISEQVAL(node, name, type)       \
-  new_child_iseq(iseq, node, name, 0, type)
+#define NEW_ISEQVAL(node, name, type, line_no)       \
+  new_child_iseq(iseq, node, name, 0, type, line_no)

-#define NEW_CHILD_ISEQVAL(node, name, type)       \
-  new_child_iseq(iseq, node, name, iseq->self, type)
+#define NEW_CHILD_ISEQVAL(node, name, type, line_no)       \
+  new_child_iseq(iseq, node, name, iseq->self, type, line_no)

-#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
-  new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq,
iseq->type, sym)
-
 /* add instructions */
 #define ADD_SEQ(seq1, seq2) \
   APPEND_LIST(seq1, seq2)
@@ -448,13 +445,13 @@
 	    break;
 	  }
 	  case ISEQ_TYPE_CLASS: {
-	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CLASS);
+	    ADD_TRACE(ret, FIX2INT(iseq->line_no), RUBY_EVENT_CLASS);
 	    COMPILE(ret, "scoped node", node->nd_body);
 	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
 	    break;
 	  }
 	  case ISEQ_TYPE_METHOD: {
-	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CALL);
+	    ADD_TRACE(ret, FIX2INT(iseq->line_no), RUBY_EVENT_CALL);
 	    COMPILE(ret, "scoped node", node->nd_body);
 	    ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
 	    break;
@@ -911,12 +908,12 @@

 static VALUE
 new_child_iseq(rb_iseq_t *iseq, NODE *node,
-	       VALUE name, VALUE parent, VALUE type)
+	       VALUE name, VALUE parent, VALUE type, int line_no)
 {
     VALUE ret;

     debugs("[new_child_iseq]> ---------------------------------------\n");
-    ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self),
+    ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self),
INT2FIX(line_no),
 			       parent, type, iseq->compile_data->option);
     debugs("[new_child_iseq]< ---------------------------------------\n");
     iseq_add_mark_object(iseq, ret);
@@ -2686,7 +2683,7 @@
 					     rb_str_concat(rb_str_new2
 							   ("defined guard in "),
 							   iseq->name),
-					     ISEQ_TYPE_DEFINED_GUARD);
+					     ISEQ_TYPE_DEFINED_GUARD, 0);

 	    defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse);
 	    ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
@@ -3264,7 +3261,7 @@

 	    iseq->compile_data->current_block =
 		NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
-				  ISEQ_TYPE_BLOCK);
+				  ISEQ_TYPE_BLOCK, nd_line(node));

 	    mid = idEach;
 	    ADD_SEND_R(ret, nd_line(node), ID2SYM(idEach), INT2FIX(0),
@@ -3273,7 +3270,7 @@
 	else {
 	    iseq->compile_data->current_block =
 		NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
-				  ISEQ_TYPE_BLOCK);
+				  ISEQ_TYPE_BLOCK, nd_line(node));
 	    COMPILE(ret, "iter caller", node->nd_iter);
 	}
 	ADD_LABEL(ret, retry_end_l);
@@ -3507,7 +3504,7 @@
 	VALUE rescue = NEW_CHILD_ISEQVAL(
 	    node->nd_resq,
 	    rb_str_concat(rb_str_new2("rescue in "), iseq->name),
-	    ISEQ_TYPE_RESCUE);
+	    ISEQ_TYPE_RESCUE, nd_line(node));

 	ADD_LABEL(ret, lstart);
 	COMPILE(ret, "rescue head", node->nd_head);
@@ -3589,7 +3586,7 @@
 					 rb_str_concat(rb_str_new2
 						       ("ensure in "),
 						       iseq->name),
-					 ISEQ_TYPE_ENSURE);
+					 ISEQ_TYPE_ENSURE, nd_line(node));
 	LABEL *lstart = NEW_LABEL(nd_line(node));
 	LABEL *lend = NEW_LABEL(nd_line(node));
 	LABEL *lcont = NEW_LABEL(nd_line(node));
@@ -4503,7 +4500,7 @@
       case NODE_DEFN:{
 	VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
 				    rb_str_dup(rb_id2str(node->nd_mid)),
-				    ISEQ_TYPE_METHOD);
+				    ISEQ_TYPE_METHOD, nd_line(node));

 	debugp_param("defn/iseq", iseqval);

@@ -4523,7 +4520,7 @@
       case NODE_DEFS:{
 	VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
 				    rb_str_dup(rb_id2str(node->nd_mid)),
-				    ISEQ_TYPE_METHOD);
+				    ISEQ_TYPE_METHOD, nd_line(node));

 	debugp_param("defs/iseq", iseqval);

@@ -4577,7 +4574,7 @@
 	    NEW_CHILD_ISEQVAL(
 		node->nd_body,
 		rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)),
-		ISEQ_TYPE_CLASS);
+		ISEQ_TYPE_CLASS, nd_line(node));
 	compile_cpath(ret, iseq, node->nd_cpath);
 	COMPILE(ret, "super", node->nd_super);
 	ADD_INSN3(ret, nd_line(node), defineclass,
@@ -4592,7 +4589,7 @@
 	VALUE iseqval = NEW_CHILD_ISEQVAL(
 	    node->nd_body,
 	    rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)),
-	    ISEQ_TYPE_CLASS);
+	    ISEQ_TYPE_CLASS, nd_line(node));

 	compile_cpath(ret, iseq, node->nd_cpath);
 	ADD_INSN (ret, nd_line(node), putnil); /* dummy */
@@ -4607,7 +4604,7 @@
 	ID singletonclass;
 	VALUE iseqval =
 	    NEW_ISEQVAL(node->nd_body, rb_str_new2("singletonclass"),
-			ISEQ_TYPE_CLASS);
+			ISEQ_TYPE_CLASS, nd_line(node));

 	COMPILE(ret, "sclass#recv", node->nd_recv);
 	ADD_INSN (ret, nd_line(node), putnil);
@@ -4810,7 +4807,7 @@
       case NODE_POSTEXE:{
 	LABEL *lstart = NEW_LABEL(nd_line(node));
 	LABEL *lend = NEW_LABEL(nd_line(node));
-	VALUE block = NEW_CHILD_ISEQVAL(node->nd_body,
make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
+	VALUE block = NEW_CHILD_ISEQVAL(node->nd_body,
make_name_for_block(iseq), ISEQ_TYPE_BLOCK, nd_line(node));

 	ADD_LABEL(ret, lstart);
 	ADD_INSN2(ret, nd_line(node), onceinlinecache, 0, lend);
@@ -4903,7 +4900,7 @@
       }
       case NODE_LAMBDA:{
 	/* compile same as lambda{...} */
-	VALUE block = NEW_CHILD_ISEQVAL(node->nd_body,
make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
+	VALUE block = NEW_CHILD_ISEQVAL(node->nd_body,
make_name_for_block(iseq), ISEQ_TYPE_BLOCK, nd_line(node));
 	VALUE argc = INT2FIX(0);
 	ADD_CALL_RECEIVER(ret, nd_line(node));
 	ADD_CALL_WITH_BLOCK(ret, nd_line(node), ID2SYM(idLambda), argc, block);
Index: parse.y
===================================================================
--- parse.y	(revision 23832)
+++ parse.y	(working copy)
@@ -2897,7 +2897,6 @@
 			reduce_nodes(&body);
 			$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
 			fixpos($$, $4);
-			fixpos($$->nd_defn, $4);
 			local_pop();
 		    /*%
 			$$ = dispatch3(def, $2, $4, $5);
@@ -2923,7 +2922,6 @@
 			reduce_nodes(&body);
 			$$ = NEW_DEFS($2, $5, $7, body);
 			fixpos($$, $2);
-			fixpos($$->nd_defn, $2);
 			local_pop();
 		    /*%
 			$$ = dispatch5(defs, $2, $3, $5, $7, $8);
@@ -3637,8 +3635,6 @@
 		    /*%%%*/
 			$$ = NEW_ITER($3,$4);
 			nd_set_line($$, $<num>2);
-			nd_set_line($$->nd_body, $<num>2);
-			nd_set_line($$->nd_body->nd_body, $<num>2);
 			dyna_pop();
 		    /*%
 			$$ = dispatch2(brace_block, escape_Qundef($3), $4);
Index: test/ruby/test_settracefunc.rb
===================================================================
--- test/ruby/test_settracefunc.rb	(revision 23832)
+++ test/ruby/test_settracefunc.rb	(working copy)
@@ -68,7 +68,7 @@
                  events.shift)
     assert_equal(["c-return", 5, :+, Fixnum],
                  events.shift)
-    assert_equal(["return", 4, :add, self.class],
+    assert_equal(["return", 6, :add, self.class],
                  events.shift)
     assert_equal(["line", 8, __method__, self.class],
                  events.shift)
@@ -98,7 +98,7 @@
                  events.shift)
     assert_equal(["c-return", 4, :inherited, Class],
                  events.shift)
-    assert_equal(["class", 7, nil, nil],
+    assert_equal(["class", 4, nil, nil],
                  events.shift)
     assert_equal(["line", 5, nil, nil],
                  events.shift)
@@ -120,7 +120,7 @@
                  events.shift)
     assert_equal(["call", 5, :bar, Foo],
                  events.shift)
-    assert_equal(["return", 5, :bar, Foo],
+    assert_equal(["return", 6, :bar, Foo],
                  events.shift)
     assert_equal(["line", 9, __method__, self.class],
                  events.shift)

-- 
Yusuke ENDOH <mame@tsg.ne.jp>

In This Thread