jruby icon indicating copy to clipboard operation
jruby copied to clipboard

define_method conversion fails to yield after indy JIT

Open headius opened this issue 4 months ago • 0 comments

Under certain circumstances, a define_method method will fail to yield to the surrounding scope's block:

  • define_method with yield
  • inside another method
  • closure-based define_method has been converted to a normal method
  • converted method has JIT compiled
  • indy is enabled and has optimized

This reproduces on both 10 and 9.4 when indy is enabled.

class Foo
  class << self
    def go(&xxx)
      define_method(:foo) { yield }
    end
  end
end
f = Foo.new
Foo.go {puts 1}
4.times { f.foo }

When run with jit.threshold=0 it iterates twice and then fails to yield on the third iteration:

$ jruby -Xjit.threshold=0 -Xjit.logging blah.rb                                                                                                                     
2025-08-07T12:06:42.080+03:00 [main] INFO Ruby : done compiling target script: blah.rb
2025-08-07T12:06:42.135+03:00 [main] INFO JITCompiler : method done jitting: Foo foo at blah.rb:3
1
1
LocalJumpError: no block given
     foo at blah.rb:4
  <main> at blah.rb:10
   times at org/jruby/RubyFixnum.java:338
  <main> at blah.rb:10

Something about the indy logic for this define_method body causes it to lose context for the surrounding go method's block.

For JRuby 10.0.2.0 we have disabled define_method conversion when it is called within another method, but since that is a fairly common pattern we would like to figure out the problem and re-enable conversion in a future release.

See #8943 for the temporary workaround. The issue was discovered in #8930 by forcing language specs to run repeatedly.

headius avatar Aug 07 '25 09:08 headius