https://bugs.ruby-lang.org/
https://bugs.ruby-lang.org/favicon.ico?1711330511
2009-01-07T02:20:42Z
Ruby Issue Tracking System
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=2539
2009-01-07T02:20:42Z
mame (Yusuke Endoh)
mame@ruby-lang.org
<ul></ul><p>=begin<br>
遠藤です。</p>
<blockquote>
<p>次のスクリプトが stack level too deep (SystemStackError) で終わります。</p>
</blockquote>
<blockquote>
<p>ruby -e 'puts "A=["; 0.upto(1000000) { puts " [22, 55]," }; puts "]"' | ruby</p>
</blockquote>
<p>どういうときにこれが必要になったのか興味があります。</p>
<p>それはそれとして、パッチを書いてみました。</p>
<ul>
<li>concatarray 命令を廃止して、引数をとる concatarrays 命令を導入した</li>
<li>checkints 命令を導入した</li>
<li>巨大な配列リテラルは 1000 個ごとに newarray して最後に concatarrays する</li>
</ul>
<p>とりあえず配列だけの対処なので、巨大なハッシュリテラルを書くとたぶん落ちます。</p>
<a name="Index-insnsdef"></a>
<h1 >Index: insns.def<a href="#Index-insnsdef" class="wiki-anchor">¶</a></h1>
<p>--- insns.def (revision 21356)<br>
+++ insns.def (working copy)<br>
@@ -40,6 +40,20 @@<br>
/* none */<br>
}</p>
<p>+/**</p>
<ul>
<li>@c check interrupts</li>
<li>@e check interrupts</li>
<li>@j</li>
<li>*/<br>
+DEFINE_INSN<br>
+checkints<br>
+()<br>
+()<br>
+()<br>
+{</li>
<li>RUBY_VM_CHECK_INTS();<br>
+}</li>
<li>
</ul>
<p>/<em><strong><em>/<br>
/</em> deal with variables <em>/<br>
/</em></strong></em>/<br>
@@ -486,31 +500,27 @@</p>
<p>/**<br>
@c put</p>
<ul>
<li>@e concat two arrays</li>
<li>@j 二つの配列 ary1, ary2 を連結しスタックへプッシュする。</li>
</ul>
<ul>
<li>@e put concatenate arrays</li>
<li>@j スタックトップの配列を n 個連結し,結果をスタックにプッシュする。<br>
*/<br>
DEFINE_INSN<br>
-concatarray<br>
-()<br>
-(VALUE ary1, VALUE ary2st)<br>
-(VALUE ary)<br>
+concatarrays<br>
+(rb_num_t num)<br>
+(...)<br>
+(VALUE val) // inc += 1 - num;<br>
{</li>
</ul>
<ul>
<li>const VALUE ary2 = ary2st;</li>
<li>VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a");</li>
<li>VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a");</li>
</ul>
<ul>
<li>int i;</li>
</ul>
<ul>
<li>if (NIL_P(tmp1)) {</li>
<li>tmp1 = rb_ary_new3(1, ary1);</li>
</ul>
<ul>
<li>val = rb_ary_new();</li>
<li>for (i = num - 1; i >= 0; i--) {</li>
<li>const VALUE v = TOPN(i);</li>
<li>VALUE tmp = rb_check_convert_type(v, T_ARRAY, "Array", "to_a");</li>
<li>if (NIL_P(tmp)) {</li>
<li>
<pre><code> tmp = rb_ary_new3(1, v);
</code></pre>
</li>
<li>}</li>
<li>rb_ary_concat(val, tmp);<br>
}</li>
</ul>
<ul>
<li>
<li>if (NIL_P(tmp2)) {</li>
<li>tmp2 = rb_ary_new3(1, ary2);</li>
<li>}</li>
<li>
<li>if (tmp1 == ary1) {</li>
<li>tmp1 = rb_ary_dup(ary1);</li>
<li>}</li>
<li>ary = rb_ary_concat(tmp1, tmp2);</li>
</ul>
<ul>
<li>POPN(num);<br>
}</li>
</ul>
<h1>/**<br>
Index: compile.c</h1>
<p>--- compile.c (revision 21356)<br>
+++ compile.c (working copy)<br>
@@ -2195,12 +2195,14 @@<br>
return COMPILE_OK;<br>
}</p>
<p>+#define ARRAY_LITERAL_SPLIT_THRESHOLD 1000<br>
+<br>
static int<br>
-compile_array_(rb_iseq_t *iseq, LINK_ANCHOR <em>ret, NODE</em> node_root,</p>
<ul>
<li>
<pre><code> VALUE opt_p, int poped)
</code></pre>
</li>
</ul>
<p>+compile_array(rb_iseq_t *iseq, LINK_ANCHOR <em>ret, NODE</em> node_root, int poped)<br>
{<br>
NODE *node = node_root;</p>
<ul>
<li>int len = node->nd_alen, line = nd_line(node), i=0;</li>
</ul>
<ul>
<li>
<p>int len = node->nd_alen, line = nd_line(node), i=0, split = 0;</p>
</li>
<li>
<p>VALUE opt_p = Qtrue;<br>
DECL_ANCHOR(anchor);</p>
<p>INIT_ANCHOR(anchor);<br>
@@ -2211,6 +2213,11 @@<br>
ruby_node_name(nd_type(node)));<br>
}</p>
</li>
<li>
<pre><code> if (i > 0 && i % ARRAY_LITERAL_SPLIT_THRESHOLD == 0 && !poped) {
</code></pre>
</li>
<li>
<pre><code> ADD_INSN1(anchor, line, newarray, INT2FIX(ARRAY_LITERAL_SPLIT_THRESHOLD));
</code></pre>
</li>
<li>
<pre><code> ADD_INSN(anchor, line, checkints);
</code></pre>
</li>
<li>
<pre><code> split++;
</code></pre>
</li>
<li>
<pre><code> }
i++;
if (opt_p && nd_type(node->nd_head) != NODE_LIT) {
opt_p = Qfalse;
</code></pre>
</li>
</ul>
<p>@@ -2243,17 +2250,36 @@<br>
}<br>
else {<br>
if (!poped) {</p>
<ul>
<li>
<pre><code> ADD_INSN1(anchor, line, newarray, INT2FIX(len));
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> if (len % ARRAY_LITERAL_SPLIT_THRESHOLD) {
</code></pre>
</li>
<li>
<pre><code> ADD_INSN1(anchor, line, newarray, INT2FIX(len % ARRAY_LITERAL_SPLIT_THRESHOLD));
</code></pre>
</li>
<li>
<pre><code> split++;
</code></pre>
</li>
<li>
<pre><code> }
</code></pre>
</li>
<li>
<pre><code> if (split >= 2) ADD_INSN1(anchor, line, concatarrays, INT2FIX(split));
</code></pre>
}<br>
APPEND_LIST(ret, anchor);<br>
}<br>
return len;<br>
}</li>
</ul>
<p>-static VALUE<br>
-compile_array(rb_iseq_t *iseq, LINK_ANCHOR <em>ret, NODE</em> node_root, VALUE opt_p)<br>
+static long<br>
+compile_list(rb_iseq_t *iseq, LINK_ANCHOR <em>ret, NODE</em> node_root)<br>
{</p>
<ul>
<li>return compile_array_(iseq, ret, node_root, opt_p, 0);</li>
</ul>
<ul>
<li>NODE *node = node_root;</li>
<li>int i = 0;</li>
<li>
<li>if (nd_type(node) != NODE_ZARRAY) {</li>
<li>while (node) {</li>
<li>
<pre><code> if (nd_type(node) != NODE_ARRAY) {
</code></pre>
</li>
<li>
<pre><code> rb_bug("compile_list: This node is not NODE_ARRAY, but %s",
</code></pre>
</li>
<li>
<pre><code> ruby_node_name(nd_type(node)));
</code></pre>
</li>
<li>
<pre><code> }
</code></pre>
</li>
<li>
<pre><code> i++;
</code></pre>
</li>
<li>
<pre><code> COMPILE(ret, "list element", node->nd_head);
</code></pre>
</li>
<li>
<pre><code> node = node->nd_next;
</code></pre>
</li>
<li>}</li>
<li>}</li>
<li>
<li>return i;<br>
}</li>
</ul>
<p>static VALUE<br>
@@ -2841,8 +2867,7 @@<br>
*flag |= VM_CALL_ARGS_SPLAT_BIT;</p>
<pre><code> if (next_is_array) {
</code></pre>
<ul>
<li>
<pre><code> argc = INT2FIX(compile_array(iseq, args, argn->nd_head, Qfalse) + 1);
</code></pre>
</li>
<li>
<pre><code> POP_ELEMENT(args);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> argc = INT2FIX(compile_list(iseq, args, argn->nd_head) + 1);
}
else {
argn = argn->nd_head;
</code></pre>
</li>
</ul>
<p>@@ -2851,8 +2876,7 @@<br>
break;<br>
}<br>
case NODE_ARRAY: {</p>
<ul>
<li>
<pre><code> argc = INT2FIX(compile_array(iseq, args, argn, Qfalse));
</code></pre>
</li>
<li>
<pre><code> POP_ELEMENT(args);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> argc = INT2FIX(compile_list(iseq, args, argn));
break;
</code></pre>
<p>}<br>
default: {<br>
@@ -2862,10 +2886,7 @@<br>
}</p>
<p>if (nsplat > 1) {</p>
</li>
</ul>
<ul>
<li>int i;</li>
<li>for (i=1; i<nsplat; i++) {</li>
<li>
<pre><code> ADD_INSN(args_splat, nd_line(args), concatarray);
</code></pre>
</li>
<li>}</li>
</ul>
<ul>
<li>
<p>ADD_INSN1(args_splat, nd_line(args), concatarrays, INT2FIX(nsplat));<br>
}</p>
<p>if (!LIST_SIZE_ZERO(args_splat)) {<br>
@@ -3746,7 +3767,7 @@<br>
COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);<br>
if (flag & VM_CALL_ARGS_SPLAT_BIT) {<br>
ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));</p>
</li>
</ul>
<ul>
<li>
<pre><code> ADD_INSN(ret, nd_line(node), concatarray);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> ADD_INSN1(ret, nd_line(node), concatarrays, INT2FIX(2));
ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
argc, Qfalse, LONG2FIX(flag));
}
</code></pre>
</li>
</ul>
<p>@@ -3769,7 +3790,7 @@<br>
ADD_SEND(ret, nd_line(node), ID2SYM(id), INT2FIX(1));<br>
if (flag & VM_CALL_ARGS_SPLAT_BIT) {<br>
ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));</p>
<ul>
<li>
<pre><code> ADD_INSN(ret, nd_line(node), concatarray);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> ADD_INSN1(ret, nd_line(node), concatarrays, INT2FIX(2));
ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
argc, Qfalse, LONG2FIX(flag));
}
</code></pre>
</li>
</ul>
<p>@@ -4070,7 +4091,7 @@<br>
ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx));<br>
}<br>
ADD_INSN1(args, nd_line(node), newarray, INT2FIX(j));</p>
<ul>
<li>
<pre><code> ADD_INSN (args, nd_line(node), concatarray);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> ADD_INSN1(args, nd_line(node), concatarrays, INT2FIX(2));
/* argc is setteled at above */
}
else {
</code></pre>
</li>
</ul>
<p>@@ -4098,7 +4119,7 @@<br>
break;<br>
}<br>
case NODE_ARRAY:{</p>
<ul>
<li>compile_array_(iseq, ret, node, Qtrue, poped);</li>
</ul>
<ul>
<li>compile_array(iseq, ret, node, poped);<br>
break;<br>
}<br>
case NODE_ZARRAY:{<br>
@@ -4127,8 +4148,7 @@<br>
INIT_ANCHOR(list);<br>
switch (type) {<br>
case NODE_ARRAY:{</li>
</ul>
<ul>
<li>
<pre><code> compile_array(iseq, list, node->nd_head, Qfalse);
</code></pre>
</li>
<li>
<pre><code> size = OPERAND_AT(POP_ELEMENT(list), 0);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> size = INT2FIX(compile_list(iseq, list, node->nd_head));
ADD_SEQ(ret, list);
break;
</code></pre>
}<br>
@@ -4426,14 +4446,14 @@<br>
case NODE_ARGSCAT:{<br>
COMPILE(ret, "argscat head", node->nd_head);<br>
COMPILE(ret, "argscat body", node->nd_body);</li>
</ul>
<ul>
<li>ADD_INSN(ret, nd_line(node), concatarray);</li>
</ul>
<ul>
<li>ADD_INSN1(ret, nd_line(node), concatarrays, INT2FIX(2));<br>
break;<br>
}<br>
case NODE_ARGSPUSH:{<br>
COMPILE(ret, "arsgpush head", node->nd_head);<br>
COMPILE(ret, "argspush body", node->nd_body);<br>
ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));</li>
</ul>
<ul>
<li>ADD_INSN(ret, nd_line(node), concatarray);</li>
</ul>
<ul>
<li>ADD_INSN1(ret, nd_line(node), concatarrays, INT2FIX(2));<br>
break;<br>
}<br>
case NODE_SPLAT:{</li>
</ul>
<p>--<br>
Yusuke ENDOH <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>
<p>=end</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=10558
2010-04-27T21:18:31Z
mame (Yusuke Endoh)
mame@ruby-lang.org
<ul><li><strong>Target version</strong> changed from <i>1.9.2</i> to <i>2.0.0</i></li><li><strong>ruby -v</strong> set to <i>-</i></li></ul><p>=begin<br>
遠藤です。</p>
<p>ささださんが「1.9.2 には不要ではないでしょうか」との見解を出したので、<br>
target を 1.9.x とします。当面は Array#<< などを使ってください。</p>
<p>何とかして欲しいと言う声が多数あれば、早めに直されるかもしれません。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a><br>
=end</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=13389
2010-09-14T16:44:59Z
shyouhei (Shyouhei Urabe)
shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li></ul><p>=begin</p>
<p>=end</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=14140
2010-11-12T18:46:39Z
duerst (Martin Dürst)
duerst@it.aoyama.ac.jp
<ul></ul><p>=begin</p>
<blockquote>
<p>どういうときにこれが必要になったのか興味があります。</p>
</blockquote>
<p>具体的に言いますと、GB-18030 の変換テーブルのためです。<br>
=end</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=18394
2011-06-26T17:31:00Z
nahi (Hiroshi Nakamura)
nakahiro@gmail.com
<ul><li><strong>Target version</strong> changed from <i>2.0.0</i> to <i>1.9.3</i></li></ul>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=18491
2011-06-26T19:29:39Z
ko1 (Koichi Sasada)
<ul><li><strong>Target version</strong> changed from <i>1.9.3</i> to <i>2.0.0</i></li></ul><p>すみません,1.9.3 の後の課題とさせて下さい.</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=25845
2012-04-12T10:51:11Z
ko1 (Koichi Sasada)
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>なおしました.<br>
命令をいじるのではなく,core メソッドを呼ぶようにしてみました.<br>
ちょっと,余計な配列が増えちゃうのが良くないかも....<br>
誰か性能評価してくれると助かります.</p>
Ruby master - Bug #982: stack level too deep for long Array initialization
https://bugs.ruby-lang.org/issues/982?journal_id=25852
2012-04-12T19:00:36Z
shugo (Shugo Maeda)
<ul></ul><p>前田です。</p>
<p>ko1 (Koichi Sasada) wrote:</p>
<blockquote>
<p>なおしました.<br>
命令をいじるのではなく,core メソッドを呼ぶようにしてみました.<br>
ちょっと,余計な配列が増えちゃうのが良くないかも....<br>
誰か性能評価してくれると助かります.</p>
</blockquote>
<p>内容はぜんぜん追っていないのですが、r35306のcommitから以下のような警告が出るようになっているようです。</p>
<p>compile.c: 関数 ‘iseq_compile_each’ 内:<br>
compile.c:4363:8: 警告: 変数 ‘size’ が設定されましたが使用されていません [-Wunused-but-set-variable]</p>
<p>たしかに使われなくなっているように見えるのですが、これはこういうものでしょうか。</p>