diff options
Diffstat (limited to 'rjit.c')
-rw-r--r-- | rjit.c | 88 |
1 files changed, 56 insertions, 32 deletions
@@ -101,6 +101,9 @@ VALUE rb_rjit_raw_samples = 0; // Line numbers for --rjit-trace-exits VALUE rb_rjit_line_samples = 0; +// Postponed job handle for triggering rjit_iseq_update_references +static rb_postponed_job_handle_t rjit_iseq_update_references_pjob; + // A default threshold used to add iseq to JIT. #define DEFAULT_CALL_THRESHOLD 10 // Size of executable memory block in MiB. @@ -118,15 +121,21 @@ rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt) if (l == 0) { return; } - else if (opt_match_arg(s, l, "call-threshold")) { - rjit_opt->call_threshold = atoi(s + 1); - } else if (opt_match_arg(s, l, "exec-mem-size")) { rjit_opt->exec_mem_size = atoi(s + 1); } + else if (opt_match_arg(s, l, "call-threshold")) { + rjit_opt->call_threshold = atoi(s + 1); + } else if (opt_match_noarg(s, l, "stats")) { rjit_opt->stats = true; } + else if (opt_match_noarg(s, l, "disable")) { + rjit_opt->disable = true; + } + else if (opt_match_noarg(s, l, "trace")) { + rjit_opt->trace = true; + } else if (opt_match_noarg(s, l, "trace-exits")) { rjit_opt->trace_exits = true; } @@ -136,24 +145,20 @@ rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt) else if (opt_match_noarg(s, l, "verify-ctx")) { rjit_opt->verify_ctx = true; } - // --rjit=pause is an undocumented feature for experiments - else if (opt_match_noarg(s, l, "pause")) { - rjit_opt->pause = true; - } else { rb_raise(rb_eRuntimeError, - "invalid RJIT option `%s' (--help will show valid RJIT options)", s); + "invalid RJIT option '%s' (--help will show valid RJIT options)", s); } } #define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc) const struct ruby_opt_message rb_rjit_option_messages[] = { - M("--rjit-stats", "", "Enable collecting RJIT statistics"), -#if RJIT_STATS - M("--rjit-trace-exits", "", "Trace side exit locations"), -#endif - M("--rjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: " STRINGIZE(DEFAULT_EXEC_MEM_SIZE) ")"), - M("--rjit-call-threshold=num", "", "Number of calls to trigger JIT (default: " STRINGIZE(DEFAULT_CALL_THRESHOLD) ")"), + M("--rjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: " STRINGIZE(DEFAULT_EXEC_MEM_SIZE) ")."), + M("--rjit-call-threshold=num", "", "Number of calls to trigger JIT (default: " STRINGIZE(DEFAULT_CALL_THRESHOLD) ")."), + M("--rjit-stats", "", "Enable collecting RJIT statistics."), + M("--rjit-disable", "", "Disable RJIT for lazily enabling it with RubyVM::RJIT.enable."), + M("--rjit-trace", "", "Allow TracePoint during JIT compilation."), + M("--rjit-trace-exits", "", "Trace side exit locations."), #ifdef HAVE_LIBCAPSTONE M("--rjit-dump-disasm", "", "Dump all JIT code"), #endif @@ -163,32 +168,47 @@ const struct ruby_opt_message rb_rjit_option_messages[] = { struct rb_rjit_runtime_counters rb_rjit_counters = { 0 }; -#if RJIT_STATS -void -rb_rjit_collect_vm_usage_insn(int insn) -{ - if (!rjit_stats_p) return; - rb_rjit_counters.vm_insns_count++; -} -#endif // YJIT_STATS - extern VALUE rb_gc_enable(void); extern VALUE rb_gc_disable(void); +extern uint64_t rb_vm_insns_count; -#define WITH_RJIT_ISOLATED(stmt) do { \ +// Disable GC, TracePoint, JIT, stats, and $! +#define WITH_RJIT_ISOLATED_USING_PC(using_pc, stmt) do { \ VALUE was_disabled = rb_gc_disable(); \ + \ rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(GET_EC()); \ rb_rjit_global_events = global_hooks->events; \ - global_hooks->events = 0; \ + \ + const VALUE *pc = NULL; \ + if (rb_rjit_opts.trace) { \ + pc = GET_EC()->cfp->pc; \ + if (!using_pc) GET_EC()->cfp->pc = 0; /* avoid crashing on calc_lineno */ \ + } \ + else global_hooks->events = 0; \ + \ bool original_call_p = rb_rjit_call_p; \ - rjit_stats_p = false; \ rb_rjit_call_p = false; \ + \ + rjit_stats_p = false; \ + uint64_t insns_count = rb_vm_insns_count; \ + \ + VALUE err = rb_errinfo(); \ + \ stmt; \ - rb_rjit_call_p = (rjit_cancel_p ? false : original_call_p); \ + \ + rb_set_errinfo(err); \ + \ + rb_vm_insns_count = insns_count; \ rjit_stats_p = rb_rjit_opts.stats; \ - global_hooks->events = rb_rjit_global_events; \ + \ + rb_rjit_call_p = (rjit_cancel_p ? false : original_call_p); \ + \ + if (rb_rjit_opts.trace) GET_EC()->cfp->pc = pc; \ + else global_hooks->events = rb_rjit_global_events; \ + \ if (!was_disabled) rb_gc_enable(); \ } while (0); +#define WITH_RJIT_ISOLATED(stmt) WITH_RJIT_ISOLATED_USING_PC(false, stmt) void rb_rjit_cancel_all(const char *reason) @@ -301,7 +321,7 @@ rb_rjit_iseq_update_references(struct rb_iseq_constant_body *const body) // Asynchronously hook the Ruby code to avoid allocation during GC.compact. // Using _one because it's too slow to invalidate all for each ISEQ. Thus // not giving an ISEQ pointer. - rb_postponed_job_register_one(0, rjit_iseq_update_references, NULL); + rb_postponed_job_trigger(rjit_iseq_update_references_pjob); } void @@ -354,7 +374,7 @@ rb_rjit_compile(const rb_iseq_t *iseq) RB_VM_LOCK_ENTER(); rb_vm_barrier(); - WITH_RJIT_ISOLATED({ + WITH_RJIT_ISOLATED_USING_PC(true, { VALUE iseq_ptr = rb_funcall(rb_cRJITIseqPtr, rb_intern("new"), 1, SIZET2NUM((size_t)iseq)); VALUE cfp_ptr = rb_funcall(rb_cRJITCfpPtr, rb_intern("new"), 1, SIZET2NUM((size_t)GET_EC()->cfp)); rb_funcall(rb_RJITCompiler, rb_intern("compile"), 2, iseq_ptr, cfp_ptr); @@ -373,7 +393,7 @@ rb_rjit_entry_stub_hit(VALUE branch_stub) rb_control_frame_t *cfp = GET_EC()->cfp; - WITH_RJIT_ISOLATED({ + WITH_RJIT_ISOLATED_USING_PC(true, { VALUE cfp_ptr = rb_funcall(rb_cRJITCfpPtr, rb_intern("new"), 1, SIZET2NUM((size_t)cfp)); result = rb_funcall(rb_RJITCompiler, rb_intern("entry_stub_hit"), 2, branch_stub, cfp_ptr); }); @@ -429,6 +449,10 @@ rb_rjit_init(const struct rb_rjit_options *opts) rb_rjit_enabled = false; return; } + rjit_iseq_update_references_pjob = rb_postponed_job_preregister(0, rjit_iseq_update_references, NULL); + if (rjit_iseq_update_references_pjob == POSTPONED_JOB_HANDLE_INVALID) { + rb_bug("Could not preregister postponed job for RJIT"); + } rb_mRJITC = rb_const_get(rb_mRJIT, rb_intern("C")); VALUE rb_cRJITCompiler = rb_const_get(rb_mRJIT, rb_intern("Compiler")); rb_RJITCompiler = rb_funcall(rb_cRJITCompiler, rb_intern("new"), 0); @@ -441,7 +465,7 @@ rb_rjit_init(const struct rb_rjit_options *opts) } // Enable RJIT and stats from here - rb_rjit_call_p = !rb_rjit_opts.pause; + rb_rjit_call_p = !rb_rjit_opts.disable; rjit_stats_p = rb_rjit_opts.stats; } |