summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2022-08-10 10:35:48 -0700
committerJohn Hawthorn <john@hawthorn.email>2022-09-01 15:20:49 -0700
commit679ef34586e7a43151865cb7f33a3253d815f7cf (patch)
tree1f46e901c2c77438e050585e9e9708492cc985a6 /test
parent7064d259bc20050d467874e5622082c29529a2d3 (diff)
New constant caching insn: opt_getconstant_path
Previously YARV bytecode implemented constant caching by having a pair of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a series of getconstant calls (with putobject providing supporting arguments). This commit replaces that pattern with a new instruction, opt_getconstant_path, handling both getting/setting the inline cache and fetching the constant on a cache miss. This is implemented by storing the full constant path as a null-terminated array of IDs inside of the IC structure. idNULL is used to signal an absolute constant reference. $ ./miniruby --dump=insns -e '::Foo::Bar::Baz' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE) 0000 opt_getconstant_path <ic:0 ::Foo::Bar::Baz> ( 1)[Li] 0002 leave The motivation for this is that we had increasingly found the need to disassemble the instructions between the opt_getinlinecache and opt_setinlinecache in order to determine the constant we are fetching, or otherwise store metadata. This disassembly was done: * In opt_setinlinecache, to register the IC against the constant names it is using for granular invalidation. * In rb_iseq_free, to unregister the IC from the invalidation table. * In YJIT to find the position of a opt_getinlinecache instruction to invalidate it when the cache is populated * In YJIT to register the constant names being used for invalidation. With this change we no longe need disassemly for these (in fact rb_iseq_each is now unused), as the list of constant names being referenced is held in the IC. This should also make it possible to make more optimizations in the future. This may also reduce the size of iseqs, as previously each segment required 32 bytes (on 64-bit platforms) for each constant segment. This implementation only stores one ID per-segment. There should be no significant performance change between this and the previous implementation. Previously opt_getinlinecache was a "leaf" instruction, but it included a jump (almost always to a separate cache line). Now opt_getconstant_path is a non-leaf (it may raise/autoload/call const_missing) but it does not jump. These seem to even out.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6187
Diffstat (limited to 'test')
-rw-r--r--test/ruby/test_mjit.rb6
-rw-r--r--test/ruby/test_yjit.rb8
2 files changed, 7 insertions, 7 deletions
diff --git a/test/ruby/test_mjit.rb b/test/ruby/test_mjit.rb
index 9cd93855bd..e49195f763 100644
--- a/test/ruby/test_mjit.rb
+++ b/test/ruby/test_mjit.rb
@@ -179,7 +179,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_constant
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getconstant setconstant])
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_getconstant_path setconstant])
begin;
FOO = 1
FOO
@@ -490,8 +490,8 @@ class TestMJIT < Test::Unit::TestCase
end;
end
- def test_compile_insn_inlinecache
- assert_compile_once('Struct', result_inspect: 'Struct', insns: %i[opt_getinlinecache opt_setinlinecache])
+ def test_compile_insn_getconstant_path
+ assert_compile_once('Struct', result_inspect: 'Struct', insns: %i[opt_getconstant_path])
end
def test_compile_insn_once
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 37e72dcafa..6cafb21698 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -389,8 +389,8 @@ class TestYJIT < Test::Unit::TestCase
assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil)
end
- def test_compile_opt_getinlinecache
- assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, call_threshold: 2)
+ def test_compile_opt_getconstant_path
+ assert_compiles(<<~RUBY, insns: %i[opt_getconstant_path], result: 123, call_threshold: 2)
def get_foo
FOO
end
@@ -402,8 +402,8 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_opt_getinlinecache_slowpath
- assert_compiles(<<~RUBY, exits: { opt_getinlinecache: 1 }, result: [42, 42, 1, 1], call_threshold: 2)
+ def test_opt_getconstant_path_slowpath
+ assert_compiles(<<~RUBY, exits: { opt_getconstant_path: 1 }, result: [42, 42, 1, 1], call_threshold: 2)
class A
FOO = 42
class << self