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

Jordan Rose jordan_rose at apple.com
Fri Dec 7 09:47:49 PST 2012


Yuck. Can we push this up to ASTContext or AnalysisManager?

Also, it seems like a waste to double the size of every value in the map by using Optional, even if you would otherwise need to do two lookups (first find() and then insert()) in the slow case.


On Dec 6, 2012, at 23:30 , Ted Kremenek <kremenek at apple.com> wrote:

> 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
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list