diff options
-rw-r--r-- | lib/mjit/compiler.rb | 117 |
1 files changed, 81 insertions, 36 deletions
@@ -73,6 +73,23 @@ module RubyVM::MJIT src << "#undef GET_SELF\n" src << "#define GET_SELF() cfp_self\n" # Simulate `opt_pc` in setup_parameters_complex. Other PCs which may be passed by catch tables # are not considered since vm_exec doesn't call jit_exec for catch tables. if iseq.body.param.flags.has_opt @@ -86,13 +103,6 @@ module RubyVM::MJIT src << " }\n" 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)))) {" - src << " goto ivar_cancel;\n" - src << " }\n" - end - C.fprintf(f, src) compile_insns(0, 0, status, iseq.body, f) compile_cancel_handler(f, iseq.body, status) @@ -353,37 +363,52 @@ module RubyVM::MJIT ic_copy = (status.is_entries + (C.iseq_inline_storage_entry.new(operands[1]) - body.is_entries)).iv_cache src = +'' - if !status.compile_info.disable_ivar_cache && ic_copy.source_shape_id != C.INVALID_SHAPE_ID # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`. # compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos) # JIT: prepare vm_getivar/vm_setivar arguments and variables src << "{\n" src << " VALUE obj = GET_SELF();\n" - src << " const shape_id_t source_shape_id = (rb_serial_t)#{ic_copy.source_shape_id};\n" - # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar) - if insn_name == :setinstancevariable - src << " const uint32_t index = #{ic_copy.attr_index - 1};\n" - src << " const shape_id_t dest_shape_id = (rb_serial_t)#{ic_copy.dest_shape_id};\n" - src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj) && \n" - src << " dest_shape_id != ROBJECT_SHAPE_ID(obj)) {\n" - src << " if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {\n" - src << " rb_init_iv_list(obj);\n" - src << " }\n" - src << " ROBJECT_SET_SHAPE_ID(obj, dest_shape_id);\n" - src << " VALUE *ptr = ROBJECT_IVPTR(obj);\n" - src << " RB_OBJ_WRITE(obj, &ptr[index], stack[#{stack_size - 1}]);\n" - src << " }\n" else - if ic_copy.attr_index == 0 # cache hit, but uninitialized iv - src << " /* Uninitialized instance variable */\n" - src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n" - src << " stack[#{stack_size}] = Qnil;\n" src << " }\n" else - src << " const uint32_t index = #{ic_copy.attr_index - 1};\n" - src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n" - src << " stack[#{stack_size}] = ROBJECT_IVPTR(obj)[index];\n" src << " }\n" end end @@ -394,19 +419,20 @@ module RubyVM::MJIT src << " }\n" src << "}\n" return src - elsif insn_name == :getinstancevariable && !status.compile_info.disable_exivar_cache && ic_copy.source_shape_id != C.INVALID_SHAPE_ID # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`. # compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos) # JIT: prepare vm_getivar's arguments and variables src << "{\n" src << " VALUE obj = GET_SELF();\n" - src << " const shape_id_t source_shape_id = (rb_serial_t)#{ic_copy.source_shape_id};\n" - src << " const uint32_t index = #{ic_copy.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 << " stack[#{stack_size}] = ivtbl->ivptr[index];\n" src << " }\n" src << " else {\n" src << " reg_cfp->pc = original_body_iseq + #{pos};\n" @@ -806,16 +832,35 @@ module RubyVM::MJIT def init_ivar_compile_status(body, status) C.mjit_capture_is_entries(body, status.is_entries) 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 end pos += insn.len end end # Expand simple macro that doesn't require dynamic C code. |