Ejemplo n.º 1
0
    def export_state(self, targetop):
        original_jump_args = targetop.getarglist()
        jump_args = [
            self.getvalue(a).get_key_box() for a in original_jump_args
        ]

        assert self.optimizer.loop.resume_at_jump_descr
        resume_at_jump_descr = self.optimizer.loop.resume_at_jump_descr.clone_if_mutable(
        )
        assert isinstance(resume_at_jump_descr, ResumeGuardDescr)
        resume_at_jump_descr.rd_snapshot = self.fix_snapshot(
            jump_args, resume_at_jump_descr.rd_snapshot)

        modifier = VirtualStateAdder(self.optimizer)
        virtual_state = modifier.get_virtual_state(jump_args)

        values = [self.getvalue(arg) for arg in jump_args]
        inputargs = virtual_state.make_inputargs(values, self.optimizer)
        short_inputargs = virtual_state.make_inputargs(values,
                                                       self.optimizer,
                                                       keyboxes=True)

        if self.boxes_created_this_iteration is not None:
            for box in self.inputargs:
                self.boxes_created_this_iteration[box] = True

        short_boxes = ShortBoxes(self.optimizer, inputargs,
                                 self.boxes_created_this_iteration)

        self.optimizer.clear_newoperations()
        for i in range(len(original_jump_args)):
            if values[i].is_virtual():
                values[i].force_box(self.optimizer)
            if original_jump_args[i] is not jump_args[i]:
                op = ResOperation(rop.SAME_AS, [jump_args[i]],
                                  original_jump_args[i])
                self.optimizer.emit_operation(op)
        inputarg_setup_ops = self.optimizer.get_newoperations()

        target_token = targetop.getdescr()
        assert isinstance(target_token, TargetToken)
        targetop.initarglist(inputargs)
        target_token.virtual_state = virtual_state
        target_token.short_preamble = [
            ResOperation(rop.LABEL, short_inputargs, None)
        ]
        target_token.resume_at_jump_descr = resume_at_jump_descr

        exported_values = {}
        for box in inputargs:
            exported_values[box] = self.optimizer.getvalue(box)
        for op in short_boxes.operations():
            if op and op.result:
                box = op.result
                exported_values[box] = self.optimizer.getvalue(box)

        target_token.exported_state = ExportedState(short_boxes,
                                                    inputarg_setup_ops,
                                                    exported_values)
Ejemplo n.º 2
0
    def jump_to_already_compiled_trace(self, jumpop):
        assert jumpop.getopnum() == rop.JUMP
        cell_token = jumpop.getdescr()

        assert isinstance(cell_token, JitCellToken)
        if not cell_token.target_tokens:
            return False

        if not self.inline_short_preamble:
            assert cell_token.target_tokens[0].virtual_state is None
            jumpop.setdescr(cell_token.target_tokens[0])
            self.optimizer.send_extra_operation(jumpop)
            return True

        args = jumpop.getarglist()
        modifier = VirtualStateAdder(self.optimizer)
        virtual_state = modifier.get_virtual_state(args)
        debug_start('jit-log-virtualstate')
        virtual_state.debug_print("Looking for ")

        for target in cell_token.target_tokens:
            if not target.virtual_state:
                continue
            ok = False
            extra_guards = []

            bad = {}
            debugmsg = 'Did not match '
            if target.virtual_state.generalization_of(virtual_state, bad):
                ok = True
                debugmsg = 'Matched '
            else:
                try:
                    cpu = self.optimizer.cpu
                    target.virtual_state.generate_guards(virtual_state,
                                                         args, cpu,
                                                         extra_guards)

                    ok = True
                    debugmsg = 'Guarded to match '
                except InvalidLoop:
                    pass
            target.virtual_state.debug_print(debugmsg, bad)

            if ok:
                debug_stop('jit-log-virtualstate')

                values = [self.getvalue(arg)
                          for arg in jumpop.getarglist()]
                args = target.virtual_state.make_inputargs(values, self.optimizer,
                                                           keyboxes=True)
                short_inputargs = target.short_preamble[0].getarglist()
                inliner = Inliner(short_inputargs, args)

                for guard in extra_guards:
                    if guard.is_guard():
                        descr = target.resume_at_jump_descr.clone_if_mutable()
                        inliner.inline_descr_inplace(descr)
                        guard.setdescr(descr)
                    self.optimizer.send_extra_operation(guard)

                try:
                    for shop in target.short_preamble[1:]:
                        newop = inliner.inline_op(shop)
                        self.optimizer.send_extra_operation(newop)
                except InvalidLoop:
                    debug_print("Inlining failed unexpectedly",
                                "jumping to preamble instead")
                    assert cell_token.target_tokens[0].virtual_state is None
                    jumpop.setdescr(cell_token.target_tokens[0])
                    self.optimizer.send_extra_operation(jumpop)
                return True
        debug_stop('jit-log-virtualstate')
        return False
Ejemplo n.º 3
0
    def close_loop(self, start_label, jumpop):
        virtual_state = self.initial_virtual_state
        short_inputargs = self.short[0].getarglist()
        inputargs = self.inputargs
        short_jumpargs = inputargs[:]

        # Construct jumpargs from the virtual state
        original_jumpargs = jumpop.getarglist()[:]
        values = [self.getvalue(arg) for arg in jumpop.getarglist()]
        try:
            jumpargs = virtual_state.make_inputargs(values, self.optimizer)
        except BadVirtualState:
            raise InvalidLoop
        jumpop.initarglist(jumpargs)

        # Inline the short preamble at the end of the loop
        jmp_to_short_args = virtual_state.make_inputargs(values, self.optimizer, keyboxes=True)
        assert len(short_inputargs) == len(jmp_to_short_args)
        args = {}
        for i in range(len(short_inputargs)):
            if short_inputargs[i] in args:
                if args[short_inputargs[i]] != jmp_to_short_args[i]:
                    raise InvalidLoop
            args[short_inputargs[i]] = jmp_to_short_args[i]
        self.short_inliner = Inliner(short_inputargs, jmp_to_short_args)
        for op in self.short[1:]:
            newop = self.short_inliner.inline_op(op)
            self.optimizer.send_extra_operation(newop)

        # Import boxes produced in the preamble but used in the loop
        newoperations = self.optimizer.get_newoperations()
        self.boxes_created_this_iteration = {}
        i = j = 0
        while i < len(newoperations) or j < len(jumpargs):
            if i == len(newoperations):
                while j < len(jumpargs):
                    a = jumpargs[j]
                    if self.optimizer.loop.logops:
                        debug_print('J:  ' + self.optimizer.loop.logops.repr_of_arg(a))
                    self.import_box(a, inputargs, short_jumpargs, jumpargs)
                    j += 1
            else:
                op = newoperations[i]

                self.boxes_created_this_iteration[op.result] = True
                args = op.getarglist()
                if op.is_guard():
                    args = args + op.getfailargs()

                if self.optimizer.loop.logops:
                    debug_print('OP: ' + self.optimizer.loop.logops.repr_of_resop(op))
                for a in args:
                    if self.optimizer.loop.logops:
                        debug_print('A:  ' + self.optimizer.loop.logops.repr_of_arg(a))
                    self.import_box(a, inputargs, short_jumpargs, jumpargs)
                i += 1
            newoperations = self.optimizer.get_newoperations()

        jumpop.initarglist(jumpargs)
        self.optimizer.send_extra_operation(jumpop)
        self.short.append(ResOperation(rop.JUMP, short_jumpargs, None, descr=jumpop.getdescr()))

        # Verify that the virtual state at the end of the loop is one
        # that is compatible with the virtual state at the start of the loop
        modifier = VirtualStateAdder(self.optimizer)
        final_virtual_state = modifier.get_virtual_state(original_jumpargs)
        debug_start('jit-log-virtualstate')
        virtual_state.debug_print('Closed loop with ')
        bad = {}
        if not virtual_state.generalization_of(final_virtual_state, bad):
            # We ended up with a virtual state that is not compatible
            # and we are thus unable to jump to the start of the loop
            final_virtual_state.debug_print("Bad virtual state at end of loop, ",
                                            bad)
            debug_stop('jit-log-virtualstate')
            raise InvalidLoop
            
        debug_stop('jit-log-virtualstate')

        maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards
        if self.optimizer.emitted_guards > maxguards:
            target_token = jumpop.getdescr()
            assert isinstance(target_token, TargetToken)
            target_token.targeting_jitcell_token.retraced_count = sys.maxint
            
        self.finilize_short_preamble(start_label)
Ejemplo n.º 4
0
    def import_state(self, targetop):
        if not targetop: # Trace did not start with a label
            self.inputargs = self.optimizer.loop.inputargs
            self.short = None
            self.initial_virtual_state = None
            return

        self.inputargs = targetop.getarglist()
        target_token = targetop.getdescr()
        assert isinstance(target_token, TargetToken)
        exported_state = target_token.exported_state
        if not exported_state:
            # No state exported, construct one without virtuals
            self.short = None
            modifier = VirtualStateAdder(self.optimizer)
            virtual_state = modifier.get_virtual_state(self.inputargs)
            self.initial_virtual_state = virtual_state
            return
        
        self.short = target_token.short_preamble[:]
        self.short_seen = {}
        self.short_boxes = exported_state.short_boxes
        self.short_resume_at_jump_descr = target_token.resume_at_jump_descr
        self.initial_virtual_state = target_token.virtual_state

        seen = {}
        for box in self.inputargs:
            if box in seen:
                continue
            seen[box] = True
            preamble_value = exported_state.exported_values[box]
            value = self.optimizer.getvalue(box)
            value.import_from(preamble_value, self.optimizer)

        # Setup the state of the new optimizer by emiting the
        # short operations and discarding the result
        self.optimizer.emitting_dissabled = True
        for op in exported_state.inputarg_setup_ops:
            self.optimizer.send_extra_operation(op)

        seen = {}
        for op in self.short_boxes.operations():
            self.ensure_short_op_emitted(op, self.optimizer, seen)
            if op and op.result:
                preamble_value = exported_state.exported_values[op.result]
                value = self.optimizer.getvalue(op.result)
                if not value.is_virtual():
                    imp = ValueImporter(self, preamble_value, op)
                    self.optimizer.importable_values[value] = imp
                newvalue = self.optimizer.getvalue(op.result)
                newresult = newvalue.get_key_box()
                # note that emitting here SAME_AS should not happen, but
                # in case it does, we would prefer to be suboptimal in asm
                # to a fatal RPython exception.
                if newresult is not op.result and not newvalue.is_constant():
                    op = ResOperation(rop.SAME_AS, [op.result], newresult)
                    self.optimizer._newoperations.append(op)
                    if self.optimizer.loop.logops:
                        debug_print('  Falling back to add extra: ' +
                                    self.optimizer.loop.logops.repr_of_resop(op))
                    
        self.optimizer.flush()
        self.optimizer.emitting_dissabled = False