aboutsummaryrefslogtreecommitdiffstats
path: root/test/ruby
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2022-12-10 22:21:06 -0800
committerGitHub <noreply@github.com>2022-12-10 22:21:06 -0800
commit9d59d093bd99ca7f4266dec1e9b4cd8b5efbd2d4 (patch)
tree79b98a225e9451e280518f06c33d02d06cbcfbcb /test/ruby
parent7055574cf9dbcabd9d440c364f3e7b7812527bde (diff)
downloadruby-9d59d093bd99ca7f4266dec1e9b4cd8b5efbd2d4.tar.gz
MJIT: Compile methods in batches (#6900)
* MJIT: Compile methods in batches * MJIT: make mjit-bindgen * MJIT: Fix RubyVM::MJIT tests
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/test_mjit.rb269
-rw-r--r--test/ruby/test_rubyvm_mjit.rb23
2 files changed, 138 insertions, 154 deletions
diff --git a/test/ruby/test_mjit.rb b/test/ruby/test_mjit.rb
index efdf4e9606..3120d7e780 100644
--- a/test/ruby/test_mjit.rb
+++ b/test/ruby/test_mjit.rb
@@ -11,6 +11,7 @@ class TestMJIT < Test::Unit::TestCase
/\AJIT recompile: .+\n\z/,
/\AJIT inline: .+\n\z/,
/\AJIT cancel: .+\n\z/,
+ /\AJIT batch \([^)]+ms\): .+\n\z/,
/\ASuccessful MJIT finish\n\z/,
]
MAX_CACHE_PATTERNS = [
@@ -67,11 +68,11 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_nop
- assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop])
+ assert_compile_twice('nil rescue true', result_inspect: 'nil', insns: %i[nop])
end
def test_compile_insn_local
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0])
begin;
foo = 1
foo
@@ -96,7 +97,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_blockparam
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 2, insns: %i[getblockparam setblockparam])
begin;
def foo(&b)
a = b
@@ -105,6 +106,7 @@ class TestMJIT < Test::Unit::TestCase
end
print foo { 1 }
+ print foo { 1 }
end;
end
@@ -124,25 +126,25 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_getspecial
- assert_compile_once('$1', result_inspect: 'nil', insns: %i[getspecial])
+ assert_compile_twice('$1', result_inspect: 'nil', insns: %i[getspecial])
end
def test_compile_insn_setspecial
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial])
begin;
true if nil.nil?..nil.nil?
end;
end
def test_compile_insn_instancevariable
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getinstancevariable setinstancevariable])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getinstancevariable setinstancevariable])
begin;
@foo = 1
@foo
end;
# optimized getinstancevariable call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 2, call_threshold: 2)
begin;
class A
def initialize
@@ -162,7 +164,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_classvariable
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 1, insns: %i[getclassvariable setclassvariable])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, insns: %i[getclassvariable setclassvariable])
begin;
class Foo
def self.foo
@@ -172,19 +174,22 @@ class TestMJIT < Test::Unit::TestCase
end
print Foo.foo
+ print Foo.foo
end;
end
def test_compile_insn_constant
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_getconstant_path setconstant])
- begin;
- FOO = 1
- FOO
- end;
+ EnvUtil.suppress_warning do
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_getconstant_path setconstant])
+ begin;
+ FOO = 1
+ FOO
+ end;
+ end
end
def test_compile_insn_global
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getglobal setglobal])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getglobal setglobal])
begin;
$foo = 1
$foo
@@ -192,26 +197,26 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_putnil
- assert_compile_once('nil', result_inspect: 'nil', insns: %i[putnil])
+ assert_compile_twice('nil', result_inspect: 'nil', insns: %i[putnil])
end
def test_compile_insn_putself
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 1, insns: %i[putself])
begin;
- proc { print "hello" }.call
+ 2.times { print "hello" }
end;
end
def test_compile_insn_putobject
- assert_compile_once('0', result_inspect: '0', insns: %i[putobject_INT2FIX_0_])
- assert_compile_once('1', result_inspect: '1', insns: %i[putobject_INT2FIX_1_])
- assert_compile_once('2', result_inspect: '2', insns: %i[putobject])
+ assert_compile_twice('0', result_inspect: '0', insns: %i[putobject_INT2FIX_0_])
+ assert_compile_twice('1', result_inspect: '1', insns: %i[putobject_INT2FIX_1_])
+ assert_compile_twice('2', result_inspect: '2', insns: %i[putobject])
end
def test_compile_insn_definemethod_definesmethod
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'helloworld', success_count: 3, insns: %i[definemethod definesmethod])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'helloworldhelloworld', success_count: 3, insns: %i[definemethod definesmethod])
begin;
- print 1.times.map {
+ print 2.times.map {
def method_definition
'hello'
end
@@ -226,9 +231,9 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_putspecialobject
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'a', success_count: 2, insns: %i[putspecialobject])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'aa', success_count: 2, insns: %i[putspecialobject])
begin;
- print 1.times.map {
+ print 2.times.map {
def a
'a'
end
@@ -241,15 +246,15 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_putstring_concatstrings_objtostring
- assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings objtostring])
+ assert_compile_twice('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings objtostring])
end
def test_compile_insn_toregexp
- assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
+ assert_compile_twice('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
end
def test_compile_insn_newarray
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '[1, 2, 3]', insns: %i[newarray])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '[1, 2, 3]', insns: %i[newarray])
begin;
a, b, c = 1, 2, 3
[a, b, c]
@@ -257,39 +262,39 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_newarraykwsplat
- assert_compile_once('[**{ x: 1 }]', result_inspect: '[{:x=>1}]', insns: %i[newarraykwsplat])
+ assert_compile_twice('[**{ x: 1 }]', result_inspect: '[{:x=>1}]', insns: %i[newarraykwsplat])
end
def test_compile_insn_intern_duparray
- assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray])
+ assert_compile_twice('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray])
end
def test_compile_insn_expandarray
- assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true', insns: %i[expandarray])
+ assert_compile_twice('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true', insns: %i[expandarray])
end
def test_compile_insn_concatarray
- assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray])
+ assert_compile_twice('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray])
end
def test_compile_insn_splatarray
- assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]', insns: %i[splatarray])
+ assert_compile_twice('[*(1..2)]', result_inspect: '[1, 2]', insns: %i[splatarray])
end
def test_compile_insn_newhash
- assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}', insns: %i[newhash])
+ assert_compile_twice('a = 1; { a: a }', result_inspect: '{:a=>1}', insns: %i[newhash])
end
def test_compile_insn_duphash
- assert_compile_once('{ a: 1 }', result_inspect: '{:a=>1}', insns: %i[duphash])
+ assert_compile_twice('{ a: 1 }', result_inspect: '{:a=>1}', insns: %i[duphash])
end
def test_compile_insn_newrange
- assert_compile_once('a = 1; 0..a', result_inspect: '0..1', insns: %i[newrange])
+ assert_compile_twice('a = 1; 0..a', result_inspect: '0..1', insns: %i[newrange])
end
def test_compile_insn_pop
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[pop])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[pop])
begin;
a = false
b = 1
@@ -298,7 +303,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_dup
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3', insns: %i[dup])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3', insns: %i[dup])
begin;
a = 1
a&.+(2)
@@ -306,7 +311,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_dupn
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn])
begin;
klass = Class.new
klass::X ||= true
@@ -314,7 +319,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_swap_topn
- assert_compile_once('{}["true"] = true', result_inspect: 'true', insns: %i[swap topn])
+ assert_compile_twice('{}["true"] = true', result_inspect: 'true', insns: %i[swap topn])
end
def test_compile_insn_reput
@@ -322,11 +327,11 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_setn
- assert_compile_once('[nil][0] = 1', result_inspect: '1', insns: %i[setn])
+ assert_compile_twice('[nil][0] = 1', result_inspect: '1', insns: %i[setn])
end
def test_compile_insn_adjuststack
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[adjuststack])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[adjuststack])
begin;
x = [true]
x[0] ||= nil
@@ -335,16 +340,17 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_defined
- assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined])
+ assert_compile_twice('defined?(a)', result_inspect: 'nil', insns: %i[defined])
end
def test_compile_insn_checkkeyword
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'truetrue', success_count: 1, insns: %i[checkkeyword])
begin;
def test(x: rand)
x
end
print test(x: true)
+ print test(x: true)
end;
end
@@ -357,35 +363,36 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_send
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 4, insns: %i[send])
begin;
print proc { yield_self { 1 } }.call
+ print proc { yield_self { 1 } }.call
end;
end
def test_compile_insn_opt_str_freeze
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"', insns: %i[opt_str_freeze])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"', insns: %i[opt_str_freeze])
begin;
'foo'.freeze
end;
end
def test_compile_insn_opt_nil_p
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'false', insns: %i[opt_nil_p])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'false', insns: %i[opt_nil_p])
begin;
nil.nil?.nil?
end;
end
def test_compile_insn_opt_str_uminus
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"', insns: %i[opt_str_uminus])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"', insns: %i[opt_str_uminus])
begin;
-'bar'
end;
end
def test_compile_insn_opt_newarray_max
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2', insns: %i[opt_newarray_max])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2', insns: %i[opt_newarray_max])
begin;
a = 1
b = 2
@@ -394,7 +401,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_newarray_min
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_newarray_min])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_newarray_min])
begin;
a = 1
b = 2
@@ -403,11 +410,11 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_send_without_block
- assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
+ assert_compile_twice('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
end
def test_compile_insn_invokesuper
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 4, insns: %i[invokesuper])
begin;
mod = Module.new {
def test
@@ -421,21 +428,23 @@ class TestMJIT < Test::Unit::TestCase
end
}
print klass.new.test
+ print klass.new.test
end;
end
def test_compile_insn_invokeblock_leave
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '22', success_count: 2, insns: %i[invokeblock leave])
begin;
def foo
yield
end
print foo { 2 }
+ print foo { 2 }
end;
end
def test_compile_insn_throw
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '44', success_count: 2, insns: %i[throw])
begin;
def test
proc do
@@ -448,11 +457,12 @@ class TestMJIT < Test::Unit::TestCase
end.call
end
print test
+ print test
end;
end
def test_compile_insn_jump_branchif
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil', insns: %i[jump branchif])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil', insns: %i[jump branchif])
begin;
a = false
1 + 1 while a
@@ -460,7 +470,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_branchunless
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1', insns: %i[branchunless])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1', insns: %i[branchunless])
begin;
a = true
if a
@@ -472,7 +482,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_branchnil
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3', insns: %i[branchnil])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3', insns: %i[branchnil])
begin;
a = 2
a&.+(1)
@@ -480,7 +490,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_objtostring
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[objtostring])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[objtostring])
begin;
a = '2'
"4#{a}"
@@ -488,15 +498,15 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_getconstant_path
- assert_compile_once('Struct', result_inspect: 'Struct', insns: %i[opt_getconstant_path])
+ assert_compile_twice('Struct', result_inspect: 'Struct', insns: %i[opt_getconstant_path])
end
def test_compile_insn_once
- assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once])
+ assert_compile_twice('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once])
end
def test_compile_insn_checkmatch_opt_case_dispatch
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch])
begin;
case 'hello'
when 'hello'
@@ -506,34 +516,34 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_calc
- assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
- assert_compile_once('4.0 + 2.0 - ((2.0 * 3.0 / 2.0) % 2.0)', result_inspect: '5.0', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
- assert_compile_once('4 + 2', result_inspect: '6')
+ assert_compile_twice('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
+ assert_compile_twice('4.0 + 2.0 - ((2.0 * 3.0 / 2.0) % 2.0)', result_inspect: '5.0', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
+ assert_compile_twice('4 + 2', result_inspect: '6')
end
def test_compile_insn_opt_cmp
- assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq])
+ assert_compile_twice('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq])
end
def test_compile_insn_opt_rel
- assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true', insns: %i[opt_lt opt_le opt_gt opt_ge])
+ assert_compile_twice('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true', insns: %i[opt_lt opt_le opt_gt opt_ge])
end
def test_compile_insn_opt_ltlt
- assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
+ assert_compile_twice('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
end
def test_compile_insn_opt_and
- assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and])
+ assert_compile_twice('1 & 3', result_inspect: '1', insns: %i[opt_and])
end
def test_compile_insn_opt_or
- assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or])
+ assert_compile_twice('1 | 3', result_inspect: '3', insns: %i[opt_or])
end
def test_compile_insn_opt_aref
# optimized call (optimized JIT) -> send call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, call_threshold: 1, insns: %i[opt_aref])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '221', success_count: 1, call_threshold: 2, insns: %i[opt_aref])
begin;
obj = Object.new
def obj.[](h)
@@ -542,11 +552,12 @@ class TestMJIT < Test::Unit::TestCase
block = proc { |h| h[1] }
print block.call({ 1 => 2 })
+ print block.call({ 1 => 2 })
print block.call(obj)
end;
# send call -> optimized call (send JIT) -> optimized call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 3, call_threshold: 2)
begin;
obj = Object.new
def obj.[](h)
@@ -561,11 +572,11 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_aref_with
- assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with])
+ assert_compile_twice("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with])
end
def test_compile_insn_opt_aset
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
begin;
hash = { '1' => 2 }
(hash['2'] = 2) + (hash[1.to_s] = 3)
@@ -573,7 +584,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_length_size
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4', insns: %i[opt_length opt_size])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4', insns: %i[opt_length opt_size])
begin;
array = [1, 2]
array.length + array.size
@@ -581,20 +592,20 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_insn_opt_empty_p
- assert_compile_once('[].empty?', result_inspect: 'true', insns: %i[opt_empty_p])
+ assert_compile_twice('[].empty?', result_inspect: 'true', insns: %i[opt_empty_p])
end
def test_compile_insn_opt_succ
- assert_compile_once('1.succ', result_inspect: '2', insns: %i[opt_succ])
+ assert_compile_twice('1.succ', result_inspect: '2', insns: %i[opt_succ])
end
def test_compile_insn_opt_not
- assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not])
+ assert_compile_twice('!!true', result_inspect: 'true', insns: %i[opt_not])
end
def test_compile_insn_opt_regexpmatch2
- assert_compile_once("/true/ =~ 'true'", result_inspect: '0', insns: %i[opt_regexpmatch2])
- assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2])
+ assert_compile_twice("/true/ =~ 'true'", result_inspect: '0', insns: %i[opt_regexpmatch2])
+ assert_compile_twice("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2])
end
def test_compile_insn_invokebuiltin
@@ -603,7 +614,7 @@ class TestMJIT < Test::Unit::TestCase
EOS
insns = collect_insns(iseq)
mark_tested_insn(:invokebuiltin, used_insns: insns)
- assert_eval_with_jit('print [].sample(1)', stdout: '[]', success_count: 1)
+ assert_eval_with_jit('print [].sample(1); print [].sample(1)', stdout: '[][]', success_count: 1)
end
def test_compile_insn_opt_invokebuiltin_delegate_leave
@@ -612,11 +623,11 @@ class TestMJIT < Test::Unit::TestCase
EOS
insns = collect_insns(iseq)
mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns)
- assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1)
+ assert_eval_with_jit('print "\x00".unpack("c");print "\x00".unpack("c")', stdout: '[0][0]', success_count: 1)
end
def test_compile_insn_checkmatch
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch])
+ assert_compile_twice("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch])
begin;
ary = %w(hello good-bye)
case 'hello'
@@ -627,23 +638,25 @@ class TestMJIT < Test::Unit::TestCase
end
def test_compile_opt_pc
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 1)
begin;
def test(arg = 'hello')
print arg
end
test
+ test
end;
end
def test_mjit_output
- out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, call_threshold: 5)
- assert_equal("MJIT\n" * 5, out)
- assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
+ out, err = eval_with_jit('4.times { puts "MJIT" }', verbose: 1, call_threshold: 2)
+ assert_equal("MJIT\n" * 4, out)
+ assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1$/, err)
assert_match(/^Successful MJIT finish$/, err)
end
def test_nothing_to_unload_with_jit_wait
+ omit 'unload_units is removed for now'
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 11, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
begin;
def a1() a2() end
@@ -662,6 +675,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_unload_units_on_fiber
+ omit 'unload_units is removed for now'
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 12, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
begin;
def a1() a2(false); a2(true) end
@@ -684,9 +698,10 @@ class TestMJIT < Test::Unit::TestCase
end
def test_unload_units_and_compaction
+ omit 'unload_units is removed for now'
Dir.mktmpdir("jit_test_unload_units_") do |dir|
# MIN_CACHE_SIZE is 10
- out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, call_threshold: 1, max_cache: 10)
+ out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, call_threshold: 2, max_cache: 10)
begin;
i = 0
while i < 11
@@ -741,12 +756,13 @@ class TestMJIT < Test::Unit::TestCase
def arr
[nil, [:type => :development]]
end
+ arr
p arr
end;
end
def test_local_stack_on_exception
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 2)
begin;
def b
raise
@@ -761,11 +777,12 @@ class TestMJIT < Test::Unit::TestCase
end
print a
+ print a
end;
end
def test_local_stack_with_sp_motion_by_blockargs
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 2)
begin;
def b(base)
1
@@ -782,11 +799,12 @@ class TestMJIT < Test::Unit::TestCase
end
print a
+ print a
end;
end
def test_catching_deep_exception
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 4)
begin;
def catch_true(paths, prefixes) # catch_except_p: true
prefixes.each do |prefix| # catch_except_p: true
@@ -801,6 +819,7 @@ class TestMJIT < Test::Unit::TestCase
end
print wrapper(['1'], ['2'])
+ print wrapper(['1'], ['2'])
end;
end
@@ -819,7 +838,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_inlined_c_method
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 1, recompile_count: 1, call_threshold: 2)
begin;
def test(obj, recursive: nil)
if recursive
@@ -856,7 +875,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_inlined_undefined_ivar
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 5, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 4, call_threshold: 2)
begin;
class Foo
def initialize
@@ -877,7 +896,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_inlined_setivar_frozen
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, call_threshold: 3)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 1, call_threshold: 2)
begin;
class A
def a
@@ -911,7 +930,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_attr_reader
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 3, call_threshold: 2)
begin;
class A
attr_reader :a, :b
@@ -942,7 +961,7 @@ class TestMJIT < Test::Unit::TestCase
print(2 * a.test)
end;
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 3, call_threshold: 2)
begin;
class Hoge
attr_reader :foo
@@ -1004,12 +1023,13 @@ class TestMJIT < Test::Unit::TestCase
end
def test_jump_to_precompiled_branch
- assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, call_threshold: 1)
+ assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0.0", success_count: 1, call_threshold: 2)
begin;
def test(foo)
".#{foo unless foo == 1}" if true
end
print test(0)
+ print test(0)
end;
end
@@ -1038,7 +1058,7 @@ class TestMJIT < Test::Unit::TestCase
omit '.bundle.dSYM directory is left but removing it is not supported for now'
end
Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir|
- eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1)
+ eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 2)
begin;
def a; end; a
exec "true"
@@ -1070,7 +1090,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_frame_omitted_inlining
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\ntrue\n", success_count: 2, call_threshold: 2)
begin;
class Integer
remove_method :zero?
@@ -1079,20 +1099,20 @@ class TestMJIT < Test::Unit::TestCase
end
end
- 3.times do
+ 4.times do
p 0.zero?
end
end;
end
def test_block_handler_with_possible_frame_omitted_inlining
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n70.0\n", success_count: 2, call_threshold: 2)
begin;
def multiply(a, b)
a *= b
end
- 3.times do
+ 4.times do
p multiply(7.0, 10.0)
end
end;
@@ -1131,7 +1151,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_mjit_pause_wait
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, call_threshold: 1)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, call_threshold: 2)
begin;
RubyVM::MJIT.pause
proc {}.call
@@ -1139,7 +1159,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_not_cancel_by_tracepoint_class
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, call_threshold: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 3, call_threshold: 2)
begin;
TracePoint.new(:class) {}.enable
2.times {}
@@ -1155,7 +1175,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_caller_locations_without_catch_table
- out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1)
+ out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 2)
begin;
def b # 2
caller_locations.first # 3
@@ -1173,64 +1193,31 @@ class TestMJIT < Test::Unit::TestCase
assert_equal("-e:8:in `a'\n", lines[1])
end
- def test_fork_with_mjit_worker_thread
- Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir|
- # call_threshold: 2 to skip fork block
- out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 2, verbose: 1)
- begin;
- def before_fork; end
- def after_fork; end
-
- before_fork; before_fork # the child should not delete this .o file
- pid = Process.fork do # this child should not delete shared .pch file
- sleep 2.0 # to prevent mixing outputs on Solaris
- after_fork; after_fork # this child does not share JIT-ed after_fork with parent
- end
- after_fork; after_fork # this parent does not share JIT-ed after_fork with child
-
- Process.waitpid(pid)
- end;
- success_count = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
- debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n"
- assert_equal(3, success_count, debug_info)
-
- # assert no remove error
- assert_equal("Successful MJIT finish\n" * 2, err.gsub(/^#{JIT_SUCCESS_PREFIX}:[^\n]+\n/, ''), debug_info)
-
- # ensure objects are deleted
- if RUBY_PLATFORM.match?(/darwin/)
- omit '.bundle.dSYM directory is left but removing it is not supported for now'
- end
- assert_send([Dir, :empty?, dir], debug_info)
- end
- end if defined?(fork)
-
def test_jit_failure
- _, err = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 1, verbose: 1)
+ _, err = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", call_threshold: 2, verbose: 1)
begin;
- 1.times do
+ 2.times do
class A
end
end
end;
assert_match(/^MJIT warning: .+ unsupported instruction: defineclass/, err)
- assert_match(/^JIT failure: block in <main>/, err)
end
private
# The shortest way to test one proc
- def assert_compile_once(script, result_inspect:, insns: [], uplevel: 1)
+ def assert_compile_twice(script, result_inspect:, insns: [], uplevel: 1)
if script.match?(/\A\n.+\n\z/m)
script = script.gsub(/^/, ' ')
else
script = " #{script} "
end
- assert_eval_with_jit("p proc {#{script}}.call", stdout: "#{result_inspect}\n", success_count: 1, insns: insns, uplevel: uplevel + 1)
+ assert_eval_with_jit("test = proc {#{script}}; p test.call; p test.call", stdout: "#{result_inspect}\n#{result_inspect}\n", success_count: 1, insns: insns, uplevel: uplevel + 1)
end
# Shorthand for normal test cases
- def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, call_threshold: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
+ def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, call_threshold: 2, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
out, err = eval_with_jit(script, verbose: 1, call_threshold: call_threshold, max_cache: max_cache)
success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
diff --git a/test/ruby/test_rubyvm_mjit.rb b/test/ruby/test_rubyvm_mjit.rb
index 90ff2edc8e..73f43af7f9 100644
--- a/test/ruby/test_rubyvm_mjit.rb
+++ b/test/ruby/test_rubyvm_mjit.rb
@@ -14,10 +14,10 @@ class TestRubyVMMJIT < Test::Unit::TestCase
end
def test_pause
- out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
+ out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, wait: false)
i = 0
while i < 5
- eval("def mjit#{i}; end; mjit#{i}")
+ eval("def mjit#{i}; end; mjit#{i}; mjit#{i}")
i += 1
end
print RubyVM::MJIT.pause
@@ -36,25 +36,22 @@ class TestRubyVMMJIT < Test::Unit::TestCase
end
def test_pause_waits_until_compaction
- out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
- def a() end; a
- def b() end; b
+ out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, wait: false)
+ def a() end; a; a
+ def b() end; b; b
RubyVM::MJIT.pause
EOS
assert_equal(
2, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size,
"unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```",
)
- assert_equal(
- 1, err.scan(/#{JITSupport::JIT_COMPACTION_PREFIX}/).size,
- "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```",
- ) unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet
end
def test_pause_after_waitall
- out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
+ out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, wait: false)
def test() = nil
test
+ test
Process.waitall
print RubyVM::MJIT.pause
EOS
@@ -65,7 +62,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
end
def test_pause_does_not_hang_on_full_units
- out, _ = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, max_cache: 10, wait: false)
+ out, _ = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, max_cache: 10, wait: false)
i = 0
while i < 11
eval("def mjit#{i}; end; mjit#{i}")
@@ -77,7 +74,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
end
def test_pause_wait_false
- out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
+ out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, wait: false)
i = 0
while i < 10
eval("def mjit#{i}; end; mjit#{i}")
@@ -95,7 +92,7 @@ class TestRubyVMMJIT < Test::Unit::TestCase
end
def test_resume
- out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 1, wait: false)
+ out, err = eval_with_jit(<<~'EOS', verbose: 1, call_threshold: 2, wait: false)
print RubyVM::MJIT.resume
print RubyVM::MJIT.pause
print RubyVM::MJIT.resume