Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: tools/telemetry/third_party/coverage/lab/disgen.py

Issue 1366913004: Add coverage Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 """Disassembler of Python byte code into mnemonics."""
2
3 # Adapted from stdlib dis.py, but returns structured information
4 # instead of printing to stdout.
5
6 import sys
7 import types
8 import collections
9
10 from opcode import *
11 from opcode import __all__ as _opcodes_all
12
13 __all__ = ["dis", "disassemble", "distb", "disco",
14 "findlinestarts", "findlabels"] + _opcodes_all
15 del _opcodes_all
16
17 def dis(x=None):
18 for disline in disgen(x):
19 if disline.first and disline.offset > 0:
20 print()
21 print(format_dis_line(disline))
22
23 def format_dis_line(disline):
24 if disline.first:
25 lineno = "%3d" % disline.lineno
26 else:
27 lineno = " "
28 if disline.target:
29 label = ">>"
30 else:
31 label = " "
32 if disline.oparg is not None:
33 oparg = repr(disline.oparg)
34 else:
35 oparg = ""
36 return "%s %s %4r %-20s %5s %s" % (lineno, label, disline.offset, disline .opcode, oparg, disline.argstr)
37
38 def disgen(x=None):
39 """Disassemble methods, functions, or code.
40
41 With no argument, disassemble the last traceback.
42
43 """
44 if x is None:
45 return distb()
46 if hasattr(x, 'im_func'):
47 x = x.im_func
48 if hasattr(x, 'func_code'):
49 x = x.func_code
50 if hasattr(x, 'co_code'):
51 return disassemble(x)
52 else:
53 raise TypeError(
54 "don't know how to disassemble %s objects" %
55 type(x).__name__
56 )
57
58 def distb(tb=None):
59 """Disassemble a traceback (default: last traceback)."""
60 if tb is None:
61 try:
62 tb = sys.last_traceback
63 except AttributeError:
64 raise RuntimeError("no last traceback to disassemble")
65 while tb.tb_next:
66 tb = tb.tb_next
67 return disassemble(tb.tb_frame.f_code, tb.tb_lasti)
68
69 DisLine = collections.namedtuple(
70 'DisLine',
71 "lineno first target offset opcode oparg argstr"
72 )
73
74 def disassemble(co, lasti=-1):
75 """Disassemble a code object."""
76 code = co.co_code
77 labels = findlabels(code)
78 linestarts = dict(findlinestarts(co))
79 n = len(code)
80 i = 0
81 extended_arg = 0
82 free = None
83
84 dislines = []
85 lineno = linestarts[0]
86
87 while i < n:
88 op = byte_from_code(code, i)
89 first = i in linestarts
90 if first:
91 lineno = linestarts[i]
92
93 #if i == lasti: print '-->',
94 #else: print ' ',
95 target = i in labels
96 offset = i
97 opcode = opname[op]
98 i = i+1
99 if op >= HAVE_ARGUMENT:
100 oparg = byte_from_code(code, i) + byte_from_code(code, i+1)*256 + ex tended_arg
101 extended_arg = 0
102 i = i+2
103 if op == EXTENDED_ARG:
104 extended_arg = oparg*65536
105 if op in hasconst:
106 argstr = '(' + repr(co.co_consts[oparg]) + ')'
107 elif op in hasname:
108 argstr = '(' + co.co_names[oparg] + ')'
109 elif op in hasjabs:
110 argstr = '(-> ' + repr(oparg) + ')'
111 elif op in hasjrel:
112 argstr = '(-> ' + repr(i + oparg) + ')'
113 elif op in haslocal:
114 argstr = '(' + co.co_varnames[oparg] + ')'
115 elif op in hascompare:
116 argstr = '(' + cmp_op[oparg] + ')'
117 elif op in hasfree:
118 if free is None:
119 free = co.co_cellvars + co.co_freevars
120 argstr = '(' + free[oparg] + ')'
121 else:
122 argstr = ""
123 else:
124 oparg = None
125 argstr = ""
126 yield DisLine(lineno=lineno, first=first, target=target, offset=offset, opcode=opcode, oparg=oparg, argstr=argstr)
127
128
129 def byte_from_code(code, i):
130 byte = code[i]
131 if not isinstance(byte, int):
132 byte = ord(byte)
133 return byte
134
135 def findlabels(code):
136 """Detect all offsets in a byte code which are jump targets.
137
138 Return the list of offsets.
139
140 """
141 labels = []
142 n = len(code)
143 i = 0
144 while i < n:
145 op = byte_from_code(code, i)
146 i = i+1
147 if op >= HAVE_ARGUMENT:
148 oparg = byte_from_code(code, i) + byte_from_code(code, i+1)*256
149 i = i+2
150 label = -1
151 if op in hasjrel:
152 label = i+oparg
153 elif op in hasjabs:
154 label = oparg
155 if label >= 0:
156 if label not in labels:
157 labels.append(label)
158 return labels
159
160 def findlinestarts(code):
161 """Find the offsets in a byte code which are start of lines in the source.
162
163 Generate pairs (offset, lineno) as described in Python/compile.c.
164
165 """
166 byte_increments = [byte_from_code(code.co_lnotab, i) for i in range(0, len(c ode.co_lnotab), 2)]
167 line_increments = [byte_from_code(code.co_lnotab, i) for i in range(1, len(c ode.co_lnotab), 2)]
168
169 lastlineno = None
170 lineno = code.co_firstlineno
171 addr = 0
172 for byte_incr, line_incr in zip(byte_increments, line_increments):
173 if byte_incr:
174 if lineno != lastlineno:
175 yield (addr, lineno)
176 lastlineno = lineno
177 addr += byte_incr
178 lineno += line_incr
179 if lineno != lastlineno:
180 yield (addr, lineno)
181
182 def _test():
183 """Simple test program to disassemble a file."""
184 if sys.argv[1:]:
185 if sys.argv[2:]:
186 sys.stderr.write("usage: python dis.py [-|file]\n")
187 sys.exit(2)
188 fn = sys.argv[1]
189 if not fn or fn == "-":
190 fn = None
191 else:
192 fn = None
193 if fn is None:
194 f = sys.stdin
195 else:
196 f = open(fn)
197 source = f.read()
198 if fn is not None:
199 f.close()
200 else:
201 fn = "<stdin>"
202 code = compile(source, fn, "exec")
203 dis(code)
204
205 if __name__ == "__main__":
206 _test()
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/coverage/lab/coverage-03.dtd ('k') | tools/telemetry/third_party/coverage/lab/hack_pyc.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698