mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
test_jit.rb: split test_compile_insns
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62378 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
8547caede1
commit
30bcbfd339
1 changed files with 270 additions and 192 deletions
|
@ -1,8 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
|
|
||||||
# Test for --jit option
|
module TestJITSupport
|
||||||
class TestJIT < Test::Unit::TestCase
|
|
||||||
JIT_TIMEOUT = 600 # 10min for each...
|
JIT_TIMEOUT = 600 # 10min for each...
|
||||||
JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
|
JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
|
||||||
SUPPORTED_COMPILERS = [
|
SUPPORTED_COMPILERS = [
|
||||||
|
@ -10,24 +9,55 @@ class TestJIT < Test::Unit::TestCase
|
||||||
'clang',
|
'clang',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
module_function
|
||||||
|
def eval_with_jit(script, verbose: 0, min_calls: 5, timeout: JIT_TIMEOUT)
|
||||||
|
EnvUtil.invoke_ruby(
|
||||||
|
['--disable-gems', '--jit-wait', "--jit-verbose=#{verbose}", "--jit-min-calls=#{min_calls}", '-e', script],
|
||||||
|
'', true, true, timeout: timeout,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def supported?
|
||||||
|
# Experimental. If you want to ensure JIT is working with this test, please set this for now.
|
||||||
|
if ENV.key?('RUBY_FORCE_TEST_JIT')
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Very pessimistic check. With this check, we can't ensure JIT is working.
|
||||||
|
begin
|
||||||
|
_, err = TestJITSupport.eval_with_jit('proc {}.call', verbose: 1, min_calls: 1, timeout: 10)
|
||||||
|
rescue Timeout::Error
|
||||||
|
$stderr.puts "TestJIT: #jit_supported? check timed out"
|
||||||
|
false
|
||||||
|
else
|
||||||
|
err.match?(JIT_SUCCESS_PREFIX)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless TestJITSupport.supported?
|
||||||
|
|
||||||
|
# Test for --jit option
|
||||||
|
class TestJIT < Test::Unit::TestCase
|
||||||
|
include TestJITSupport
|
||||||
# Ensure all supported insns can be compiled. Only basic tests are included.
|
# Ensure all supported insns can be compiled. Only basic tests are included.
|
||||||
# TODO: ensure --dump=insns includes the expected insn
|
# TODO: ensure --dump=insns includes the expected insn
|
||||||
def test_compile_insns
|
|
||||||
skip unless jit_supported?
|
|
||||||
|
|
||||||
# nop
|
def test_compile_insn_nop
|
||||||
assert_compile_once('nil rescue true', result_inspect: 'nil')
|
assert_compile_once('nil rescue true', result_inspect: 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
# getlocal
|
def test_compile_insn_local
|
||||||
# setlocal
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
begin;
|
||||||
foo = 1
|
foo = 1
|
||||||
foo
|
foo
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getblockparam
|
def test_compile_insn_blockparam
|
||||||
# setblockparam
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 2)
|
begin;
|
||||||
def foo(&b)
|
def foo(&b)
|
||||||
a = b
|
a = b
|
||||||
b = 2
|
b = 2
|
||||||
|
@ -35,185 +65,243 @@ class TestJIT < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
print foo { 1 }
|
print foo { 1 }
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getblockparamproxy
|
def test_compile_insn_getblockparamproxy
|
||||||
# TODO: support this in mjit_compile
|
skip "support this in mjit_compile"
|
||||||
|
end
|
||||||
|
|
||||||
# getspecial
|
def test_compile_insn_getspecial
|
||||||
assert_compile_once('$1', result_inspect: 'nil')
|
assert_compile_once('$1', result_inspect: 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
# setspecial
|
def test_compile_insn_setspecial
|
||||||
assert_compile_once(<<~RUBY, result_inspect: 'true')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
|
||||||
|
begin;
|
||||||
true if nil.nil?..nil.nil?
|
true if nil.nil?..nil.nil?
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getinstancevariable
|
def test_compile_insn_instancevariable
|
||||||
# setinstancevariable
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
begin;
|
||||||
@foo = 1
|
@foo = 1
|
||||||
@foo
|
@foo
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getclassvariable
|
def test_compile_insn_classvariable
|
||||||
# setclassvariable
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
begin;
|
||||||
@@foo = 1
|
@@foo = 1
|
||||||
@@foo
|
@@foo
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getconstant
|
def test_compile_insn_constant
|
||||||
# setconstant
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
begin;
|
||||||
FOO = 1
|
FOO = 1
|
||||||
FOO
|
FOO
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getglobal
|
def test_compile_insn_global
|
||||||
# setglobal
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
begin;
|
||||||
$foo = 1
|
$foo = 1
|
||||||
$foo
|
$foo
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# putnil
|
def test_compile_insn_putnil
|
||||||
assert_compile_once('nil', result_inspect: 'nil')
|
assert_compile_once('nil', result_inspect: 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
# putself
|
def test_compile_insn_putself
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 1)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1)
|
||||||
|
begin;
|
||||||
proc { print "hello" }.call
|
proc { print "hello" }.call
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# putobject
|
def test_compile_insn_putobject
|
||||||
assert_compile_once('0', result_inspect: '0') # putobject_OP_INT2FIX_O_0_C_
|
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('1', result_inspect: '1') # putobject_OP_INT2FIX_O_1_C_
|
||||||
assert_compile_once('2', result_inspect: '2')
|
assert_compile_once('2', result_inspect: '2')
|
||||||
|
end
|
||||||
|
|
||||||
# putspecialobject
|
def test_compile_insn_putspecialobject_putiseq
|
||||||
# putiseq
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 2)
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 2)
|
begin;
|
||||||
print proc {
|
print proc {
|
||||||
def method_definition
|
def method_definition
|
||||||
'hello'
|
'hello'
|
||||||
end
|
end
|
||||||
method_definition
|
method_definition
|
||||||
}.call
|
}.call
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# putstring
|
def test_compile_insn_putstring_concatstrings_tostring
|
||||||
# concatstrings
|
|
||||||
# tostring
|
|
||||||
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"')
|
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"')
|
||||||
|
end
|
||||||
|
|
||||||
# freezestring
|
def test_compile_insn_freezestring
|
||||||
assert_eval_with_jit(<<~'RUBY', stdout: 'true', success_count: 1)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1)
|
||||||
|
begin;
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
print proc { "#{true}".frozen? }.call
|
print proc { "#{true}".frozen? }.call
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# toregexp
|
def test_compile_insn_toregexp
|
||||||
assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0')
|
assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0')
|
||||||
|
end
|
||||||
|
|
||||||
# intern
|
def test_compile_insn_intern_newarray_duparray
|
||||||
# newarray
|
|
||||||
# duparray
|
|
||||||
assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]')
|
assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]')
|
||||||
|
end
|
||||||
|
|
||||||
# expandarray
|
def test_compile_insn_expandarray
|
||||||
assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true')
|
assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# concatarray
|
def test_compile_insn_concatarray
|
||||||
assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"')
|
assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"')
|
||||||
|
end
|
||||||
|
|
||||||
# splatarray
|
def test_compile_insn_splatarray
|
||||||
assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]')
|
assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]')
|
||||||
|
end
|
||||||
|
|
||||||
# newhash
|
def test_compile_insn_newhash
|
||||||
assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}')
|
assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}')
|
||||||
|
end
|
||||||
|
|
||||||
# newrange
|
def test_compile_insn_newrange
|
||||||
assert_compile_once('a = 1; 0..a', result_inspect: '0..1')
|
assert_compile_once('a = 1; 0..a', result_inspect: '0..1')
|
||||||
|
end
|
||||||
|
|
||||||
# pop
|
def test_compile_insn_pop
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '1')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
|
begin;
|
||||||
a = false
|
a = false
|
||||||
b = 1
|
b = 1
|
||||||
a || b
|
a || b
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# dup
|
def test_compile_insn_dup
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '3')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3')
|
||||||
|
begin;
|
||||||
a = 1
|
a = 1
|
||||||
a&.+(2)
|
a&.+(2)
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# dupn
|
def test_compile_insn_dupn
|
||||||
assert_compile_once(<<~RUBY, result_inspect: 'true')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
|
||||||
|
begin;
|
||||||
klass = Class.new
|
klass = Class.new
|
||||||
klass::X ||= true
|
klass::X ||= true
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# swap
|
def test_compile_insn_swap_topn
|
||||||
# topn
|
|
||||||
assert_compile_once('{}["true"] = true', result_inspect: 'true')
|
assert_compile_once('{}["true"] = true', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# reverse
|
def test_compile_insn_reverse
|
||||||
assert_compile_once('q, (w, e), r = 1, [2, 3], 4; e == 3', result_inspect: 'true')
|
assert_compile_once('q, (w, e), r = 1, [2, 3], 4; e == 3', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# reput
|
def test_compile_insn_reput
|
||||||
# TODO: write test
|
skip "write test"
|
||||||
|
end
|
||||||
|
|
||||||
# setn
|
def test_compile_insn_setn
|
||||||
assert_compile_once('[nil][0] = 1', result_inspect: '1')
|
assert_compile_once('[nil][0] = 1', result_inspect: '1')
|
||||||
|
end
|
||||||
|
|
||||||
# adjuststack
|
def test_compile_insn_adjuststack
|
||||||
assert_compile_once(<<~RUBY, result_inspect: 'true')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
|
||||||
|
begin;
|
||||||
x = [true]
|
x = [true]
|
||||||
x[0] ||= nil
|
x[0] ||= nil
|
||||||
x[0]
|
x[0]
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# defined
|
def test_compile_insn_defined
|
||||||
assert_compile_once('defined?(a)', result_inspect: 'nil')
|
assert_compile_once('defined?(a)', result_inspect: 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
# checkkeyword
|
def test_compile_insn_checkkeyword
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: 'true', success_count: 1)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1)
|
||||||
|
begin;
|
||||||
def test(x: rand)
|
def test(x: rand)
|
||||||
x
|
x
|
||||||
end
|
end
|
||||||
print test(x: true)
|
print test(x: true)
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# tracecoverage
|
def test_compile_insn_tracecoverage
|
||||||
# TODO: write test
|
skip "write test"
|
||||||
|
end
|
||||||
|
|
||||||
# defineclass
|
def test_compile_insn_defineclass
|
||||||
# TODO: support this in mjit_compile (low priority)
|
skip "support this in mjit_compile (low priority)"
|
||||||
|
end
|
||||||
|
|
||||||
# send
|
def test_compile_insn_send
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: '1', success_count: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
|
||||||
|
begin;
|
||||||
print proc { yield_self { 1 } }.call
|
print proc { yield_self { 1 } }.call
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_str_freeze
|
def test_compile_insn_opt_str_freeze
|
||||||
# opt_str_uminus
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '"foobar"')
|
begin;
|
||||||
'foo'.freeze + -'bar'
|
'foo'.freeze
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_newarray_max
|
def test_compile_insn_opt_str_uminus
|
||||||
# opt_newarray_min
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '3')
|
begin;
|
||||||
|
-'bar'
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_compile_insn_opt_newarray_max
|
||||||
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2')
|
||||||
|
begin;
|
||||||
a = 1
|
a = 1
|
||||||
b = 2
|
b = 2
|
||||||
[a, b].max + [a, b].min
|
[a, b].max
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_send_without_block
|
def test_compile_insn_opt_newarray_min
|
||||||
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
|
||||||
|
begin;
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
[a, b].min
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_compile_insn_opt_send_without_block
|
||||||
assert_compile_once('print', result_inspect: 'nil')
|
assert_compile_once('print', result_inspect: 'nil')
|
||||||
|
end
|
||||||
|
|
||||||
# invokesuper
|
def test_compile_insn_invokesuper
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 4)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4)
|
||||||
|
begin;
|
||||||
mod = Module.new {
|
mod = Module.new {
|
||||||
def test
|
def test
|
||||||
super + 2
|
super + 2
|
||||||
|
@ -226,19 +314,22 @@ class TestJIT < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
print klass.new.test
|
print klass.new.test
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# invokeblock
|
def test_compile_insn_invokeblock_leave
|
||||||
# leave
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2)
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: '2', success_count: 2)
|
begin;
|
||||||
def foo
|
def foo
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
print foo { 2 }
|
print foo { 2 }
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# throw
|
def test_compile_insn_throw
|
||||||
assert_eval_with_jit(<<~RUBY, stdout: '4', success_count: 2)
|
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2)
|
||||||
|
begin;
|
||||||
def test
|
def test
|
||||||
proc do
|
proc do
|
||||||
if 1+1 == 1
|
if 1+1 == 1
|
||||||
|
@ -250,111 +341,121 @@ class TestJIT < Test::Unit::TestCase
|
||||||
end.call
|
end.call
|
||||||
end
|
end
|
||||||
print test
|
print test
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# jump
|
def test_compile_insn_jump_branchif
|
||||||
# branchif
|
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil')
|
||||||
assert_compile_once(<<~'RUBY', result_inspect: 'nil')
|
begin;
|
||||||
a = false
|
a = false
|
||||||
1 + 1 while false
|
1 + 1 while false
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# branchunless
|
def test_compile_insn_branchunless
|
||||||
assert_compile_once(<<~'RUBY', result_inspect: '1')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1')
|
||||||
|
begin;
|
||||||
a = true
|
a = true
|
||||||
if a
|
if a
|
||||||
1
|
1
|
||||||
else
|
else
|
||||||
2
|
2
|
||||||
end
|
end
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# branchnil
|
def test_compile_insn_branchnil
|
||||||
assert_compile_once(<<~'RUBY', result_inspect: '3')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3')
|
||||||
|
begin;
|
||||||
a = 2
|
a = 2
|
||||||
a&.+(1)
|
a&.+(1)
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# branchiftype
|
def test_compile_insn_branchiftype
|
||||||
assert_compile_once(<<~'RUBY', result_inspect: '"42"')
|
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"')
|
||||||
|
begin;
|
||||||
a = '2'
|
a = '2'
|
||||||
"4#{a}"
|
"4#{a}"
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# getinlinecache
|
def test_compile_insn_inlinecache
|
||||||
# setinlinecache
|
|
||||||
assert_compile_once('Struct', result_inspect: 'Struct')
|
assert_compile_once('Struct', result_inspect: 'Struct')
|
||||||
|
end
|
||||||
|
|
||||||
# once
|
def test_compile_insn_once
|
||||||
assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]')
|
assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]')
|
||||||
|
end
|
||||||
|
|
||||||
# checkmatch
|
def test_compile_insn_checkmatch_opt_case_dispatch
|
||||||
# opt_case_dispatch
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '"world"')
|
begin;
|
||||||
case 'hello'
|
case 'hello'
|
||||||
when /hello/
|
when /hello/
|
||||||
'world'
|
'world'
|
||||||
end
|
end
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_plus
|
def test_compile_insn_opt_calc
|
||||||
# opt_minus
|
|
||||||
# opt_mult
|
|
||||||
# opt_div
|
|
||||||
# opt_mod
|
|
||||||
assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5')
|
assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5')
|
||||||
|
assert_compile_once('4 + 2', result_inspect: '6')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_eq
|
def test_compile_insn_opt_cmp
|
||||||
# opt_neq
|
|
||||||
assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true')
|
assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_lt
|
def test_compile_insn_opt_rel
|
||||||
# opt_le
|
|
||||||
# opt_gt
|
|
||||||
# opt_ge
|
|
||||||
assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true')
|
assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_ltlt
|
def test_compile_insn_opt_ltlt
|
||||||
assert_compile_once('[1] << 2', result_inspect: '[1, 2]')
|
assert_compile_once('[1] << 2', result_inspect: '[1, 2]')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_aref
|
def test_compile_insn_opt_aref_aset
|
||||||
# opt_aset
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '8')
|
||||||
# opt_aset_with
|
begin;
|
||||||
# opt_aref_with
|
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '8')
|
|
||||||
hash = { '1' => 2 }
|
hash = { '1' => 2 }
|
||||||
hash['1'] + hash[1.to_s] + (hash['2'] = 2) + (hash[2.to_s] = 2)
|
hash['1'] + hash[1.to_s] + (hash['2'] = 2) + (hash[2.to_s] = 2)
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_length
|
def test_compile_insn_opt_length_size
|
||||||
# opt_size
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4')
|
||||||
assert_compile_once(<<~RUBY, result_inspect: '4')
|
begin;
|
||||||
array = [1, 2]
|
array = [1, 2]
|
||||||
array.size + array.length
|
array.length + array.size
|
||||||
RUBY
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
# opt_empty_p
|
def test_compile_insn_opt_empty_p
|
||||||
assert_compile_once('[].empty?', result_inspect: 'true')
|
assert_compile_once('[].empty?', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_succ
|
def test_compile_insn_opt_succ
|
||||||
assert_compile_once('1.succ', result_inspect: '2')
|
assert_compile_once('1.succ', result_inspect: '2')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_not
|
def test_compile_insn_opt_not
|
||||||
assert_compile_once('!!true', result_inspect: 'true')
|
assert_compile_once('!!true', result_inspect: 'true')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_regexpmatch1
|
def test_compile_insn_opt_regexpmatch1
|
||||||
assert_compile_once("/true/ =~ 'true'", result_inspect: '0')
|
assert_compile_once("/true/ =~ 'true'", result_inspect: '0')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_regexpmatch2
|
def test_compile_insn_opt_regexpmatch2
|
||||||
assert_compile_once("'true' =~ /true/", result_inspect: '0')
|
assert_compile_once("'true' =~ /true/", result_inspect: '0')
|
||||||
|
end
|
||||||
|
|
||||||
# opt_call_c_function
|
def test_compile_insn_opt_call_c_function
|
||||||
# TODO: support this in opt_call_c_function (low priority)
|
skip "support this in opt_call_c_function (low priority)"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_jit_output
|
def test_jit_output
|
||||||
skip unless jit_supported?
|
|
||||||
|
|
||||||
out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5)
|
out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5)
|
||||||
assert_equal("MJIT\n" * 5, out)
|
assert_equal("MJIT\n" * 5, out)
|
||||||
assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
|
assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
|
||||||
|
@ -371,14 +472,12 @@ class TestJIT < Test::Unit::TestCase
|
||||||
# Shorthand for normal test cases
|
# Shorthand for normal test cases
|
||||||
def assert_eval_with_jit(script, stdout: nil, success_count:)
|
def assert_eval_with_jit(script, stdout: nil, success_count:)
|
||||||
out, err = eval_with_jit(script, verbose: 1, min_calls: 1)
|
out, err = eval_with_jit(script, verbose: 1, min_calls: 1)
|
||||||
if jit_supported?
|
actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
|
||||||
actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
|
assert_equal(
|
||||||
assert_equal(
|
success_count, actual,
|
||||||
success_count, actual,
|
"Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\
|
||||||
"Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\
|
"script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}",
|
||||||
"script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}",
|
)
|
||||||
)
|
|
||||||
end
|
|
||||||
if stdout
|
if stdout
|
||||||
assert_equal(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
|
||||||
|
@ -386,11 +485,8 @@ class TestJIT < Test::Unit::TestCase
|
||||||
|
|
||||||
# Run Ruby script with --jit-wait (Synchronous JIT compilation).
|
# Run Ruby script with --jit-wait (Synchronous JIT compilation).
|
||||||
# Returns [stdout, stderr]
|
# Returns [stdout, stderr]
|
||||||
def eval_with_jit(script, verbose: 0, min_calls: 5, timeout: JIT_TIMEOUT)
|
def eval_with_jit(script, **opts)
|
||||||
stdout, stderr, status = EnvUtil.invoke_ruby(
|
stdout, stderr, status = super
|
||||||
['--disable-gems', '--jit-wait', "--jit-verbose=#{verbose}", "--jit-min-calls=#{min_calls}", '-e', script],
|
|
||||||
'', true, true, timeout: timeout,
|
|
||||||
)
|
|
||||||
assert_equal(true, status.success?, "Failed to run script with JIT:\n#{code_block(script)}\nstdout:\n#{code_block(stdout)}\nstderr:\n#{code_block(stderr)}")
|
assert_equal(true, status.success?, "Failed to run script with JIT:\n#{code_block(script)}\nstdout:\n#{code_block(stdout)}\nstderr:\n#{code_block(stderr)}")
|
||||||
[stdout, stderr]
|
[stdout, stderr]
|
||||||
end
|
end
|
||||||
|
@ -398,22 +494,4 @@ class TestJIT < Test::Unit::TestCase
|
||||||
def code_block(code)
|
def code_block(code)
|
||||||
"```\n#{code}\n```\n\n"
|
"```\n#{code}\n```\n\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
def jit_supported?
|
|
||||||
return @jit_supported if defined?(@jit_supported)
|
|
||||||
|
|
||||||
# Experimental. If you want to ensure JIT is working with this test, please set this for now.
|
|
||||||
if ENV.key?('RUBY_FORCE_TEST_JIT')
|
|
||||||
return @jit_supported = true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Very pessimistic check. With this check, we can't ensure JIT is working.
|
|
||||||
begin
|
|
||||||
_, err = eval_with_jit('proc {}.call', verbose: 1, min_calls: 1, timeout: 10)
|
|
||||||
@jit_supported = err.match?(JIT_SUCCESS_PREFIX)
|
|
||||||
rescue Timeout::Error
|
|
||||||
$stderr.puts "TestJIT: #jit_supported? check timed out"
|
|
||||||
@jit_supported = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue