File: resumecode.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 (142 lines) | stat: -rw-r--r-- 4,145 bytes parent folder | download | duplicates (7)
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

""" Resume bytecode. It goes as following:

  # ----- resume section
  [total size of resume section]
  [number of failargs]
  [<length> <virtualizable object> <numb> <numb> <numb>]    if vinfo is not None
   -OR-
  [1 <ginfo object>]                                        if ginfo is not None
   -OR-
  [0]                                                       if both are None

  [<length> <virtual> <vref> <virtual> <vref>]     for virtualrefs

  [<pc> <jitcode> <numb> <numb> <numb>]            the frames
  [<pc> <jitcode> <numb> <numb>]
  ...

  until the size of the resume section

  # ----- optimization section
  <more code>                                      further sections according to bridgeopt.py
"""

from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import objectmodel

NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
NUMBERING = lltype.GcStruct('Numbering',
                            ('code', lltype.Array(rffi.UCHAR)))
NUMBERINGP.TO.become(NUMBERING)
NULL_NUMBER = lltype.nullptr(NUMBERING)

def append_numbering(lst, item):
    item = rffi.cast(lltype.Signed, item)
    item *= 2
    if item < 0:
        item = -1 - item

    assert item >= 0
    if item < 2**7:
        lst.append(rffi.cast(rffi.UCHAR, item))
    elif item < 2**14:
        lst.append(rffi.cast(rffi.UCHAR, item | 0x80))
        lst.append(rffi.cast(rffi.UCHAR, item >> 7))
    else:
        assert item < 2**16
        lst.append(rffi.cast(rffi.UCHAR, item | 0x80))
        lst.append(rffi.cast(rffi.UCHAR, (item >> 7) | 0x80))
        lst.append(rffi.cast(rffi.UCHAR, item >> 14))


def numb_next_item(numb, index):
    value = rffi.cast(lltype.Signed, numb.code[index])
    index += 1
    if value & (2**7):
        value &= 2**7 - 1
        value |= rffi.cast(lltype.Signed, numb.code[index]) << 7
        index += 1
        if value & (2**14):
            value &= 2**14 - 1
            value |= rffi.cast(lltype.Signed, numb.code[index]) << 14
            index += 1
    if value & 1:
        value = -1 - value
    value >>= 1
    return value, index
numb_next_item._always_inline_ = True

def numb_next_n_items(numb, size, index):
    for i in range(size):
        _, index = numb_next_item(numb, index)
    return index

def unpack_numbering(numb):
    l = []
    i = 0
    while i < len(numb.code):
        next, i = numb_next_item(numb, i)
        l.append(next)
    return l

class Writer(object):
    def __init__(self, size=0):
        self.current = objectmodel.newlist_hint(size)

    def append_short(self, item):
        self.current.append(item)

    def append_int(self, item):
        short = rffi.cast(rffi.SHORT, item)
        assert rffi.cast(lltype.Signed, short) == item
        return self.append_short(short)

    def create_numbering(self):
        final = objectmodel.newlist_hint(len(self.current) * 3)
        for item in self.current:
            append_numbering(final, item)
        numb = lltype.malloc(NUMBERING, len(final))
        for i, elt in enumerate(final):
            numb.code[i] = elt
        return numb

    def patch_current_size(self, index):
        self.patch(index, len(self.current))

    def patch(self, index, item):
        self.current[index] = item

def create_numbering(l):
    w = Writer()
    for item in l:
        w.append_int(item)
    return w.create_numbering()


class Reader(object):
    def __init__(self, code):
        self.code = code
        self.cur_pos = 0 # index into the code
        self.items_read = 0 # number of items read

    def next_item(self):
        result, self.cur_pos = numb_next_item(self.code, self.cur_pos)
        self.items_read += 1
        return result

    def peek(self):
        result, _ = numb_next_item(self.code, self.cur_pos)
        return result

    def jump(self, size):
        """ jump n items forward without returning anything """
        index = self.cur_pos
        for i in range(size):
            _, index = numb_next_item(self.code, index)
        self.items_read += size
        self.cur_pos = index

    def unpack(self):
        # mainly for debugging
        return unpack_numbering(self.code)