r175233 - [analyzer] Cache the bindings accessible through a LazyCompoundVal.

Jordan Rose jordan_rose at apple.com
Thu Feb 14 16:32:12 PST 2013


Author: jrose
Date: Thu Feb 14 18:32:12 2013
New Revision: 175233

URL: http://llvm.org/viewvc/llvm-project?rev=175233&view=rev
Log:
[analyzer] Cache the bindings accessible through a LazyCompoundVal.

This means we don't have to recompute them all later for every
removeDeadSymbols check.

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

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=175233&r1=175232&r2=175233&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Thu Feb 14 18:32:12 2013
@@ -323,6 +323,13 @@ public:
   RegionBindings::Factory RBFactory;
   mutable ClusterBindings::Factory CBFactory;
 
+  typedef std::vector<SVal> SValListTy;
+private:
+  typedef llvm::DenseMap<const LazyCompoundValData *,
+                         SValListTy> LazyBindingsMapTy;
+  LazyBindingsMapTy LazyBindingsMap;
+
+public:
   RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
     : StoreManager(mgr), Features(f),
       RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()) {}
@@ -495,6 +502,14 @@ public: // Part of public interface to c
   getLazyBinding(RegionBindingsConstRef B, const MemRegion *R,
                  const MemRegion *originalRegion);
 
+  /// Returns the cached set of interesting SVals contained within a lazy
+  /// binding.
+  ///
+  /// The precise value of "interesting" is determined for the purposes of
+  /// RegionStore's internal analysis. It must always contain all regions and
+  /// symbols, but may omit constants and other kinds of SVal.
+  const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
+
   //===------------------------------------------------------------------===//
   // State pruning.
   //===------------------------------------------------------------------===//
@@ -878,23 +893,12 @@ void invalidateRegionsWorker::VisitBindi
   if (const nonloc::LazyCompoundVal *LCS =
         dyn_cast<nonloc::LazyCompoundVal>(&V)) {
 
-    const MemRegion *LazyR = LCS->getRegion();
-    RegionBindingsRef B = RM.getRegionBindings(LCS->getStore());
+    const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
 
-    // FIXME: This should not have to walk all bindings in the old store.
-    for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
-      const ClusterBindings &Cluster = RI.getData();
-      for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
-           CI != CE; ++CI) {
-        BindingKey K = CI.getKey();
-        if (const SubRegion *BaseR = dyn_cast<SubRegion>(K.getRegion())) {
-          if (BaseR == LazyR)
-            VisitBinding(CI.getData());
-          else if (K.hasSymbolicOffset() && BaseR->isSubRegionOf(LazyR))
-            VisitBinding(CI.getData());
-        }
-      }
-    }
+    for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
+                                                        E = Vals.end();
+         I != E; ++I)
+      VisitBinding(*I);
 
     return;
   }
@@ -1595,6 +1599,49 @@ SVal RegionStoreManager::getBindingForLa
   return svalBuilder.getRegionValueSymbolVal(R);
 }
 
+const RegionStoreManager::SValListTy &
+RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
+  // First, check the cache.
+  LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
+  if (I != LazyBindingsMap.end())
+    return I->second;
+
+  // If we don't have a list of values cached, start constructing it.
+  SValListTy &List = LazyBindingsMap[LCV.getCVData()];
+
+  const SubRegion *LazyR = LCV.getRegion();
+  RegionBindingsRef B = getRegionBindings(LCV.getStore());
+
+  // If this region had /no/ bindings at the time, there are no interesting
+  // values to return.
+  const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
+  if (!Cluster)
+    return List;
+
+  SmallVector<BindingKey, 32> Keys;
+  collectSubRegionKeys(Keys, svalBuilder, *Cluster, LazyR,
+                       /*IncludeAllDefaultBindings=*/true);
+  for (SmallVectorImpl<BindingKey>::const_iterator I = Keys.begin(),
+                                                   E = Keys.end();
+       I != E; ++I) {
+    SVal V = *Cluster->lookup(*I);
+    if (V.isUnknownOrUndef() || V.isConstant())
+      continue;
+
+    const nonloc::LazyCompoundVal *InnerLCV =
+      dyn_cast<nonloc::LazyCompoundVal>(&V);
+    if (InnerLCV) {
+      const SValListTy &InnerList = getInterestingValues(*InnerLCV);
+      List.insert(List.end(), InnerList.begin(), InnerList.end());
+      continue;
+    }
+    
+    List.push_back(V);
+  }
+
+  return List;
+}
+
 NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
                                              const TypedValueRegion *R) {
   // If we already have a lazy binding, and it's for the whole structure,
@@ -1991,21 +2038,12 @@ void removeDeadBindingsWorker::VisitBind
   if (const nonloc::LazyCompoundVal *LCS =
         dyn_cast<nonloc::LazyCompoundVal>(&V)) {
 
-    const SubRegion *LazyR = LCS->getRegion();
-    RegionBindingsRef B = RM.getRegionBindings(LCS->getStore());
+    const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
 
-    const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
-    if (!Cluster)
-      return;
-
-    SmallVector<BindingKey, 32> Keys;
-    collectSubRegionKeys(Keys, svalBuilder, *Cluster, LazyR,
-                         /*IncludeAllDefaultBindings=*/true);
-    for (SmallVectorImpl<BindingKey>::const_iterator I = Keys.begin(),
-                                                     E = Keys.end();
-         I != E; ++I) {
-      VisitBinding(*Cluster->lookup(*I));
-    }
+    for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
+                                                        E = Vals.end();
+         I != E; ++I)
+      VisitBinding(*I);
 
     return;
   }





More information about the cfe-commits mailing list