summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2021-08-12 22:54:40 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2021-08-12 23:11:38 -0700
commitb3f8c491efefc0461ab225d062f6c64286498609 (patch)
tree5d3fbb4fe76d37f91bafbdb4b5fff9ce28d8f7ce
parent1a16940291301ace49cba0f37154a67033ab27c0 (diff)
Print JIT cancel when all JIT-ed code is cancelled
-rw-r--r--NEWS.md3
-rw-r--r--mjit.c12
-rw-r--r--mjit.h2
-rw-r--r--test/ruby/test_jit.rb9
-rw-r--r--vm_trace.c6
5 files changed, 27 insertions, 5 deletions
diff --git a/NEWS.md b/NEWS.md
index a040aebeae..85f49d4846 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -176,6 +176,9 @@ Excluding feature bug fixes.
* The JIT compiler no longer skips compilation of methods longer than
1000 instructions.
+* `--jit-verbose` and `--jit-warning` output "JIT cancel" when JIT-ed
+ code is disabled because TracePoint or GC.compact is used.
+
* `RubyVM::MJIT` is renamed to `RubyVM::JIT`. [[Feature #17490]]
## Static analysis
diff --git a/mjit.c b/mjit.c
index 5ca4d6849e..57f28476ca 100644
--- a/mjit.c
+++ b/mjit.c
@@ -83,6 +83,16 @@ mjit_gc_exit_hook(void)
CRITICAL_SECTION_FINISH(4, "mjit_gc_exit_hook");
}
+// Prohibit calling JIT-ed code and let existing JIT-ed frames exit before the next insn.
+void
+mjit_cancel_all(const char *reason)
+{
+ mjit_call_p = false;
+ if (mjit_opts.warnings || mjit_opts.verbose) {
+ fprintf(stderr, "JIT cancel: Disabled JIT-ed code because %s\n", reason);
+ }
+}
+
// Deal with ISeq movement from compactor
void
mjit_update_references(const rb_iseq_t *iseq)
@@ -96,7 +106,7 @@ mjit_update_references(const rb_iseq_t *iseq)
// We need to invalidate JIT-ed code for the ISeq because it embeds pointer addresses.
// To efficiently do that, we use the same thing as TracePoint and thus everything is cancelled for now.
// See mjit.h and tool/ruby_vm/views/_mjit_compile_insn.erb for how `mjit_call_p` is used.
- mjit_call_p = false; // TODO: instead of cancelling all, invalidate only this one and recompile it with some threshold.
+ mjit_cancel_all("GC.compact is used"); // TODO: instead of cancelling all, invalidate only this one and recompile it with some threshold.
}
// Units in stale_units (list of over-speculated and invalidated code) are not referenced from
diff --git a/mjit.h b/mjit.h
index 4d27e39e3c..813ac0cf21 100644
--- a/mjit.h
+++ b/mjit.h
@@ -90,6 +90,7 @@ extern void rb_mjit_recompile_inlining(const rb_iseq_t *iseq);
extern void rb_mjit_recompile_const(const rb_iseq_t *iseq);
RUBY_SYMBOL_EXPORT_END
+extern void mjit_cancel_all(const char *reason);
extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id);
extern void mjit_init(const struct mjit_options *opts);
extern void mjit_gc_start_hook(void);
@@ -181,6 +182,7 @@ void mjit_finish(bool close_handle_p);
# else // USE_MJIT
+static inline void mjit_cancel_all(const char *reason){}
static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;}
static inline void mjit_cont_free(struct mjit_cont *cont){}
static inline void mjit_gc_start_hook(void){}
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 5b79f8c0ea..d6306dcfc9 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -10,6 +10,7 @@ class TestJIT < Test::Unit::TestCase
IGNORABLE_PATTERNS = [
/\AJIT recompile: .+\n\z/,
/\AJIT inline: .+\n\z/,
+ /\AJIT cancel: .+\n\z/,
/\ASuccessful MJIT finish\n\z/,
]
MAX_CACHE_PATTERNS = [
@@ -1100,6 +1101,14 @@ class TestJIT < Test::Unit::TestCase
end;
end
+ def test_cancel_by_tracepoint
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, min_calls: 2)
+ begin;
+ TracePoint.new(:line) {}.enable
+ 2.times {}
+ end;
+ end
+
def test_caller_locations_without_catch_table
out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
begin;
diff --git a/vm_trace.c b/vm_trace.c
index 398ca97de3..b603293d34 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -81,10 +81,8 @@ update_global_event_hook(rb_event_flag_t vm_events)
rb_event_flag_t enabled_iseq_events = ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS;
if (new_iseq_events & ~enabled_iseq_events) {
- /* Stop calling all JIT-ed code. Compiling trace insns is not supported for now. */
-#if USE_MJIT
- mjit_call_p = FALSE;
-#endif
+ // Stop calling all JIT-ed code. We can't rewrite existing JIT-ed code to trace_ insns for now.
+ mjit_cancel_all("TracePoint is enabled");
/* write all ISeqs if and only if new events are added */
rb_iseq_trace_set_all(new_iseq_events | enabled_iseq_events);