forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjitcode.py
More file actions
176 lines (147 loc) · 6.37 KB
/
jitcode.py
File metadata and controls
176 lines (147 loc) · 6.37 KB
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
166
167
168
169
170
171
172
173
174
175
176
from rpython.jit.metainterp.history import AbstractDescr, ConstInt
from rpython.jit.codewriter import heaptracker
from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.rarithmetic import base_int
class JitCode(AbstractDescr):
_empty_i = []
_empty_r = []
_empty_f = []
def __init__(self, name, fnaddr=None, calldescr=None, called_from=None):
self.name = name
self.fnaddr = fnaddr
self.calldescr = calldescr
self.jitdriver_sd = None # None for non-portals
self._called_from = called_from # debugging
self._ssarepr = None # debugging
def setup(self, code='', constants_i=[], constants_r=[], constants_f=[],
num_regs_i=255, num_regs_r=255, num_regs_f=255,
liveness=None, startpoints=None, alllabels=None,
resulttypes=None):
self.code = code
for x in constants_i:
assert not isinstance(x, base_int), (
"found constant %r of type %r, must not appear in "
"JitCode.constants_i" % (x, type(x)))
# if the following lists are empty, use a single shared empty list
self.constants_i = constants_i or self._empty_i
self.constants_r = constants_r or self._empty_r
self.constants_f = constants_f or self._empty_f
# encode the three num_regs into a single char each
assert num_regs_i < 256 and num_regs_r < 256 and num_regs_f < 256
self.c_num_regs_i = chr(num_regs_i)
self.c_num_regs_r = chr(num_regs_r)
self.c_num_regs_f = chr(num_regs_f)
self.liveness = make_liveness_cache(liveness)
self._startpoints = startpoints # debugging
self._alllabels = alllabels # debugging
self._resulttypes = resulttypes # debugging
def get_fnaddr_as_int(self):
return heaptracker.adr2int(self.fnaddr)
def num_regs_i(self):
return ord(self.c_num_regs_i)
def num_regs_r(self):
return ord(self.c_num_regs_r)
def num_regs_f(self):
return ord(self.c_num_regs_f)
def has_liveness_info(self, pc):
return pc in self.liveness
def get_live_vars_info(self, pc):
# 'pc' gives a position in this bytecode. This returns an object
# of class LiveVarsInfo that describes all variables that are live
# across the instruction boundary at 'pc'.
try:
return self.liveness[pc] # XXX compactify!!
except KeyError:
self._missing_liveness(pc)
def _live_vars(self, pc):
# for testing only
info = self.get_live_vars_info(pc)
lst_i = ['%%i%d' % info.get_register_index_i(index)
for index in range(info.get_register_count_i()-1, -1, -1)]
lst_r = ['%%r%d' % info.get_register_index_r(index)
for index in range(info.get_register_count_r()-1, -1, -1)]
lst_f = ['%%f%d' % info.get_register_index_f(index)
for index in range(info.get_register_count_f()-1, -1, -1)]
return ' '.join(lst_i + lst_r + lst_f)
def _missing_liveness(self, pc):
msg = "missing liveness[%d] in %s" % (pc, self.name)
if we_are_translated():
print msg
raise AssertionError
raise MissingLiveness("%s\n%s" % (msg, self.dump()))
def follow_jump(self, position):
"""Assuming that 'position' points just after a bytecode
instruction that ends with a label, follow that label."""
code = self.code
position -= 2
assert position >= 0
if not we_are_translated():
assert position in self._alllabels
labelvalue = ord(code[position]) | (ord(code[position+1])<<8)
assert labelvalue < len(code)
return labelvalue
def dump(self):
if self._ssarepr is None:
return '<no dump available for %r>' % (self.name,)
else:
from rpython.jit.codewriter.format import format_assembler
return format_assembler(self._ssarepr)
def __repr__(self):
return '<JitCode %r>' % self.name
def _clone_if_mutable(self):
raise NotImplementedError
class MissingLiveness(Exception):
pass
class SwitchDictDescr(AbstractDescr):
"Get a 'dict' attribute mapping integer values to bytecode positions."
def attach(self, as_dict):
self.dict = as_dict
self.const_keys_in_order = map(ConstInt, sorted(as_dict.keys()))
def __repr__(self):
dict = getattr(self, 'dict', '?')
return '<SwitchDictDescr %s>' % (dict,)
def _clone_if_mutable(self):
raise NotImplementedError
class LiveVarsInfo(object):
def __init__(self, live_i, live_r, live_f):
self.live_i = live_i
self.live_r = live_r
self.live_f = live_f
def get_register_count_i(self):
return len(self.live_i)
def get_register_count_r(self):
return len(self.live_r)
def get_register_count_f(self):
return len(self.live_f)
def get_register_index_i(self, index):
return ord(self.live_i[index])
def get_register_index_r(self, index):
return ord(self.live_r[index])
def get_register_index_f(self, index):
return ord(self.live_f[index])
def enumerate_vars(self, callback_i, callback_r, callback_f, spec):
for i in range(self.get_register_count_i()):
callback_i(self.get_register_index_i(i))
for i in range(self.get_register_count_r()):
callback_r(self.get_register_index_r(i))
for i in range(self.get_register_count_f()):
callback_f(self.get_register_index_f(i))
enumerate_vars._annspecialcase_ = 'specialize:arg(4)'
_liveness_cache = {}
def make_liveness_cache(liveness):
if liveness is None:
return None
result = {}
for key, (value_i, value_r, value_f) in liveness.items():
# Sort the lists to increase the chances of sharing between unrelated
# strings that happen to contain the same characters. We sort in the
# reversed order just to reduce the risks of tests passing by chance.
value = (''.join(sorted(value_i, reverse=True)),
''.join(sorted(value_r, reverse=True)),
''.join(sorted(value_f, reverse=True)))
try:
info = _liveness_cache[value]
except KeyError:
info = _liveness_cache[value] = LiveVarsInfo(*value)
result[key] = info
return result