[llvm-commits] [poolalloc] r107284 - /poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp

John Criswell criswell at uiuc.edu
Wed Jun 30 07:55:41 PDT 2010


Author: criswell
Date: Wed Jun 30 09:55:41 2010
New Revision: 107284

URL: http://llvm.org/viewvc/llvm-project?rev=107284&view=rev
Log:
Proactively modified code to avert a potential iterator invalidation error.

Modified:
    poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp

Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp?rev=107284&r1=107283&r2=107284&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Wed Jun 30 09:55:41 2010
@@ -143,23 +143,49 @@
   std::map<Function*, Function*> FuncMap;
 
   //
+  // Functions that require pool handles to be passed in as parameters will
+  // need to be cloned.  Scan through the set of all functions and record which
+  // ones need to be cloned.
+  //
+  // We record the list of functions to clone and then clone them to avoid
+  // iterator invalidation errors (creating a function clone adds a function to
+  // the set of functions in a Module).  This may be a little slower, but
+  // random memory errors are a pain to debug.
+  //
+  std::vector<Function *> FunctionsToClone;
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+    if (!I->isDeclaration() && Graphs->hasDSGraph(*I)) {
+      FunctionsToClone.push_back (I);
+    }
+  }
+
+  //
   // Now clone a function using the pool arg list obtained in the previous
   // pass over the modules.  Loop over only the function initially in the
-  // program, don't traverse newly added ones.  If the function needs new
+  // program; don't traverse newly added ones.  If the function needs new
   // arguments, make its clone.
   //
-  // FIXME: Can the code below invalidate the function iterator?
   // FIXME: Should use a isClone() method.
   //
   std::set<Function*> ClonedFunctions;
-  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
-    if (!I->isDeclaration() && !ClonedFunctions.count(I) &&
-        Graphs->hasDSGraph(*I))
-      if (Function *Clone = MakeFunctionClone(*I)) {
-        FuncMap[I] = Clone;
-        ClonedFunctions.insert(Clone);
-      }
+  while (FunctionsToClone.size()) {
+    //
+    // Remove a function from the list of functions to clone.
+    //
+    Function * Original = FunctionsToClone.back();
+    FunctionsToClone.pop_back ();
+
+    //
+    // Clone the function.  Record a pointer to the new clone if one was
+    // created.
+    //
+    if (Function *Clone = MakeFunctionClone(*Original)) {
+      FuncMap[Original] = Clone;
+      ClonedFunctions.insert(Clone);
+    }
+  }
   
+  //
   // Now that all call targets are available, rewrite the function bodies of the
   // clones or the original function (if the original has no clone).
   //
@@ -452,14 +478,13 @@
         }
       }
     }
-  }
 
-  //
-  // Mark the returned node as needing to be passed in.
-  // FIXME: We should not do this for main().
-  //
-  if (DSNode *RetNode = G->getReturnNodeFor(F).getNode())
-    RetNode->markReachableNodes(MarkedNodes);
+    //
+    // Mark the returned node as needing to be passed in.
+    //
+    if (DSNode *RetNode = G->getReturnNodeFor(F).getNode())
+      RetNode->markReachableNodes(MarkedNodes);
+  }
 
   //
   // Calculate which DSNodes are reachable from globals.  If a node is reachable





More information about the llvm-commits mailing list