File: version.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (122 lines) | stat: -rw-r--r-- 4,507 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

from rpython.jit.metainterp.resoperation import rop
from rpython.jit.metainterp.optimizeopt.optimizer import BasicLoopInfo
from rpython.jit.metainterp.compile import (send_bridge_to_backend, record_loop_or_bridge,
        ResumeGuardDescr, create_empty_loop)
from rpython.jit.metainterp.history import AbstractFailDescr


class LoopVersionInfo(BasicLoopInfo):
    def __init__(self, info):
        assert isinstance(info, BasicLoopInfo)
        #self.target_token = info.target_token
        self.label_op = info.label_op
        self.extra_same_as = info.extra_same_as
        self.quasi_immutable_deps = info.quasi_immutable_deps
        self.descrs = []
        self.leads_to = {}
        self.insert_index = -1
        self.versions = []

    def mark(self):
        self.insert_index = len(self.descrs)

    def clear(self):
        self.insert_index = -1

    def track(self, op, descr, version):
        assert descr.loop_version()
        i = self.insert_index
        if i >= 0:
            assert i >= 0
            self.descrs.insert(i, descr)
        else:
            self.descrs.append(descr)
        assert descr not in self.leads_to
        self.leads_to[descr] = version

    def remove(self, descr):
        if descr in self.leads_to:
            del self.leads_to[descr]
        else:
            assert 0, "could not remove %s" % descr

    def get(self, descr):
        return self.leads_to.get(descr, None)

    def snapshot(self, loop):
        newloop = loop.clone()
        version = LoopVersion(newloop)
        version.setup_once(self)
        self.versions.append(version)
        # register the faildescr for later stitching
        return version

    def post_loop_compilation(self, loop, jitdriver_sd, metainterp, jitcell_token):
        """ if a loop version is created for a guard instruction (e.g. they are known
            to fail frequently) then a version can be created that is immediatly compiled
            and stitched to the guard.
        """
        metainterp_sd = metainterp.staticdata
        cpu = metainterp_sd.cpu
        if not self.versions:
            return
        # compile each version once for the first fail descr!
        # this assumes that the root trace (= loop) is already compiled
        compiled = {}
        for descr in self.descrs:
            version = self.get(descr)
            if not version:
                # the guard might have been removed from the trace
                continue
            if version not in compiled:
                assert isinstance(descr, AbstractFailDescr)
                vl = version.create_backend_loop(metainterp, jitcell_token)
                asminfo = send_bridge_to_backend(jitdriver_sd, metainterp_sd,
                                                 descr, vl.inputargs,
                                                 vl.operations, jitcell_token,
                                                 metainterp.box_names_memo)
                record_loop_or_bridge(metainterp_sd, vl)
                assert asminfo is not None
                compiled[version] = (asminfo, descr, version, jitcell_token)
            else:
                param = compiled[version]
                cpu.stitch_bridge(descr, param)

        self.versions = [] # dismiss versions


class LoopVersion(object):
    """ A special version of a trace loop. Use loop.snaphost() to
        create one instance and attach it to a guard descr.
        If not attached to a descriptor, it will not be compiled.
    """
    _attrs_ = ('label', 'loop', 'inputargs')

    def __init__(self, loop):
        self.loop = loop
        self.inputargs = loop.label.getarglist()

    def setup_once(self, info):
        for op in self.loop.operations:
            if not op.is_guard():
                continue
            olddescr = op.getdescr()
            if not olddescr:
                continue
            descr = olddescr.clone()
            op.setdescr(descr)
            if descr.loop_version():
                toversion = info.leads_to.get(olddescr,None)
                if toversion:
                    info.track(op, descr, toversion)
                else:
                    assert 0, "olddescr must be found"

    def create_backend_loop(self, metainterp, jitcell_token):
        vl = create_empty_loop(metainterp)
        vl.operations = self.loop.finaloplist(jitcell_token,True,True)
        vl.inputargs = self.loop.label.getarglist_copy()
        vl.original_jitcell_token = jitcell_token
        return vl