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. |