[Ruby 1.9 - Bug #5217][Open] lineno is broken when source code has about 7000 lines

Issue #5217 has been reported by Yusuke E…


Bug #5217: lineno is broken when source code has about 7000 lines

Author: Yusuke E.
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 1.9.4dev (2011-08-23 trunk 33019) [i686-linux]

遠藤です。

asakusa.rb で出た話だそうですが (なひさんからの伝聞) 、soap4r と
simplecov を組み合わせると [BUG] bug が出るそうです。

いろいろ話を聞かせてもらった結果、以下のようにすると再現できました。

$ ruby -e ‘puts “p\n” * 7000; puts “p([1”; puts “])”’ > t.rb

$ cat t.rb
p
p
p

… 7000 行ほど p …

p
p

$ ./ruby -rcoverage -e ‘Coverage.start; load “t.rb”’

応急措置ですが、以下のパッチで直ります。
(rb_bug(“bug”) というアホメッセージは私の所業のようです。スミマセン)
害はないと思うので、これはこれでコミットしておこうと思います。

diff --git a/thread.c b/thread.c
index 6970d8f…57a6962 100644
— a/thread.c
+++ b/thread.c
@@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE proc,
VALUE self, ID id, VALUE klas
long line = rb_sourceline() - 1;
long count;
if (RARRAY_PTR(coverage)[line] == Qnil) {

  •  rb_bug("bug");
    
  •  return;
    
    }
    count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
    if (POSFIXABLE(count)) {

しかしそもそもの原因は、iseq のバイトコードの大きさが unsigned short
で管理されているために、バイトコードの大きさが 65536 を超えると行番号を
見失ってしまうという問題のような気がします。
私も最初勘違いしたのですが、行番号が 16 ビットという問題とは別であること
に注意。65536 行ほど大きくなくても 7000 行くらいで発症します。

これにより、rb_vm_get_sourceline の挙動が怪しくなっています。
これは coverage に限らず、

set_trace_func(proc {|type, file, line,| p line if type == “line” })
p
p
p

… 7000 行ほど p …

p
p
p

というコードの出力が、

2
3
4
5

6550
6551
6552
6553
7001
7001
7001
7001
7001

となります。行番号が飛んでいることがわかります。

直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで
いるのは省メモリ化のためだと思いますので、これは既知の制限ということで
しょうか > ささださん

diff --git a/iseq.h b/iseq.h
index beeacbb…9c19501 100644
— a/iseq.h
+++ b/iseq.h
@@ -44,9 +44,9 @@ struct rb_compile_option_struct {
};

struct iseq_insn_info_entry {

  • unsigned short position;
  • unsigned short line_no;
  • unsigned short sp;
  • unsigned long position;
  • unsigned long line_no;
  • unsigned long sp;
    };

struct iseq_catch_table_entry {


Yuskue E. [email protected]

Issue #5217 has been updated by Yusuke E…

Assignee set to Koichi Sasada


Bug #5217: lineno is broken when source code has about 7000 lines

Author: Yusuke E.
Status: Open
Priority: Normal
Assignee: Koichi Sasada
Category:
Target version:
ruby -v: ruby 1.9.4dev (2011-08-23 trunk 33019) [i686-linux]

遠藤です。

asakusa.rb で出た話だそうですが (なひさんからの伝聞) 、soap4r と
simplecov を組み合わせると [BUG] bug が出るそうです。

いろいろ話を聞かせてもらった結果、以下のようにすると再現できました。

$ ruby -e ‘puts “p\n” * 7000; puts “p([1”; puts “])”’ > t.rb

$ cat t.rb
p
p
p

… 7000 行ほど p …

p
p

$ ./ruby -rcoverage -e ‘Coverage.start; load “t.rb”’

応急措置ですが、以下のパッチで直ります。
(rb_bug(“bug”) というアホメッセージは私の所業のようです。スミマセン)
害はないと思うので、これはこれでコミットしておこうと思います。

diff --git a/thread.c b/thread.c
index 6970d8f…57a6962 100644
— a/thread.c
+++ b/thread.c
@@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE proc,
VALUE self, ID id, VALUE klas
long line = rb_sourceline() - 1;
long count;
if (RARRAY_PTR(coverage)[line] == Qnil) {

  •  rb_bug("bug");
    
  •  return;
    
    }
    count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
    if (POSFIXABLE(count)) {

しかしそもそもの原因は、iseq のバイトコードの大きさが unsigned short
で管理されているために、バイトコードの大きさが 65536 を超えると行番号を
見失ってしまうという問題のような気がします。
私も最初勘違いしたのですが、行番号が 16 ビットという問題とは別であること
に注意。65536 行ほど大きくなくても 7000 行くらいで発症します。

これにより、rb_vm_get_sourceline の挙動が怪しくなっています。
これは coverage に限らず、

set_trace_func(proc {|type, file, line,| p line if type == “line” })
p
p
p

… 7000 行ほど p …

p
p
p

というコードの出力が、

2
3
4
5

6550
6551
6552
6553
7001
7001
7001
7001
7001

となります。行番号が飛んでいることがわかります。

直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで
いるのは省メモリ化のためだと思いますので、これは既知の制限ということで
しょうか > ささださん

diff --git a/iseq.h b/iseq.h
index beeacbb…9c19501 100644
— a/iseq.h
+++ b/iseq.h
@@ -44,9 +44,9 @@ struct rb_compile_option_struct {
};

struct iseq_insn_info_entry {

  • unsigned short position;
  • unsigned short line_no;
  • unsigned short sp;
  • unsigned long position;
  • unsigned long line_no;
  • unsigned long sp;
    };

struct iseq_catch_table_entry {


Yuskue E. [email protected]

ささだです.

(2011/08/23 7:43), Yusuke E. wrote:

直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで
いるのは省メモリ化のためだと思いますので、これは既知の制限ということで
しょうか > ささださん

どうもすみません.

色々考えて,遠藤さんに IRC でアドバイスしてもらった,「改行位置が変
わったところだけ情報を付ける」という方法でやり直しました.

ある大きな Rails アプリで,ロード後にバイトコード全部のサイズを測った
ところ (*1),
改善前:24,699,850 B(約 24.7MB)
改善後:21,835,244 B(約 21.8MB)
となりました.32bit 環境です: ruby 1.9.4dev (2011-08-22 trunk 33022)
[i686-linux].

*1: objspace を使うと,こんな風に測れます.

    require 'objspace'
    p ObjectSpace.memsize_of_all(RubyVM::InstructionSequence)
    exit!

これを,rack-*/lib/rack/handler/webrick.rb の self.run
に無理矢理書き加えるというかっこ悪さ.
もうちょっとなんとかならないかな.

バイトコードのサイズ自体は,fork した後で共有できるとかあるので,あん
まり削減しても嬉しくないような気もしますが,まぁちょっとは効果があったと
いうことで.

パッチ自体は結構大きくなりました.
http://www.atdot.net/sp/view/wpheql/readonly?lang=diff

コミットしてもいいでしょうか.って,trunk ならさくっと入れちゃえばいい
かなぁ.

$B1sF#$G$9!#(B

2011$BG/(B8$B7n(B24$BF|(B10:08 Hiroshi N. [email protected]:

Koichi Sasada wrote:

$B!!(B $B?'!99M$($F!$1sF#$5$s$K(B IRC
$B$G%"%I%P%$%9$7$F$b$i$C$?!$!V2~9T0LCV$,JQ(B
$B$o$C$?$H$3$m$@$1>pJs$rIU$1$k!W$H$$$&J}K!$G$d$jD>$7$^$7$?!%(B

$B$"$j$,$H$&$4$6$$$^$7$?!#(B

$B$$!#$5$5$@$5$s$,0lHU$G$d$C$F$/$l$^$7$?!#(B

$B!!(B $B%Q%C%A<+BN$O7k9=Bg$-$/$J$j$^$7$?!%(B
http://www.atdot.net/sp/view/wpheql/readonly?lang=diff

$B!!(B $B%3%_%C%H$7$F$b$$$$$G$7$g$&$+!%$C$F!$(Btrunk
$B$J$i$5$/$C$HF~$l$A$c$($P$$$$(B
$B$+$J$!!%(B

trunk $B$J$i$$$$$s$8$c$J$$$G$9$+$M!#(B
1.9.3 $B$O$$$8$i$J$/$F$$$$$H;W$$$^$9!#(B

$B:#$N$^$^$G$OI>2A$r0MMj$7$K$/$$$N$G!"F~$l$F$/$@$5$$$J!#(B

$B85LdBj(B ([BUG] bug) $B$NOC$G$7$?$i!“(Btrunk
$B$K$OA0=R$N!V1~5^A<CV!W(B
$B%Q%C%A$r%3%%C%H:Q$(B (r33030)
$B$J$N$G!”$5$5$@$5$s$N%Q%C%A$K4X$o$i$:!"(B
$B$b$&(B [BUG] $B$K$O$J$i$J$/$J$C$F$k$H;W$$$^$9!#(B

Yugui $B$5$s!"$3$N%Q%C%A(B (r33030) $B$O(B 1.9.3
$B$K%P%C%/%]!<%H4uK>$G$9!#(B

Issue #5217 has been updated by Hiroshi N…

Koichi Sasada wrote:

色々考えて,遠藤さんに IRC でアドバイスしてもらった,「改行位置が変
わったところだけ情報を付ける」という方法でやり直しました.

ありがとうございました。

パッチ自体は結構大きくなりました.
http://www.atdot.net/sp/view/wpheql/readonly?lang=diff

コミットしてもいいでしょうか.って,trunk ならさくっと入れちゃえばいい
かなぁ.

今のままでは評価を依頼しにくいので、入れてくださいな。

Bug #5217: lineno is broken when source code has about 7000 lines

Author: Yusuke E.
Status: Open
Priority: Normal
Assignee: Koichi Sasada
Category:
Target version:
ruby -v: -

遠藤です。

asakusa.rb で出た話だそうですが (なひさんからの伝聞) 、soap4r と
simplecov を組み合わせると [BUG] bug が出るそうです。

いろいろ話を聞かせてもらった結果、以下のようにすると再現できました。

$ ruby -e ‘puts “p\n” * 7000; puts “p([1”; puts “])”’ > t.rb

$ cat t.rb
p
p
p

… 7000 行ほど p …

p
p

$ ./ruby -rcoverage -e ‘Coverage.start; load “t.rb”’

応急措置ですが、以下のパッチで直ります。
(rb_bug(“bug”) というアホメッセージは私の所業のようです。スミマセン)
害はないと思うので、これはこれでコミットしておこうと思います。

diff --git a/thread.c b/thread.c
index 6970d8f…57a6962 100644
— a/thread.c
+++ b/thread.c
@@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE proc,
VALUE self, ID id, VALUE klas
long line = rb_sourceline() - 1;
long count;
if (RARRAY_PTR(coverage)[line] == Qnil) {

  •  rb_bug("bug");
    
  •  return;
    
    }
    count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
    if (POSFIXABLE(count)) {

しかしそもそもの原因は、iseq のバイトコードの大きさが unsigned short
で管理されているために、バイトコードの大きさが 65536 を超えると行番号を
見失ってしまうという問題のような気がします。
私も最初勘違いしたのですが、行番号が 16 ビットという問題とは別であること
に注意。65536 行ほど大きくなくても 7000 行くらいで発症します。

これにより、rb_vm_get_sourceline の挙動が怪しくなっています。
これは coverage に限らず、

set_trace_func(proc {|type, file, line,| p line if type == “line” })
p
p
p

… 7000 行ほど p …

p
p
p

というコードの出力が、

2
3
4
5

6550
6551
6552
6553
7001
7001
7001
7001
7001

となります。行番号が飛んでいることがわかります。

直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで
いるのは省メモリ化のためだと思いますので、これは既知の制限ということで
しょうか > ささださん

diff --git a/iseq.h b/iseq.h
index beeacbb…9c19501 100644
— a/iseq.h
+++ b/iseq.h
@@ -44,9 +44,9 @@ struct rb_compile_option_struct {
};

struct iseq_insn_info_entry {

  • unsigned short position;
  • unsigned short line_no;
  • unsigned short sp;
  • unsigned long position;
  • unsigned long line_no;
  • unsigned long sp;
    };

struct iseq_catch_table_entry {


Yuskue E. [email protected]

$B85LdBj(B ([BUG] bug) $B$NOC$G$7$?$i!"(Btrunk $B$K$OA0=R$N!V1~5^A<CV!W(B
$B%Q%C%A$r%3%%C%H:Q$(B (r33030) $B$J$N$G!"$5$5$@$5$s$N%Q%C%A$K4X$o$i$:!"(B
$B$b$&(B [BUG] $B$K$O$J$i$J$/$J$C$F$k$H;W$$$^$9!#(B

Yugui $B$5$s!"$3$N%Q%C%A(B (r33030) $B$O(B 1.9.3 $B$K%P%C%/%]!<%H4uK>$G$9!#(B

$BC&@~$G$9$,!"$=$m$=$m(Bbackport
project$B$K(B1.9.3$B$rDI2C$7$F%A%1%C%H$G4IM}$7$^$;$s$+!)(B
$B%a!<%k$G%P%C%/%]!<%H0MMj$O$"$V$J$C$+$7$$$H;W$$$^$9!#(B

(2011/08/23 20:43), Yusuke ENDOH wrote:

$B$$!#$5$5$@$5$s$,0lHU$G$d$C$F$/$l$^$7$?!#(B

$B!!$3$C$A$OD+$@$C$?$1$I$M!%%3%_%C%H$7$^$9!%(B

$B1:V:$H?=$7$^$9!#(B
Asakusa.rb $B$G$J$R$5$s$KAjCL$K>h$C$F$$$?$@$-$^$7$?!#(B

[BUG] $B$,=P$F$$$?%3!<%I$r(B r33046
$B$G;n$7$F$$?$H$3$m!"@5>o$KF0$$$F$$$k$h$&$K8+$($^$7$?!#(B
$BG0$N$?$a0J2<$N%Q%C%A$rEv$F$?>uBV$G$b;n$7$F$
$^$7$?$,!“Mn$A$k$h$&$J$3$H$O$”$j$^$;$s$G$7$?!#(B

$B$4BP1~$"$j$,$H$&$4$6$$$^$7$?!#(B

diff --git a/thread.c b/thread.c
index 57a6962…880e5f8 100644
— a/thread.c
+++ b/thread.c
@@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE
proc, VALUE self, ID id, VALUE klas
long line = rb_sourceline() - 1;
long count;
if (RARRAY_PTR(coverage)[line] == Qnil) {

  •  return;
    
  •  rb_bug("mame");
    
    }
    count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
    if (POSFIXABLE(count)) {

2011$BG/(B8$B7n(B24$BF|(B18:09 KOSAKI Motohiro
[email protected]:

$B85LdBj(B ([BUG] bug) $B$NOC$G$7$?$i!“(Btrunk $B$K$OA0=R$N!V1~5^A<CV!W(B
$B%Q%C%A$r%3%%C%H:Q$(B (r33030) $B$J$N$G!”$5$5$@$5$s$N%Q%C%A$K4X$o$i$:!"(B
$B$b$&(B [BUG] $B$K$O$J$i$J$/$J$C$F$k$H;W$$$^$9!#(B

Yugui $B$5$s!"$3$N%Q%C%A(B (r33030) $B$O(B 1.9.3 $B$K%P%C%/%]!<%H4uK>$G$9!#(B

$BC&@~$G$9$,!“$=$m$=$m(Bbackport
project$B$K(B1.9.3$B$rDI2C$7$F%A%1%C%H$G4IM}$7$^$;$s$+!)(B
$B%a!<%k$G%P%C%/%]!<%H0MMj$O$”$V$J$C$+$7$$$H;W$$$^$9!#(B

$B$d$C$H$-$^$7$?!*(B

2011/8/24 KOSAKI Motohiro [email protected]:

$BC&@~$G$9$,!“$=$m$=$m(Bbackport
project$B$K(B1.9.3$B$rDI2C$7$F%A%1%C%H$G4IM}$7$^$;$s$+!)(B
$B%a!<%k$G%P%C%/%]!<%H0MMj$O$”$V$J$C$+$7$$$H;W$$$^$9!#(B

done

$B1sF#$G$9!#(B

2011$BG/(B8$B7n(B24$BF|(B19:30 Keita U. [email protected]:

$B1:V:$H?=$7$^$9!#(B
Asakusa.rb $B$G$J$R$5$s$KAjCL$K>h$C$F$$$?$@$-$^$7$?!#(B

[BUG] $B$,=P$F$$$?%3!<%I$r(B r33046
$B$G;n$7$F$_$?$H$3$m!"@5>o$KF0$$$F$$$k$h$&$K8+$($^$7$?!#(B

$BG0$N$?$a0J2<$N%Q%C%A$rEv$F$?>uBV$G$b;n$7$F$_$^$7$?$,!“Mn$A$k$h$&$J$3$H$O$”$j$^$;$s$G$7$?!#(B

$B$4BP1~$"$j$,$H$&$4$6$$$^$7$?!#(B

$B$3$A$i$3$=$46(NO$"$j$,$H$&$4$6$$$^$7$?!#(B

$B$5$5$@$5$s$N%Q%C%A$K$h$C$F$3$NLdBj$O:,K\E*$KD>$C$?$N$G$9$,!"9THV9f$N(B
$B%!<%P!<%U%m!<$,5/$-$k$H$d$O$j(B coverage
$BB,Dj$OJQ$J$3$H$K$J$k$h$&$J(B
$B5$$,$9$k(B ($BL$3NG’$G$9$,(B) $B$N$G!"(Brb_bug $B$r(B return
$B$K$9$k%Q%C%A$O$=$N(B
$B$^$^$K$7$F$
$3$&$+$J$H;W$C$F$*$j$^$9!#(B

$B%l%“%1!<%9$G%+%P%l%C%8$NB,DjO3$l$,5/$-$k$N$H!”(Brb_bug
$B$GMn$A$FB,Dj(B
$BITG=$K$J$k$N$H!“$I$C$A$,9,$;$+$H$$$&OC$G$9$,!”$J$s$H$J$/A0<T$+$J$"$H(B
$B;W$C$?$N$G!#(B