Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: tools/binary_size/libsupersize/cluster_symbols.py

Issue 2870743003: supersize: Add symbol.template_name, and strip <>s from symbol.name (Closed)
Patch Set: review comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Logic for clustering similar symbols.""" 5 """Logic for clustering similar symbols."""
6 6
7 import collections 7 import collections
8 import logging 8 import logging
9 import re 9 import re
10 10
11 import function_signature
11 12
12 # Refer to models.SymbolGroup.Cluster() for pydoc 13
14 def _StripCloneSuffix(name):
15 # Multiple attributes could exist, so search from left-to-right.
16 idx = name.find(' [clone ')
17 if idx != -1:
18 return name[:idx]
19 return name
20
21
22 # Refer to models.SymbolGroup.Clustered() for pydoc
23 # TODO(agrieve): This logic should likely be combined with
24 # SymbolGroup.GroupedBy(), as it conceptually does the same thing.
25 # One could also thing of this as GroupedByFullName().
13 def ClusterSymbols(symbols): 26 def ClusterSymbols(symbols):
14 # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suf fix-after-compilation 27 # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suf fix-after-compilation
15 # Example name suffixes: 28 # Example name suffixes:
16 # [clone .part.322] # GCC 29 # [clone .part.322] # GCC
17 # [clone .isra.322] # GCC 30 # [clone .isra.322] # GCC
18 # [clone .constprop.1064] # GCC 31 # [clone .constprop.1064] # GCC
19 # [clone .11064] # clang 32 # [clone .11064] # clang
20 33
21 # Step 1: Create name map, find clones, collect star syms into replacements. 34 # Step 1: Create name map, find clones, collect star syms into replacements.
22 logging.debug('Creating name -> symbol map') 35 logging.debug('Creating name -> symbol map')
23 clone_indices = [] 36 clone_indices = []
24 indices_by_full_name = {} 37 indices_by_full_name = {}
25 # (section_name, name, full_name) -> [(index, sym),...] 38 # (section_name, full_name_no_attr) -> [(index, sym),...]
26 replacements_by_tup = collections.defaultdict(list) 39 replacements_by_tup = collections.defaultdict(list)
27 for i, symbol in enumerate(symbols): 40 for i, symbol in enumerate(symbols):
28 if symbol.name.startswith('**'): 41 name = symbol.full_name
42 if not name:
43 continue
44 if name.startswith('*'):
29 # "symbol gap 3" -> "symbol gaps" 45 # "symbol gap 3" -> "symbol gaps"
30 name = re.sub(r'\s+\d+( \(.*\))?$', 's', symbol.name) 46 name = re.sub(r'\s+\d+( \(.*\))?$', 's', name)
31 replacements_by_tup[(symbol.section_name, name, None)].append((i, symbol)) 47 replacements_by_tup[(symbol.section_name, name)].append((i, symbol))
32 elif symbol.full_name: 48 elif name.endswith(']') and ' [clone ' in name:
33 if symbol.full_name.endswith(']') and ' [clone ' in symbol.full_name: 49 clone_indices.append(i)
34 clone_indices.append(i) 50 else:
35 else: 51 indices_by_full_name[name] = i
36 indices_by_full_name[symbol.full_name] = i
37 52
38 # Step 2: Collect same-named clone symbols. 53 # Step 2: Collect same-named clone symbols.
39 logging.debug('Grouping all clones') 54 logging.debug('Grouping all clones')
40 group_names_by_index = {} 55 group_names_by_index = {}
41 for i in clone_indices: 56 for i in clone_indices:
42 symbol = symbols[i] 57 symbol = symbols[i]
43 # Multiple attributes could exist, so search from left-to-right. 58 stripped_full_name = _StripCloneSuffix(symbol.full_name)
44 stripped_name = symbol.name[:symbol.name.index(' [clone ')] 59 name_tup = (symbol.section_name, stripped_full_name)
45 stripped_full_name = symbol.full_name[:symbol.full_name.index(' [clone ')]
46 name_tup = (symbol.section_name, stripped_name, stripped_full_name)
47 replacement_list = replacements_by_tup[name_tup] 60 replacement_list = replacements_by_tup[name_tup]
48 61
49 if not replacement_list: 62 if not replacement_list:
50 # First occurance, check for non-clone symbol. 63 # First occurance, check for non-clone symbol.
51 non_clone_idx = indices_by_full_name.get(stripped_name) 64 non_clone_idx = indices_by_full_name.get(stripped_full_name)
52 if non_clone_idx is not None: 65 if non_clone_idx is not None:
53 non_clone_symbol = symbols[non_clone_idx] 66 non_clone_symbol = symbols[non_clone_idx]
54 replacement_list.append((non_clone_idx, non_clone_symbol)) 67 replacement_list.append((non_clone_idx, non_clone_symbol))
55 group_names_by_index[non_clone_idx] = stripped_name 68 group_names_by_index[non_clone_idx] = stripped_full_name
56 69
57 replacement_list.append((i, symbol)) 70 replacement_list.append((i, symbol))
58 group_names_by_index[i] = stripped_name 71 group_names_by_index[i] = stripped_full_name
59 72
60 # Step 3: Undo clustering when length=1. 73 # Step 3: Undo clustering when length=1.
61 # Removing these groups means Diff() logic must know about [clone] suffix. 74 # Removing these groups means Diff() logic must know about [clone] suffix.
62 to_clear = [] 75 to_clear = []
63 for name_tup, replacement_list in replacements_by_tup.iteritems(): 76 for name_tup, replacement_list in replacements_by_tup.iteritems():
64 if len(replacement_list) == 1: 77 if len(replacement_list) == 1:
65 to_clear.append(name_tup) 78 to_clear.append(name_tup)
66 for name_tup in to_clear: 79 for name_tup in to_clear:
67 del replacements_by_tup[name_tup] 80 del replacements_by_tup[name_tup]
68 81
69 # Step 4: Replace first symbol from each cluster with a SymbolGroup. 82 # Step 4: Replace first symbol from each cluster with a SymbolGroup.
70 before_symbol_count = sum(len(x) for x in replacements_by_tup.itervalues()) 83 before_symbol_count = sum(len(x) for x in replacements_by_tup.itervalues())
71 logging.debug('Creating %d symbol groups from %d symbols. %d clones had only ' 84 logging.debug('Creating %d symbol groups from %d symbols. %d clones had only '
72 'one symbol.', len(replacements_by_tup), before_symbol_count, 85 'one symbol.', len(replacements_by_tup), before_symbol_count,
73 len(to_clear)) 86 len(to_clear))
74 87
75 len_delta = len(replacements_by_tup) - before_symbol_count 88 len_delta = len(replacements_by_tup) - before_symbol_count
76 grouped_symbols = [None] * (len(symbols) + len_delta) 89 grouped_symbols = [None] * (len(symbols) + len_delta)
77 dest_index = 0 90 dest_index = 0
78 src_index = 0 91 src_index = 0
79 seen_tups = set() 92 seen_tups = set()
80 replacement_tup_by_index = {} 93 index_and_name_tups = []
81 for name_tup, replacement_list in replacements_by_tup.iteritems(): 94 for name_tup, replacement_list in replacements_by_tup.iteritems():
82 for tup in replacement_list: 95 for symbol_tup in replacement_list:
83 replacement_tup_by_index[tup[0]] = name_tup 96 index_and_name_tups.append((symbol_tup[0], name_tup))
84 97
85 sorted_items = replacement_tup_by_index.items() 98 index_and_name_tups.sort(key=lambda tup: tup[0])
86 sorted_items.sort(key=lambda tup: tup[0]) 99 for index, name_tup in index_and_name_tups:
87 for index, name_tup in sorted_items:
88 count = index - src_index 100 count = index - src_index
89 grouped_symbols[dest_index:dest_index + count] = ( 101 grouped_symbols[dest_index:dest_index + count] = (
90 symbols[src_index:src_index + count]) 102 symbols[src_index:src_index + count])
91 src_index = index + 1 103 src_index = index + 1
92 dest_index += count 104 dest_index += count
93 if name_tup not in seen_tups: 105 if name_tup not in seen_tups:
94 seen_tups.add(name_tup) 106 seen_tups.add(name_tup)
95 group_symbols = [tup[1] for tup in replacements_by_tup[name_tup]] 107 group_symbols = [tup[1] for tup in replacements_by_tup[name_tup]]
96 grouped_symbols[dest_index] = symbols._CreateTransformed( 108 section_name, stripped_full_name = name_tup
97 group_symbols, name=name_tup[1], full_name=name_tup[2], 109 if stripped_full_name.startswith('*'):
98 section_name=name_tup[0]) 110 stripped_template_name = stripped_full_name
111 stripped_name = stripped_full_name
112 else:
113 stripped_template_name = _StripCloneSuffix(
114 group_symbols[0].template_name)
115 stripped_name = _StripCloneSuffix(group_symbols[0].name)
116 cluster = symbols._CreateTransformed(
117 group_symbols, full_name=stripped_full_name,
118 template_name=stripped_template_name, name=stripped_name,
119 section_name=section_name)
120 function_signature.InternSameNames(cluster)
121 grouped_symbols[dest_index] = cluster
99 dest_index += 1 122 dest_index += 1
100 123
101 assert len(grouped_symbols[dest_index:None]) == len(symbols[src_index:None]) 124 assert len(grouped_symbols[dest_index:None]) == len(symbols[src_index:None])
102 grouped_symbols[dest_index:None] = symbols[src_index:None] 125 grouped_symbols[dest_index:None] = symbols[src_index:None]
103 logging.debug('Finished clustering symbols.') 126 logging.debug('Finished clustering symbols.')
104 return grouped_symbols 127 return grouped_symbols
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/canned_queries.py ('k') | tools/binary_size/libsupersize/console.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698