1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64940 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2018-10-07 13:11:27 +00:00
parent b62c1a22b3
commit 950d100700
4 changed files with 21 additions and 44 deletions

12
mjit.h
View file

@ -11,6 +11,18 @@
#include "ruby.h" #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 /* Special address values of a function generated from the
corresponding iseq by MJIT: */ corresponding iseq by MJIT: */
enum rb_mjit_iseq_func { enum rb_mjit_iseq_func {

View file

@ -52,7 +52,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_local 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]) assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0])
begin; begin;
foo = 1 foo = 1
@ -79,7 +78,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_blockparam def test_compile_insn_blockparam
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam])
begin; begin;
def foo(&b) def foo(&b)
@ -102,7 +100,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_setspecial def test_compile_insn_setspecial
verbose_bak, $VERBOSE = $VERBOSE, nil verbose_bak, $VERBOSE = $VERBOSE, nil
skip_on_mswin
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial]) assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial])
begin; begin;
true if nil.nil?..nil.nil? true if nil.nil?..nil.nil?
@ -154,7 +151,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_putself def test_compile_insn_putself
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself])
begin; begin;
proc { print "hello" }.call proc { print "hello" }.call
@ -169,7 +165,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_putspecialobject_putiseq def test_compile_insn_putspecialobject_putiseq
skip_on_mingw # [Bug #14948] skip_on_mingw # [Bug #14948]
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 2, insns: %i[putspecialobject putiseq]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 2, insns: %i[putspecialobject putiseq])
begin; begin;
@ -184,12 +179,10 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_putstring_concatstrings_tostring def test_compile_insn_putstring_concatstrings_tostring
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring]) assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring])
end end
def test_compile_insn_freezestring def test_compile_insn_freezestring
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring])
begin; begin;
# frozen_string_literal: true # frozen_string_literal: true
@ -198,7 +191,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_toregexp def test_compile_insn_toregexp
skip_on_mswin
assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp]) assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
end end
@ -212,7 +204,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_intern_duparray def test_compile_insn_intern_duparray
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray]) assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray])
end end
@ -221,7 +212,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_concatarray def test_compile_insn_concatarray
skip_on_mswin
assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray]) assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray])
end end
@ -255,7 +245,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_dupn def test_compile_insn_dupn
skip_on_mswin
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn]) assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn])
begin; begin;
klass = Class.new klass = Class.new
@ -289,12 +278,10 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_defined def test_compile_insn_defined
skip_on_mswin
assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined]) assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined])
end end
def test_compile_insn_checkkeyword def test_compile_insn_checkkeyword
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword])
begin; begin;
def test(x: rand) def test(x: rand)
@ -313,7 +300,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_send def test_compile_insn_send
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send])
begin; begin;
print proc { yield_self { 1 } }.call print proc { yield_self { 1 } }.call
@ -353,13 +339,11 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_opt_send_without_block def test_compile_insn_opt_send_without_block
skip_on_mswin
assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block]) assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
end end
def test_compile_insn_invokesuper def test_compile_insn_invokesuper
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper])
begin; begin;
mod = Module.new { mod = Module.new {
@ -379,7 +363,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_invokeblock_leave def test_compile_insn_invokeblock_leave
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave])
begin; begin;
def foo def foo
@ -390,7 +373,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_throw def test_compile_insn_throw
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw])
begin; begin;
def test def test
@ -436,7 +418,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_checktype def test_compile_insn_checktype
skip_on_mswin
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype]) assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype])
begin; begin;
a = '2' a = '2'
@ -450,7 +431,6 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_once def test_compile_insn_once
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once]) assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once])
end end
@ -470,7 +450,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_opt_cmp 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]) assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq])
end end
@ -491,7 +470,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_opt_aref def test_compile_insn_opt_aref
skip_on_mswin
# optimized call (optimized JIT) -> send call # 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]) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref])
begin; begin;
@ -522,13 +500,11 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_opt_aref_with def test_compile_insn_opt_aref_with
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with]) assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with])
end end
def test_compile_insn_opt_aset def test_compile_insn_opt_aset
skip_on_mingw skip_on_mingw
skip_on_mswin
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with]) assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
begin; begin;
hash = { '1' => 2 } hash = { '1' => 2 }
@ -553,7 +529,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_compile_insn_opt_not def test_compile_insn_opt_not
skip_on_mswin
assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not]) assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not])
end end
@ -570,7 +545,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_jit_output def test_jit_output
skip_on_mswin
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)
@ -618,7 +592,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_local_stack_on_exception def test_local_stack_on_exception
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
begin; begin;
def b def b
@ -638,7 +611,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_local_stack_with_sp_motion_by_blockargs def test_local_stack_with_sp_motion_by_blockargs
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
begin; begin;
def b(base) def b(base)
@ -660,7 +632,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_catching_deep_exception def test_catching_deep_exception
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4)
begin; begin;
def catch_true(paths, prefixes) # catch_except_p: TRUE def catch_true(paths, prefixes) # catch_except_p: TRUE
@ -680,7 +651,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_attr_reader def test_attr_reader
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
begin; begin;
class A class A
@ -758,7 +728,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_lambda_longjmp def test_lambda_longjmp
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1)
begin; begin;
fib = lambda do |x| fib = lambda do |x|
@ -770,7 +739,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_stack_pointer_with_assignment def test_stack_pointer_with_assignment
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
begin; begin;
2.times do 2.times do
@ -781,7 +749,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_program_pointer_with_regexpmatch def test_program_pointer_with_regexpmatch
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1)
begin; begin;
2.times do 2.times do
@ -792,7 +759,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_pushed_values_with_opt_aset_with def test_pushed_values_with_opt_aset_with
skip_on_mswin
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1)
begin; begin;
2.times do 2.times do
@ -802,7 +768,6 @@ class TestJIT < Test::Unit::TestCase
end end
def test_pushed_values_with_opt_aref_with 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) assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
begin; begin;
2.times do 2.times do

2
vm.c
View file

@ -549,7 +549,7 @@ vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_
return 0; return 0;
} }
void MJIT_STATIC void
rb_vm_pop_cfunc_frame(void) rb_vm_pop_cfunc_frame(void)
{ {
rb_execution_context_t *ec = GET_EC(); rb_execution_context_t *ec = GET_EC();

View file

@ -23,7 +23,7 @@
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); 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) ruby_vm_special_exception_copy(VALUE exc)
{ {
VALUE e = rb_obj_alloc(rb_class_real(RBASIC_CLASS(exc))); VALUE e = rb_obj_alloc(rb_class_real(RBASIC_CLASS(exc)));
@ -55,8 +55,8 @@ vm_stackoverflow(void)
ec_stack_overflow(GET_EC(), TRUE); ec_stack_overflow(GET_EC(), TRUE);
} }
NORETURN(void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit)); NORETURN(MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit));
void MJIT_STATIC void
rb_ec_stack_overflow(rb_execution_context_t *ec, int crit) rb_ec_stack_overflow(rb_execution_context_t *ec, int crit)
{ {
if (crit || rb_during_gc()) { if (crit || rb_during_gc()) {
@ -314,7 +314,7 @@ vm_pop_frame(rb_execution_context_t *ec, rb_control_frame_t *cfp, const VALUE *e
return flags & VM_FRAME_FLAG_FINISH; return flags & VM_FRAME_FLAG_FINISH;
} }
void MJIT_STATIC void
rb_vm_pop_frame(rb_execution_context_t *ec) rb_vm_pop_frame(rb_execution_context_t *ec)
{ {
vm_pop_frame(ec, ec->cfp, ec->cfp->ep); vm_pop_frame(ec, ec->cfp, ec->cfp->ep);
@ -337,7 +337,7 @@ rb_arity_error_new(int argc, int min, int max)
return rb_exc_new3(rb_eArgError, err_mess); return rb_exc_new3(rb_eArgError, err_mess);
} }
void MJIT_STATIC void
rb_error_arity(int argc, int min, int max) rb_error_arity(int argc, int min, int max)
{ {
rb_exc_raise(rb_arity_error_new(argc, min, max)); rb_exc_raise(rb_arity_error_new(argc, min, max));
@ -369,7 +369,7 @@ vm_env_write(const VALUE *ep, int index, VALUE v)
} }
} }
VALUE MJIT_STATIC VALUE
rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler) rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler)
{ {
if (block_handler == VM_BLOCK_HANDLER_NONE) { if (block_handler == VM_BLOCK_HANDLER_NONE) {
@ -562,7 +562,7 @@ check_method_entry(VALUE obj, int can_be_svar)
} }
} }
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) rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
{ {
const VALUE *ep = cfp->ep; const VALUE *ep = cfp->ep;
@ -1628,7 +1628,7 @@ vm_call_iseq_setup_normal_0start(rb_execution_context_t *ec, rb_control_frame_t
return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, 0, param, local); 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) rb_simple_iseq_p(const rb_iseq_t *iseq)
{ {
return iseq->body->param.flags.has_opt == FALSE && return iseq->body->param.flags.has_opt == FALSE &&