Exemple #1
0
 def _emit_operation(self, op):
     assert not rop.is_call_pure(op.getopnum())
     orig_op = op
     op = self.get_box_replacement(op)
     if op.is_constant():
         return  # can happen e.g. if we postpone the operation that becomes
         # constant
     # XXX kill, requires thinking
     #op = self.replace_op_with(op, op.opnum)
     for i in range(op.numargs()):
         arg = self.force_box(op.getarg(i))
         op.setarg(i, arg)
     self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
     if rop.is_guard(op.opnum):
         assert isinstance(op, GuardResOp)
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
         pendingfields = self.pendingfields
         self.pendingfields = None
         if self.replaces_guard and orig_op in self.replaces_guard:
             self.replace_guard_op(self.replaces_guard[orig_op], op)
             del self.replaces_guard[orig_op]
             return
         else:
             op = self.emit_guard_operation(op, pendingfields)
     opnum = op.opnum
     if ((rop.has_no_side_effect(opnum) or rop.is_guard(opnum)
          or rop.is_jit_debug(opnum) or rop.is_ovf(opnum))
             and not self.is_call_pure_pure_canraise(op)):
         pass
     else:
         self._last_guard_op = None
     self._really_emitted_operation = op
     self._newoperations.append(op)
     self._emittedoperations[op] = None
Exemple #2
0
 def _emit_operation(self, op):
     assert not rop.is_call_pure(op.getopnum())
     orig_op = op
     op = self.get_box_replacement(op)
     if op.is_constant():
         return # can happen e.g. if we postpone the operation that becomes
         # constant
     # XXX kill, requires thinking
     #op = self.replace_op_with(op, op.opnum)
     for i in range(op.numargs()):
         arg = self.force_box(op.getarg(i))
         op.setarg(i, arg)
     self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
     if rop.is_guard(op.opnum):
         assert isinstance(op, GuardResOp)
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
         pendingfields = self.pendingfields
         self.pendingfields = None
         if self.replaces_guard and orig_op in self.replaces_guard:
             self.replace_guard_op(self.replaces_guard[orig_op], op)
             del self.replaces_guard[orig_op]
             return
         else:
             op = self.emit_guard_operation(op, pendingfields)
     elif op.can_raise():
         self.exception_might_have_happened = True
     opnum = op.opnum
     if ((rop.has_no_side_effect(opnum) or rop.is_guard(opnum) or
          rop.is_jit_debug(opnum) or
          rop.is_ovf(opnum)) and not self.is_call_pure_pure_canraise(op)):
         pass
     else:
         self._last_guard_op = None
     self._really_emitted_operation = op
     self._newoperations.append(op)
Exemple #3
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(
                    op.opnum) and ops[i +
                                      1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            # Also, don't move cond_call_value in the short preamble.
            # The issue there is that it's usually pointless to try to
            # because the 'value' argument is typically not a loop
            # invariant, and would really need to be in order to end up
            # in the short preamble.  Maybe the code works anyway in the
            # other rare case, but better safe than sorry and don't try.
            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                if not OpHelpers.is_cond_call_value(op.opnum):
                    sb.add_pure_op(op)
Exemple #4
0
 def emit(self, op):
     self.emitting_operation(op)
     self.emit_postponed_op()
     opnum = op.opnum
     if (rop.is_comparison(opnum) or rop.is_call_may_force(opnum)
             or rop.is_ovf(opnum)):
         self.postponed_op = op
     else:
         return Optimization.emit(self, op)
Exemple #5
0
 def emit_operation(self, op):        
     self.emitting_operation(op)
     self.emit_postponed_op()
     opnum = op.opnum
     if (rop.is_comparison(opnum) or rop.is_call_may_force(opnum)
         or rop.is_ovf(opnum)):
         self.postponed_op = op
     else:
         Optimization.emit_operation(self, op)
Exemple #6
0
 def could_merge_with_next_guard(self, op, i, operations):
     # return True in cases where the operation and the following guard
     # should likely remain together.  Simplified version of
     # can_merge_with_next_guard() in llsupport/regalloc.py.
     if not rop.is_comparison(op.opnum):
         return rop.is_ovf(op.opnum)  # int_xxx_ovf() / guard_no_overflow()
     if i + 1 >= len(operations):
         return False
     next_op = operations[i + 1]
     opnum = next_op.getopnum()
     if not (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE
             or opnum == rop.COND_CALL):
         return False
     if next_op.getarg(0) is not op:
         return False
     self.remove_tested_failarg(next_op)
     return True
Exemple #7
0
 def could_merge_with_next_guard(self, op, i, operations):
     # return True in cases where the operation and the following guard
     # should likely remain together.  Simplified version of
     # can_merge_with_next_guard() in llsupport/regalloc.py.
     if not rop.is_comparison(op.opnum):
         return rop.is_ovf(op.opnum)    # int_xxx_ovf() / guard_no_overflow()
     if i + 1 >= len(operations):
         return False
     next_op = operations[i + 1]
     opnum = next_op.getopnum()
     if not (opnum == rop.GUARD_TRUE or
             opnum == rop.GUARD_FALSE or
             opnum == rop.COND_CALL):
         return False
     if next_op.getarg(0) is not op:
         return False
     self.remove_tested_failarg(next_op)
     return True
Exemple #8
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(
                    op.opnum) and ops[i +
                                      1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                sb.add_pure_op(op)
Exemple #9
0
    def optimize_default(self, op):
        canfold = rop.is_always_pure(op.opnum)
        if rop.is_ovf(op.opnum):
            self.postponed_op = op
            return
        if self.postponed_op:
            nextop = op
            op = self.postponed_op
            self.postponed_op = None
            canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
        else:
            nextop = None

        save = False
        if canfold:
            for i in range(op.numargs()):
                if self.get_constant_box(op.getarg(i)) is None:
                    break
            else:
                # all constant arguments: constant-fold away
                resbox = self.optimizer.constant_fold(op)
                # note that INT_xxx_OVF is not done from here, and the
                # overflows in the INT_xxx operations are ignored
                self.optimizer.make_constant(op, resbox)
                return

            # did we do the exact same operation already?
            recentops = self.getrecentops(op.getopnum())
            save = True
            oldop = recentops.lookup(self.optimizer, op)
            if oldop is not None:
                self.optimizer.make_equal_to(op, oldop)
                return

        # otherwise, the operation remains
        self.emit_operation(op)
        if rop.returns_bool_result(op.opnum):
            self.getintbound(op).make_bool()
        if save:
            recentops = self.getrecentops(op.getopnum())
            recentops.add(op)
        if nextop:
            self.emit_operation(nextop)
Exemple #10
0
 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()
Exemple #11
0
 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()
Exemple #12
0
    def produce_potential_short_preamble_ops(self, sb):
        ops = self.optimizer._newoperations
        for i, op in enumerate(ops):
            if rop.is_always_pure(op.opnum):
                sb.add_pure_op(op)
            if rop.is_ovf(op.opnum) and ops[i + 1].getopnum() == rop.GUARD_NO_OVERFLOW:
                sb.add_pure_op(op)
        for i in self.call_pure_positions:
            op = ops[i]
            # don't move call_pure_with_exception in the short preamble...
            # issue #2015

            # Also, don't move cond_call_value in the short preamble.
            # The issue there is that it's usually pointless to try to
            # because the 'value' argument is typically not a loop
            # invariant, and would really need to be in order to end up
            # in the short preamble.  Maybe the code works anyway in the
            # other rare case, but better safe than sorry and don't try.
            effectinfo = op.getdescr().get_extra_info()
            if not effectinfo.check_can_raise(ignore_memoryerror=True):
                assert rop.is_call(op.opnum)
                if not OpHelpers.is_cond_call_value(op.opnum):
                    sb.add_pure_op(op)
Exemple #13
0
    def optimize_default(self, op):
        canfold = rop.is_always_pure(op.opnum)
        if rop.is_ovf(op.opnum):
            self.postponed_op = op
            return
        if self.postponed_op:
            nextop = op
            op = self.postponed_op
            self.postponed_op = None
            canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
        else:
            nextop = None

        save = False
        if canfold:
            for i in range(op.numargs()):
                if self.get_constant_box(op.getarg(i)) is None:
                    break
            else:
                # all constant arguments: constant-fold away
                resbox = self.optimizer.constant_fold(op)
                # note that INT_xxx_OVF is not done from here, and the
                # overflows in the INT_xxx operations are ignored
                self.optimizer.make_constant(op, resbox)
                return

            # did we do the exact same operation already?
            recentops = self.getrecentops(op.getopnum())
            save = True
            oldop = recentops.lookup(self.optimizer, op)
            if oldop is not None:
                self.optimizer.make_equal_to(op, oldop)
                return

        # otherwise, the operation remains
        return self.emit_result(DefaultOptimizationResult(self, op, save, nextop))
Exemple #14
0
def is_comparison_or_ovf_op(opnum):
    return rop.is_comparison(opnum) or rop.is_ovf(opnum)
Exemple #15
0
def is_comparison_or_ovf_op(opnum):
    return rop.is_comparison(opnum) or rop.is_ovf(opnum)