blob: dc8b76f5c687d24125c2ca39232b2db94a25088a [file] [log] [blame]
#!/usr/bin/python
import re
import argparse
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
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 = []
for line in rootingHazards:
m = re.match(r'^Time: (.*)', line)
mm = re.match(r'^Run on:', line)
if m or mm:
print >>hazards, line
print >>extra, line
print >>refs, line
continue
m = re.match(r'^Function.*has unnecessary root', line)
if m:
print >>extra, line
continue
m = re.match(r'^Function.*takes unsafe address of unrooted', line)
if m:
num_refs += 1
print >>refs, line
continue
m = re.match(r"^Function.*has unrooted.*of type.*live across GC call ('?)(.*?)('?) at \S+:\d+$", line)
if m:
# Function names are surrounded by single quotes. Field calls
# are unquoted.
current_gcFunction = m.group(2)
hazardousGCFunctions[current_gcFunction].append(line)
hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1))
num_hazards += 1
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 >>hazards, (gcHazards[index] + gcExplanations[gcFunction])
else:
print >>hazards, gcHazards[index]
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 and %d unsafe references" % (num_hazards, num_refs))