From: Jordy Rose Date: Sun, 18 Mar 2012 01:26:10 +0000 (+0000) Subject: [analyzer] Use a FoldingSet to cache simple RetainSummary instances, rather than... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ef94588752babc1b7c46b955e57945fc4c183db2;p=clang [analyzer] Use a FoldingSet to cache simple RetainSummary instances, rather than explicitly keeping DoNothing and StopTracking summaries and nothing else. I tried to test the effects of this change on memory usage and run time, but what I saw on retain-release.m was indistinguishable from noise (debug and release builds). Even so, some caveman profiling showed 101 cache hits that we would have generated new summaries for before (i.e. not default or stop summaries), and the more code we analyze, the more memory we should save. Maybe we should have a standard project for benchmarking the retain count checker's memory and time? git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153007 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index dae115ba49..b06a50d856 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -132,6 +132,11 @@ public: static RetEffect MakeNoRet() { return RetEffect(NoRet); } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ID.AddInteger((unsigned) K); + ID.AddInteger((unsigned) O); + } }; //===----------------------------------------------------------------------===// @@ -352,7 +357,7 @@ struct ProgramStateTrait namespace { class RetainSummary { - /// Args - an ordered vector of (index, ArgEffect) pairs, where index + /// Args - a map of (index, ArgEffect) pairs, where index /// specifies the argument (starting from 0). This can be sparsely /// populated; arguments with no entry in Args use 'DefaultArgEffect'. ArgEffects Args; @@ -413,6 +418,19 @@ public: return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect && Receiver == Other.Receiver && Ret == Other.Ret; } + + /// Profile this summary for inclusion in a FoldingSet. + void Profile(llvm::FoldingSetNodeID& ID) const { + ID.Add(Args); + ID.Add(DefaultArgEffect); + ID.Add(Receiver); + ID.Add(Ret); + } + + /// A retain summary is simple if it has no ArgEffects other than the default. + bool isSimple() const { + return Args.isEmpty(); + } }; } // end anonymous namespace @@ -554,6 +572,8 @@ class RetainSummaryManager { typedef ObjCSummaryCache ObjCMethodSummariesTy; + typedef llvm::FoldingSetNodeWrapper CachedSummaryNode; + //==-----------------------------------------------------------------==// // Data. //==-----------------------------------------------------------------==// @@ -595,8 +615,9 @@ class RetainSummaryManager { /// Objective-C objects. RetEffect ObjCInitRetE; - RetainSummary DefaultSummary; - const RetainSummary *StopSummary; + /// SimpleSummaries - Used for uniquing summaries that don't have special + /// effects. + llvm::FoldingSet SimpleSummaries; //==-----------------------------------------------------------------==// // Methods. @@ -610,10 +631,6 @@ class RetainSummaryManager { public: RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; } - - const RetainSummary *getDefaultSummary() { - return &DefaultSummary; - } const RetainSummary *getUnarySummary(const FunctionType* FT, UnaryFuncKind func); @@ -622,24 +639,23 @@ public: const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD); const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD); - const RetainSummary *getPersistentSummary(ArgEffects AE, RetEffect RetEff, - ArgEffect ReceiverEff = DoNothing, - ArgEffect DefaultEff = MayEscape); + const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm); - const RetainSummary *getPersistentSummary(RetEffect RE, + const RetainSummary *getPersistentSummary(RetEffect RetEff, ArgEffect ReceiverEff = DoNothing, ArgEffect DefaultEff = MayEscape) { - return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff); + RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff); + return getPersistentSummary(Summ); } - const RetainSummary *getPersistentStopSummary() { - if (StopSummary) - return StopSummary; - - StopSummary = getPersistentSummary(RetEffect::MakeNoRet(), - StopTracking, StopTracking); + const RetainSummary *getDefaultSummary() { + return getPersistentSummary(RetEffect::MakeNoRet(), + DoNothing, MayEscape); + } - return StopSummary; + const RetainSummary *getPersistentStopSummary() { + return getPersistentSummary(RetEffect::MakeNoRet(), + StopTracking, StopTracking); } void InitializeClassMethodSummaries(); @@ -718,13 +734,7 @@ public: ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned() : (usesARC ? RetEffect::MakeARCNotOwned() - : RetEffect::MakeOwnedWhenTrackedReceiver())), - DefaultSummary(AF.getEmptyMap() /* per-argument effects (none) */, - RetEffect::MakeNoRet() /* return effect */, - MayEscape, /* default argument effect */ - DoNothing /* receiver effect */), - StopSummary(0) { - + : RetEffect::MakeOwnedWhenTrackedReceiver())) { InitializeClassMethodSummaries(); InitializeMethodSummaries(); } @@ -789,12 +799,6 @@ public: bool isARCEnabled() const { return ARCEnabled; } bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; } - - const RetainSummary *copySummary(const RetainSummary *OldSumm) { - RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate(); - new (Summ) RetainSummary(*OldSumm); - return Summ; - } }; // Used to avoid allocating long-term (BPAlloc'd) memory for default retain @@ -814,7 +818,7 @@ public: ~RetainSummaryTemplate() { if (Accessed) - RealSummary = Manager.copySummary(&ScratchSummary); + RealSummary = Manager.getPersistentSummary(ScratchSummary); } RetainSummary &operator*() { @@ -841,12 +845,26 @@ ArgEffects RetainSummaryManager::getArgEffects() { } const RetainSummary * -RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff, - ArgEffect ReceiverEff, - ArgEffect DefaultEff) { - // Create the summary and return it. +RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) { + // Unique "simple" summaries -- those without ArgEffects. + if (OldSumm.isSimple()) { + llvm::FoldingSetNodeID ID; + OldSumm.Profile(ID); + + void *Pos; + CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos); + + if (!N) { + N = (CachedSummaryNode *) BPAlloc.Allocate(); + new (N) CachedSummaryNode(OldSumm); + SimpleSummaries.InsertNode(N, Pos); + } + + return &N->getValue(); + } + RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate(); - new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff); + new (Summ) RetainSummary(OldSumm); return Summ; } @@ -1119,7 +1137,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, if (!FD) return; - RetainSummaryTemplate Template(Summ, DefaultSummary, *this); + RetainSummaryTemplate Template(Summ, *getDefaultSummary(), *this); // Effects on the parameters. unsigned parm_idx = 0; @@ -1167,7 +1185,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, if (!MD) return; - RetainSummaryTemplate Template(Summ, DefaultSummary, *this); + RetainSummaryTemplate Template(Summ, *getDefaultSummary(), *this); bool isTrackedLoc = false; // Effects on the receiver.