1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#!/usr/bin/env python 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier# Copyright 2014 the V8 project authors. All rights reserved. 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier# Use of this source code is governed by a BSD-style license that can be 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier# found in the LICENSE file. 5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierimport sys 7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernieraction = sys.argv[1] 10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierif action in ["help", "-h", "--help"] or len(sys.argv) != 3: 12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("Usage: %s <action> <inputfile>, where action can be: \n" 13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "help Print this message\n" 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "plain Print ASCII tree to stdout\n" 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "dot Print dot file to stdout\n" 16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier "count Count most frequent transition reasons\n" % sys.argv[0]) 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier sys.exit(0) 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierfilename = sys.argv[2] 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniermaps = {} 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierroot_maps = [] 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertransitions = {} 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierannotations = {} 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass Map(object): 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def __init__(self, pointer, origin): 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.pointer = pointer 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.origin = origin 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def __str__(self): 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "%s (%s)" % (self.pointer, self.origin) 35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass Transition(object): 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier def __init__(self, from_map, to_map, reason): 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.from_map = from_map 41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.to_map = to_map 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier self.reason = reason 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef RegisterNewMap(raw_map): 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if raw_map in annotations: 47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier annotations[raw_map] += 1 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier else: 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier annotations[raw_map] = 0 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return AnnotateExistingMap(raw_map) 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef AnnotateExistingMap(raw_map): 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return "%s_%d" % (raw_map, annotations[raw_map]) 55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef AddMap(pointer, origin): 58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier pointer = RegisterNewMap(pointer) 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier maps[pointer] = Map(pointer, origin) 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return pointer 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef AddTransition(from_map, to_map, reason): 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier from_map = AnnotateExistingMap(from_map) 65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier to_map = AnnotateExistingMap(to_map) 66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if from_map not in transitions: 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier transitions[from_map] = {} 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier targets = transitions[from_map] 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if to_map in targets: 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Some events get printed twice, that's OK. In some cases, ignore the 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # second output... 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier old_reason = targets[to_map].reason 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if old_reason.startswith("ReplaceDescriptors"): 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # ...and in others use it for additional detail. 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if reason in []: 77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier targets[to_map].reason = reason 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return 79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # Unexpected duplicate events? Warn. 80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("// warning: already have a transition from %s to %s, reason: %s" % 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (from_map, to_map, targets[to_map].reason)) 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier targets[to_map] = Transition(from_map, to_map, reason) 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierwith open(filename, "r") as f: 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier last_to_map = "" 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for line in f: 89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if not line.startswith("[TraceMaps: "): continue 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier words = line.split(" ") 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier event = words[1] 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if event == "InitialMap": 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier assert words[2] == "map=" 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier assert words[4] == "SFI=" 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier new_map = AddMap(words[3], "SFI#%s" % words[5]) 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier root_maps.append(new_map) 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier continue 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if words[2] == "from=" and words[4] == "to=": 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier from_map = words[3] 100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier to_map = words[5] 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if from_map not in annotations: 102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("// warning: unknown from_map %s" % from_map) 103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier new_map = AddMap(from_map, "<unknown>") 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier root_maps.append(new_map) 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if to_map != last_to_map: 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddMap(to_map, "<transition> (%s)" % event) 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier last_to_map = to_map 108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if event in ["Transition", "NoTransition"]: 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier assert words[6] == "name=", line 110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = "%s: %s" % (event, words[7]) 111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier elif event in ["Normalize", "ReplaceDescriptors", "SlowToFast"]: 112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier assert words[6] == "reason=", line 113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = "%s: %s" % (event, words[7]) 114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if words[8].strip() != "]": 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = "%s_%s" % (reason, words[8]) 116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier else: 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = event 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddTransition(from_map, to_map, reason) 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier continue 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef PlainPrint(m, indent, label): 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("%s%s (%s)" % (indent, m, label)) 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if m in transitions: 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for t in transitions[m]: 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PlainPrint(t, indent + " ", transitions[m][t].reason) 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef CountTransitions(m): 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if m not in transitions: return 0 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return len(transitions[m]) 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierdef DotPrint(m, label): 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("m%s [label=\"%s\"]" % (m[2:], label)) 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if m in transitions: 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for t in transitions[m]: 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # GraphViz doesn't like node labels looking like numbers, so use 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier # "m..." instead of "0x...". 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("m%s -> m%s" % (m[2:], t[2:])) 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = transitions[m][t].reason 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = reason.replace("\\", "BACKSLASH") 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = reason.replace("\"", "\\\"") 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DotPrint(t, reason) 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierif action == "plain": 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier root_maps = sorted(root_maps, key=CountTransitions, reverse=True) 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for m in root_maps: 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PlainPrint(m, "", maps[m].origin) 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierelif action == "dot": 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("digraph g {") 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for m in root_maps: 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DotPrint(m, maps[m].origin) 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print("}") 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierelif action == "count": 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons = {} 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for s in transitions: 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for t in transitions[s]: 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reason = transitions[s][t].reason 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if reason not in reasons: 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons[reason] = 1 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier else: 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons[reason] += 1 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons_list = [] 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for r in reasons: 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons_list.append("%8d %s" % (reasons[r], r)) 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reasons_list.sort(reverse=True) 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for r in reasons_list[:20]: 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier print r 173