зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
b40f9d55b6
Коммит
92413440bd
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче