| Index: tools/binary_size/libsupersize/models.py
|
| diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py
|
| index 18280164bfdf3b1b301216ca66563fce990f513d..e1eeacbba8c379efa500e8ea28ab5e5ce485bd78 100644
|
| --- a/tools/binary_size/libsupersize/models.py
|
| +++ b/tools/binary_size/libsupersize/models.py
|
| @@ -55,6 +55,7 @@ FLAG_STARTUP = 2
|
| FLAG_UNLIKELY = 4
|
| FLAG_REL = 8
|
| FLAG_REL_LOCAL = 16
|
| +FLAG_GENERATED_SOURCE = 32
|
|
|
|
|
| class SizeInfo(object):
|
| @@ -136,6 +137,17 @@ class BaseSymbol(object):
|
| return bool(self.flags & FLAG_ANONYMOUS)
|
|
|
| @property
|
| + def generated_source(self):
|
| + return bool(self.flags & FLAG_GENERATED_SOURCE)
|
| +
|
| + @generated_source.setter
|
| + def generated_source(self, value):
|
| + if value:
|
| + self.flags |= FLAG_GENERATED_SOURCE
|
| + else:
|
| + self.flags &= ~FLAG_GENERATED_SOURCE
|
| +
|
| + @property
|
| def num_aliases(self):
|
| return len(self.aliases) if self.aliases else 1
|
|
|
| @@ -155,6 +167,8 @@ class BaseSymbol(object):
|
| parts.append('rel')
|
| if flags & FLAG_REL_LOCAL:
|
| parts.append('rel.loc')
|
| + if flags & FLAG_GENERATED_SOURCE:
|
| + parts.append('gen')
|
| # Not actually a part of flags, but useful to show it here.
|
| if self.aliases:
|
| parts.append('{} aliases'.format(self.num_aliases))
|
| @@ -166,10 +180,9 @@ class BaseSymbol(object):
|
| def IsGroup(self):
|
| return False
|
|
|
| - def IsGenerated(self):
|
| - # TODO(agrieve): Also match generated functions such as:
|
| - # startup._GLOBAL__sub_I_page_allocator.cc
|
| - return self.name.endswith(']') and not self.name.endswith('[]')
|
| + def IsGeneratedByToolchain(self):
|
| + return '.' in self.name or (
|
| + self.name.endswith(']') and not self.name.endswith('[]'))
|
|
|
|
|
| class Symbol(BaseSymbol):
|
| @@ -302,22 +315,22 @@ class SymbolGroup(BaseSymbol):
|
|
|
| @property
|
| def address(self):
|
| - first = self._symbols[0].address
|
| + first = self._symbols[0].address if self else 0
|
| return first if all(s.address == first for s in self._symbols) else 0
|
|
|
| @property
|
| def flags(self):
|
| - first = self._symbols[0].flags
|
| + first = self._symbols[0].flags if self else 0
|
| return first if all(s.flags == first for s in self._symbols) else 0
|
|
|
| @property
|
| def object_path(self):
|
| - first = self._symbols[0].object_path
|
| + first = self._symbols[0].object_path if self else ''
|
| return first if all(s.object_path == first for s in self._symbols) else ''
|
|
|
| @property
|
| def source_path(self):
|
| - first = self._symbols[0].source_path
|
| + first = self._symbols[0].source_path if self else ''
|
| return first if all(s.source_path == first for s in self._symbols) else ''
|
|
|
| def IterUniqueSymbols(self):
|
| @@ -384,10 +397,9 @@ class SymbolGroup(BaseSymbol):
|
| return self._CreateTransformed(cluster_symbols.ClusterSymbols(self))
|
|
|
| def Sorted(self, cmp_func=None, key=None, reverse=False):
|
| - # Default to sorting by abs(size) then name.
|
| if cmp_func is None and key is None:
|
| - cmp_func = lambda a, b: cmp((a.IsBss(), abs(b.size), a.name),
|
| - (b.IsBss(), abs(a.size), b.name))
|
| + cmp_func = lambda a, b: cmp((a.IsBss(), abs(b.pss), a.name),
|
| + (b.IsBss(), abs(a.pss), b.name))
|
|
|
| after_symbols = sorted(self._symbols, cmp_func, key, reverse)
|
| return self._CreateTransformed(
|
| @@ -398,7 +410,8 @@ class SymbolGroup(BaseSymbol):
|
| return self.Sorted(key=(lambda s:s.name), reverse=reverse)
|
|
|
| def SortedByAddress(self, reverse=False):
|
| - return self.Sorted(key=(lambda s:s.address), reverse=reverse)
|
| + return self.Sorted(key=(lambda s:(s.address, s.object_path, s.name)),
|
| + reverse=reverse)
|
|
|
| def SortedByCount(self, reverse=False):
|
| return self.Sorted(key=(lambda s:len(s) if s.IsGroup() else 1),
|
| @@ -430,13 +443,20 @@ class SymbolGroup(BaseSymbol):
|
| ret.section_name = section
|
| return ret
|
|
|
| - def WhereIsGenerated(self):
|
| - return self.Filter(lambda s: s.IsGenerated())
|
| + def WhereSourceIsGenerated(self):
|
| + return self.Filter(lambda s: s.generated_source)
|
| +
|
| + def WhereGeneratedByToolchain(self):
|
| + return self.Filter(lambda s: s.IsGeneratedByToolchain())
|
|
|
| def WhereNameMatches(self, pattern):
|
| regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
|
| return self.Filter(lambda s: regex.search(s.name))
|
|
|
| + def WhereFullNameMatches(self, pattern):
|
| + regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
|
| + return self.Filter(lambda s: regex.search(s.full_name or s.name))
|
| +
|
| def WhereObjectPathMatches(self, pattern):
|
| regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
|
| return self.Filter(lambda s: regex.search(s.object_path))
|
| @@ -469,6 +489,9 @@ class SymbolGroup(BaseSymbol):
|
| end = start + 1
|
| return self.Filter(lambda s: s.address >= start and s.address < end)
|
|
|
| + def WhereHasPath(self):
|
| + return self.Filter(lambda s: s.source_path or s.object_path)
|
| +
|
| def WhereHasAnyAttribution(self):
|
| return self.Filter(lambda s: s.name or s.source_path or s.object_path)
|
|
|
| @@ -519,9 +542,11 @@ class SymbolGroup(BaseSymbol):
|
| after_syms.extend(symbols)
|
| else:
|
| filtered_symbols.extend(symbols)
|
| - return self._CreateTransformed(
|
| + grouped = self._CreateTransformed(
|
| after_syms, filtered_symbols=filtered_symbols,
|
| section_name=self.section_name, is_sorted=False)
|
| + # Grouping is rarely an intermediate step, so assume sorting is useful.
|
| + return grouped.Sorted()
|
|
|
| def GroupBySectionName(self):
|
| return self.GroupBy(lambda s: s.section_name)
|
| @@ -556,8 +581,8 @@ class SymbolGroup(BaseSymbol):
|
| return _ExtractPrefixBeforeSeparator(name, '::', depth)
|
| return self.GroupBy(extract_namespace, min_count=min_count)
|
|
|
| - def GroupBySourcePath(self, depth=0, fallback='{no path}',
|
| - fallback_to_object_path=True, min_count=0):
|
| + def GroupByPath(self, depth=0, fallback='{no path}',
|
| + fallback_to_object_path=True, min_count=0):
|
| """Groups by source_path.
|
|
|
| Args:
|
| @@ -579,23 +604,6 @@ class SymbolGroup(BaseSymbol):
|
| return _ExtractPrefixBeforeSeparator(path, os.path.sep, depth)
|
| return self.GroupBy(extract_path, min_count=min_count)
|
|
|
| - def GroupByObjectPath(self, depth=0, fallback='{no path}', min_count=0):
|
| - """Groups by object_path.
|
| -
|
| - Args:
|
| - depth: When 0 (default), groups by entire path. When 1, groups by
|
| - top-level directory, when 2, groups by top 2 directories, etc.
|
| - fallback: Use this value when no namespace exists.
|
| - min_count: Miniumum number of symbols for a group. If fewer than this many
|
| - symbols end up in a group, they will not be put within a group.
|
| - Use a negative value to omit symbols entirely rather than
|
| - include them outside of a group.
|
| - """
|
| - def extract_path(symbol):
|
| - path = symbol.object_path or fallback
|
| - return _ExtractPrefixBeforeSeparator(path, os.path.sep, depth)
|
| - return self.GroupBy(extract_path, min_count=min_count)
|
| -
|
|
|
| class SymbolDiff(SymbolGroup):
|
| """A SymbolGroup subclass representing a diff of two other SymbolGroups.
|
|
|