summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-02-10 16:09:55 +0000
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-02-10 16:09:55 +0000
commit92413440bd1a4d9a159220f79404ab4db6764937 (patch)
tree41a0d7a0e8ba4407b49b09f04c4d9e5499c6dc5f
parentb40f9d55b61fa554838c2120edc22e187063a94d (diff)
test_jit.rb: cover most insn compilations
test_compile_insns has only basic tests to improve coverage. Other severer tests should be added with different names. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62348 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--test/ruby/test_jit.rb347
1 files changed, 344 insertions, 3 deletions
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 5414904e5a..d0a3323dc5 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -10,10 +10,346 @@ class TestJIT < Test::Unit::TestCase
'clang',
]
- def test_jit
+ # Ensure all supported insns can be compiled. Only basic tests are included.
+ # TODO: ensure --dump=insns includes the expected insn
+ def test_compile_insns
skip unless jit_supported?
- assert_eval_with_jit('print proc { 1 + 1 }.call', stdout: '2', success_count: 1)
+ # nop
+ assert_compile_once('nil rescue true', result_inspect: 'nil')
+
+ # getlocal
+ # setlocal
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ foo = 1
+ foo
+ RUBY
+
+ # getblockparam
+ # setblockparam
+ assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 2)
+ def foo(&b)
+ a = b
+ b = 2
+ a.call + 2
+ end
+
+ print foo { 1 }
+ RUBY
+
+ # getblockparamproxy
+ # TODO: support this in mjit_compile
+
+ # getspecial
+ assert_compile_once('$1', result_inspect: 'nil')
+
+ # setspecial
+ assert_compile_once(<<~RUBY, result_inspect: 'true')
+ true if nil.nil?..nil.nil?
+ RUBY
+
+ # getinstancevariable
+ # setinstancevariable
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ @foo = 1
+ @foo
+ RUBY
+
+ # getclassvariable
+ # setclassvariable
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ @@foo = 1
+ @@foo
+ RUBY
+
+ # getconstant
+ # setconstant
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ FOO = 1
+ FOO
+ RUBY
+
+ # getglobal
+ # setglobal
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ $foo = 1
+ $foo
+ RUBY
+
+ # putnil
+ assert_compile_once('nil', result_inspect: 'nil')
+
+ # putself
+ assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 1)
+ proc { print "hello" }.call
+ RUBY
+
+ # putobject
+ assert_compile_once('0', result_inspect: '0') # putobject_OP_INT2FIX_O_0_C_
+ assert_compile_once('1', result_inspect: '1') # putobject_OP_INT2FIX_O_1_C_
+ assert_compile_once('2', result_inspect: '2')
+
+ # putspecialobject
+ # putiseq
+ assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 2)
+ print proc {
+ def method_definition
+ 'hello'
+ end
+ method_definition
+ }.call
+ RUBY
+
+ # putstring
+ # concatstrings
+ # tostring
+ assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"')
+
+ # freezestring
+ assert_eval_with_jit(<<~'RUBY', stdout: 'true', success_count: 1)
+ # frozen_string_literal: true
+ print proc { "#{true}".frozen? }.call
+ RUBY
+
+ # toregexp
+ assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0')
+
+ # intern
+ # newarray
+ # duparray
+ assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]')
+
+ # expandarray
+ assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true')
+
+ # concatarray
+ assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"')
+
+ # splatarray
+ assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]')
+
+ # newhash
+ assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}')
+
+ # newrange
+ assert_compile_once('a = 1; 0..a', result_inspect: '0..1')
+
+ # pop
+ assert_compile_once(<<~RUBY, result_inspect: '1')
+ a = false
+ b = 1
+ a || b
+ RUBY
+
+ # dup
+ assert_compile_once(<<~RUBY, result_inspect: '3')
+ a = 1
+ a&.+(2)
+ RUBY
+
+ # dupn
+ assert_compile_once(<<~RUBY, result_inspect: 'true')
+ klass = Class.new
+ klass::X ||= true
+ RUBY
+
+ # swap
+ # topn
+ assert_compile_once('{}["true"] = true', result_inspect: 'true')
+
+ # reverse
+ assert_compile_once('q, (w, e), r = 1, [2, 3], 4; e == 3', result_inspect: 'true')
+
+ # reput
+ # TODO: write test
+
+ # setn
+ assert_compile_once('[nil][0] = 1', result_inspect: '1')
+
+ # adjuststack
+ assert_compile_once(<<~RUBY, result_inspect: 'true')
+ x = [true]
+ x[0] ||= nil
+ x[0]
+ RUBY
+
+ # defined
+ assert_compile_once('defined?(a)', result_inspect: 'nil')
+
+ # checkkeyword
+ assert_eval_with_jit(<<~RUBY, stdout: 'true', success_count: 1)
+ def test(x: rand)
+ x
+ end
+ print test(x: true)
+ RUBY
+
+ # tracecoverage
+ # TODO: write test
+
+ # defineclass
+ # TODO: support this in mjit_compile (low priority)
+
+ # send
+ assert_eval_with_jit(<<~RUBY, stdout: '1', success_count: 2)
+ print proc { yield_self { 1 } }.call
+ RUBY
+
+ # opt_str_freeze
+ # opt_str_uminus
+ assert_compile_once(<<~RUBY, result_inspect: '"foobar"')
+ 'foo'.freeze + -'bar'
+ RUBY
+
+ # opt_newarray_max
+ # opt_newarray_min
+ assert_compile_once(<<~RUBY, result_inspect: '3')
+ a = 1
+ b = 2
+ [a, b].max + [a, b].min
+ RUBY
+
+ # opt_send_without_block
+ assert_compile_once('print', result_inspect: 'nil')
+
+ # invokesuper
+ assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 4)
+ mod = Module.new {
+ def test
+ super + 2
+ end
+ }
+ klass = Class.new {
+ prepend mod
+ def test
+ 1
+ end
+ }
+ print klass.new.test
+ RUBY
+
+ # invokeblock
+ # leave
+ assert_eval_with_jit(<<~RUBY, stdout: '2', success_count: 2)
+ def foo
+ yield
+ end
+ print foo { 2 }
+ RUBY
+
+ # throw
+ assert_eval_with_jit(<<~RUBY, stdout: '4', success_count: 2)
+ def test
+ proc do
+ if 1+1 == 1
+ return 3
+ else
+ return 4
+ end
+ 5
+ end.call
+ end
+ print test
+ RUBY
+
+ # jump
+ # branchif
+ assert_compile_once(<<~'RUBY', result_inspect: 'nil')
+ a = false
+ 1 + 1 while false
+ RUBY
+
+ # branchunless
+ assert_compile_once(<<~'RUBY', result_inspect: '1')
+ a = true
+ if a
+ 1
+ else
+ 2
+ end
+ RUBY
+
+ # branchnil
+ assert_compile_once(<<~'RUBY', result_inspect: '3')
+ a = 2
+ a&.+(1)
+ RUBY
+
+ # branchiftype
+ assert_compile_once(<<~'RUBY', result_inspect: '"42"')
+ a = '2'
+ "4#{a}"
+ RUBY
+
+ # getinlinecache
+ # setinlinecache
+ assert_compile_once('Struct', result_inspect: 'Struct')
+
+ # once
+ assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]')
+
+ # checkmatch
+ # opt_case_dispatch
+ assert_compile_once(<<~RUBY, result_inspect: '"world"')
+ case 'hello'
+ when /hello/
+ 'world'
+ end
+ RUBY
+
+ # opt_plus
+ # opt_minus
+ # opt_mult
+ # opt_div
+ # opt_mod
+ assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5')
+
+ # opt_eq
+ # opt_neq
+ assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true')
+
+ # opt_lt
+ # opt_le
+ # opt_gt
+ # opt_ge
+ assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true')
+
+ # opt_ltlt
+ assert_compile_once('[1] << 2', result_inspect: '[1, 2]')
+
+ # opt_aref
+ # opt_aset
+ # opt_aset_with
+ # opt_aref_with
+ assert_compile_once(<<~RUBY, result_inspect: '8')
+ hash = { '1' => 2 }
+ hash['1'] + hash[1.to_s] + (hash['2'] = 2) + (hash[2.to_s] = 2)
+ RUBY
+
+ # opt_length
+ # opt_size
+ assert_compile_once(<<~RUBY, result_inspect: '4')
+ array = [1, 2]
+ array.size + array.length
+ RUBY
+
+ # opt_empty_p
+ assert_compile_once('[].empty?', result_inspect: 'true')
+
+ # opt_succ
+ assert_compile_once('1.succ', result_inspect: '2')
+
+ # opt_not
+ assert_compile_once('!!true', result_inspect: 'true')
+
+ # opt_regexpmatch1
+ assert_compile_once("/true/ =~ 'true'", result_inspect: '0')
+
+ # opt_regexpmatch2
+ assert_compile_once("'true' =~ /true/", result_inspect: '0')
+
+ # opt_call_c_function
+ # TODO: support this in opt_call_c_function (low priority)
end
def test_jit_output
@@ -27,6 +363,11 @@ class TestJIT < Test::Unit::TestCase
private
+ # The shortest way to test one proc
+ def assert_compile_once(script, result_inspect:)
+ assert_eval_with_jit("p proc { #{script} }.call", stdout: "#{result_inspect}\n", success_count: 1)
+ end
+
# Shorthand for normal test cases
def assert_eval_with_jit(script, stdout: nil, success_count:)
out, err = eval_with_jit(script, verbose: 1, min_calls: 1)
@@ -39,7 +380,7 @@ class TestJIT < Test::Unit::TestCase
)
end
if stdout
- assert_match(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
+ assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
end
end