MJIT: Merge exivar guards as well

obviating status->merge_ivar_guards_p as refactoring
This commit is contained in:
Takashi Kokubun 2022-11-28 23:32:24 -08:00
Родитель 322e546f60
Коммит 2329cbeb5b
3 изменённых файлов: 18 добавлений и 13 удалений

Просмотреть файл

@ -35,8 +35,6 @@ class RubyVM::MJIT::Compiler
return nil
end
init_ivar_compile_status(iseq.body, status)
src = +''
if !status.compile_info.disable_send_cache && !status.compile_info.disable_inlining
unless precompile_inlinable_iseqs(src, iseq, status)
@ -91,8 +89,13 @@ class RubyVM::MJIT::Compiler
end
# Generate merged ivar guards first if needed
if !status.compile_info.disable_ivar_cache && status.merge_ivar_guards_p
src << " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT)))) {"
has_getivar, has_setivar = ivar_usages(iseq.body)
if !status.compile_info.disable_ivar_cache && (has_getivar || has_setivar)
src << " if (UNLIKELY(!RB_TYPE_P(GET_SELF(), T_OBJECT))) {"
src << " goto ivar_cancel;\n"
src << " }\n"
elsif !status.compile_info.disable_exivar_cache && has_getivar
src << " if (UNLIKELY(!FL_TEST_RAW(GET_SELF(), FL_EXIVAR))) {"
src << " goto ivar_cancel;\n"
src << " }\n"
end
@ -383,7 +386,7 @@ class RubyVM::MJIT::Compiler
src << " const uint32_t index = #{attr_index - 1};\n"
# JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization)
src << " struct gen_ivtbl *ivtbl;\n"
src << " if (LIKELY(FL_TEST_RAW(obj, FL_EXIVAR) && source_shape_id == rb_shape_get_shape_id(obj) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl))) {\n"
src << " if (LIKELY(source_shape_id == rb_shape_get_shape_id(obj) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl))) {\n"
src << " stack[#{stack_size}] = ivtbl->ivptr[index];\n"
src << " }\n"
src << " else {\n"
@ -716,7 +719,6 @@ class RubyVM::MJIT::Compiler
if child_iseq.body.ci_size > 0 && child_status.cc_entries_index == -1
return false
end
init_ivar_compile_status(child_iseq.body, child_status)
src << "ALWAYS_INLINE(static VALUE _mjit#{status.compiled_id}_inlined_#{pos}(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n"
src << "static inline VALUE\n_mjit#{status.compiled_id}_inlined_#{pos}(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n"
@ -786,17 +788,22 @@ class RubyVM::MJIT::Compiler
end
end
def init_ivar_compile_status(body, status)
def ivar_usages(body)
has_getivar = false
has_setivar = false
pos = 0
while pos < body.iseq_size
insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
if insn.name == :getinstancevariable || insn.name == :setinstancevariable
status.merge_ivar_guards_p = true
return
case insn.name
when :getinstancevariable
has_getivar = true
when :setinstancevariable
has_setivar = true
end
break if has_getivar && has_setivar
pos += insn.len
end
return has_getivar, has_setivar
end
# Expand simple macro that doesn't require dynamic C code.

Просмотреть файл

@ -46,7 +46,6 @@ struct compile_status {
int compiled_id; // Just a copy of compiled_iseq->jit_unit->id
// Mutated optimization levels
struct rb_mjit_compile_info *compile_info;
bool merge_ivar_guards_p; // If true, merge guards of ivar accesses
// If `inlined_iseqs[pos]` is not NULL, `mjit_compile_body` tries to inline ISeq there.
const struct rb_iseq_constant_body **inlined_iseqs;
struct inlined_call_context inline_context;

Просмотреть файл

@ -240,7 +240,6 @@ module RubyVM::MJIT
compiled_iseq: [CType::Pointer.new { self.rb_iseq_constant_body }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compiled_iseq)")],
compiled_id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compiled_id)")],
compile_info: [CType::Pointer.new { self.rb_mjit_compile_info }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compile_info)")],
merge_ivar_guards_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), merge_ivar_guards_p)")],
inlined_iseqs: [CType::Pointer.new { CType::Pointer.new { self.rb_iseq_constant_body } }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inlined_iseqs)")],
inline_context: [self.inlined_call_context, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inline_context)")],
)