[cfe-commits] r169589 - /cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp

Ted Kremenek kremenek at apple.com
Thu Dec 6 23:30:19 PST 2012


Author: kremenek
Date: Fri Dec  7 01:30:19 2012
New Revision: 169589

URL: http://llvm.org/viewvc/llvm-project?rev=169589&view=rev
Log:
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%.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=169589&r1=169588&r2=169589&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Fri Dec  7 01:30:19 2012
@@ -835,7 +835,35 @@
     // 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





More information about the cfe-commits mailing list