Bug #19611
closedRuby hangs up with `while true && true`
Description
Fails to run this code. It hangs up. Ctrl+C does not work.
def hoge
while true && true
end
end
Compiling while true && true; end
will also hangs up
irb(main):001:0> RubyVM::InstructionSequence.compile 'while true && true; end'; puts :done
(no response)
Updated by kjtsanaktsidis (KJ Tsanaktsidis) over 1 year ago
Hm, interesting - it falls into an infinite loop in iseq_peephole_optimize
, because it's doing useless jump elimination on labels that recursively point to each other.
At the beginning of iseq_peephole_optimize
, the instruction sequence of your hoge
method looks like this:
-- raw disasm--------
0000 jump <L000> ( 2)
<L004> [sp: -1]
0002 putnil ( 2)
<L005> [sp: -1]
0003 pop ( 2)
0004 jump <L000> ( 2)
<L001> [sp: -1]
<L000> [sp: -1]
0006 jump <L006> ( 2)
<L006> [sp: -1]
0008 jump <L001> ( 2)
<L003> [sp: -1]
adjust: [label: 4]
0010 putnil ( 2)
<L002> [sp: -1]
trace: 10
0011 leave ( 4)
---------------------
Looks like the peephole optimizer is continuously changing that first jump to point to L006, then L001, then L006 again, forever.
This PR should fix it I think: https://github.com/ruby/ruby/pull/7760
Updated by kjtsanaktsidis (KJ Tsanaktsidis) over 1 year ago
After my patch, the instruction sequence for this method is:
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,23)>
0000 jump 4 ( 1)[Li]
0002 putnil
0003 pop
0004 jump 4
0006 putnil
0007 leave
which will loop forever, as expected.
This code isn't optimal though. A second pass of the peephole optimizer would reduce this down to this I think -
0000 jump 0
0002 putnil
0003 leave
but I guess optimizing something which is guaranteed to contain an infinite loop probably isn't worth doing?
Updated by nobu (Nobuyoshi Nakada) over 1 year ago
Mine:
https://github.com/ruby/ruby/pull/7753
https://github.com/ruby/ruby/pull/7754
kjtsanaktsidis (KJ Tsanaktsidis) wrote in #note-2:
This code isn't optimal though. A second pass of the peephole optimizer would reduce this down to this I think -
0000 jump 0 0002 putnil 0003 leave
It is due to the labels to next
/redo
.
Ideally, it could be only one instruction jump 0
if such labels (also for break
) are eliminated when unused.
Updated by nobu (Nobuyoshi Nakada) over 1 year ago
- Status changed from Open to Closed
Applied in changeset git|c7bacf84f04201787d26e4a4be8aca61ff1e454b.
[Bug #19611] Remove never-reachable branch in logical expression
Updated by kjtsanaktsidis (KJ Tsanaktsidis) over 1 year ago
Oh I didn't notice you already had a patch for this. Yeah, omitting the unreachable branches during the compile step entirely makes more sense.