def user_loop_bail_fast_path(loop, warmstate): """ In a fast path over the trace loop: try to prevent vecopt of spending time on a loop that will most probably fail. """ resop_count = 0 # the count of operations minus debug_merge_points vector_instr = 0 guard_count = 0 at_least_one_array_access = True for i,op in enumerate(loop.operations): if rop.is_jit_debug(op.opnum): continue if op.vector >= 0 and not rop.is_guard(op.opnum): vector_instr += 1 resop_count += 1 if op.is_primitive_array_access(): at_least_one_array_access = True if rop.is_call(op.opnum) or rop.is_call_assembler(op.opnum): return True if rop.is_guard(op.opnum): guard_count += 1 if not at_least_one_array_access: return True return False
def prepare_guard_op_guard_not_forced(self, op, prev_op): if rop.is_call_release_gil(prev_op.getopnum()): arglocs = self._prepare_call(prev_op, save_all_regs=True, first_arg_index=2) elif rop.is_call_assembler(prev_op.getopnum()): locs = self.locs_for_call_assembler(prev_op) tmploc = self.get_scratch_reg(INT, selected_reg=r.x0) resloc = self._call(prev_op, locs + [tmploc], gc_level=2) arglocs = locs + [resloc, tmploc] else: assert rop.is_call_may_force(prev_op.getopnum()) arglocs = self._prepare_call(prev_op, save_all_regs=True) guard_locs = self._guard_impl(op) return arglocs + guard_locs, len(arglocs)
def emitting_operation(self, op): if rop.has_no_side_effect(op.opnum): return if rop.is_ovf(op.opnum): return if rop.is_guard(op.opnum): self.optimizer.pendingfields = (self.force_lazy_sets_for_guard()) return opnum = op.getopnum() if (opnum == rop.SETFIELD_GC or # handled specially opnum == rop.SETFIELD_RAW or # no effect on GC struct/array opnum == rop.SETARRAYITEM_GC or # handled specially opnum == rop.SETARRAYITEM_RAW or # no effect on GC struct opnum == rop.SETINTERIORFIELD_RAW or # no effect on GC struct opnum == rop.RAW_STORE or # no effect on GC struct opnum == rop.STRSETITEM or # no effect on GC struct/array opnum == rop.UNICODESETITEM or # no effect on GC struct/array opnum == rop.DEBUG_MERGE_POINT or # no effect whatsoever opnum == rop.JIT_DEBUG or # no effect whatsoever opnum == rop.ENTER_PORTAL_FRAME or # no effect whatsoever opnum == rop.LEAVE_PORTAL_FRAME or # no effect whatsoever opnum == rop.COPYSTRCONTENT or # no effect on GC struct/array opnum == rop.COPYUNICODECONTENT or # no effect on GC struct/array opnum == rop.CHECK_MEMORY_ERROR): # may only abort the whole loop return if rop.is_call(op.opnum): if rop.is_call_assembler(op.getopnum()): self._seen_guard_not_invalidated = False else: effectinfo = op.getdescr().get_extra_info() if effectinfo.check_can_invalidate(): self._seen_guard_not_invalidated = False if not effectinfo.has_random_effects(): self.force_from_effectinfo(effectinfo) return self.force_all_lazy_sets() self.clean_caches()
def emit_guard_op_guard_not_forced(self, op, guard_op, fcond, arglocs): # arglocs is call locs + guard_locs, split them if rop.is_call_assembler(op.getopnum()): if fcond == 4: [argloc, vloc, result_loc, tmploc] = arglocs[:4] else: [argloc, result_loc, tmploc] = arglocs[:3] vloc = locations.imm(0) guard_locs = arglocs[fcond:] self._store_force_index(guard_op) self.call_assembler(op, argloc, vloc, result_loc, tmploc) else: assert fcond == op.numargs() + 3 call_args = arglocs[:fcond] guard_locs = arglocs[fcond:] self._store_force_index(guard_op) self._emit_call(op, call_args) # process the guard_not_forced ofs = self.cpu.get_ofs_of_frame_field('jf_descr') self.mc.LDR_ri(r.ip0.value, r.fp.value, ofs) self.mc.CMP_ri(r.ip0.value, 0) self._emit_guard(guard_op, c.EQ, guard_locs)
def emitting_operation(self, op): if rop.has_no_side_effect(op.opnum): return if rop.is_ovf(op.opnum): return if rop.is_guard(op.opnum): self.optimizer.pendingfields = ( self.force_lazy_sets_for_guard()) return opnum = op.getopnum() if (opnum == rop.SETFIELD_GC or # handled specially opnum == rop.SETFIELD_RAW or # no effect on GC struct/array opnum == rop.SETARRAYITEM_GC or # handled specially opnum == rop.SETARRAYITEM_RAW or # no effect on GC struct opnum == rop.SETINTERIORFIELD_RAW or # no effect on GC struct opnum == rop.RAW_STORE or # no effect on GC struct opnum == rop.STRSETITEM or # no effect on GC struct/array opnum == rop.UNICODESETITEM or # no effect on GC struct/array opnum == rop.DEBUG_MERGE_POINT or # no effect whatsoever opnum == rop.JIT_DEBUG or # no effect whatsoever opnum == rop.ENTER_PORTAL_FRAME or # no effect whatsoever opnum == rop.LEAVE_PORTAL_FRAME or # no effect whatsoever opnum == rop.COPYSTRCONTENT or # no effect on GC struct/array opnum == rop.COPYUNICODECONTENT or # no effect on GC struct/array opnum == rop.CHECK_MEMORY_ERROR): # may only abort the whole loop return if rop.is_call(op.opnum): if rop.is_call_assembler(op.getopnum()): self._seen_guard_not_invalidated = False else: effectinfo = op.getdescr().get_extra_info() if effectinfo.check_can_invalidate(): self._seen_guard_not_invalidated = False if not effectinfo.has_random_effects(): self.force_from_effectinfo(effectinfo) return self.force_all_lazy_sets() self.clean_caches()