Skip to content

Commit 7b6d151

Browse files
committed
ZJIT: Add insns keyword to test that a certain opcode is present
1 parent f8fa5c1 commit 7b6d151

1 file changed

Lines changed: 28 additions & 7 deletions

File tree

test/ruby/test_zjit.rb

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -488,11 +488,11 @@ def fib(n)
488488
end
489489

490490
def test_opt_aref_with
491-
assert_compiles ':ok', %q{
491+
assert_compiles ':ok', <<~RUBY, insns: [:opt_aref_with]
492492
def aref_with(hash) = hash["key"]
493493
494494
aref_with({ "key" => :ok })
495-
}
495+
RUBY
496496
end
497497

498498
# tool/ruby_vm/views/*.erb relies on the zjit instructions a) being contiguous and
@@ -512,26 +512,47 @@ def test_instruction_order
512512

513513
# Assert that every method call in `test_script` can be compiled by ZJIT
514514
# at a given call_threshold
515-
def assert_compiles(expected, test_script, **opts)
515+
def assert_compiles(expected, test_script, insns: [], **opts)
516516
pipe_fd = 3
517517

518518
script = <<~RUBY
519519
_test_proc = -> {
520520
RubyVM::ZJIT.assert_compiles
521521
#{test_script}
522522
}
523-
result = _test_proc.call
524-
IO.open(#{pipe_fd}).write(result.inspect)
523+
ret_val = _test_proc.call
524+
result = {
525+
ret_val:,
526+
#{ unless insns.empty?
527+
'insns: RubyVM::InstructionSequence.of(_test_proc).enum_for(:each_child).map(&:to_a)'
528+
end}
529+
}
530+
IO.open(#{pipe_fd}).write(Marshal.dump(result))
525531
RUBY
526532

527-
status, out, err, actual = eval_with_jit(script, pipe_fd:, **opts)
533+
status, out, err, result = eval_with_jit(script, pipe_fd:, **opts)
528534

529535
message = "exited with status #{status.to_i}"
530536
message << "\nstdout:\n```\n#{out}```\n" unless out.empty?
531537
message << "\nstderr:\n```\n#{err}```\n" unless err.empty?
532538
assert status.success?, message
533539

534-
assert_equal expected, actual
540+
result = Marshal.load(result)
541+
assert_equal expected, result.fetch(:ret_val).inspect
542+
543+
unless insns.empty?
544+
iseqs = result.fetch(:insns)
545+
iseqs.filter! { it[9] == :method } # ISeq type
546+
assert_equal 1, iseqs.size, "Opcode assertions tests must define exactly one method"
547+
iseq_insns = iseqs.first.last
548+
549+
expected_insns = Set.new(insns)
550+
iseq_insns.each do
551+
next unless it.is_a?(Array)
552+
expected_insns.delete(it.first)
553+
end
554+
assert(expected_insns.empty?, -> { "Not present in ISeq: #{expected_insns.to_a}" })
555+
end
535556
end
536557

537558
# Run a Ruby process with ZJIT options and a pipe for writing test results

0 commit comments

Comments
 (0)