diff options
-rw-r--r-- | iseq.c | 2 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/hooks.rb | 4 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/invariants.rb | 35 | ||||
-rw-r--r-- | mjit.c | 34 | ||||
-rw-r--r-- | mjit.h | 2 |
5 files changed, 55 insertions, 22 deletions
@@ -357,7 +357,7 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating) if (reference_updating) { #if USE_MJIT - mjit_update_references(iseq); + rb_mjit_iseq_update_references(iseq); #endif #if USE_YJIT rb_yjit_iseq_update_references(body->yjit_payload); diff --git a/lib/ruby_vm/mjit/hooks.rb b/lib/ruby_vm/mjit/hooks.rb index f3943504fd..477c4e0ae8 100644 --- a/lib/ruby_vm/mjit/hooks.rb +++ b/lib/ruby_vm/mjit/hooks.rb @@ -26,5 +26,9 @@ module RubyVM::MJIT def self.on_tracing_invalidate_all(_new_iseq_events) Invariants.on_tracing_invalidate_all end + + def self.on_update_references + Invariants.on_update_references + end end end diff --git a/lib/ruby_vm/mjit/invariants.rb b/lib/ruby_vm/mjit/invariants.rb index e68a6e5503..0e8063c0c6 100644 --- a/lib/ruby_vm/mjit/invariants.rb +++ b/lib/ruby_vm/mjit/invariants.rb @@ -78,6 +78,28 @@ module RubyVM::MJIT end def on_tracing_invalidate_all + invalidate_all + end + + def on_update_references + invalidate_all + end + + # @param jit [RubyVM::MJIT::JITState] + # @param block [RubyVM::MJIT::Block] + def ensure_block_entry_exit(jit, cause:) + block = jit.block + if block.entry_exit.nil? + block.entry_exit = Assembler.new.then do |asm| + @exit_compiler.compile_entry_exit(block.pc, block.ctx, asm, cause:) + @ocb.write(asm) + end + end + end + + private + + def invalidate_all # On-Stack Replacement @patches.each do |address, target| # TODO: assert patches don't overlap each other @@ -88,6 +110,7 @@ module RubyVM::MJIT @cb.write(asm) end end + @patches.clear # Avoid reusing past code Compiler.reset_blocks @@ -99,18 +122,6 @@ module RubyVM::MJIT iseq.body.total_calls = 0 end end - - # @param jit [RubyVM::MJIT::JITState] - # @param block [RubyVM::MJIT::Block] - def ensure_block_entry_exit(jit, cause:) - block = jit.block - if block.entry_exit.nil? - block.entry_exit = Assembler.new.then do |asm| - @exit_compiler.compile_entry_exit(block.pc, block.ctx, asm, cause:) - @ocb.write(asm) - end - end - end end end end @@ -114,12 +114,6 @@ mjit_cancel_all(const char *reason) } void -mjit_update_references(const rb_iseq_t *iseq) -{ - // TODO: remove this -} - -void mjit_free_iseq(const rb_iseq_t *iseq) { // TODO: remove this @@ -348,12 +342,13 @@ mjit_cme_invalidate(void *data) }); } +extern int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data); + void rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme) { if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return; // Asynchronously hook the Ruby code since running Ruby in the middle of cme invalidation is dangerous. - extern int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data); rb_workqueue_register(0, mjit_cme_invalidate, (void *)cme); } @@ -389,6 +384,28 @@ rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events) }); } +static void +mjit_iseq_update_references(void *data) +{ + if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return; + WITH_MJIT_ISOLATED({ + rb_funcall(rb_mMJITHooks, rb_intern("on_update_references"), 0); + }); +} + +void +rb_mjit_iseq_update_references(const rb_iseq_t *iseq) +{ + if (!mjit_enabled) return; + + // TODO: update mjit_blocks + + // 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, mjit_iseq_update_references, NULL); +} + // TODO: Use this in more places VALUE rb_mjit_iseq_new(rb_iseq_t *iseq) @@ -442,10 +459,11 @@ mjit_mark(void) return; RUBY_MARK_ENTER("mjit"); - // Mark objects used by the MJIT compiler + // Pin object pointers used in this file rb_gc_mark(rb_MJITCompiler); rb_gc_mark(rb_cMJITIseqPtr); rb_gc_mark(rb_cMJITCfpPtr); + rb_gc_mark(rb_mMJITHooks); RUBY_MARK_LEAVE("mjit"); } @@ -106,7 +106,7 @@ 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_free_iseq(const rb_iseq_t *iseq); -extern void mjit_update_references(const rb_iseq_t *iseq); +extern void rb_mjit_iseq_update_references(const rb_iseq_t *iseq); extern void mjit_mark(void); extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body); extern void mjit_notify_waitpid(int exit_code); |