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
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)
INSNS.fetch(C.rb_vm_insn_decode(encoded))

View File

@ -58,8 +58,9 @@ module RubyVM::MJIT
end
def on_tracing_invalidate_all
# TODO: assert patches don't overlap each other
# On-Stack Replacement
@patches.each do |address, target|
# TODO: assert patches don't overlap each other
@cb.with_write_addr(address) do
asm = Assembler.new
asm.comment('on_tracing_invalidate_all')
@ -67,6 +68,16 @@ module RubyVM::MJIT
@cb.write(asm)
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
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({
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

View File

@ -15,6 +15,8 @@
#include "internal.h"
#include "internal/compile.h"
#include "internal/hash.h"
#include "internal/sanitizers.h"
#include "internal/gc.h"
#include "yjit.h"
#include "vm_insnhelper.h"
@ -86,6 +88,33 @@ mjit_enabled_p(rb_execution_context_t *ec, VALUE self)
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);
#include "mjit_c.rbinc"

View File

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