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
|
#!/usr/bin/python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import print_function
import argparse
import re
from collections import defaultdict
parser = argparse.ArgumentParser(description="Process some integers.")
parser.add_argument("rootingHazards", nargs="?", default="rootingHazards.txt")
parser.add_argument("gcFunctions", nargs="?", default="gcFunctions.txt")
parser.add_argument("hazards", nargs="?", default="hazards.txt")
parser.add_argument("extra", nargs="?", default="unnecessary.txt")
parser.add_argument("refs", nargs="?", default="refs.txt")
args = parser.parse_args()
num_hazards = 0
num_refs = 0
num_missing = 0
try:
with open(args.rootingHazards) as rootingHazards, open(
args.hazards, "w"
) as hazards, open(args.extra, "w") as extra, open(args.refs, "w") as refs:
current_gcFunction = None
# Map from a GC function name to the list of hazards resulting from
# that GC function
hazardousGCFunctions = defaultdict(list)
# List of tuples (gcFunction, index of hazard) used to maintain the
# ordering of the hazards
hazardOrder = []
# Map from a hazardous GC function to the filename containing it.
fileOfFunction = {}
for line in rootingHazards:
m = re.match(r"^Time: (.*)", line)
mm = re.match(r"^Run on:", line)
if m or mm:
print(line, file=hazards)
print(line, file=extra)
print(line, file=refs)
continue
m = re.match(r"^Function.*has unnecessary root", line)
if m:
print(line, file=extra)
continue
m = re.match(r"^Function.*takes unsafe address of unrooted", line)
if m:
num_refs += 1
print(line, file=refs)
continue
m = re.match(
r"^Function.*has unrooted.*of type.*live across GC call '(.*?)' at (\S+):\d+$",
line,
) # NOQA: E501
if m:
current_gcFunction = m.group(1)
hazardousGCFunctions[current_gcFunction].append(line)
hazardOrder.append(
(
current_gcFunction,
len(hazardousGCFunctions[current_gcFunction]) - 1,
)
)
num_hazards += 1
fileOfFunction[current_gcFunction] = m.group(2)
continue
m = re.match(r"Function.*expected hazard.*but none were found", line)
if m:
num_missing += 1
print(line + "\n", file=hazards)
continue
if current_gcFunction:
if not line.strip():
# Blank line => end of this hazard
current_gcFunction = None
else:
hazardousGCFunctions[current_gcFunction][-1] += line
with open(args.gcFunctions) as gcFunctions:
gcExplanations = {} # gcFunction => stack showing why it can GC
current_func = None
explanation = None
for line in gcFunctions:
m = re.match(r"^GC Function: (.*)", line)
if m:
if current_func:
gcExplanations[current_func] = explanation
current_func = None
if m.group(1) in hazardousGCFunctions:
current_func = m.group(1)
explanation = line
elif current_func:
explanation += line
if current_func:
gcExplanations[current_func] = explanation
for gcFunction, index in hazardOrder:
gcHazards = hazardousGCFunctions[gcFunction]
if gcFunction in gcExplanations:
print(gcHazards[index] + gcExplanations[gcFunction], file=hazards)
else:
print(gcHazards[index], file=hazards)
except IOError as e:
print("Failed: %s" % str(e))
print("Wrote %s" % args.hazards)
print("Wrote %s" % args.extra)
print("Wrote %s" % args.refs)
print(
"Found %d hazards %d unsafe references %d missing"
% (num_hazards, num_refs, num_missing)
)
|