20
20
import lit .util
21
21
22
22
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
30
44
31
45
def _executeScriptInternal (test , commands ):
32
46
"""
@@ -72,6 +86,7 @@ def __enter__(self): return self
72
86
def __exit__ (self , * args ): os .remove (tmp .name )
73
87
return TestWrapper (suite , pathInSuite , config )
74
88
89
+ @_memoizeExpensiveOperation (lambda c , s : (c .substitutions , c .environment , s ))
75
90
def sourceBuilds (config , source ):
76
91
"""
77
92
Return whether the program in the given string builds successfully.
@@ -88,6 +103,7 @@ def sourceBuilds(config, source):
88
103
_executeScriptInternal (test , ['rm %t.exe' ])
89
104
return exitCode == 0
90
105
106
+ @_memoizeExpensiveOperation (lambda c , p , args = None , testPrefix = '' : (c .substitutions , c .environment , p , args ))
91
107
def programOutput (config , program , args = None , testPrefix = '' ):
92
108
"""
93
109
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=''):
122
138
finally :
123
139
_executeScriptInternal (test , ['rm %t.exe' ])
124
140
141
+ @_memoizeExpensiveOperation (lambda c , f : (c .substitutions , c .environment , f ))
125
142
def hasCompileFlag (config , flag ):
126
143
"""
127
144
Return whether the compiler in the configuration supports a given compiler flag.
@@ -135,6 +152,7 @@ def hasCompileFlag(config, flag):
135
152
])
136
153
return exitCode == 0
137
154
155
+ @_memoizeExpensiveOperation (lambda c , l : (c .substitutions , c .environment , l ))
138
156
def hasLocale (config , locale ):
139
157
"""
140
158
Return whether the runtime execution environment supports a given locale.
@@ -153,6 +171,7 @@ def hasLocale(config, locale):
153
171
return programOutput (config , program , args = [pipes .quote (locale )],
154
172
testPrefix = "check_locale_" + locale ) is not None
155
173
174
+ @_memoizeExpensiveOperation (lambda c , flags = '' : (c .substitutions , c .environment , flags ))
156
175
def compilerMacros (config , flags = '' ):
157
176
"""
158
177
Return a dictionary of predefined compiler macros.
0 commit comments