Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JRuby 9.1.*.* on multiple platforms incorrectly handles block in [] method calls #4217

Closed
ab opened this issue Oct 10, 2016 · 4 comments
Closed

Comments

@ab
Copy link

ab commented Oct 10, 2016

JRuby starting with 9.1.0.0 and affecting all 9.1.x.x versions appears to incorrectly handle blocks passed as procs to the special [] method.

In MRI ruby 2.x and in jruby 9.0.5.0, foo[i, &block] works as expected.
In jruby 9.1.x.x, the block is not passed through and the method receives nil instead.

Versions tested

Tested jruby versions on OS X:

  • jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.0.0 (2.3.0) 2016-05-02 a633c63 Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.1.0 (2.3.0) 2016-05-19 fe84e89 Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.2.0 (2.3.0) 2016-05-26 7357c8f Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.3.0 (2.3.1) 2016-08-29 a2a3b29 Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.4.0 (2.3.1) 2016-09-01 2e1327f Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]
  • jruby 9.1.5.0 (2.3.1) 2016-09-07 036ce39 Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64]

Tested jruby versions on linux:

  • jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d OpenJDK 64-Bit Server VM 25.91-b14 on 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14 +jit [linux-amd64]
  • jruby 9.1.5.0 (2.3.1) 2016-09-07 036ce39 OpenJDK 64-Bit Server VM 25.91-b14 on 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14 +jit [linux-x86_64]

What is especially interesting is that calling the :[] method with send() passes the block through correctly.

Test script

#!/usr/bin/env ruby

class Foo
  attr_reader :failed

  def initialize
    @failed = false
  end

  def [](foo, &block)
    if block_given?
      puts "block_given, block: " + block.inspect
    else
      puts "NOT block_given, block: " + block.inspect
      @failed = true
    end
  end

  def test_method(foo, &block)
    if block_given?
      puts "block_given, block: " + block.inspect
    else
      puts "NOT block_given, block: " + block.inspect
      @failed = true
    end
  end
end


f = Foo.new

puts '--'
puts RUBY_DESCRIPTION

block = proc {|r| r}

puts
puts 'Test 1: f[&block]'
f['foo', &block]

puts
puts 'Test 2: test_method(&block)'
f.test_method('foo', &block)

puts
puts 'Test 3: f.[](&block)'
f.[]('foo', &block)

puts
puts 'Test 4: f.public_send(:[], &block)'
f.public_send(:[], 'foo', &block)

if f.failed
  puts 'FAILED'
  exit 1
else
  puts 'Succeeded'
end

Results

Sample output from successful MRI ruby 2.3.1

ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-linux]

Test 1: f[&block]
block_given, block: #<Proc:0x00556f28d89dd8@./test.rb:35>

Test 2: test_method(&block)
block_given, block: #<Proc:0x00556f28d89dd8@./test.rb:35>

Test 3: f.[](&block)
block_given, block: #<Proc:0x00556f28d89dd8@./test.rb:35>

Test 4: f.public_send(:[], &block)
block_given, block: #<Proc:0x00556f28d89dd8@./test.rb:35>
Succeeded

Sample output from successful jruby 9.0.5.0

jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d OpenJDK 64-Bit Server VM 25.91-b14 on 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14 +jit [linux-amd64]

Test 1: f[&block]
block_given, block: #<Proc:0x9629756@./test.rb:35>

Test 2: test_method(&block)
block_given, block: #<Proc:0x9629756@./test.rb:35>

Test 3: f.[](&block)
block_given, block: #<Proc:0x9629756@./test.rb:35>

Test 4: f.public_send(:[], &block)
block_given, block: #<Proc:0x9629756@./test.rb:35>
Succeeded

Sample output from failing jruby 9.1.5.0

jruby 9.1.5.0 (2.3.1) 2016-09-07 036ce39 OpenJDK 64-Bit Server VM 25.91-b14 on 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14 +jit [linux-x86_64]

Test 1: f[&block]
NOT block_given, block: nil

Test 2: test_method(&block)
block_given, block: #<Proc:0x6e0e048a@./test.rb:35>

Test 3: f.[](&block)
NOT block_given, block: nil

Test 4: f.public_send(:[], &block)
block_given, block: #<Proc:0x6e0e048a@./test.rb:35>
FAILED

Versions 9.1.0.0, 9.1.1.0, 9.1.2.0, 9.1.3.0, 9.1.4.0, and 9.1.5.0 are all affected.

@headius
Copy link
Member

headius commented Oct 11, 2016

Thanks for the great bug report! I would guess we're simply not passing the block through for [].

@headius
Copy link
Member

headius commented Oct 11, 2016

Results the same in JIT and interpreter. Seems to only affect the cases where the block is passed along with arguments, since f[&block] and f.[&block] work correctly.

@headius
Copy link
Member

headius commented Oct 11, 2016

Looks like this is an overzealous optimization in 2d9ff09...I'm not checking single-arg array dereference calls for a closure, which would disqualify them from this optimization.

headius added a commit that referenced this issue Oct 11, 2016
@headius headius added this to the JRuby 9.1.6.0 milestone Oct 11, 2016
@ab
Copy link
Author

ab commented Oct 11, 2016

👍 Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants