ruby-changes:52728
From: k0kubun <ko1@a...>
Date: Sun, 7 Oct 2018 22:11:33 +0900 (JST)
Subject: [ruby-changes:52728] k0kubun:r64940 (trunk): mjit.h: introduce MJIT_STATIC for full mswin JIT support
k0kubun 2018-10-07 22:11:27 +0900 (Sun, 07 Oct 2018) New Revision: 64940 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64940 Log: mjit.h: introduce MJIT_STATIC for full mswin JIT support This change resolves most of major remaining MJIT bugs on mswin. Since Visual Studio doesn't support generating pre-processed code preserving macros, we can't use transform_mjit_header approach for mswin. So we need to transform MJIT header using macro like this. vm.c: use MJIT_STATIC for non-static functions that exist on MJIT header and cause conflict on link. vm_insnhelper.c: ditto test_jit.rb: remove many skips for mswin. Modified files: trunk/mjit.h trunk/test/ruby/test_jit.rb trunk/vm.c trunk/vm_insnhelper.c Index: vm.c =================================================================== --- vm.c (revision 64939) +++ vm.c (revision 64940) @@ -549,7 +549,7 @@ vm_get_ruby_level_caller_cfp(const rb_ex https://github.com/ruby/ruby/blob/trunk/vm.c#L549 return 0; } -void +MJIT_STATIC void rb_vm_pop_cfunc_frame(void) { rb_execution_context_t *ec = GET_EC(); Index: test/ruby/test_jit.rb =================================================================== --- test/ruby/test_jit.rb (revision 64939) +++ test/ruby/test_jit.rb (revision 64940) @@ -52,7 +52,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L52 end def test_compile_insn_local - skip_on_mswin assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0]) begin; foo = 1 @@ -79,7 +78,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L78 def test_compile_insn_blockparam skip_on_mingw - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam]) begin; def foo(&b) @@ -102,7 +100,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L100 def test_compile_insn_setspecial verbose_bak, $VERBOSE = $VERBOSE, nil - skip_on_mswin assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial]) begin; true if nil.nil?..nil.nil? @@ -154,7 +151,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L151 end def test_compile_insn_putself - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself]) begin; proc { print "hello" }.call @@ -169,7 +165,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L165 def test_compile_insn_putspecialobject_putiseq skip_on_mingw # [Bug #14948] - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 2, insns: %i[putspecialobject putiseq]) begin; @@ -184,12 +179,10 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L179 def test_compile_insn_putstring_concatstrings_tostring skip_on_mingw - skip_on_mswin assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring]) end def test_compile_insn_freezestring - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring]) begin; # frozen_string_literal: true @@ -198,7 +191,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L191 end def test_compile_insn_toregexp - skip_on_mswin assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp]) end @@ -212,7 +204,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L204 def test_compile_insn_intern_duparray skip_on_mingw - skip_on_mswin assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray]) end @@ -221,7 +212,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L212 end def test_compile_insn_concatarray - skip_on_mswin assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray]) end @@ -255,7 +245,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L245 end def test_compile_insn_dupn - skip_on_mswin assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn]) begin; klass = Class.new @@ -289,12 +278,10 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L278 end def test_compile_insn_defined - skip_on_mswin assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined]) end def test_compile_insn_checkkeyword - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword]) begin; def test(x: rand) @@ -313,7 +300,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L300 end def test_compile_insn_send - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send]) begin; print proc { yield_self { 1 } }.call @@ -353,13 +339,11 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L339 end def test_compile_insn_opt_send_without_block - skip_on_mswin assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block]) end def test_compile_insn_invokesuper skip_on_mingw - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper]) begin; mod = Module.new { @@ -379,7 +363,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L363 def test_compile_insn_invokeblock_leave skip_on_mingw - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave]) begin; def foo @@ -390,7 +373,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L373 end def test_compile_insn_throw - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw]) begin; def test @@ -436,7 +418,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L418 end def test_compile_insn_checktype - skip_on_mswin assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype]) begin; a = '2' @@ -450,7 +431,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L431 def test_compile_insn_once skip_on_mingw - skip_on_mswin assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once]) end @@ -470,7 +450,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L450 end def test_compile_insn_opt_cmp - skip_on_mswin assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq]) end @@ -491,7 +470,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L470 end def test_compile_insn_opt_aref - skip_on_mswin # optimized call (optimized JIT) -> send call assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref]) begin; @@ -522,13 +500,11 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L500 def test_compile_insn_opt_aref_with skip_on_mingw - skip_on_mswin assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with]) end def test_compile_insn_opt_aset skip_on_mingw - skip_on_mswin assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with]) begin; hash = { '1' => 2 } @@ -553,7 +529,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L529 end def test_compile_insn_opt_not - skip_on_mswin assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not]) end @@ -570,7 +545,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L545 end def test_jit_output - skip_on_mswin 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) @@ -618,7 +592,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L592 end def test_local_stack_on_exception - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2) begin; def b @@ -638,7 +611,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L611 end def test_local_stack_with_sp_motion_by_blockargs - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2) begin; def b(base) @@ -660,7 +632,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L632 end def test_catching_deep_exception - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4) begin; def catch_true(paths, prefixes) # catch_except_p: TRUE @@ -680,7 +651,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L651 end def test_attr_reader - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2) begin; class A @@ -758,7 +728,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L728 end def test_lambda_longjmp - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1) begin; fib = lambda do |x| @@ -770,7 +739,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L739 end def test_stack_pointer_with_assignment - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1) begin; 2.times do @@ -781,7 +749,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L749 end def test_program_pointer_with_regexpmatch - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1) begin; 2.times do @@ -792,7 +759,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L759 end def test_pushed_values_with_opt_aset_with - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1) begin; 2.times do @@ -802,7 +768,6 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L768 end def test_pushed_values_with_opt_aref_with - skip_on_mswin assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1) begin; 2.times do Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 64939) +++ vm_insnhelper.c (revision 64940) @@ -23,7 +23,7 @@ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L23 static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); -VALUE +MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE exc) { VALUE e = rb_obj_alloc(rb_class_real(RBASIC_CLASS(exc))); @@ -55,8 +55,8 @@ vm_stackoverflow(void) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L55 ec_stack_overflow(GET_EC(), TRUE); } -NORETURN(void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit)); -void +NORETURN(MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit)); +MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit) { if (crit || rb_during_gc()) { @@ -314,7 +314,7 @@ vm_pop_frame(rb_execution_context_t *ec, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L314 return flags & VM_FRAME_FLAG_FINISH; } -void +MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec) { vm_pop_frame(ec, ec->cfp, ec->cfp->ep); @@ -337,7 +337,7 @@ rb_arity_error_new(int argc, int min, in https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L337 return rb_exc_new3(rb_eArgError, err_mess); } -void +MJIT_STATIC void rb_error_arity(int argc, int min, int max) { rb_exc_raise(rb_arity_error_new(argc, min, max)); @@ -369,7 +369,7 @@ vm_env_write(const VALUE *ep, int index, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L369 } } -VALUE +MJIT_STATIC VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler) { if (block_handler == VM_BLOCK_HANDLER_NONE) { @@ -562,7 +562,7 @@ check_method_entry(VALUE obj, int can_be https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L562 } } -const rb_callable_method_entry_t * +MJIT_STATIC const rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp) { const VALUE *ep = cfp->ep; @@ -1628,7 +1628,7 @@ vm_call_iseq_setup_normal_0start(rb_exec https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1628 return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, 0, param, local); } -int +MJIT_STATIC int rb_simple_iseq_p(const rb_iseq_t *iseq) { return iseq->body->param.flags.has_opt == FALSE && Index: mjit.h =================================================================== --- mjit.h (revision 64939) +++ mjit.h (revision 64940) @@ -11,6 +11,18 @@ https://github.com/ruby/ruby/blob/trunk/mjit.h#L11 #include "ruby.h" +/* On mswin, MJIT header transformation can't be used since cl.exe can't output + preprocessed output preserving macros. So this `MJIT_STATIC` is needed + to force non-static function to static on MJIT header to avoid symbol conflict. + `MJIT_FUNC_EXPORTED` is also changed to `static` on MJIT header for the same reason. */ +#ifdef MJIT_HEADER +# define MJIT_STATIC static +# undef MJIT_FUNC_EXPORTED +# define MJIT_FUNC_EXPORTED static +#else +# define MJIT_STATIC +#endif + /* Special address values of a function generated from the corresponding iseq by MJIT: */ enum rb_mjit_iseq_func { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/