diff options
| author | Ted Kremenek <kremenek@apple.com> | 2012-12-07 07:30:19 +0000 |
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2012-12-07 07:30:19 +0000 |
| commit | 245e45af7daa5ef8cb8b529906f4be807d2169a3 (patch) | |
| tree | 233fe0a554a5b38523e74f86c6cdc8596ee7010f | |
| parent | c818bbb8b283739934f42f328711bbd900984c8d (diff) | |
| download | bcm5719-llvm-245e45af7daa5ef8cb8b529906f4be807d2169a3.tar.gz bcm5719-llvm-245e45af7daa5ef8cb8b529906f4be807d2169a3.zip | |
Cache queries to lookupPrivateMethod() within ObjCMethodCall::getRuntimeDefinition().
The same queries can happen thousands of times. This reduces the analysis
time on one heavy Objective-C file by 2.4%.
llvm-svn: 169589
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 57f2f3355d9..60b4d988d68 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -835,7 +835,35 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { // Lookup the method implementation. if (ReceiverT) if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterfaceDecl()) { - const ObjCMethodDecl *MD = IDecl->lookupPrivateMethod(Sel); + // Repeatedly calling lookupPrivateMethod() is expensive, especially + // when in many cases it returns null. We cache the results so + // that repeated queries on the same ObjCIntefaceDecl and Selector + // don't incur the same cost. On some test cases, we can see the + // same query being issued thousands of times. + // + // NOTE: This cache is essentially a "global" variable, but it + // only gets lazily created when we get here. The value of the + // cache probably comes from it being global across ExprEngines, + // where the same queries may get issued. If we are worried about + // concurrency, or possibly loading/unloading ASTs, etc., we may + // need to revisit this someday. In terms of memory, this table + // stays around until clang quits, which also may be bad if we + // need to release memory. + typedef std::pair<const ObjCInterfaceDecl*, Selector> + PrivateMethodKey; + typedef llvm::DenseMap<PrivateMethodKey, + llvm::Optional<const ObjCMethodDecl *> > + PrivateMethodCache; + + static PrivateMethodCache PMC; + llvm::Optional<const ObjCMethodDecl *> &Val = + PMC[std::make_pair(IDecl, Sel)]; + + // Query lookupPrivateMethod() if the cache does not hit. + if (!Val.hasValue()) + Val = IDecl->lookupPrivateMethod(Sel); + + const ObjCMethodDecl *MD = Val.getValue(); if (CanBeSubClassed) return RuntimeDefinition(MD, Receiver); else |

