[前][次][番号順一覧][スレッド一覧]

ruby-changes:67138

From: Takashi <ko1@a...>
Date: Fri, 13 Aug 2021 15:11:58 +0900 (JST)
Subject: [ruby-changes:67138] b3f8c491ef (master): Print JIT cancel when all JIT-ed code is cancelled

https://git.ruby-lang.org/ruby.git/commit/?id=b3f8c491ef

From b3f8c491efefc0461ab225d062f6c64286498609 Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Thu, 12 Aug 2021 22:54:40 -0700
Subject: Print JIT cancel when all JIT-ed code is cancelled

---
 NEWS.md               |  3 +++
 mjit.c                | 12 +++++++++++-
 mjit.h                |  2 ++
 test/ruby/test_jit.rb |  9 +++++++++
 vm_trace.c            |  6 ++----
 5 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index a040aeb..85f49d4 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -176,6 +176,9 @@ Excluding feature bug fixes. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L176
 * 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 5ca4d68..57f2847 100644
--- a/mjit.c
+++ b/mjit.c
@@ -83,6 +83,16 @@ mjit_gc_exit_hook(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L83
     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) https://github.com/ruby/ruby/blob/trunk/mjit.c#L106
         // 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 4d27e39..813ac0c 100644
--- a/mjit.h
+++ b/mjit.h
@@ -90,6 +90,7 @@ extern void rb_mjit_recompile_inlining(const rb_iseq_t *iseq); https://github.com/ruby/ruby/blob/trunk/mjit.h#L90
 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); https://github.com/ruby/ruby/blob/trunk/mjit.h#L182
 
 # 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 5b79f8c..d6306dc 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -10,6 +10,7 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L10
   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 https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L1101
     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 398ca97..b603293 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -81,10 +81,8 @@ update_global_event_hook(rb_event_flag_t vm_events) https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L81
     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);
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]