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

Side by Side Diff: tools/telemetry/third_party/coverage/lab/hack_pyc.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 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3
4 """ Wicked hack to get .pyc files to do bytecode tracing instead of
5 line tracing.
6 """
7
8 import marshal, new, opcode, sys, types
9
10 from lnotab import lnotab_numbers, lnotab_string
11
12 class PycFile:
13 def read(self, f):
14 if isinstance(f, basestring):
15 f = open(f, "rb")
16 self.magic = f.read(4)
17 self.modtime = f.read(4)
18 self.code = marshal.load(f)
19
20 def write(self, f):
21 if isinstance(f, basestring):
22 f = open(f, "wb")
23 f.write(self.magic)
24 f.write(self.modtime)
25 marshal.dump(self.code, f)
26
27 def hack_line_numbers(self):
28 self.code = hack_line_numbers(self.code)
29
30 def hack_line_numbers(code):
31 """ Replace a code object's line number information to claim that every
32 byte of the bytecode is a new source line. Returns a new code
33 object. Also recurses to hack the line numbers in nested code objects.
34 """
35
36 # Create a new lnotab table. Each opcode is claimed to be at
37 # 1000*lineno + (opcode number within line), so for example, the opcodes on
38 # source line 12 will be given new line numbers 12000, 12001, 12002, etc.
39 old_num = list(lnotab_numbers(code.co_lnotab, code.co_firstlineno))
40 n_bytes = len(code.co_code)
41 new_num = []
42 line = 0
43 opnum_in_line = 0
44 i_byte = 0
45 while i_byte < n_bytes:
46 if old_num and i_byte == old_num[0][0]:
47 line = old_num.pop(0)[1]
48 opnum_in_line = 0
49 new_num.append((i_byte, 100000000 + 1000*line + opnum_in_line))
50 if ord(code.co_code[i_byte]) >= opcode.HAVE_ARGUMENT:
51 i_byte += 3
52 else:
53 i_byte += 1
54 opnum_in_line += 1
55
56 # new_num is a list of pairs, (byteoff, lineoff). Turn it into an lnotab.
57 new_firstlineno = new_num[0][1]-1
58 new_lnotab = lnotab_string(new_num, new_firstlineno)
59
60 # Recurse into code constants in this code object.
61 new_consts = []
62 for const in code.co_consts:
63 if type(const) == types.CodeType:
64 new_consts.append(hack_line_numbers(const))
65 else:
66 new_consts.append(const)
67
68 # Create a new code object, just like the old one, except with new
69 # line numbers.
70 new_code = new.code(
71 code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags,
72 code.co_code, tuple(new_consts), code.co_names, code.co_varnames,
73 code.co_filename, code.co_name, new_firstlineno, new_lnotab
74 )
75
76 return new_code
77
78 def hack_file(f):
79 pyc = PycFile()
80 pyc.read(f)
81 pyc.hack_line_numbers()
82 pyc.write(f)
83
84 if __name__ == '__main__':
85 hack_file(sys.argv[1])
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/coverage/lab/disgen.py ('k') | tools/telemetry/third_party/coverage/lab/new-data.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698