[前][次][番号順一覧][スレッド一覧]

ruby-changes:50260

From: nobu <ko1@a...>
Date: Mon, 12 Feb 2018 12:33:06 +0900 (JST)
Subject: [ruby-changes:50260] nobu:r62378 (trunk): test_jit.rb: split test_compile_insns

nobu	2018-02-12 12:33:00 +0900 (Mon, 12 Feb 2018)

  New Revision: 62378

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62378

  Log:
    test_jit.rb: split test_compile_insns

  Modified files:
    trunk/test/ruby/test_jit.rb
Index: test/ruby/test_jit.rb
===================================================================
--- test/ruby/test_jit.rb	(revision 62377)
+++ test/ruby/test_jit.rb	(revision 62378)
@@ -1,8 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L1
 # frozen_string_literal: true
 require 'test/unit'
 
-# Test for --jit option
-class TestJIT < Test::Unit::TestCase
+module TestJITSupport
   JIT_TIMEOUT = 600 # 10min for each...
   JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
   SUPPORTED_COMPILERS = [
@@ -10,24 +9,55 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L9
     '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.
   # 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')
+  end
 
-    # getlocal
-    # setlocal
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_local
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       foo = 1
       foo
-    RUBY
+    end;
+  end
 
-    # getblockparam
-    # setblockparam
-    assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 2)
+  def test_compile_insn_blockparam
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
+    begin;
       def foo(&b)
         a = b
         b = 2
@@ -35,185 +65,243 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L65
       end
 
       print foo { 1 }
-    RUBY
+    end;
+  end
 
-    # getblockparamproxy
-    # TODO: support this in mjit_compile
+  def test_compile_insn_getblockparamproxy
+    skip "support this in mjit_compile"
+  end
 
-    # getspecial
+  def test_compile_insn_getspecial
     assert_compile_once('$1', result_inspect: 'nil')
+  end
 
-    # setspecial
-    assert_compile_once(<<~RUBY, result_inspect: 'true')
+  def test_compile_insn_setspecial
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
+    begin;
       true if nil.nil?..nil.nil?
-    RUBY
+    end;
+  end
 
-    # getinstancevariable
-    # setinstancevariable
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_instancevariable
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       @foo = 1
       @foo
-    RUBY
+    end;
+  end
 
-    # getclassvariable
-    # setclassvariable
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_classvariable
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       @@foo = 1
       @@foo
-    RUBY
+    end;
+  end
 
-    # getconstant
-    # setconstant
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_constant
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       FOO = 1
       FOO
-    RUBY
+    end;
+  end
 
-    # getglobal
-    # setglobal
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_global
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       $foo = 1
       $foo
-    RUBY
+    end;
+  end
 
-    # putnil
+  def test_compile_insn_putnil
     assert_compile_once('nil', result_inspect: 'nil')
+  end
 
-    # putself
-    assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 1)
+  def test_compile_insn_putself
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1)
+    begin;
       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('1', result_inspect: '1') # putobject_OP_INT2FIX_O_1_C_
     assert_compile_once('2', result_inspect: '2')
+  end
 
-    # putspecialobject
-    # putiseq
-    assert_eval_with_jit(<<~RUBY, stdout: 'hello', success_count: 2)
+  def test_compile_insn_putspecialobject_putiseq
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 2)
+    begin;
       print proc {
         def method_definition
           'hello'
         end
         method_definition
       }.call
-    RUBY
+    end;
+  end
 
-    # putstring
-    # concatstrings
-    # tostring
+  def test_compile_insn_putstring_concatstrings_tostring
     assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"')
+  end
 
-    # freezestring
-    assert_eval_with_jit(<<~'RUBY', stdout: 'true', success_count: 1)
+  def test_compile_insn_freezestring
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1)
+    begin;
       # frozen_string_literal: true
       print proc { "#{true}".frozen? }.call
-    RUBY
+    end;
+  end
 
-    # toregexp
+  def test_compile_insn_toregexp
     assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0')
+  end
 
-    # intern
-    # newarray
-    # duparray
+  def test_compile_insn_intern_newarray_duparray
     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')
+  end
 
-    # concatarray
+  def test_compile_insn_concatarray
     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]')
+  end
 
-    # newhash
+  def test_compile_insn_newhash
     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')
+  end
 
-    # pop
-    assert_compile_once(<<~RUBY, result_inspect: '1')
+  def test_compile_insn_pop
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1')
+    begin;
       a = false
       b = 1
       a || b
-    RUBY
+    end;
+  end
 
-    # dup
-    assert_compile_once(<<~RUBY, result_inspect: '3')
+  def test_compile_insn_dup
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3')
+    begin;
       a = 1
       a&.+(2)
-    RUBY
+    end;
+  end
 
-    # dupn
-    assert_compile_once(<<~RUBY, result_inspect: 'true')
+  def test_compile_insn_dupn
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
+    begin;
       klass = Class.new
       klass::X ||= true
-    RUBY
+    end;
+  end
 
-    # swap
-    # topn
+  def test_compile_insn_swap_topn
     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')
+  end
 
-    # reput
-    # TODO: write test
+  def test_compile_insn_reput
+    skip "write test"
+  end
 
-    # setn
+  def test_compile_insn_setn
     assert_compile_once('[nil][0] = 1', result_inspect: '1')
+  end
 
-    # adjuststack
-    assert_compile_once(<<~RUBY, result_inspect: 'true')
+  def test_compile_insn_adjuststack
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true')
+    begin;
       x = [true]
       x[0] ||= nil
       x[0]
-    RUBY
+    end;
+  end
 
-    # defined
+  def test_compile_insn_defined
     assert_compile_once('defined?(a)', result_inspect: 'nil')
+  end
 
-    # checkkeyword
-    assert_eval_with_jit(<<~RUBY, stdout: 'true', success_count: 1)
+  def test_compile_insn_checkkeyword
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1)
+    begin;
       def test(x: rand)
         x
       end
       print test(x: true)
-    RUBY
+    end;
+  end
 
-    # tracecoverage
-    # TODO: write test
+  def test_compile_insn_tracecoverage
+    skip "write test"
+  end
 
-    # defineclass
-    # TODO: support this in mjit_compile (low priority)
+  def test_compile_insn_defineclass
+    skip "support this in mjit_compile (low priority)"
+  end
 
-    # send
-    assert_eval_with_jit(<<~RUBY, stdout: '1', success_count: 2)
+  def test_compile_insn_send
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
+    begin;
       print proc { yield_self { 1 } }.call
-    RUBY
+    end;
+  end
+
+  def test_compile_insn_opt_str_freeze
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"')
+    begin;
+      'foo'.freeze
+    end;
+  end
+
+  def test_compile_insn_opt_str_uminus
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"')
+    begin;
+      -'bar'
+    end;
+  end
 
-    # 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')
+  def test_compile_insn_opt_newarray_max
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2')
+    begin;
       a = 1
       b = 2
-      [a, b].max + [a, b].min
-    RUBY
+      [a, b].max
+    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')
+  end
 
-    # invokesuper
-    assert_eval_with_jit(<<~RUBY, stdout: '3', success_count: 4)
+  def test_compile_insn_invokesuper
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4)
+    begin;
       mod = Module.new {
         def test
           super + 2
@@ -226,19 +314,22 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L314
         end
       }
       print klass.new.test
-    RUBY
+    end;
+  end
 
-    # invokeblock
-    # leave
-    assert_eval_with_jit(<<~RUBY, stdout: '2', success_count: 2)
+  def test_compile_insn_invokeblock_leave
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2)
+    begin;
       def foo
         yield
       end
       print foo { 2 }
-    RUBY
+    end;
+  end
 
-    # throw
-    assert_eval_with_jit(<<~RUBY, stdout: '4', success_count: 2)
+  def test_compile_insn_throw
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2)
+    begin;
       def test
         proc do
           if 1+1 == 1
@@ -250,111 +341,121 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L341
         end.call
       end
       print test
-    RUBY
+    end;
+  end
 
-    # jump
-    # branchif
-    assert_compile_once(<<~'RUBY', result_inspect: 'nil')
+  def test_compile_insn_jump_branchif
+    assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil')
+    begin;
       a = false
       1 + 1 while false
-    RUBY
+    end;
+  end
 
-    # branchunless
-    assert_compile_once(<<~'RUBY', result_inspect: '1')
+  def test_compile_insn_branchunless
+    assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1')
+    begin;
       a = true
       if a
         1
       else
         2
       end
-    RUBY
+    end;
+  end
 
-    # branchnil
-    assert_compile_once(<<~'RUBY', result_inspect: '3')
+  def test_compile_insn_branchnil
+    assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3')
+    begin;
       a = 2
       a&.+(1)
-    RUBY
+    end;
+  end
 
-    # branchiftype
-    assert_compile_once(<<~'RUBY', result_inspect: '"42"')
+  def test_compile_insn_branchiftype
+    assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"')
+    begin;
       a = '2'
       "4#{a}"
-    RUBY
+    end;
+  end
 
-    # getinlinecache
-    # setinlinecache
+  def test_compile_insn_inlinecache
     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"]')
+  end
 
-    # checkmatch
-    # opt_case_dispatch
-    assert_compile_once(<<~RUBY, result_inspect: '"world"')
+  def test_compile_insn_checkmatch_opt_case_dispatch
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"')
+    begin;
       case 'hello'
       when /hello/
         'world'
       end
-    RUBY
+    end;
+  end
 
-    # opt_plus
-    # opt_minus
-    # opt_mult
-    # opt_div
-    # opt_mod
+  def test_compile_insn_opt_calc
     assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5')
+    assert_compile_once('4 + 2', result_inspect: '6')
+  end
 
-    # opt_eq
-    # opt_neq
+  def test_compile_insn_opt_cmp
     assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true')
+  end
 
-    # opt_lt
-    # opt_le
-    # opt_gt
-    # opt_ge
+  def test_compile_insn_opt_rel
     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]')
+  end
 
-    # opt_aref
-    # opt_aset
-    # opt_aset_with
-    # opt_aref_with
-    assert_compile_once(<<~RUBY, result_inspect: '8')
+  def test_compile_insn_opt_aref_aset
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '8')
+    begin;
       hash = { '1' => 2 }
       hash['1'] + hash[1.to_s] + (hash['2'] = 2) + (hash[2.to_s] = 2)
-    RUBY
+    end;
+  end
 
-    # opt_length
-    # opt_size
-    assert_compile_once(<<~RUBY, result_inspect: '4')
+  def test_compile_insn_opt_length_size
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4')
+    begin;
       array = [1, 2]
-      array.size + array.length
-    RUBY
+      array.length + array.size
+    end;
+  end
 
-    # opt_empty_p
+  def test_compile_insn_opt_empty_p
     assert_compile_once('[].empty?', result_inspect: 'true')
+  end
 
-    # opt_succ
+  def test_compile_insn_opt_succ
     assert_compile_once('1.succ', result_inspect: '2')
+  end
 
-    # opt_not
+  def test_compile_insn_opt_not
     assert_compile_once('!!true', result_inspect: 'true')
+  end
 
-    # opt_regexpmatch1
+  def test_compile_insn_opt_regexpmatch1
     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')
+  end
 
-    # opt_call_c_function
-    # TODO: support this in opt_call_c_function (low priority)
+  def test_compile_insn_opt_call_c_function
+    skip "support this in opt_call_c_function (low priority)"
   end
 
   def test_jit_output
-    skip unless jit_supported?
-
     out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 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)
@@ -371,14 +472,12 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L472
   # 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)
-    if jit_supported?
-      actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
-      assert_equal(
-        success_count, actual,
-        "Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\
-        "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}",
-      )
-    end
+    actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
+    assert_equal(
+      success_count, actual,
+      "Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\
+      "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}",
+    )
     if stdout
       assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
     end
@@ -386,11 +485,8 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L485
 
   # Run Ruby script with --jit-wait (Synchronous JIT compilation).
   # Returns [stdout, stderr]
-  def eval_with_jit(script, verbose: 0, min_calls: 5, timeout: JIT_TIMEOUT)
-    stdout, stderr, status = EnvUtil.invoke_ruby(
-      ['--disable-gems', '--jit-wait', "--jit-verbose=#{verbose}", "--jit-min-calls=#{min_calls}", '-e', script],
-      '', true, true, timeout: timeout,
-    )
+  def eval_with_jit(script, **opts)
+    stdout, stderr, status = super
     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]
   end
@@ -398,22 +494,4 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L494
   def code_block(code)
     "```\n#{code}\n```\n\n"
   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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]