File: llgroup.py

package info (click to toggle)
pypy 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 107,216 kB
  • sloc: python: 1,201,787; ansic: 62,419; asm: 5,169; cpp: 3,017; sh: 2,534; makefile: 545; xml: 243; lisp: 45; awk: 4
file content (165 lines) | stat: -rw-r--r-- 5,572 bytes parent folder | download | duplicates (9)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import weakref
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.rlib.rarithmetic import LONG_BIT


class GroupType(lltype.ContainerType):
    """A 'group' that stores static structs together in memory.

    On 32-bit platforms, the point is that they can be referenced by a
    GroupMemberOffset which only takes 2 bytes (a USHORT), so the total
    size of a group is limited to 18 (= the 16 bits in a USHORT, plus 2
    bits at the end that are zero and so don't need to be stored).

    On 64-bit platforms, we check that the address they end up at is
    within the first 32 bits, so that we can store that address in half
    a long (i.e. in a UINT).
    """
    _gckind = 'raw'

Group = GroupType()


class group(lltype._container):
    _TYPE = Group
    outdated = None

    def __init__(self, name):
        self.name = name
        self.members = []

    def add_member(self, structptr):
        TYPE = lltype.typeOf(structptr)
        assert isinstance(TYPE.TO, lltype.Struct)
        assert TYPE.TO._gckind == 'raw'
        struct = structptr._as_obj()
        prevgroup = _membership.get(struct)
        if prevgroup is not None:
            prevgroup.outdated = (
                "structure %s was inserted into another group" % (struct,))
        assert struct._parentstructure() is None
        index = len(self.members)
        self.members.append(struct)
        _membership[struct] = self
        return GroupMemberOffset(self, index)

def member_of_group(structptr):
    return _membership.get(structptr._as_obj(), None)

_membership = weakref.WeakValueDictionary()


if LONG_BIT == 32:
    HALFSHIFT = 16
    HALFWORD = rffi.USHORT
    r_halfword = rffi.r_ushort
else:
    HALFSHIFT = 32
    HALFWORD = rffi.UINT
    r_halfword = rffi.r_uint


class GroupMemberOffset(llmemory.Symbolic):
    """The offset of a struct inside a group, stored compactly in a HALFWORD
    (a USHORT or UINT). Can only be used by the lloperation 'get_group_member'.
    """
    def annotation(self):
        from rpython.annotator import model
        return model.SomeInteger(knowntype=r_halfword)

    def lltype(self):
        return HALFWORD

    def __init__(self, grp, memberindex):
        assert lltype.typeOf(grp) == Group
        self.grpptr = grp._as_ptr()
        self.index = memberindex
        self.member = grp.members[memberindex]._as_ptr()

    def __repr__(self):
        return '%s(%s, %s)' % (self.__class__.__name__,
                               self.grpptr, self.index)

    def __nonzero__(self):
        return True

    def _get_group_member(self, grpptr):
        assert grpptr == self.grpptr, "get_group_member: wrong group!"
        return self.member

    def _get_next_group_member(self, grpptr, skipoffset):
        # ad-hoc: returns a pointer to the group member that follows this one,
        # given information in 'skipoffset' about how much to skip -- which
        # is the size of the current member.
        assert grpptr == self.grpptr, "get_next_group_member: wrong group!"
        assert isinstance(skipoffset, llmemory.ItemOffset)
        assert skipoffset.TYPE == lltype.typeOf(self.member).TO
        assert skipoffset.repeat == 1
        return self.grpptr._as_obj().members[self.index + 1]._as_ptr()


class CombinedSymbolic(llmemory.Symbolic):
    """A general-purpose Signed symbolic that combines an unsigned half-word
    (USHORT on 32-bit platforms, UINT on 64-bit platforms) and the rest
    of the word (typically flags).  Only supports extracting the half-word
    with 'llop.extract_ushort', and extracting the rest of the word with
    '&~0xFFFF' or with a direct masking like '&0x10000' (resp. on 64-bit
    platform, with '&~0xFFFFFFFF' or '&0x100000000').
    """
    __slots__ = ['lowpart', 'rest']
    MASK = (1<<HALFSHIFT)-1     # 0xFFFF or 0xFFFFFFFF

    def annotation(self):
        from rpython.annotator import model
        return model.SomeInteger()

    def lltype(self):
        return lltype.Signed

    def __init__(self, lowpart, rest):
        assert (rest & CombinedSymbolic.MASK) == 0
        self.lowpart = lowpart
        self.rest = rest

    def __repr__(self):
        return '<CombinedSymbolic %r|%s>' % (self.lowpart, self.rest)

    def __nonzero__(self):
        return True

    def __and__(self, other):
        if (other & CombinedSymbolic.MASK) == 0:
            return self.rest & other
        if (other & CombinedSymbolic.MASK) == CombinedSymbolic.MASK:
            return CombinedSymbolic(self.lowpart, self.rest & other)
        raise Exception("other=0x%x" % other)

    def __or__(self, other):
        assert (other & CombinedSymbolic.MASK) == 0
        return CombinedSymbolic(self.lowpart, self.rest | other)

    def __add__(self, other):
        assert (other & CombinedSymbolic.MASK) == 0
        return CombinedSymbolic(self.lowpart, self.rest + other)

    def __sub__(self, other):
        assert (other & CombinedSymbolic.MASK) == 0
        return CombinedSymbolic(self.lowpart, self.rest - other)

    def __rshift__(self, other):
        assert other >= HALFSHIFT
        return self.rest >> other

    def __eq__(self, other):
        if (isinstance(other, CombinedSymbolic) and
            self.lowpart is other.lowpart):
            return self.rest == other.rest
        else:
            return NotImplemented

    def __ne__(self, other):
        if (isinstance(other, CombinedSymbolic) and
            self.lowpart is other.lowpart):
            return self.rest != other.rest
        else:
            return NotImplemented