mirror of
https://github.com/ruby/ruby.git
synced 2025-09-21 19:44:01 +02:00
Fix excessive invalidation for opt_getinlinecache
YJIT expects the VM to invalidate opt_getinlinecache when updating the constant cache, and the invalidation used to happen even when YJIT can't use the cached value. Once the first invalidation happens, the block for opt_getinlinecache becomes a stub. When the stub is hit, YJIT fails to compile the instruction as the cache is not usable. The stub becomes a block that exits for opt_getinlinecache which can be invalidated again. Some workloads that bust the interpreter's constant cache can create an invalidation loop with this behavior. Check if the cache is usable become doing invalidation to fix this problem. In the test harness, evaluate the test script in a lambda instead of a proc so `return` doesn't return out of the harness.
This commit is contained in:
parent
6ef1609fab
commit
c46bda6f19
3 changed files with 36 additions and 3 deletions
|
@ -394,6 +394,31 @@ class TestYJIT < Test::Unit::TestCase
|
|||
RUBY
|
||||
end
|
||||
|
||||
def test_no_excessive_opt_getinlinecache_invalidation
|
||||
assert_compiles(<<~'RUBY', exits: :any, result: :ok)
|
||||
objects = [Object.new, Object.new]
|
||||
|
||||
objects.each do |o|
|
||||
class << o
|
||||
def foo
|
||||
Object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
9000.times {
|
||||
objects[0].foo
|
||||
objects[1].foo
|
||||
}
|
||||
|
||||
stats = YJIT.runtime_stats
|
||||
return :ok unless stats[:all_stats]
|
||||
return :ok if stats[:invalidation_count] < 10
|
||||
|
||||
:fail
|
||||
RUBY
|
||||
end
|
||||
|
||||
def assert_no_exits(script)
|
||||
assert_compiles(script)
|
||||
end
|
||||
|
@ -437,7 +462,7 @@ class TestYJIT < Test::Unit::TestCase
|
|||
|
||||
script = <<~RUBY
|
||||
#{"# frozen_string_literal: true" if frozen_string_literal}
|
||||
_test_proc = proc {
|
||||
_test_proc = -> {
|
||||
#{test_script}
|
||||
}
|
||||
#{reset_stats}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue