1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/devtools/rootAnalysis/explain.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,100 @@ 1.4 +#!/usr/bin/python 1.5 + 1.6 +import re 1.7 +import argparse 1.8 + 1.9 +parser = argparse.ArgumentParser(description='Process some integers.') 1.10 +parser.add_argument('rootingHazards', nargs='?', default='rootingHazards.txt') 1.11 +parser.add_argument('gcFunctions', nargs='?', default='gcFunctions.txt') 1.12 +parser.add_argument('hazards', nargs='?', default='hazards.txt') 1.13 +parser.add_argument('extra', nargs='?', default='unnecessary.txt') 1.14 +parser.add_argument('refs', nargs='?', default='refs.txt') 1.15 +args = parser.parse_args() 1.16 + 1.17 +num_hazards = 0 1.18 +num_refs = 0 1.19 +try: 1.20 + with open(args.rootingHazards) as rootingHazards, \ 1.21 + open(args.hazards, 'w') as hazards, \ 1.22 + open(args.extra, 'w') as extra, \ 1.23 + open(args.refs, 'w') as refs: 1.24 + current_gcFunction = None 1.25 + 1.26 + # Map from a GC function name to the list of hazards resulting from 1.27 + # that GC function 1.28 + hazardousGCFunctions = {} 1.29 + 1.30 + # List of tuples (gcFunction, index of hazard) used to maintain the 1.31 + # ordering of the hazards 1.32 + hazardOrder = [] 1.33 + 1.34 + for line in rootingHazards: 1.35 + m = re.match(r'^Time: (.*)', line) 1.36 + mm = re.match(r'^Run on:', line) 1.37 + if m or mm: 1.38 + print >>hazards, line 1.39 + print >>extra, line 1.40 + print >>refs, line 1.41 + continue 1.42 + 1.43 + m = re.match(r'^Function.*has unnecessary root', line) 1.44 + if m: 1.45 + print >>extra, line 1.46 + continue 1.47 + 1.48 + m = re.match(r'^Function.*takes unsafe address of unrooted', line) 1.49 + if m: 1.50 + num_refs += 1 1.51 + print >>refs, line 1.52 + continue 1.53 + 1.54 + m = re.match(r"^Function.*has unrooted.*of type.*live across GC call ('?)(.*?)('?) at \S+:\d+$", line) 1.55 + if m: 1.56 + # Function names are surrounded by single quotes. Field calls 1.57 + # are unquoted. 1.58 + current_gcFunction = m.group(2) 1.59 + hazardousGCFunctions.setdefault(current_gcFunction, []).append(line) 1.60 + hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1)) 1.61 + num_hazards += 1 1.62 + continue 1.63 + 1.64 + if current_gcFunction: 1.65 + if not line.strip(): 1.66 + # Blank line => end of this hazard 1.67 + current_gcFunction = None 1.68 + else: 1.69 + hazardousGCFunctions[current_gcFunction][-1] += line 1.70 + 1.71 + with open(args.gcFunctions) as gcFunctions: 1.72 + gcExplanations = {} # gcFunction => stack showing why it can GC 1.73 + 1.74 + current_func = None 1.75 + explanation = None 1.76 + for line in gcFunctions: 1.77 + m = re.match(r'^GC Function: (.*)', line) 1.78 + if m: 1.79 + if current_func: 1.80 + gcExplanations[current_func] = explanation 1.81 + current_func = None 1.82 + if m.group(1) in hazardousGCFunctions: 1.83 + current_func = m.group(1) 1.84 + explanation = line 1.85 + elif current_func: 1.86 + explanation += line 1.87 + if current_func: 1.88 + gcExplanations[current_func] = explanation 1.89 + 1.90 + for gcFunction, index in hazardOrder: 1.91 + gcHazards = hazardousGCFunctions[gcFunction] 1.92 + if gcFunction in gcExplanations: 1.93 + print >>hazards, (gcHazards[index] + gcExplanations[gcFunction]) 1.94 + else: 1.95 + print >>hazards, gcHazards[index] 1.96 + 1.97 +except IOError as e: 1.98 + print 'Failed: %s' % str(e) 1.99 + 1.100 +print("Wrote %s" % args.hazards) 1.101 +print("Wrote %s" % args.extra) 1.102 +print("Wrote %s" % args.refs) 1.103 +print("Found %d hazards and %d unsafe references" % (num_hazards, num_refs))