Skip to content

Commit 5390c5a

Browse files
committed
[libc++] Add caching for feature-detection Lit tests
This significantly speeds up the configuration of libc++'s test suite by making sure that we don't perform the same operations over and over again. Differential Revision: https://reviews.llvm.org/D89003
1 parent 66face6 commit 5390c5a

File tree

1 file changed

+26
-7
lines changed
  • libcxx/utils/libcxx/test

1 file changed

+26
-7
lines changed

libcxx/utils/libcxx/test/dsl.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,27 @@
2020
import lit.util
2121

2222

23-
def _memoize(f):
24-
cache = dict()
25-
def memoized(x):
26-
if x not in cache:
27-
cache[x] = f(x)
28-
return cache[x]
29-
return memoized
23+
def _memoizeExpensiveOperation(extractCacheKey):
24+
"""
25+
Allows memoizing a very expensive operation.
26+
27+
The caching is implemented as a list, and we search linearly for existing
28+
entries. This is incredibly naive, however this allows the cache keys to
29+
contain lists and other non-hashable objects. Assuming the operation we're
30+
memoizing is very expensive, this is still a win anyway.
31+
"""
32+
def decorator(function):
33+
cache = []
34+
def f(*args, **kwargs):
35+
cacheKey = extractCacheKey(*args, **kwargs)
36+
try:
37+
result = next(res for (key, res) in cache if key == cacheKey)
38+
except StopIteration: # This wasn't in the cache
39+
result = function(*args, **kwargs)
40+
cache.append((cacheKey, result))
41+
return result
42+
return f
43+
return decorator
3044

3145
def _executeScriptInternal(test, commands):
3246
"""
@@ -72,6 +86,7 @@ def __enter__(self): return self
7286
def __exit__(self, *args): os.remove(tmp.name)
7387
return TestWrapper(suite, pathInSuite, config)
7488

89+
@_memoizeExpensiveOperation(lambda c, s: (c.substitutions, c.environment, s))
7590
def sourceBuilds(config, source):
7691
"""
7792
Return whether the program in the given string builds successfully.
@@ -88,6 +103,7 @@ def sourceBuilds(config, source):
88103
_executeScriptInternal(test, ['rm %t.exe'])
89104
return exitCode == 0
90105

106+
@_memoizeExpensiveOperation(lambda c, p, args=None, testPrefix='': (c.substitutions, c.environment, p, args))
91107
def programOutput(config, program, args=None, testPrefix=''):
92108
"""
93109
Compiles a program for the test target, run it on the test target and return
@@ -122,6 +138,7 @@ def programOutput(config, program, args=None, testPrefix=''):
122138
finally:
123139
_executeScriptInternal(test, ['rm %t.exe'])
124140

141+
@_memoizeExpensiveOperation(lambda c, f: (c.substitutions, c.environment, f))
125142
def hasCompileFlag(config, flag):
126143
"""
127144
Return whether the compiler in the configuration supports a given compiler flag.
@@ -135,6 +152,7 @@ def hasCompileFlag(config, flag):
135152
])
136153
return exitCode == 0
137154

155+
@_memoizeExpensiveOperation(lambda c, l: (c.substitutions, c.environment, l))
138156
def hasLocale(config, locale):
139157
"""
140158
Return whether the runtime execution environment supports a given locale.
@@ -153,6 +171,7 @@ def hasLocale(config, locale):
153171
return programOutput(config, program, args=[pipes.quote(locale)],
154172
testPrefix="check_locale_" + locale) is not None
155173

174+
@_memoizeExpensiveOperation(lambda c, flags='': (c.substitutions, c.environment, flags))
156175
def compilerMacros(config, flags=''):
157176
"""
158177
Return a dictionary of predefined compiler macros.

0 commit comments

Comments
 (0)