Project

General

Profile

Actions

Bug #19611

closed

Ruby hangs up with `while true && true`

Added by tompng (tomoya ishida) about 1 year ago. Updated 12 months ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.2.0 (2022-12-25 revision a528908271) +YJIT [x86_64-darwin20]
[ruby-core:113308]

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) almost 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) almost 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) 12 months 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.

Actions #4

Updated by nobu (Nobuyoshi Nakada) 12 months 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) 12 months 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.

Updated by Anonymous 12 months ago

aa

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0