зеркало из https://github.com/github/ruby.git
MJIT: Merge exivar guards as well
obviating status->merge_ivar_guards_p as refactoring
This commit is contained in:
Родитель
322e546f60
Коммит
2329cbeb5b
|
@ -35,8 +35,6 @@ class RubyVM::MJIT::Compiler
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
init_ivar_compile_status(iseq.body, status)
|
|
||||||
|
|
||||||
src = +''
|
src = +''
|
||||||
if !status.compile_info.disable_send_cache && !status.compile_info.disable_inlining
|
if !status.compile_info.disable_send_cache && !status.compile_info.disable_inlining
|
||||||
unless precompile_inlinable_iseqs(src, iseq, status)
|
unless precompile_inlinable_iseqs(src, iseq, status)
|
||||||
|
@ -91,8 +89,13 @@ class RubyVM::MJIT::Compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generate merged ivar guards first if needed
|
# Generate merged ivar guards first if needed
|
||||||
if !status.compile_info.disable_ivar_cache && status.merge_ivar_guards_p
|
has_getivar, has_setivar = ivar_usages(iseq.body)
|
||||||
src << " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT)))) {"
|
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 << " goto ivar_cancel;\n"
|
||||||
src << " }\n"
|
src << " }\n"
|
||||||
end
|
end
|
||||||
|
@ -383,7 +386,7 @@ class RubyVM::MJIT::Compiler
|
||||||
src << " const uint32_t index = #{attr_index - 1};\n"
|
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)
|
# JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization)
|
||||||
src << " struct gen_ivtbl *ivtbl;\n"
|
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 << " stack[#{stack_size}] = ivtbl->ivptr[index];\n"
|
||||||
src << " }\n"
|
src << " }\n"
|
||||||
src << " else {\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
|
if child_iseq.body.ci_size > 0 && child_status.cc_entries_index == -1
|
||||||
return false
|
return false
|
||||||
end
|
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 << "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"
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def init_ivar_compile_status(body, status)
|
def ivar_usages(body)
|
||||||
|
has_getivar = false
|
||||||
|
has_setivar = false
|
||||||
pos = 0
|
pos = 0
|
||||||
|
|
||||||
while pos < body.iseq_size
|
while pos < body.iseq_size
|
||||||
insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
|
insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
|
||||||
if insn.name == :getinstancevariable || insn.name == :setinstancevariable
|
case insn.name
|
||||||
status.merge_ivar_guards_p = true
|
when :getinstancevariable
|
||||||
return
|
has_getivar = true
|
||||||
|
when :setinstancevariable
|
||||||
|
has_setivar = true
|
||||||
end
|
end
|
||||||
|
break if has_getivar && has_setivar
|
||||||
pos += insn.len
|
pos += insn.len
|
||||||
end
|
end
|
||||||
|
return has_getivar, has_setivar
|
||||||
end
|
end
|
||||||
|
|
||||||
# Expand simple macro that doesn't require dynamic C code.
|
# Expand simple macro that doesn't require dynamic C code.
|
||||||
|
|
1
mjit_c.h
1
mjit_c.h
|
@ -46,7 +46,6 @@ struct compile_status {
|
||||||
int compiled_id; // Just a copy of compiled_iseq->jit_unit->id
|
int compiled_id; // Just a copy of compiled_iseq->jit_unit->id
|
||||||
// Mutated optimization levels
|
// Mutated optimization levels
|
||||||
struct rb_mjit_compile_info *compile_info;
|
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.
|
// If `inlined_iseqs[pos]` is not NULL, `mjit_compile_body` tries to inline ISeq there.
|
||||||
const struct rb_iseq_constant_body **inlined_iseqs;
|
const struct rb_iseq_constant_body **inlined_iseqs;
|
||||||
struct inlined_call_context inline_context;
|
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_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)")],
|
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)")],
|
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)")],
|
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)")],
|
inline_context: [self.inlined_call_context, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inline_context)")],
|
||||||
)
|
)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче