Redo compilation of all ISEQs after invalidation

This commit is contained in:
Takashi Kokubun 2023-02-10 14:41:45 -08:00
parent b379ccf755
commit 1bdc23f35b
5 changed files with 58 additions and 2 deletions

View File

@ -33,6 +33,12 @@ module RubyVM::MJIT
attr_accessor :write_pos attr_accessor :write_pos
IseqBlocks = Hash.new { |h, k| h[k] = {} } IseqBlocks = Hash.new { |h, k| h[k] = {} }
DeadBlocks = [] # invalidated IseqBlocks, but kept for safety
def self.reset_blocks
DeadBlocks << IseqBlocks.dup
IseqBlocks.clear
end
def self.decode_insn(encoded) def self.decode_insn(encoded)
INSNS.fetch(C.rb_vm_insn_decode(encoded)) INSNS.fetch(C.rb_vm_insn_decode(encoded))

View File

@ -58,8 +58,9 @@ module RubyVM::MJIT
end end
def on_tracing_invalidate_all def on_tracing_invalidate_all
# TODO: assert patches don't overlap each other # On-Stack Replacement
@patches.each do |address, target| @patches.each do |address, target|
# TODO: assert patches don't overlap each other
@cb.with_write_addr(address) do @cb.with_write_addr(address) do
asm = Assembler.new asm = Assembler.new
asm.comment('on_tracing_invalidate_all') asm.comment('on_tracing_invalidate_all')
@ -67,6 +68,16 @@ module RubyVM::MJIT
@cb.write(asm) @cb.write(asm)
end end
end end
# Avoid reusing past code
Compiler.reset_blocks
C.mjit_for_each_iseq do |iseq|
# Disable entering past code
iseq.body.jit_func = 0
# Compile this again if not converted to trace_* insns
iseq.body.total_calls = 0
end
end end
private private

8
mjit.c
View File

@ -356,7 +356,13 @@ rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events)
WITH_MJIT_DISABLED({ WITH_MJIT_DISABLED({
rb_funcall(rb_mMJITHooks, rb_intern("on_tracing_invalidate_all"), 1, UINT2NUM(new_iseq_events)); rb_funcall(rb_mMJITHooks, rb_intern("on_tracing_invalidate_all"), 1, UINT2NUM(new_iseq_events));
}); });
mjit_call_p = false; }
// TODO: Use this in more places
VALUE
rb_mjit_iseq_new(rb_iseq_t *iseq)
{
return rb_funcall(rb_cMJITIseqPtr, rb_intern("new"), 1, SIZET2NUM((size_t)iseq));
} }
void void

View File

@ -15,6 +15,8 @@
#include "internal.h" #include "internal.h"
#include "internal/compile.h" #include "internal/compile.h"
#include "internal/hash.h" #include "internal/hash.h"
#include "internal/sanitizers.h"
#include "internal/gc.h"
#include "yjit.h" #include "yjit.h"
#include "vm_insnhelper.h" #include "vm_insnhelper.h"
@ -86,6 +88,33 @@ mjit_enabled_p(rb_execution_context_t *ec, VALUE self)
return RBOOL(mjit_enabled); return RBOOL(mjit_enabled);
} }
static int
for_each_iseq_i(void *vstart, void *vend, size_t stride, void *data)
{
VALUE block = (VALUE)data;
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
void *ptr = asan_poisoned_object_p(v);
asan_unpoison_object(v, false);
if (rb_obj_is_iseq(v)) {
extern VALUE rb_mjit_iseq_new(rb_iseq_t *iseq);
rb_iseq_t *iseq = (rb_iseq_t *)v;
rb_funcall(block, rb_intern("call"), 1, rb_mjit_iseq_new(iseq));
}
asan_poison_object_if(ptr, v);
}
return 0;
}
static VALUE
mjit_for_each_iseq(rb_execution_context_t *ec, VALUE self, VALUE block)
{
rb_objspace_each_objects(for_each_iseq_i, (void *)block);
return Qnil;
}
extern bool rb_simple_iseq_p(const rb_iseq_t *iseq); extern bool rb_simple_iseq_p(const rb_iseq_t *iseq);
#include "mjit_c.rbinc" #include "mjit_c.rbinc"

View File

@ -145,6 +145,10 @@ module RubyVM::MJIT # :nodoc: all
} }
end end
def mjit_for_each_iseq(&block)
Primitive.mjit_for_each_iseq(block)
end
#======================================================================================== #========================================================================================
# #
# Old stuff # Old stuff