|
1 #!/usr/bin/python |
|
2 |
|
3 import re |
|
4 import argparse |
|
5 |
|
6 parser = argparse.ArgumentParser(description='Process some integers.') |
|
7 parser.add_argument('rootingHazards', nargs='?', default='rootingHazards.txt') |
|
8 parser.add_argument('gcFunctions', nargs='?', default='gcFunctions.txt') |
|
9 parser.add_argument('hazards', nargs='?', default='hazards.txt') |
|
10 parser.add_argument('extra', nargs='?', default='unnecessary.txt') |
|
11 parser.add_argument('refs', nargs='?', default='refs.txt') |
|
12 args = parser.parse_args() |
|
13 |
|
14 num_hazards = 0 |
|
15 num_refs = 0 |
|
16 try: |
|
17 with open(args.rootingHazards) as rootingHazards, \ |
|
18 open(args.hazards, 'w') as hazards, \ |
|
19 open(args.extra, 'w') as extra, \ |
|
20 open(args.refs, 'w') as refs: |
|
21 current_gcFunction = None |
|
22 |
|
23 # Map from a GC function name to the list of hazards resulting from |
|
24 # that GC function |
|
25 hazardousGCFunctions = {} |
|
26 |
|
27 # List of tuples (gcFunction, index of hazard) used to maintain the |
|
28 # ordering of the hazards |
|
29 hazardOrder = [] |
|
30 |
|
31 for line in rootingHazards: |
|
32 m = re.match(r'^Time: (.*)', line) |
|
33 mm = re.match(r'^Run on:', line) |
|
34 if m or mm: |
|
35 print >>hazards, line |
|
36 print >>extra, line |
|
37 print >>refs, line |
|
38 continue |
|
39 |
|
40 m = re.match(r'^Function.*has unnecessary root', line) |
|
41 if m: |
|
42 print >>extra, line |
|
43 continue |
|
44 |
|
45 m = re.match(r'^Function.*takes unsafe address of unrooted', line) |
|
46 if m: |
|
47 num_refs += 1 |
|
48 print >>refs, line |
|
49 continue |
|
50 |
|
51 m = re.match(r"^Function.*has unrooted.*of type.*live across GC call ('?)(.*?)('?) at \S+:\d+$", line) |
|
52 if m: |
|
53 # Function names are surrounded by single quotes. Field calls |
|
54 # are unquoted. |
|
55 current_gcFunction = m.group(2) |
|
56 hazardousGCFunctions.setdefault(current_gcFunction, []).append(line) |
|
57 hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1)) |
|
58 num_hazards += 1 |
|
59 continue |
|
60 |
|
61 if current_gcFunction: |
|
62 if not line.strip(): |
|
63 # Blank line => end of this hazard |
|
64 current_gcFunction = None |
|
65 else: |
|
66 hazardousGCFunctions[current_gcFunction][-1] += line |
|
67 |
|
68 with open(args.gcFunctions) as gcFunctions: |
|
69 gcExplanations = {} # gcFunction => stack showing why it can GC |
|
70 |
|
71 current_func = None |
|
72 explanation = None |
|
73 for line in gcFunctions: |
|
74 m = re.match(r'^GC Function: (.*)', line) |
|
75 if m: |
|
76 if current_func: |
|
77 gcExplanations[current_func] = explanation |
|
78 current_func = None |
|
79 if m.group(1) in hazardousGCFunctions: |
|
80 current_func = m.group(1) |
|
81 explanation = line |
|
82 elif current_func: |
|
83 explanation += line |
|
84 if current_func: |
|
85 gcExplanations[current_func] = explanation |
|
86 |
|
87 for gcFunction, index in hazardOrder: |
|
88 gcHazards = hazardousGCFunctions[gcFunction] |
|
89 if gcFunction in gcExplanations: |
|
90 print >>hazards, (gcHazards[index] + gcExplanations[gcFunction]) |
|
91 else: |
|
92 print >>hazards, gcHazards[index] |
|
93 |
|
94 except IOError as e: |
|
95 print 'Failed: %s' % str(e) |
|
96 |
|
97 print("Wrote %s" % args.hazards) |
|
98 print("Wrote %s" % args.extra) |
|
99 print("Wrote %s" % args.refs) |
|
100 print("Found %d hazards and %d unsafe references" % (num_hazards, num_refs)) |