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

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: canned query 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
13 def ClusterSymbols(symbols): 23 def ClusterSymbols(symbols):
14 # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suf fix-after-compilation 24 # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suf fix-after-compilation
15 # Example name suffixes: 25 # Example name suffixes:
16 # [clone .part.322] # GCC 26 # [clone .part.322] # GCC
17 # [clone .isra.322] # GCC 27 # [clone .isra.322] # GCC
18 # [clone .constprop.1064] # GCC 28 # [clone .constprop.1064] # GCC
19 # [clone .11064] # clang 29 # [clone .11064] # clang
20 30
21 # Step 1: Create name map, find clones, collect star syms into replacements. 31 # Step 1: Create name map, find clones, collect star syms into replacements.
22 logging.debug('Creating name -> symbol map') 32 logging.debug('Creating name -> symbol map')
23 clone_indices = [] 33 clone_indices = []
24 indices_by_full_name = {} 34 indices_by_full_name = {}
25 # (section_name, name, full_name) -> [(index, sym),...] 35 # (section_name, full_name_no_attr) -> [(index, sym),...]
26 replacements_by_tup = collections.defaultdict(list) 36 replacements_by_tup = collections.defaultdict(list)
27 for i, symbol in enumerate(symbols): 37 for i, symbol in enumerate(symbols):
28 if symbol.name.startswith('**'): 38 name = symbol.full_name
39 if not name:
40 continue
41 if name.startswith('*'):
29 # "symbol gap 3" -> "symbol gaps" 42 # "symbol gap 3" -> "symbol gaps"
30 name = re.sub(r'\s+\d+( \(.*\))?$', 's', symbol.name) 43 name = re.sub(r'\s+\d+( \(.*\))?$', 's', name)
31 replacements_by_tup[(symbol.section_name, name, None)].append((i, symbol)) 44 replacements_by_tup[(symbol.section_name, name)].append((i, symbol))
32 elif symbol.full_name: 45 elif name.endswith(']') and ' [clone ' in name:
33 if symbol.full_name.endswith(']') and ' [clone ' in symbol.full_name: 46 clone_indices.append(i)
34 clone_indices.append(i) 47 else:
35 else: 48 indices_by_full_name[name] = i
36 indices_by_full_name[symbol.full_name] = i
37 49
38 # Step 2: Collect same-named clone symbols. 50 # Step 2: Collect same-named clone symbols.
39 logging.debug('Grouping all clones') 51 logging.debug('Grouping all clones')
40 group_names_by_index = {} 52 group_names_by_index = {}
41 for i in clone_indices: 53 for i in clone_indices:
42 symbol = symbols[i] 54 symbol = symbols[i]
43 # Multiple attributes could exist, so search from left-to-right. 55 stripped_full_name = _StripCloneSuffix(symbol.full_name)
44 stripped_name = symbol.name[:symbol.name.index(' [clone ')] 56 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] 57 replacement_list = replacements_by_tup[name_tup]
48 58
49 if not replacement_list: 59 if not replacement_list:
50 # First occurance, check for non-clone symbol. 60 # First occurance, check for non-clone symbol.
51 non_clone_idx = indices_by_full_name.get(stripped_name) 61 non_clone_idx = indices_by_full_name.get(stripped_full_name)
52 if non_clone_idx is not None: 62 if non_clone_idx is not None:
53 non_clone_symbol = symbols[non_clone_idx] 63 non_clone_symbol = symbols[non_clone_idx]
54 replacement_list.append((non_clone_idx, non_clone_symbol)) 64 replacement_list.append((non_clone_idx, non_clone_symbol))
55 group_names_by_index[non_clone_idx] = stripped_name 65 group_names_by_index[non_clone_idx] = stripped_full_name
56 66
57 replacement_list.append((i, symbol)) 67 replacement_list.append((i, symbol))
58 group_names_by_index[i] = stripped_name 68 group_names_by_index[i] = stripped_full_name
59 69
60 # Step 3: Undo clustering when length=1. 70 # Step 3: Undo clustering when length=1.
61 # Removing these groups means Diff() logic must know about [clone] suffix. 71 # Removing these groups means Diff() logic must know about [clone] suffix.
62 to_clear = [] 72 to_clear = []
63 for name_tup, replacement_list in replacements_by_tup.iteritems(): 73 for name_tup, replacement_list in replacements_by_tup.iteritems():
64 if len(replacement_list) == 1: 74 if len(replacement_list) == 1:
65 to_clear.append(name_tup) 75 to_clear.append(name_tup)
66 for name_tup in to_clear: 76 for name_tup in to_clear:
67 del replacements_by_tup[name_tup] 77 del replacements_by_tup[name_tup]
68 78
69 # Step 4: Replace first symbol from each cluster with a SymbolGroup. 79 # 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()) 80 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 ' 81 logging.debug('Creating %d symbol groups from %d symbols. %d clones had only '
72 'one symbol.', len(replacements_by_tup), before_symbol_count, 82 'one symbol.', len(replacements_by_tup), before_symbol_count,
73 len(to_clear)) 83 len(to_clear))
74 84
75 len_delta = len(replacements_by_tup) - before_symbol_count 85 len_delta = len(replacements_by_tup) - before_symbol_count
76 grouped_symbols = [None] * (len(symbols) + len_delta) 86 grouped_symbols = [None] * (len(symbols) + len_delta)
77 dest_index = 0 87 dest_index = 0
78 src_index = 0 88 src_index = 0
79 seen_tups = set() 89 seen_tups = set()
80 replacement_tup_by_index = {} 90 index_and_name_tups = []
estevenson 2017/05/09 22:15:12 I find this function hard to grok, basically had t
agrieve 2017/05/10 00:51:38 likewise. For now I've just added a TODO comment t
81 for name_tup, replacement_list in replacements_by_tup.iteritems(): 91 for name_tup, replacement_list in replacements_by_tup.iteritems():
82 for tup in replacement_list: 92 for symbol_tup in replacement_list:
83 replacement_tup_by_index[tup[0]] = name_tup 93 index_and_name_tups.append((symbol_tup[0], name_tup))
84 94
85 sorted_items = replacement_tup_by_index.items() 95 index_and_name_tups.sort(key=lambda tup: tup[0])
86 sorted_items.sort(key=lambda tup: tup[0]) 96 for index, name_tup in index_and_name_tups:
87 for index, name_tup in sorted_items:
88 count = index - src_index 97 count = index - src_index
89 grouped_symbols[dest_index:dest_index + count] = ( 98 grouped_symbols[dest_index:dest_index + count] = (
90 symbols[src_index:src_index + count]) 99 symbols[src_index:src_index + count])
91 src_index = index + 1 100 src_index = index + 1
92 dest_index += count 101 dest_index += count
93 if name_tup not in seen_tups: 102 if name_tup not in seen_tups:
94 seen_tups.add(name_tup) 103 seen_tups.add(name_tup)
95 group_symbols = [tup[1] for tup in replacements_by_tup[name_tup]] 104 group_symbols = [tup[1] for tup in replacements_by_tup[name_tup]]
96 grouped_symbols[dest_index] = symbols._CreateTransformed( 105 section_name, stripped_full_name = name_tup
97 group_symbols, name=name_tup[1], full_name=name_tup[2], 106 if stripped_full_name.startswith('*'):
98 section_name=name_tup[0]) 107 stripped_template_name = stripped_full_name
108 stripped_name = stripped_full_name
109 else:
110 stripped_template_name = _StripCloneSuffix(
111 group_symbols[0].template_name)
112 stripped_name = _StripCloneSuffix(group_symbols[0].name)
113 cluster = symbols._CreateTransformed(
114 group_symbols, full_name=stripped_full_name,
115 template_name=stripped_template_name, name=stripped_name,
116 section_name=section_name)
117 function_signature.InternSameNames(cluster)
118 grouped_symbols[dest_index] = cluster
99 dest_index += 1 119 dest_index += 1
100 120
101 assert len(grouped_symbols[dest_index:None]) == len(symbols[src_index:None]) 121 assert len(grouped_symbols[dest_index:None]) == len(symbols[src_index:None])
102 grouped_symbols[dest_index:None] = symbols[src_index:None] 122 grouped_symbols[dest_index:None] = symbols[src_index:None]
103 logging.debug('Finished clustering symbols.') 123 logging.debug('Finished clustering symbols.')
104 return grouped_symbols 124 return grouped_symbols
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698