Пример #1
0
    def parse_loop(self, ops, add_label=True):
        loop = self.parse(ops)
        loop.operations = filter(
            lambda op: op.getopnum() != rop.DEBUG_MERGE_POINT, loop.operations)
        token = JitCellToken()
        if add_label:
            label = ResOperation(rop.LABEL,
                                 loop.inputargs,
                                 descr=TargetToken(token))
        else:
            label = loop.operations[0]
            label.setdescr(TargetToken(token))
        jump = loop.operations[-1]
        loop = VectorLoop(label, loop.operations[0:-1], jump)
        loop.jump.setdescr(token)

        class Optimizer(object):
            metainterp_sd = FakeMetaInterpStaticData(self.cpu)
            jitdriver_sd = FakeJitDriverStaticData()

        opt = Optimizer()
        opt.jitdriver_sd.vec = True
        for op in loop.operations:
            if op.is_guard() and not op.getdescr():
                descr = invent_fail_descr_for_op(op.getopnum(), opt)
                op.setdescr(descr)
        return loop
Пример #2
0
 def exc_handling(guard_op):
     # operations need to start with correct GUARD_EXCEPTION
     if guard_op._exc_box is None:
         op = ResOperation(rop.GUARD_NO_EXCEPTION, [])
     else:
         op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box])
     op.setdescr(self.builder.getfaildescr())
     op.setfailargs([])
     return op
Пример #3
0
 def exc_handling(guard_op):
     # operations need to start with correct GUARD_EXCEPTION
     if guard_op._exc_box is None:
         op = ResOperation(rop.GUARD_NO_EXCEPTION, [])
     else:
         op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box])
     op.setdescr(self.builder.getfaildescr())
     op.setfailargs([])
     return op
Пример #4
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     original_intvars = builder.intvars[:]
     builder.fakemetainterp.ovf_flag = False
     super(AbstractOvfOperation, self).produce_into(builder, r)
     if builder.fakemetainterp.ovf_flag:  # overflow detected
         op = ResOperation(rop.GUARD_OVERFLOW, [])
         # the overflowed result should not be used any more, but can
         # be used on the failure path: recompute fail_subset including
         # the result, and then remove it from builder.intvars.
         fail_subset = builder.subset_of_intvars(r)
         builder.intvars[:] = original_intvars
     else:
         op = ResOperation(rop.GUARD_NO_OVERFLOW, [])
     op.setdescr(builder.getfaildescr())
     op.setfailargs(fail_subset)
     builder.loop.operations.append(op)
Пример #5
0
 def produce_into(self, builder, r):
     fail_subset = builder.subset_of_intvars(r)
     original_intvars = builder.intvars[:]
     builder.fakemetainterp.ovf_flag = False
     super(AbstractOvfOperation, self).produce_into(builder, r)
     if builder.fakemetainterp.ovf_flag:   # overflow detected
         op = ResOperation(rop.GUARD_OVERFLOW, [])
         # the overflowed result should not be used any more, but can
         # be used on the failure path: recompute fail_subset including
         # the result, and then remove it from builder.intvars.
         fail_subset = builder.subset_of_intvars(r)
         builder.intvars[:] = original_intvars
     else:
         op = ResOperation(rop.GUARD_NO_OVERFLOW, [])
     op.setdescr(builder.getfaildescr())
     op.setfailargs(fail_subset)
     builder.loop.operations.append(op)
Пример #6
0
 def next(self):
     opnum = self._next()
     argnum = oparity[opnum]
     if argnum == -1:
         argnum = self._next()
     if not (0 <= oparity[opnum] <= 3):
         args = []
         for i in range(argnum):
             args.append(self._untag(self._next()))
         res = ResOperation(opnum, args)
     else:
         cls = opclasses[opnum]
         res = cls()
         argnum = oparity[opnum]
         if argnum == 0:
             pass
         elif argnum == 1:
             res.setarg(0, self._untag(self._next()))
         elif argnum == 2:
             res.setarg(0, self._untag(self._next()))
             res.setarg(1, self._untag(self._next()))
         else:
             assert argnum == 3
             res.setarg(0, self._untag(self._next()))
             res.setarg(1, self._untag(self._next()))
             res.setarg(2, self._untag(self._next()))
     descr_index = -1
     if opwithdescr[opnum]:
         descr_index = self._next()
         if descr_index == 0 or rop.is_guard(opnum):
             descr = None
         else:
             if descr_index < self.all_descr_len + 1:
                 descr = self.metainterp_sd.all_descrs[descr_index - 1]
             else:
                 descr = self.trace._descrs[descr_index -
                                            self.all_descr_len - 1]
             res.setdescr(descr)
         if rop.is_guard(opnum):  # all guards have descrs
             assert isinstance(res, GuardResOp)
             res.rd_resume_position = descr_index
     if res.type != 'v':
         self._cache[self._index] = res
         self._index += 1
     self._count += 1
     return res
Пример #7
0
 def parse_loop(self, ops, add_label=True):
     loop = self.parse(ops, postprocess=self.postprocess)
     loop.operations = filter(lambda op: op.getopnum() != rop.DEBUG_MERGE_POINT, loop.operations)
     token = JitCellToken()
     if add_label:
         label = ResOperation(rop.LABEL, loop.inputargs, descr=TargetToken(token))
     else:
         label = loop.operations[0]
         label.setdescr(TargetToken(token))
     jump = loop.operations[-1]
     loop = VectorLoop(label, loop.operations[0:-1], jump)
     loop.jump.setdescr(token)
     class Optimizer(object):
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
         jitdriver_sd = FakeJitDriverStaticData()
     opt = Optimizer()
     opt.jitdriver_sd.vec = True
     for op in loop.operations:
         if op.is_guard() and not op.getdescr():
             descr = invent_fail_descr_for_op(op.getopnum(), opt)
             op.setdescr(descr)
     return loop
Пример #8
0
def compile_simple_loop(metainterp, greenkey, start, inputargs, ops, jumpargs,
                        enable_opts):
    from rpython.jit.metainterp.optimizeopt import optimize_trace

    jitdriver_sd = metainterp.jitdriver_sd
    metainterp_sd = metainterp.staticdata
    jitcell_token = make_jitcell_token(jitdriver_sd)
    label = ResOperation(rop.LABEL, inputargs[:], descr=jitcell_token)
    jump_op = ResOperation(rop.JUMP, jumpargs[:], descr=jitcell_token)
    call_pure_results = metainterp.call_pure_results
    data = SimpleCompileData(label, ops + [jump_op],
                                 call_pure_results=call_pure_results,
                                 enable_opts=enable_opts)
    try:
        loop_info, ops = optimize_trace(metainterp_sd, jitdriver_sd,
                                        data, metainterp.box_names_memo)
    except InvalidLoop:
        return None
    loop = create_empty_loop(metainterp)
    loop.original_jitcell_token = jitcell_token
    loop.inputargs = loop_info.inputargs
    if loop_info.quasi_immutable_deps:
        loop.quasi_immutable_deps = loop_info.quasi_immutable_deps
    jump_op = ops[-1]
    target_token = TargetToken(jitcell_token)
    target_token.original_jitcell_token = jitcell_token
    label = ResOperation(rop.LABEL, loop_info.inputargs[:], descr=target_token)
    jump_op.setdescr(target_token)
    loop.operations = [label] + ops
    if not we_are_translated():
        loop.check_consistency()
    jitcell_token.target_tokens = [target_token]
    send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop",
                         inputargs, metainterp.box_names_memo)
    record_loop_or_bridge(metainterp_sd, loop)
    return target_token
Пример #9
0
    def propagate_all_forward(self, starting_state, export_state=True):
        self.optimizer.exporting_state = export_state
        loop = self.optimizer.loop
        self.optimizer.clear_newoperations()

        start_label = loop.operations[0]
        if start_label.getopnum() == rop.LABEL:
            loop.operations = loop.operations[1:]
            # We need to emit the label op before import_state() as emitting it
            # will clear heap caches
            self.optimizer.send_extra_operation(start_label)
        else:
            start_label = None

        patchguardop = None
        if len(loop.operations) > 1:
            patchguardop = loop.operations[-2]
            if patchguardop.getopnum() != rop.GUARD_FUTURE_CONDITION:
                patchguardop = None

        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL:
            loop.operations = loop.operations[:-1]
        else:
            jumpop = None

        self.import_state(start_label, starting_state)
        self.optimizer.propagate_all_forward(clear=False)

        if not jumpop:
            return

        cell_token = jumpop.getdescr()
        assert isinstance(cell_token, JitCellToken)
        stop_label = ResOperation(rop.LABEL, jumpop.getarglist(), None, TargetToken(cell_token))

        if jumpop.getopnum() == rop.JUMP:
            if self.jump_to_already_compiled_trace(jumpop, patchguardop):
                # Found a compiled trace to jump to
                if self.short:
                    # Construct our short preamble
                    assert start_label
                    self.close_bridge(start_label)
                return

            if start_label and self.jump_to_start_label(start_label, stop_label):
                # Initial label matches, jump to it
                jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None,
                                      descr=start_label.getdescr())
                if self.short:
                    # Construct our short preamble
                    self.close_loop(start_label, jumpop, patchguardop)
                else:
                    self.optimizer.send_extra_operation(jumpop)
                return

            if cell_token.target_tokens:
                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
                if cell_token.retraced_count < limit:
                    cell_token.retraced_count += 1
                    debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit))
                else:
                    debug_print("Retrace count reached, jumping to preamble")
                    assert cell_token.target_tokens[0].virtual_state is None
                    jumpop = jumpop.clone()
                    jumpop.setdescr(cell_token.target_tokens[0])
                    self.optimizer.send_extra_operation(jumpop)
                    return

        # Found nothing to jump to, emit a label instead

        if self.short:
            # Construct our short preamble
            assert start_label
            self.close_bridge(start_label)

        self.optimizer.flush()
        if export_state:
            KillHugeIntBounds(self.optimizer).apply()

        loop.operations = self.optimizer.get_newoperations()
        if export_state:
            jd_sd = self.optimizer.jitdriver_sd
            try:
                threshold = jd_sd.warmstate.disable_unrolling_threshold
            except AttributeError:    # tests only
                threshold = sys.maxint
            if len(loop.operations) > threshold:
                if loop.operations[0].getopnum() == rop.LABEL:
                    # abandoning unrolling, too long
                    new_descr = stop_label.getdescr()
                    if loop.operations[0].getopnum() == rop.LABEL:
                        new_descr = loop.operations[0].getdescr()
                    stop_label = stop_label.copy_and_change(rop.JUMP,
                                        descr=new_descr)
                    self.optimizer.send_extra_operation(stop_label)
                    loop.operations = self.optimizer.get_newoperations()
                    return None
            final_state = self.export_state(stop_label)
        else:
            final_state = None
        loop.operations.append(stop_label)
        return final_state
Пример #10
0
    def optimize_peeled_loop(self, trace, celltoken, state, runtime_boxes,
                             call_pure_results, inline_short_preamble=True):
        trace = trace.get_iter()
        try:
            label_args = self.import_state(trace.inputargs, state)
        except VirtualStatesCantMatch:
            raise InvalidLoop("Cannot import state, virtual states don't match")
        self.potential_extra_ops = {}
        self.optimizer.init_inparg_dict_from(label_args)
        try:
            info, _ = self.optimizer.propagate_all_forward(
                trace, call_pure_results, flush=False)
        except SpeculativeError:
            raise InvalidLoop("Speculative heap access would be ill-typed")
        end_jump = info.jump_op
        label_op = ResOperation(rop.LABEL, label_args,
                                descr=celltoken)
        for a in end_jump.getarglist():
            self.optimizer.force_box_for_end_of_preamble(
                self.optimizer.get_box_replacement(a))
        current_vs = self.get_virtual_state(end_jump.getarglist())
        # pick the vs we want to jump to
        assert isinstance(celltoken, JitCellToken)

        target_virtual_state = self.pick_virtual_state(current_vs,
                                                       state.virtual_state,
                                                celltoken.target_tokens)
        # force the boxes for virtual state to match
        try:
            args = target_virtual_state.make_inputargs(
               [self.get_box_replacement(x) for x in end_jump.getarglist()],
               self.optimizer, force_boxes=True)
            for arg in args:
                if arg is not None:
                    self.optimizer.force_box(arg)
        except VirtualStatesCantMatch:
            raise InvalidLoop("Virtual states did not match "
                              "after picking the virtual state, when forcing"
                              " boxes")
        extra_same_as = self.short_preamble_producer.extra_same_as[:]
        target_token = self.finalize_short_preamble(label_op,
                                                    state.virtual_state)
        label_op.setdescr(target_token)

        if not inline_short_preamble:
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)

        try:
            new_virtual_state = self.jump_to_existing_trace(
                    end_jump, label_op, runtime_boxes, force_boxes=False)
        except InvalidLoop:
            # inlining short preamble failed, jump to preamble
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)

        if new_virtual_state is not None:
            # Attempt to force virtual boxes in order to avoid jumping
            # to the preamble.
            try:
                new_virtual_state = self.jump_to_existing_trace(
                        end_jump, label_op, runtime_boxes, force_boxes=True)
            except InvalidLoop:
                pass

        if new_virtual_state is not None:
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)

        self.disable_retracing_if_max_retrace_guards(
            self.optimizer._newoperations, target_token)

        return (UnrollInfo(target_token, label_op, extra_same_as,
                           self.optimizer.quasi_immutable_deps),
                self.optimizer._newoperations)
Пример #11
0
    def optimize_peeled_loop(self, start_label, end_jump, ops, state,
                             call_pure_results, inline_short_preamble=True):
        self._check_no_forwarding([[start_label, end_jump], ops])
        try:
            label_args = self.import_state(start_label, state)
        except VirtualStatesCantMatch:
            raise InvalidLoop("Cannot import state, virtual states don't match")
        self.potential_extra_ops = {}
        self.optimizer.init_inparg_dict_from(label_args)
        try:
            info, _ = self.optimizer.propagate_all_forward(
                start_label.getarglist()[:], ops, call_pure_results, False,
                flush=False)
        except SpeculativeError:
            raise InvalidLoop("Speculative heap access would be ill-typed")
        label_op = ResOperation(rop.LABEL, label_args, start_label.getdescr())
        for a in end_jump.getarglist():
            self.optimizer.force_box_for_end_of_preamble(
                self.optimizer.get_box_replacement(a))
        current_vs = self.get_virtual_state(end_jump.getarglist())
        # pick the vs we want to jump to
        celltoken = start_label.getdescr()
        assert isinstance(celltoken, JitCellToken)
        
        target_virtual_state = self.pick_virtual_state(current_vs,
                                                       state.virtual_state,
                                                celltoken.target_tokens)
        # force the boxes for virtual state to match
        try:
            args = target_virtual_state.make_inputargs(
               [self.get_box_replacement(x) for x in end_jump.getarglist()],
               self.optimizer, force_boxes=True)
            for arg in args:
                self.optimizer.force_box(arg)
        except VirtualStatesCantMatch:
            raise InvalidLoop("Virtual states did not match "
                              "after picking the virtual state, when forcing"
                              " boxes")
        extra_same_as = self.short_preamble_producer.extra_same_as[:]
        target_token = self.finalize_short_preamble(label_op,
                                                    state.virtual_state)
        label_op.setdescr(target_token)

        if not inline_short_preamble:
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)            

        try:
            new_virtual_state = self.jump_to_existing_trace(end_jump, label_op)
        except InvalidLoop:
            # inlining short preamble failed, jump to preamble
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)            
        if new_virtual_state is not None:
            self.jump_to_preamble(celltoken, end_jump, info)
            return (UnrollInfo(target_token, label_op, extra_same_as,
                               self.optimizer.quasi_immutable_deps),
                    self.optimizer._newoperations)

        self.disable_retracing_if_max_retrace_guards(
            self.optimizer._newoperations, target_token)
        
        return (UnrollInfo(target_token, label_op, extra_same_as,
                           self.optimizer.quasi_immutable_deps),
                self.optimizer._newoperations)
Пример #12
0
    def propagate_all_forward(self, starting_state, export_state=True):
        self.optimizer.exporting_state = export_state
        loop = self.optimizer.loop
        self.optimizer.clear_newoperations()

        start_label = loop.operations[0]
        if start_label.getopnum() == rop.LABEL:
            loop.operations = loop.operations[1:]
            # We need to emit the label op before import_state() as emitting it
            # will clear heap caches
            self.optimizer.send_extra_operation(start_label)
        else:
            start_label = None

        patchguardop = None
        if len(loop.operations) > 1:
            patchguardop = loop.operations[-2]
            if patchguardop.getopnum() != rop.GUARD_FUTURE_CONDITION:
                patchguardop = None

        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL:
            loop.operations = loop.operations[:-1]
        else:
            jumpop = None

        self.import_state(start_label, starting_state)
        self.optimizer.propagate_all_forward(clear=False)

        if not jumpop:
            return

        cell_token = jumpop.getdescr()
        assert isinstance(cell_token, JitCellToken)
        stop_label = ResOperation(rop.LABEL, jumpop.getarglist(), None, TargetToken(cell_token))

        if jumpop.getopnum() == rop.JUMP:
            if self.jump_to_already_compiled_trace(jumpop, patchguardop):
                # Found a compiled trace to jump to
                if self.short:
                    # Construct our short preamble
                    assert start_label
                    self.close_bridge(start_label)
                return

            if start_label and self.jump_to_start_label(start_label, stop_label):
                # Initial label matches, jump to it
                jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None,
                                      descr=start_label.getdescr())
                if self.short:
                    # Construct our short preamble
                    self.close_loop(start_label, jumpop, patchguardop)
                else:
                    self.optimizer.send_extra_operation(jumpop)
                return

            if cell_token.target_tokens:
                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
                if cell_token.retraced_count < limit:
                    cell_token.retraced_count += 1
                    debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit))
                else:
                    debug_print("Retrace count reached, jumping to preamble")
                    assert cell_token.target_tokens[0].virtual_state is None
                    jumpop = jumpop.clone()
                    jumpop.setdescr(cell_token.target_tokens[0])
                    self.optimizer.send_extra_operation(jumpop)
                    return

        # Found nothing to jump to, emit a label instead

        if self.short:
            # Construct our short preamble
            assert start_label
            self.close_bridge(start_label)

        self.optimizer.flush()
        if export_state:
            KillHugeIntBounds(self.optimizer).apply()

        loop.operations = self.optimizer.get_newoperations()
        if export_state:
            final_state = self.export_state(stop_label)
        else:
            final_state = None
        loop.operations.append(stop_label)
        return final_state