예제 #1
0
파일: optimizer.py 프로젝트: Mu-L/pypy
 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
예제 #2
0
def compute_vars_longevity(inputargs, operations):
    # compute a dictionary that maps variables to index in
    # operations that is a "last-time-seen"

    # returns a pair longevity/useful. Non-useful variables are ones that
    # never appear in the assembler or it does not matter if they appear on
    # stack or in registers. Main example is loop arguments that go
    # only to guard operations or to jump or to finish
    last_used = {}
    last_real_usage = {}
    for i in range(len(operations) - 1, -1, -1):
        op = operations[i]
        if op.type != 'v':
            if op not in last_used and rop.has_no_side_effect(op.opnum):
                continue
        opnum = op.getopnum()
        for j in range(op.numargs()):
            arg = op.getarg(j)
            if isinstance(arg, Const):
                continue
            if arg not in last_used:
                last_used[arg] = i
            if opnum != rop.JUMP and opnum != rop.LABEL:
                if arg not in last_real_usage:
                    last_real_usage[arg] = i
        if rop.is_guard(op.opnum):
            for arg in op.getfailargs():
                if arg is None:  # hole
                    continue
                assert not isinstance(arg, Const)
                if arg not in last_used:
                    last_used[arg] = i
    #
    longevity = {}
    for i, arg in enumerate(operations):
        if arg.type != 'v' and arg in last_used:
            assert not isinstance(arg, Const)
            assert i < last_used[arg]
            longevity[arg] = (i, last_used[arg])
            del last_used[arg]
    for arg in inputargs:
        assert not isinstance(arg, Const)
        if arg not in last_used:
            longevity[arg] = (-1, -1)
        else:
            longevity[arg] = (0, last_used[arg])
            del last_used[arg]
    assert len(last_used) == 0

    if not we_are_translated():
        produced = {}
        for arg in inputargs:
            produced[arg] = None
        for op in operations:
            for arg in op.getarglist():
                if not isinstance(arg, Const):
                    assert arg in produced
            produced[op] = None

    return longevity, last_real_usage
예제 #3
0
파일: reghint.py 프로젝트: hmrg-grmh/pypy
 def add_hints(self, longevity, inputargs, operations):
     self.longevity = longevity
     for i in range(len(operations)):
         op = operations[i]
         if rop.has_no_side_effect(op.opnum) and op not in self.longevity:
             continue
         oplist[op.getopnum()](self, op, i)
예제 #4
0
파일: optimizer.py 프로젝트: mozillazg/pypy
 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)
예제 #5
0
파일: regalloc.py 프로젝트: mozillazg/pypy
def compute_vars_longevity(inputargs, operations):
    # compute a dictionary that maps variables to index in
    # operations that is a "last-time-seen"

    # returns a pair longevity/useful. Non-useful variables are ones that
    # never appear in the assembler or it does not matter if they appear on
    # stack or in registers. Main example is loop arguments that go
    # only to guard operations or to jump or to finish
    last_used = {}
    last_real_usage = {}
    for i in range(len(operations) - 1, -1, -1):
        op = operations[i]
        if op.type != "v":
            if op not in last_used and rop.has_no_side_effect(op.opnum):
                continue
        opnum = op.getopnum()
        for j in range(op.numargs()):
            arg = op.getarg(j)
            if isinstance(arg, Const):
                continue
            if arg not in last_used:
                last_used[arg] = i
            if opnum != rop.JUMP and opnum != rop.LABEL:
                if arg not in last_real_usage:
                    last_real_usage[arg] = i
        if rop.is_guard(op.opnum):
            for arg in op.getfailargs():
                if arg is None:  # hole
                    continue
                assert not isinstance(arg, Const)
                if arg not in last_used:
                    last_used[arg] = i
    #
    longevity = {}
    for i, arg in enumerate(operations):
        if arg.type != "v" and arg in last_used:
            assert not isinstance(arg, Const)
            assert i < last_used[arg]
            longevity[arg] = (i, last_used[arg])
            del last_used[arg]
    for arg in inputargs:
        assert not isinstance(arg, Const)
        if arg not in last_used:
            longevity[arg] = (-1, -1)
        else:
            longevity[arg] = (0, last_used[arg])
            del last_used[arg]
    assert len(last_used) == 0

    if not we_are_translated():
        produced = {}
        for arg in inputargs:
            produced[arg] = None
        for op in operations:
            for arg in op.getarglist():
                if not isinstance(arg, Const):
                    assert arg in produced
            produced[op] = None

    return longevity, last_real_usage
예제 #6
0
def compute_vars_longevity(inputargs, operations):
    # compute a dictionary that maps variables to Lifetime information
    # if a variable is not in the dictionary, it's operation is dead because
    # it's side-effect-free and the result is unused
    longevity = {}
    for i in range(len(operations) - 1, -1, -1):
        op = operations[i]
        opnum = op.getopnum()
        if op not in longevity:
            if op.type != 'v' and rop.has_no_side_effect(opnum):
                # result not used, operation has no side-effect, it can be
                # removed
                continue
            longevity[op] = Lifetime(definition_pos=i, last_usage=i)
        else:
            longevity[op].definition_pos = i
        for j in range(op.numargs()):
            arg = op.getarg(j)
            if isinstance(arg, Const):
                continue
            if arg not in longevity:
                lifetime = longevity[arg] = Lifetime(last_usage=i)
            else:
                lifetime = longevity[arg]
            if opnum != rop.JUMP and opnum != rop.LABEL:
                if lifetime.real_usages is None:
                    lifetime.real_usages = []
                lifetime.real_usages.append(i)
        if rop.is_guard(op.opnum):
            for arg in op.getfailargs():
                if arg is None:  # hole
                    continue
                assert not isinstance(arg, Const)
                if arg not in longevity:
                    longevity[arg] = Lifetime(last_usage=i)
    #
    for arg in inputargs:
        assert not isinstance(arg, Const)
        if arg not in longevity:
            longevity[arg] = Lifetime(-1, -1)

    if not we_are_translated():
        produced = {}
        for arg in inputargs:
            produced[arg] = None
        for op in operations:
            for arg in op.getarglist():
                if not isinstance(arg, Const):
                    assert arg in produced
            produced[op] = None
    for lifetime in longevity.itervalues():
        if lifetime.real_usages is not None:
            lifetime.real_usages.reverse()
        if not we_are_translated():
            lifetime._check_invariants()

    return LifetimeManager(longevity)
예제 #7
0
 def walk_operations(self, inputargs, operations):
     from rpython.jit.backend.ppc.ppc_assembler import (operations as
                                                        asm_operations)
     i = 0
     self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
                              LIMIT_LOOP_BREAK)
     self.operations = operations
     while i < len(operations):
         op = operations[i]
         self.assembler.mc.mark_op(op)
         self.rm.position = i
         self.fprm.position = i
         self.vrm.position = i
         opnum = op.opnum
         if rop.has_no_side_effect(opnum) and op not in self.longevity:
             i += 1
             self.possibly_free_vars_for_op(op)
             continue
         #
         for j in range(op.numargs()):
             box = op.getarg(j)
             if box.is_vector():
                 if box.type != VOID:
                     self.vrm.temp_boxes.append(box)
             elif box.type != FLOAT:
                 self.rm.temp_boxes.append(box)
             else:
                 self.fprm.temp_boxes.append(box)
         #
         if not we_are_translated() and opnum == rop.FORCE_SPILL:
             self._consider_force_spill(op)
         else:
             arglocs = oplist[opnum](self, op)
             asm_operations[opnum](self.assembler, op, arglocs, self)
         self.free_op_vars()
         self.possibly_free_var(op)
         self.rm._check_invariants()
         self.fprm._check_invariants()
         self.vrm._check_invariants()
         if self.assembler.mc.get_relative_pos() > self.limit_loop_break:
             self.assembler.break_long_loop(self)
             self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
                                      LIMIT_LOOP_BREAK)
         i += 1
     assert not self.rm.reg_bindings
     assert not self.fprm.reg_bindings
     if not we_are_translated():
         self.assembler.mc.trap()
     self.flush_loop()
     self.assembler.mc.mark_op(None)  # end of the loop
     self.operations = None
     for arg in inputargs:
         self.possibly_free_var(arg)
예제 #8
0
파일: regalloc.py 프로젝트: mozillazg/pypy
 def walk_operations(self, inputargs, operations):
     from rpython.jit.backend.ppc.ppc_assembler import (
         operations as asm_operations)
     i = 0
     self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
                                  LIMIT_LOOP_BREAK)
     self.operations = operations
     while i < len(operations):
         op = operations[i]
         self.assembler.mc.mark_op(op)
         self.rm.position = i
         self.fprm.position = i
         self.vrm.position = i
         opnum = op.opnum
         if rop.has_no_side_effect(opnum) and op not in self.longevity:
             i += 1
             self.possibly_free_vars_for_op(op)
             continue
         #
         for j in range(op.numargs()):
             box = op.getarg(j)
             if box.is_vector():
                 if box.type != VOID:
                     self.vrm.temp_boxes.append(box)
             elif box.type != FLOAT:
                 self.rm.temp_boxes.append(box)
             else:
                 self.fprm.temp_boxes.append(box)
         #
         if not we_are_translated() and opnum == rop.FORCE_SPILL:
             self._consider_force_spill(op)
         else:
             arglocs = oplist[opnum](self, op)
             asm_operations[opnum](self.assembler, op, arglocs, self)
         self.free_op_vars()
         self.possibly_free_var(op)
         self.rm._check_invariants()
         self.fprm._check_invariants()
         self.vrm._check_invariants()
         if self.assembler.mc.get_relative_pos() > self.limit_loop_break:
             self.assembler.break_long_loop(self)
             self.limit_loop_break = (self.assembler.mc.get_relative_pos() +
                                          LIMIT_LOOP_BREAK)
         i += 1
     assert not self.rm.reg_bindings
     assert not self.fprm.reg_bindings
     if not we_are_translated():
         self.assembler.mc.trap()
     self.flush_loop()
     self.assembler.mc.mark_op(None) # end of the loop
     self.operations = None
     for arg in inputargs:
         self.possibly_free_var(arg)
예제 #9
0
 def insert_label(self, loop, position, r):
     assert not hasattr(loop, '_targettoken')
     for i in range(position):
         op = loop.operations[i]
         if (not rop.has_no_side_effect(op.opnum)
                 or op.type not in (INT, FLOAT)):
             position = i
             break       # cannot move the LABEL later
         randompos = r.randrange(0, len(self.startvars)+1)
         self.startvars.insert(randompos, op)
     loop._targettoken = TargetToken()
     loop.operations.insert(position, ResOperation(rop.LABEL, self.startvars,
                                                   loop._targettoken))
예제 #10
0
 def insert_label(self, loop, position, r):
     assert not hasattr(loop, '_targettoken')
     for i in range(position):
         op = loop.operations[i]
         if (not rop.has_no_side_effect(op.opnum)
                 or op.type not in (INT, FLOAT)):
             position = i
             break  # cannot move the LABEL later
         randompos = r.randrange(0, len(self.startvars) + 1)
         self.startvars.insert(randompos, op)
     loop._targettoken = TargetToken()
     loop.operations.insert(
         position, ResOperation(rop.LABEL, self.startvars,
                                loop._targettoken))
예제 #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()
예제 #12
0
파일: heap.py 프로젝트: mozillazg/pypy
 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()