mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Allow hooking a different method after --mjit=pause
The interface is similar to RubyVM::ISeq.translate; it's used if defined. Same as --mjit=pause, this is an undocumented feature for MJIT experiments.
This commit is contained in:
parent
341b40bd0c
commit
b726c06e7e
2 changed files with 39 additions and 10 deletions
43
mjit.c
43
mjit.c
|
@ -1404,14 +1404,39 @@ mjit_target_iseq_p(const rb_iseq_t *iseq)
|
||||||
&& strcmp("<internal:mjit>", RSTRING_PTR(rb_iseq_path(iseq))) != 0;
|
&& strcmp("<internal:mjit>", RSTRING_PTR(rb_iseq_path(iseq))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RubyVM::MJIT
|
||||||
|
static VALUE rb_mMJIT = 0;
|
||||||
|
// RubyVM::MJIT::C
|
||||||
|
VALUE rb_mMJITC = 0;
|
||||||
|
// RubyVM::MJIT::Compiler
|
||||||
|
VALUE rb_mMJITCompiler = 0;
|
||||||
|
|
||||||
|
// [experimental] Call custom RubyVM::MJIT.compile if defined
|
||||||
|
static void
|
||||||
|
mjit_hook_custom_compile(const rb_iseq_t *iseq)
|
||||||
|
{
|
||||||
|
bool original_call_p = mjit_call_p;
|
||||||
|
mjit_call_p = false; // Avoid impacting JIT metrics by itself
|
||||||
|
|
||||||
|
VALUE iseq_class = rb_funcall(rb_mMJITC, rb_intern("rb_iseq_t"), 0);
|
||||||
|
VALUE iseq_ptr = rb_funcall(iseq_class, rb_intern("new"), 1, ULONG2NUM((size_t)iseq));
|
||||||
|
VALUE jit_func = rb_funcall(rb_mMJIT, rb_intern("compile"), 1, iseq_ptr);
|
||||||
|
ISEQ_BODY(iseq)->jit_func = (mjit_func_t)NUM2ULONG(jit_func);
|
||||||
|
|
||||||
|
mjit_call_p = original_call_p;
|
||||||
|
}
|
||||||
|
|
||||||
// If recompile_p is true, the call is initiated by mjit_recompile.
|
// If recompile_p is true, the call is initiated by mjit_recompile.
|
||||||
// This assumes the caller holds CRITICAL_SECTION when recompile_p is true.
|
// This assumes the caller holds CRITICAL_SECTION when recompile_p is true.
|
||||||
static void
|
static void
|
||||||
mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool recompile_p)
|
mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool recompile_p)
|
||||||
{
|
{
|
||||||
// TODO: Support non-main Ractors
|
if (!mjit_enabled || pch_status == PCH_FAILED || !rb_ractor_main_p()) // TODO: Support non-main Ractors
|
||||||
if (!mjit_enabled || pch_status == PCH_FAILED || !rb_ractor_main_p())
|
|
||||||
return;
|
return;
|
||||||
|
if (mjit_opts.custom) {
|
||||||
|
mjit_hook_custom_compile(iseq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!mjit_target_iseq_p(iseq)) {
|
if (!mjit_target_iseq_p(iseq)) {
|
||||||
ISEQ_BODY(iseq)->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; // skip mjit_wait
|
ISEQ_BODY(iseq)->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; // skip mjit_wait
|
||||||
return;
|
return;
|
||||||
|
@ -1804,11 +1829,6 @@ const struct ruby_opt_message mjit_option_messages[] = {
|
||||||
};
|
};
|
||||||
#undef M
|
#undef M
|
||||||
|
|
||||||
// RubyVM::MJIT::Compiler
|
|
||||||
VALUE rb_mMJITCompiler = 0;
|
|
||||||
// RubyVM::MJIT::C
|
|
||||||
VALUE rb_mMJITC = 0;
|
|
||||||
|
|
||||||
// Initialize MJIT. Start a thread creating the precompiled header and
|
// Initialize MJIT. Start a thread creating the precompiled header and
|
||||||
// processing ISeqs. The function should be called first for using MJIT.
|
// processing ISeqs. The function should be called first for using MJIT.
|
||||||
// If everything is successful, MJIT_INIT_P will be TRUE.
|
// If everything is successful, MJIT_INIT_P will be TRUE.
|
||||||
|
@ -1819,7 +1839,7 @@ mjit_init(const struct mjit_options *opts)
|
||||||
mjit_opts = *opts;
|
mjit_opts = *opts;
|
||||||
|
|
||||||
// MJIT doesn't support miniruby, but it might reach here by MJIT_FORCE_ENABLE.
|
// MJIT doesn't support miniruby, but it might reach here by MJIT_FORCE_ENABLE.
|
||||||
VALUE rb_mMJIT = rb_const_get(rb_cRubyVM, rb_intern("MJIT"));
|
rb_mMJIT = rb_const_get(rb_cRubyVM, rb_intern("MJIT"));
|
||||||
if (!rb_const_defined(rb_mMJIT, rb_intern("Compiler"))) {
|
if (!rb_const_defined(rb_mMJIT, rb_intern("Compiler"))) {
|
||||||
verbose(1, "Disabling MJIT because RubyVM::MJIT::Compiler is not defined");
|
verbose(1, "Disabling MJIT because RubyVM::MJIT::Compiler is not defined");
|
||||||
mjit_enabled = false;
|
mjit_enabled = false;
|
||||||
|
@ -1937,8 +1957,15 @@ mjit_resume(void)
|
||||||
|
|
||||||
// Lazily prepare PCH when --mjit=pause is given
|
// Lazily prepare PCH when --mjit=pause is given
|
||||||
if (pch_status == PCH_NOT_READY) {
|
if (pch_status == PCH_NOT_READY) {
|
||||||
|
if (rb_respond_to(rb_mMJITCompiler, rb_intern("compile"))) {
|
||||||
|
// [experimental] defining RubyVM::MJIT.compile allows you to replace JIT
|
||||||
|
mjit_opts.custom = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Lazy MJIT boot
|
||||||
make_pch();
|
make_pch();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!start_worker()) {
|
if (!start_worker()) {
|
||||||
rb_raise(rb_eRuntimeError, "Failed to resume MJIT worker");
|
rb_raise(rb_eRuntimeError, "Failed to resume MJIT worker");
|
||||||
|
|
4
mjit.h
4
mjit.h
|
@ -59,8 +59,10 @@ struct mjit_options {
|
||||||
// Maximal permitted number of iseq JIT codes in a MJIT memory
|
// Maximal permitted number of iseq JIT codes in a MJIT memory
|
||||||
// cache.
|
// cache.
|
||||||
int max_cache_size;
|
int max_cache_size;
|
||||||
// [experimental] If true, do not start MJIT until MJIT.resume is called.
|
// [experimental] Do not start MJIT until MJIT.resume is called.
|
||||||
bool pause;
|
bool pause;
|
||||||
|
// [experimental] Call custom RubyVM::MJIT.compile instead of MJIT.
|
||||||
|
bool custom;
|
||||||
};
|
};
|
||||||
|
|
||||||
// State of optimization switches
|
// State of optimization switches
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue