зеркало из https://github.com/github/ruby.git
mjit.c: initial support for mswin MJIT
By this commit's changes in other files, now MJIT started to work on VC++. Unfortunately some features are still broken and they'll be fixed later. This also suppresses cl.exe's default output to stdout because there seems to be no option to do it. Tweaking some log messages as well. vm_core.h: declare `__declspec(dllimport)` to export them correctly on mswin. vm_insnhelper.h: ditto mjit.h: ditto test_jit.rb: skipped some pending tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64221 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7fef588378
Коммит
10bccf3465
21
mjit.c
21
mjit.c
|
@ -765,7 +765,22 @@ compile_c_to_so(const char *c_file, const char *so_file)
|
|||
if (args == NULL)
|
||||
return FALSE;
|
||||
|
||||
exit_code = exec_process(cc_path, args);
|
||||
{
|
||||
int stdout_fileno = _fileno(stdout);
|
||||
int orig_fd = dup(stdout_fileno);
|
||||
int dev_null = rb_cloexec_open(ruby_null_device, O_WRONLY, 0);
|
||||
|
||||
/* Discard cl.exe's outputs like:
|
||||
_ruby_mjit_p12u3.c
|
||||
Creating library C:.../_ruby_mjit_p12u3.lib and object C:.../_ruby_mjit_p12u3.exp
|
||||
TODO: Don't discard them on --jit-verbose=2+ */
|
||||
dup2(dev_null, stdout_fileno);
|
||||
exit_code = exec_process(cc_path, args);
|
||||
dup2(orig_fd, stdout_fileno);
|
||||
|
||||
close(orig_fd);
|
||||
close(dev_null);
|
||||
}
|
||||
free(args);
|
||||
|
||||
if (exit_code != 0)
|
||||
|
@ -1113,7 +1128,7 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
|
|||
const char *label = RSTRING_PTR(unit->iseq->body->location.label);
|
||||
const char *path = RSTRING_PTR(s);
|
||||
int lineno = FIX2INT(unit->iseq->body->location.first_lineno);
|
||||
verbose(2, "start compile: %s@%s:%d -> %s", label, path, lineno, c_file);
|
||||
verbose(2, "start compilation: %s@%s:%d -> %s", label, path, lineno, c_file);
|
||||
fprintf(f, "/* %s@%s:%d */\n\n", label, path, lineno);
|
||||
}
|
||||
success = mjit_compile(f, unit->iseq->body, funcname);
|
||||
|
@ -1812,7 +1827,7 @@ mjit_finish(void)
|
|||
return;
|
||||
|
||||
/* Wait for pch finish */
|
||||
verbose(2, "Canceling worker thread");
|
||||
verbose(2, "Stopping worker thread");
|
||||
CRITICAL_SECTION_START(3, "in mjit_finish to wakeup from pch");
|
||||
/* As our threads are detached, we could just cancel them. But it
|
||||
is a bad idea because OS processes (C compiler) started by
|
||||
|
|
4
mjit.h
4
mjit.h
|
@ -56,8 +56,8 @@ typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
|
|||
|
||||
extern int mjit_enabled;
|
||||
RUBY_SYMBOL_EXPORT_BEGIN
|
||||
extern struct mjit_options mjit_opts;
|
||||
extern int mjit_call_p;
|
||||
RUBY_EXTERN struct mjit_options mjit_opts;
|
||||
RUBY_EXTERN int mjit_call_p;
|
||||
|
||||
extern void mjit_add_iseq_to_process(const rb_iseq_t *iseq);
|
||||
extern mjit_func_t mjit_get_iseq_func(struct rb_iseq_constant_body *body);
|
||||
|
|
|
@ -52,6 +52,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -77,6 +78,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_blockparam
|
||||
skip_on_mswin
|
||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam])
|
||||
begin;
|
||||
def foo(&b)
|
||||
|
@ -99,6 +101,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
|
||||
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?
|
||||
|
@ -150,6 +153,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -163,6 +167,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_putspecialobject_putiseq
|
||||
skip_on_mswin
|
||||
if /mingw/ =~ RUBY_PLATFORM
|
||||
skip "this is currently failing on MinGW [Bug #14948]"
|
||||
end
|
||||
|
@ -179,10 +184,12 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_putstring_concatstrings_tostring
|
||||
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
|
||||
|
@ -191,6 +198,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_toregexp
|
||||
skip_on_mswin
|
||||
assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
|
||||
end
|
||||
|
||||
|
@ -203,6 +211,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_intern_duparray
|
||||
skip_on_mswin
|
||||
assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray])
|
||||
end
|
||||
|
||||
|
@ -211,6 +220,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
||||
|
@ -244,6 +254,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -277,10 +288,12 @@ class TestJIT < Test::Unit::TestCase
|
|||
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)
|
||||
|
@ -299,6 +312,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -338,10 +352,12 @@ class TestJIT < Test::Unit::TestCase
|
|||
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_mswin
|
||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper])
|
||||
begin;
|
||||
mod = Module.new {
|
||||
|
@ -360,6 +376,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_invokeblock_leave
|
||||
skip_on_mswin
|
||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave])
|
||||
begin;
|
||||
def foo
|
||||
|
@ -370,6 +387,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -415,6 +433,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_checktype
|
||||
skip_on_mswin
|
||||
assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype])
|
||||
begin;
|
||||
a = '2'
|
||||
|
@ -427,6 +446,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_once
|
||||
skip_on_mswin
|
||||
assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once])
|
||||
end
|
||||
|
||||
|
@ -446,6 +466,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
||||
|
@ -458,6 +479,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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;
|
||||
|
@ -487,10 +509,12 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_opt_aref_with
|
||||
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_mswin
|
||||
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
|
||||
begin;
|
||||
hash = { '1' => 2 }
|
||||
|
@ -515,6 +539,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_compile_insn_opt_not
|
||||
skip_on_mswin
|
||||
assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not])
|
||||
end
|
||||
|
||||
|
@ -531,6 +556,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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)
|
||||
|
@ -538,6 +564,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_unload_units
|
||||
skip_on_mswin
|
||||
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, min_calls: 1, max_cache: 10)
|
||||
|
@ -575,6 +602,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -594,6 +622,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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)
|
||||
|
@ -615,6 +644,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -634,6 +664,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -700,6 +731,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_clean_so
|
||||
skip_on_mswin
|
||||
Dir.mktmpdir("jit_test_clean_so_") do |dir|
|
||||
code = "x = 0; 10.times {|i|x+=i}"
|
||||
eval_with_jit({"TMPDIR"=>dir}, code)
|
||||
|
@ -710,6 +742,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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|
|
||||
|
@ -721,6 +754,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -731,6 +765,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -741,6 +776,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -750,6 +786,7 @@ class TestJIT < Test::Unit::TestCase
|
|||
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
|
||||
|
@ -760,6 +797,13 @@ class TestJIT < Test::Unit::TestCase
|
|||
|
||||
private
|
||||
|
||||
# Some tests are stil failing on VC++.
|
||||
def skip_on_mswin
|
||||
if RUBY_PLATFORM.match?(/mswin/)
|
||||
skip 'This test does not succeed on mswin yet.'
|
||||
end
|
||||
end
|
||||
|
||||
# The shortest way to test one proc
|
||||
def assert_compile_once(script, result_inspect:, insns: [])
|
||||
if script.match?(/\A\n.+\n\z/m)
|
||||
|
|
|
@ -1650,10 +1650,10 @@ VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_
|
|||
#if RUBY_VM_THREAD_MODEL == 2
|
||||
RUBY_SYMBOL_EXPORT_BEGIN
|
||||
|
||||
extern rb_vm_t *ruby_current_vm_ptr;
|
||||
extern rb_execution_context_t *ruby_current_execution_context_ptr;
|
||||
extern rb_event_flag_t ruby_vm_event_flags;
|
||||
extern rb_event_flag_t ruby_vm_event_enabled_flags;
|
||||
RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr;
|
||||
RUBY_EXTERN rb_execution_context_t *ruby_current_execution_context_ptr;
|
||||
RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags;
|
||||
RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_flags;
|
||||
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
RUBY_SYMBOL_EXPORT_BEGIN
|
||||
|
||||
extern VALUE ruby_vm_const_missing_count;
|
||||
extern rb_serial_t ruby_vm_global_method_state;
|
||||
extern rb_serial_t ruby_vm_global_constant_state;
|
||||
extern rb_serial_t ruby_vm_class_serial;
|
||||
RUBY_EXTERN VALUE ruby_vm_const_missing_count;
|
||||
RUBY_EXTERN rb_serial_t ruby_vm_global_method_state;
|
||||
RUBY_EXTERN rb_serial_t ruby_vm_global_constant_state;
|
||||
RUBY_EXTERN rb_serial_t ruby_vm_class_serial;
|
||||
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче