Bug #12905
closedtailcall_optimization not working as expected under certain condition order
Description
Below code gets stack too deep error:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
def run_forever(current, final)
if current < final
run_forever(current+1, final)
else
nil
end
end
run_forever(1, Float::INFINITY)
However, below code works as expected:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
def run_forever(current, final)
if current >= final
nil
else
run_forever(current+1, final)
end
end
run_forever(1, Float::INFINITY)
Thanks for looking at this :)
Updated by shugo (Shugo Maeda) about 8 years ago
- Status changed from Open to Rejected
Kai Sun wrote:
Below code gets stack too deep error:
RubyVM::InstructionSequence.compile_option must be set before
compilation of the target program, so you need eval, load, etc.
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
eval(<<EOF)
def run_forever(current, final)
if current < final
run_forever(current+1, final)
else
nil
end
end
run_forever(1, Float::INFINITY)
EOF
Updated by sunkai612 (Kai Sun) about 8 years ago
Shugo Maeda wrote:
Kai Sun wrote:
Below code gets stack too deep error:
RubyVM::InstructionSequence.compile_option must be set before
compilation of the target program, so you need eval, load, etc.RubyVM::InstructionSequence.compile_option = { :tailcall_optimization => true, :trace_instruction => false } eval(<<EOF) def run_forever(current, final) if current < final run_forever(current+1, final) else nil end end run_forever(1, Float::INFINITY) EOF
I have tried with eval but seems still getting stack level too deep error.
Updated by sunkai612 (Kai Sun) about 8 years ago
I have also tried below and still get SystemStackError:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
RubyVM::InstructionSequence.new(<<-EOF).eval
def run_forever(current, final)
if current < final
run_forever(current+1, final)
else
nil
end
end
EOF
run_forever(1, Float::INFINITY)
However, if we alter the conditional order, it will work as expected:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
RubyVM::InstructionSequence.new(<<-EOF).eval
def run_forever(current, final)
if current >= final
nil
else
run_forever(current+1, final)
end
end
EOF
run_forever(1, Float::INFINITY)
Updated by nobu (Nobuyoshi Nakada) about 8 years ago
- Status changed from Rejected to Closed
- Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.1: REQUIRED, 2.2: REQUIRED, 2.3: REQUIRED
It's a bug fixed in the trunk.
Updated by nagachika (Tomoyuki Chikanaga) about 8 years ago
- Backport changed from 2.1: REQUIRED, 2.2: REQUIRED, 2.3: REQUIRED to 2.1: REQUIRED, 2.2: REQUIRED, 2.3: DONE
ruby_2_3 r56715 merged revision(s) 56208,56663.