Skip to content

Commit 1855bd6

Browse files
committed
Bug 1829245 - Change how intl/component files are identified in check_vanilla_allocations. r=sfink
Differential Revision: https://phabricator.services.mozilla.com/D176102
1 parent acbe860 commit 1855bd6

File tree

1 file changed

+54
-30
lines changed

1 file changed

+54
-30
lines changed

config/check_vanilla_allocations.py

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import re
4343
import subprocess
4444
import sys
45+
from collections import defaultdict
4546

4647
import buildconfig
4748

@@ -77,11 +78,10 @@ def main():
7778
args = parser.parse_args()
7879

7980
# Run |nm|. Options:
80-
# -u: show only undefined symbols
8181
# -C: demangle symbol names
8282
# -A: show an object filename for each undefined symbol
8383
nm = buildconfig.substs.get("NM") or "nm"
84-
cmd = [nm, "-u", "-C", "-A", args.file]
84+
cmd = [nm, "-C", "-A", args.file]
8585
lines = subprocess.check_output(
8686
cmd, universal_newlines=True, stderr=subprocess.PIPE
8787
).split("\n")
@@ -110,23 +110,48 @@ def main():
110110
# This regexp matches the relevant lines in the output of |nm|, which look
111111
# like the following.
112112
#
113-
# js/src/libjs_static.a:Utility.o: U malloc
113+
# js/src/libjs_static.a:Utility.o: U malloc
114+
# js/src/libjs_static.a:Utility.o: 00000000000007e0 T js::SetSourceOptions(...)
114115
#
115-
alloc_fns_re = r"([^:/ ]+):\s+U (" + r"|".join(alloc_fns) + r")"
116+
nm_line_re = re.compile(r"([^:/ ]+):\s+[0-9a-fA-F]*\s+([TU]) (.*)")
117+
alloc_fns_re = re.compile(r"|".join(alloc_fns))
116118

117-
# This tracks which allocation/free functions have been seen in
118-
# util/Utility.cpp.
119-
util_Utility_cpp = set([])
119+
# This tracks which allocation/free functions have been seen.
120+
functions = defaultdict(set)
121+
files = defaultdict(int)
122+
123+
# Files to ignore allocation/free functions from.
124+
ignored_files = [
125+
# Ignore implicit call to operator new in std::condition_variable_any.
126+
#
127+
# From intl/icu/source/common/umutex.h:
128+
# On Linux, the default constructor of std::condition_variable_any
129+
# produces an in-line reference to global operator new(), [...].
130+
"umutex.o",
131+
# Ignore allocations from decimal conversion functions inside mozglue.
132+
"Decimal.o",
133+
# Ignore use of std::string in regexp AST debug output.
134+
"regexp-ast.o",
135+
]
136+
all_ignored_files = set((f, 1) for f in ignored_files)
120137

121138
# Would it be helpful to emit detailed line number information after a failure?
122139
emit_line_info = False
123140

141+
prev_filename = None
124142
for line in lines:
125-
m = re.search(alloc_fns_re, line)
143+
m = nm_line_re.search(line)
126144
if m is None:
127145
continue
128146

129-
filename = m.group(1)
147+
filename, symtype, fn = m.groups()
148+
if prev_filename != filename:
149+
# When the same filename appears multiple times, separated by other
150+
# file names, this denotes a different file. Thankfully, we can more
151+
# or less safely assume that dir1/Foo.o and dir2/Foo.o are not going
152+
# to be next to each other.
153+
files[filename] += 1
154+
prev_filename = filename
130155

131156
# The stdc++compat library has an implicit call to operator new in
132157
# thread::_M_start_thread.
@@ -147,30 +172,29 @@ def main():
147172
if "ProfilingStack" in filename:
148173
continue
149174

150-
# Ignore implicit call to operator new in std::condition_variable_any.
151-
#
152-
# From intl/icu/source/common/umutex.h:
153-
# On Linux, the default constructor of std::condition_variable_any
154-
# produces an in-line reference to global operator new(), [...].
155-
if filename == "umutex.o":
156-
continue
157-
158-
# Ignore allocations from decimal conversion functions inside mozglue.
159-
if filename == "Decimal.o":
160-
continue
175+
if symtype == "T":
176+
# We can't match intl/components files by file name because in
177+
# non-unified builds they overlap with files in js/src.
178+
# So we check symbols they define, and consider files with symbols
179+
# in the mozilla::intl namespace to be those.
180+
if fn.startswith("mozilla::intl::"):
181+
all_ignored_files.add((filename, files[filename]))
182+
else:
183+
m = alloc_fns_re.match(fn)
184+
if m:
185+
functions[(filename, files[filename])].add(m.group(0))
161186

162-
# Ignore allocations from the m-c intl/components implementations.
163-
if "intl_components" in filename:
164-
continue
187+
util_Utility_cpp = functions.pop(("Utility.o", 1))
188+
if ("Utility.o", 2) in functions:
189+
fail("There should be only one Utility.o file")
165190

166-
# Ignore use of std::string in regexp AST debug output.
167-
if filename == "regexp-ast.o":
168-
continue
191+
for f, n in all_ignored_files:
192+
functions.pop((f, n), None)
193+
if f in ignored_files and (f, 2) in functions:
194+
fail(f"There should be only one {f} file")
169195

170-
fn = m.group(2)
171-
if filename == "Utility.o":
172-
util_Utility_cpp.add(fn)
173-
else:
196+
for (filename, n) in sorted(functions):
197+
for fn in functions[(filename, n)]:
174198
# An allocation is present in a non-special file. Fail!
175199
fail("'" + fn + "' present in " + filename)
176200
# Try to give more precise information about the offending code.

0 commit comments

Comments
 (0)