Example #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)
Example #2
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)
Example #3
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
Example #4
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)
Example #5
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
Example #6
0
    def propagate_all_forward(self):
        loop = self.optimizer.loop
        jumpop = loop.operations[-1]
        if jumpop.getopnum() == rop.JUMP:
            loop.operations = loop.operations[:-1]
        else:
            loopop = None

        self.optimizer.propagate_all_forward()

        if jumpop:
            assert jumpop.getdescr() is loop.token
            jump_args = jumpop.getarglist()
            jumpop.initarglist([])
            self.optimizer.flush()

            KillHugeIntBounds(self.optimizer).apply()

            loop.preamble.operations = self.optimizer.newoperations
            jump_args = [self.getvalue(a).get_key_box() for a in jump_args]

            start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
            self.start_resumedescr = start_resumedescr
            assert isinstance(start_resumedescr, ResumeGuardDescr)
            start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args, start_resumedescr.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)
            short_inputargs = virtual_state.make_inputargs(values, keyboxes=True)

            self.constant_inputargs = {}
            for box in jump_args:
                const = self.get_constant_box(box)
                if const:
                    self.constant_inputargs[box] = const

            sb = ShortBoxes(self.optimizer, inputargs + self.constant_inputargs.keys())
            self.short_boxes = sb
            preamble_optimizer = self.optimizer
            loop.preamble.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
            self.optimizer = self.optimizer.new()
            loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps

            logops = self.optimizer.loop.logops
            if logops:
                args = ", ".join([logops.repr_of_arg(arg) for arg in inputargs])
                debug_print("inputargs:       " + args)
                args = ", ".join([logops.repr_of_arg(arg) for arg in short_inputargs])
                debug_print("short inputargs: " + args)
                self.short_boxes.debug_print(logops)

            # Force virtuals amoung the jump_args of the preamble to get the
            # operations needed to setup the proper state of those virtuals
            # in the peeled loop
            inputarg_setup_ops = []
            preamble_optimizer.newoperations = []
            seen = {}
            for box in inputargs:
                if box in seen:
                    continue
                seen[box] = True
                value = preamble_optimizer.getvalue(box)
                inputarg_setup_ops.extend(value.make_guards(box))
            for box in short_inputargs:
                if box in seen:
                    continue
                seen[box] = True
                value = preamble_optimizer.getvalue(box)
                value.force_box()
            preamble_optimizer.flush()
            inputarg_setup_ops += preamble_optimizer.newoperations

            # Setup the state of the new optimizer by emiting the
            # short preamble operations and discarding the result
            self.optimizer.emitting_dissabled = True
            for op in 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:
                    # The order of these guards is not important as
                    # self.optimizer.emitting_dissabled is False
                    value = preamble_optimizer.getvalue(op.result)
                    for guard in value.make_guards(op.result):
                        self.optimizer.send_extra_operation(guard)
                    newresult = self.optimizer.getvalue(op.result).get_key_box()
                    if newresult is not op.result:
                        self.short_boxes.alias(newresult, op.result)
            self.optimizer.flush()
            self.optimizer.emitting_dissabled = False

            # XXX Hack to prevent the arraylen/strlen/unicodelen ops generated
            #     by value.make_guards() from ending up in pure_operations
            for key, op in self.optimizer.pure_operations.items():
                if not self.short_boxes.has_producer(op.result):
                    del self.optimizer.pure_operations[key]

            initial_inputargs_len = len(inputargs)
            self.inliner = Inliner(loop.inputargs, jump_args)

            short = self.inline(inputargs, self.cloned_operations, loop.inputargs, short_inputargs, virtual_state)

            loop.inputargs = inputargs
            args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box() for a in inputargs]
            jmp = ResOperation(rop.JUMP, args, None)
            jmp.setdescr(loop.token)
            loop.preamble.operations.append(jmp)

            loop.operations = self.optimizer.newoperations
            maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards

            if self.optimizer.emitted_guards > maxguards:
                loop.preamble.token.retraced_count = sys.maxint

            if short:
                assert short[-1].getopnum() == rop.JUMP
                short[-1].setdescr(loop.token)

                # Turn guards into conditional jumps to the preamble
                for i in range(len(short)):
                    op = short[i]
                    if op.is_guard():
                        op = op.clone()
                        op.setfailargs(None)
                        descr = self.start_resumedescr.clone_if_mutable()
                        op.setdescr(descr)
                        short[i] = op

                short_loop = TreeLoop("short preamble")
                short_loop.inputargs = short_inputargs
                short_loop.operations = short

                # Clone ops and boxes to get private versions and
                boxmap = {}
                newargs = [None] * len(short_loop.inputargs)
                for i in range(len(short_loop.inputargs)):
                    a = short_loop.inputargs[i]
                    if a in boxmap:
                        newargs[i] = boxmap[a]
                    else:
                        newargs[i] = a.clonebox()
                        boxmap[a] = newargs[i]
                inliner = Inliner(short_loop.inputargs, newargs)
                for box, const in self.constant_inputargs.items():
                    inliner.argmap[box] = const
                short_loop.inputargs = newargs
                ops = [inliner.inline_op(op) for op in short_loop.operations]
                short_loop.operations = ops
                descr = self.start_resumedescr.clone_if_mutable()
                inliner.inline_descr_inplace(descr)
                short_loop.start_resumedescr = descr

                assert isinstance(loop.preamble.token, LoopToken)
                if loop.preamble.token.short_preamble:
                    loop.preamble.token.short_preamble.append(short_loop)
                else:
                    loop.preamble.token.short_preamble = [short_loop]
                short_loop.virtual_state = virtual_state

                # Forget the values to allow them to be freed
                for box in short_loop.inputargs:
                    box.forget_value()
                for op in short_loop.operations:
                    if op.result:
                        op.result.forget_value()
Example #7
0
    def propagate_forward(self, op):
        if op.getopnum() == rop.JUMP:
            loop_token = op.getdescr()
            assert isinstance(loop_token, LoopToken)
            # FIXME: Use a tree, similar to the tree formed by the full
            # preamble and it's bridges, instead of a list to save time and
            # memory. This should also allow better behaviour in
            # situations that the is_emittable() chain currently cant
            # handle and the inlining fails unexpectedly belwo.
            short = loop_token.short_preamble
            if short:
                args = op.getarglist()
                modifier = VirtualStateAdder(self.optimizer)
                virtual_state = modifier.get_virtual_state(args)
                debug_start("jit-log-virtualstate")
                virtual_state.debug_print("Looking for ")

                for sh in short:
                    ok = False
                    extra_guards = []

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

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

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

                        values = [self.getvalue(arg) for arg in op.getarglist()]
                        args = sh.virtual_state.make_inputargs(values, keyboxes=True)
                        inliner = Inliner(sh.inputargs, args)

                        for guard in extra_guards:
                            if guard.is_guard():
                                descr = sh.start_resumedescr.clone_if_mutable()
                                inliner.inline_descr_inplace(descr)
                                guard.setdescr(descr)
                            self.emit_operation(guard)

                        try:
                            for shop in sh.operations:
                                newop = inliner.inline_op(shop)
                                self.emit_operation(newop)
                        except InvalidLoop:
                            debug_print("Inlining failed unexpectedly", "jumping to preamble instead")
                            self.emit_operation(op)
                        return
                debug_stop("jit-log-virtualstate")
                retraced_count = loop_token.retraced_count
                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
                if not self.retraced and retraced_count < limit:
                    loop_token.retraced_count += 1
                    if not loop_token.failed_states:
                        debug_print("Retracing (%d of %d)" % (retraced_count, limit))
                        raise RetraceLoop
                    for failed in loop_token.failed_states:
                        if failed.generalization_of(virtual_state):
                            # Retracing once more will most likely fail again
                            break
                    else:
                        debug_print("Retracing (%d of %d)" % (retraced_count, limit))

                        raise RetraceLoop
                else:
                    if not loop_token.failed_states:
                        loop_token.failed_states = [virtual_state]
                    else:
                        loop_token.failed_states.append(virtual_state)
        self.emit_operation(op)
Example #8
0
    def inline(self, inputargs, loop_operations, loop_args, short_inputargs, virtual_state):
        inliner = self.inliner

        short_jumpargs = inputargs[:]

        short = []
        short_seen = {}
        for box, const in self.constant_inputargs.items():
            short_seen[box] = True

        for op in self.short_boxes.operations():
            if op is not None:
                if len(self.getvalue(op.result).make_guards(op.result)) > 0:
                    self.add_op_to_short(op, short, short_seen, False, True)

        # This loop is equivalent to the main optimization loop in
        # Optimizer.propagate_all_forward
        jumpop = None
        for newop in loop_operations:
            newop = inliner.inline_op(newop, clone=False)
            if newop.getopnum() == rop.JUMP:
                jumpop = newop
                break

            # self.optimizer.first_optimization.propagate_forward(newop)
            self.optimizer.send_extra_operation(newop)

        self.boxes_created_this_iteration = {}

        assert jumpop
        original_jumpargs = jumpop.getarglist()[:]
        values = [self.getvalue(arg) for arg in jumpop.getarglist()]
        jumpargs = virtual_state.make_inputargs(values)
        jumpop.initarglist(jumpargs)
        jmp_to_short_args = virtual_state.make_inputargs(values, keyboxes=True)
        self.short_inliner = Inliner(short_inputargs, jmp_to_short_args)

        for box, const in self.constant_inputargs.items():
            self.short_inliner.argmap[box] = const

        for op in short:
            newop = self.short_inliner.inline_op(op)
            self.optimizer.send_extra_operation(newop)

        self.optimizer.flush()

        i = j = 0
        while i < len(self.optimizer.newoperations) or j < len(jumpargs):
            if i == len(self.optimizer.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, short_jumpargs, jumpargs, short_seen)
                    j += 1
            else:
                op = self.optimizer.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, short_jumpargs, jumpargs, short_seen)
                i += 1

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

        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
            # XXX Is it possible to end up here? If so, consider:
            #    - Fallback on having the preamble jump to itself?
            #    - Would virtual_state.generate_guards make sense here?
            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")

        return short
Example #9
0
    def propagate_forward(self, op):
        if op.getopnum() == rop.JUMP:
            loop_token = op.getdescr()
            assert isinstance(loop_token, LoopToken)
            short = loop_token.short_preamble
            if short:
                args = op.getarglist()
                modifier = VirtualStateAdder(self.optimizer)
                virtual_state = modifier.get_virtual_state(args)
                debug_start('jit-log-virtualstate')
                virtual_state.debug_print("Looking for ")

                for sh in short:
                    ok = False
                    extra_guards = []

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

                            ok = True
                            debugmsg = 'Guarded to match '
                        except InvalidLoop:
                            pass
                    sh.virtual_state.debug_print(debugmsg, bad)
                    
                    if ok:
                        debug_stop('jit-log-virtualstate')

                        values = [self.getvalue(arg)
                                  for arg in op.getarglist()]
                        args = sh.virtual_state.make_inputargs(values, self.optimizer,
                                                               keyboxes=True)
                        inliner = Inliner(sh.inputargs, args)
                        
                        for guard in extra_guards:
                            if guard.is_guard():
                                descr = sh.start_resumedescr.clone_if_mutable()
                                inliner.inline_descr_inplace(descr)
                                guard.setdescr(descr)
                            self.emit_operation(guard)
                        
                        try:
                            for shop in sh.operations:
                                newop = inliner.inline_op(shop)
                                self.emit_operation(newop)
                        except InvalidLoop:
                            debug_print("Inlining failed unexpectedly",
                                        "jumping to preamble instead")
                            self.emit_operation(op)
                        return
                debug_stop('jit-log-virtualstate')
                retraced_count = loop_token.retraced_count
                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
                if not self.retraced and retraced_count<limit:
                    loop_token.retraced_count += 1
                    if not loop_token.failed_states:
                        debug_print("Retracing (%d of %d)" % (retraced_count,
                                                              limit))
                        raise RetraceLoop
                    for failed in loop_token.failed_states:
                        if failed.generalization_of(virtual_state):
                            # Retracing once more will most likely fail again
                            break
                    else:
                        debug_print("Retracing (%d of %d)" % (retraced_count,
                                                              limit))

                        raise RetraceLoop
                else:
                    if not loop_token.failed_states:
                        loop_token.failed_states=[virtual_state]
                    else:
                        loop_token.failed_states.append(virtual_state)
        self.emit_operation(op)