summaryrefslogtreecommitdiff
path: root/test/ruby/test_zjit.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_zjit.rb')
-rw-r--r--test/ruby/test_zjit.rb143
1 files changed, 135 insertions, 8 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index 47a9f6f7dc..2b171b02b1 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -31,6 +31,20 @@ class TestZJIT < Test::Unit::TestCase
}
end
+ def test_putstring
+ assert_compiles '""', %q{
+ def test = "#{""}"
+ test
+ }, insns: [:putstring]
+ end
+
+ def test_putchilldedstring
+ assert_compiles '""', %q{
+ def test = ""
+ test
+ }, insns: [:putchilledstring]
+ end
+
def test_leave_param
assert_compiles '5', %q{
def test(n) = n
@@ -102,12 +116,39 @@ class TestZJIT < Test::Unit::TestCase
}, call_threshold: 2
end
+ def test_opt_plus_type_guard_exit_with_locals
+ assert_compiles '[6, 6.0]', %q{
+ def test(a)
+ local = 3
+ 1 + a + local
+ end
+ test(1) # profile opt_plus
+ [test(2), test(2.0)]
+ }, call_threshold: 2
+ end
+
def test_opt_plus_type_guard_nested_exit
- omit 'rewind_caller_frames is not implemented yet'
- assert_compiles '[3, 3.0]', %q{
+ assert_compiles '[4, 4.0]', %q{
def side_exit(n) = 1 + n
def jit_frame(n) = 1 + side_exit(n)
def entry(n) = jit_frame(n)
+ entry(2) # profile send
+ [entry(2), entry(2.0)]
+ }, call_threshold: 2
+ end
+
+ def test_opt_plus_type_guard_nested_exit_with_locals
+ assert_compiles '[9, 9.0]', %q{
+ def side_exit(n)
+ local = 2
+ 1 + n + local
+ end
+ def jit_frame(n)
+ local = 3
+ 1 + side_exit(n) + local
+ end
+ def entry(n) = jit_frame(n)
+ entry(2) # profile send
[entry(2), entry(2.0)]
}, call_threshold: 2
end
@@ -130,7 +171,6 @@ class TestZJIT < Test::Unit::TestCase
end
def test_opt_mult_overflow
- omit 'side exits are not implemented yet'
assert_compiles '[6, -6, 9671406556917033397649408, -9671406556917033397649408, 21267647932558653966460912964485513216]', %q{
def test(a, b)
a * b
@@ -255,6 +295,34 @@ class TestZJIT < Test::Unit::TestCase
}, insns: [:opt_ge], call_threshold: 2
end
+ def test_opt_hash_freeze
+ assert_compiles '{}', <<~RUBY, insns: [:opt_hash_freeze]
+ def test = {}.freeze
+ test
+ RUBY
+ end
+
+ def test_opt_ary_freeze
+ assert_compiles '[]', <<~RUBY, insns: [:opt_ary_freeze]
+ def test = [].freeze
+ test
+ RUBY
+ end
+
+ def test_opt_str_freeze
+ assert_compiles '""', <<~RUBY, insns: [:opt_str_freeze]
+ def test = "".freeze
+ test
+ RUBY
+ end
+
+ def test_opt_str_uminus
+ assert_compiles '""', <<~RUBY, insns: [:opt_str_uminus]
+ def test = -""
+ test
+ RUBY
+ end
+
def test_new_array_empty
assert_compiles '[]', %q{
def test = []
@@ -610,6 +678,69 @@ class TestZJIT < Test::Unit::TestCase
}
end
+ def test_uncached_getconstant_path
+ assert_compiles RUBY_COPYRIGHT.dump, %q{
+ def test = RUBY_COPYRIGHT
+ test
+ }, call_threshold: 1, insns: [:opt_getconstant_path]
+ end
+
+ def test_getconstant_path_autoload
+ # A constant-referencing expression can run arbitrary code through Kernel#autoload.
+ Dir.mktmpdir('autoload') do |tmpdir|
+ autoload_path = File.join(tmpdir, 'test_getconstant_path_autoload.rb')
+ File.write(autoload_path, 'X = RUBY_COPYRIGHT')
+
+ assert_compiles RUBY_COPYRIGHT.dump, %Q{
+ Object.autoload(:X, #{File.realpath(autoload_path).inspect})
+ def test = X
+ test
+ }, call_threshold: 1, insns: [:opt_getconstant_path]
+ end
+ end
+
+ def test_send_backtrace
+ backtrace = [
+ "-e:2:in 'Object#jit_frame1'",
+ "-e:3:in 'Object#entry'",
+ "-e:5:in 'block in <main>'",
+ "-e:6:in '<main>'",
+ ]
+ assert_compiles backtrace.inspect, %q{
+ def jit_frame2 = caller # 1
+ def jit_frame1 = jit_frame2 # 2
+ def entry = jit_frame1 # 3
+ entry # profile send # 4
+ entry # 5
+ }, call_threshold: 2
+ end
+
+ def test_putspecialobject_vm_core_and_cbase
+ assert_compiles '10', %q{
+ def test
+ alias bar test
+ 10
+ end
+
+ test
+ bar
+ }, insns: [:putspecialobject]
+ end
+
+ def test_putspecialobject_const_base
+ assert_compiles '1', %q{
+ Foo = 1
+
+ def test = Foo
+
+ # First call: populates the constant cache
+ test
+ # Second call: triggers ZJIT compilation with warm cache
+ # RubyVM::ZJIT.assert_compiles will panic if this fails to compile
+ test
+ }, call_threshold: 2
+ end
+
# tool/ruby_vm/views/*.erb relies on the zjit instructions a) being contiguous and
# b) being reliably ordered after all the other instructions.
def test_instruction_order
@@ -631,11 +762,7 @@ class TestZJIT < Test::Unit::TestCase
pipe_fd = 3
script = <<~RUBY
- _test_proc = -> {
- RubyVM::ZJIT.assert_compiles
- #{test_script}
- }
- ret_val = _test_proc.call
+ ret_val = (_test_proc = -> { RubyVM::ZJIT.assert_compiles; #{test_script.lstrip} }).call
result = {
ret_val:,
#{ unless insns.empty?