[cfe-commits] r155841 - in /cfe/trunk/tools/libclang: CIndex.cpp CXCursor.cpp CXCursor.h CXTranslationUnit.h

Ted Kremenek kremenek at apple.com
Mon Apr 30 12:06:49 PDT 2012


Author: kremenek
Date: Mon Apr 30 14:06:49 2012
New Revision: 155841

URL: http://llvm.org/viewvc/llvm-project?rev=155841&view=rev
Log:
Reduce malloc() traffic of clang_getOverridenCursors() by using a pool of SmallVector<CXCursor> objects
under the covers.

Fixes <rdar://problem/11289160>.

Modified:
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/CXCursor.h
    cfe/trunk/tools/libclang/CXTranslationUnit.h

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=155841&r1=155840&r2=155841&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Apr 30 14:06:49 2012
@@ -61,6 +61,7 @@
   D->TUData = TU;
   D->StringPool = createCXStringPool();
   D->Diagnostics = 0;
+  D->OverridenCursorsPool = createOverridenCXCursorsPool();
   return D;
 }
 
@@ -2734,6 +2735,7 @@
     delete static_cast<ASTUnit *>(CTUnit->TUData);
     disposeCXStringPool(CTUnit->StringPool);
     delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
+    disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
     delete CTUnit;
   }
 }
@@ -5549,34 +5551,6 @@
   return clang_getNullCursor();
 }
 
-void clang_getOverriddenCursors(CXCursor cursor, 
-                                CXCursor **overridden,
-                                unsigned *num_overridden) {
-  if (overridden)
-    *overridden = 0;
-  if (num_overridden)
-    *num_overridden = 0;
-  if (!overridden || !num_overridden)
-    return;
-  if (!clang_isDeclaration(cursor.kind))
-    return;
-
-  SmallVector<CXCursor, 8> Overridden;
-  cxcursor::getOverriddenCursors(cursor, Overridden);
-
-  // Don't allocate memory if we have no overriden cursors.
-  if (Overridden.size() == 0)
-    return;
-
-  *num_overridden = Overridden.size();
-  *overridden = new CXCursor [Overridden.size()];
-  std::copy(Overridden.begin(), Overridden.end(), *overridden);
-}
-
-void clang_disposeOverriddenCursors(CXCursor *overridden) {
-  delete [] overridden;
-}
-
 CXFile clang_getIncludedFile(CXCursor cursor) {
   if (cursor.kind != CXCursor_InclusionDirective)
     return 0;

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=155841&r1=155840&r2=155841&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Mon Apr 30 14:06:49 2012
@@ -30,9 +30,9 @@
 using namespace clang;
 using namespace cxcursor;
 
-CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU) {
   assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
-  CXCursor C = { K, 0, { 0, 0, 0 } };
+  CXCursor C = { K, 0, { 0, 0, TU } };
   return C;
 }
 
@@ -1152,5 +1152,104 @@
   }
   return NULL;
 }
+
+namespace {
+  struct OverridenCursorsPool {
+    typedef llvm::SmallVector<CXCursor, 2> CursorVec;
+    std::vector<CursorVec*> AllCursors;
+    std::vector<CursorVec*> AvailableCursors;
+    
+    ~OverridenCursorsPool() {
+      for (std::vector<CursorVec*>::iterator I = AllCursors.begin(),
+           E = AllCursors.end(); I != E; ++I) {
+        delete *I;
+      }
+    }
+  };
+}
+
+void *cxcursor::createOverridenCXCursorsPool() {
+  return new OverridenCursorsPool();
+}
+  
+void cxcursor::disposeOverridenCXCursorsPool(void *pool) {
+  delete static_cast<OverridenCursorsPool*>(pool);
+}
+  
+void clang_getOverriddenCursors(CXCursor cursor,
+                                CXCursor **overridden,
+                                unsigned *num_overridden) {
+  if (overridden)
+    *overridden = 0;
+  if (num_overridden)
+    *num_overridden = 0;
+  
+  CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
+  
+  if (!overridden || !num_overridden || !TU)
+    return;
+
+  if (!clang_isDeclaration(cursor.kind))
+    return;
+    
+  OverridenCursorsPool &pool =
+    *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+  
+  OverridenCursorsPool::CursorVec *Vec = 0;
+  
+  if (!pool.AvailableCursors.empty()) {
+    Vec = pool.AvailableCursors.back();
+    pool.AvailableCursors.pop_back();
+  }
+  else {
+    Vec = new OverridenCursorsPool::CursorVec();
+    pool.AllCursors.push_back(Vec);
+  }
+  
+  // Clear out the vector, but don't free the memory contents.  This
+  // reduces malloc() traffic.
+  Vec->clear();
+
+  // Use the first entry to contain a back reference to the vector.
+  // This is a complete hack.
+  CXCursor backRefCursor = MakeCXCursorInvalid(CXCursor_InvalidFile, TU);
+  backRefCursor.data[0] = Vec;
+  assert(cxcursor::getCursorTU(backRefCursor) == TU);
+  Vec->push_back(backRefCursor);
+
+  // Get the overriden cursors.
+  cxcursor::getOverriddenCursors(cursor, *Vec);
+  
+  // Did we get any overriden cursors?  If not, return Vec to the pool
+  // of available cursor vectors.
+  if (Vec->size() == 1) {
+    pool.AvailableCursors.push_back(Vec);
+    return;
+  }
+
+  // Now tell the caller about the overriden cursors.
+  assert(Vec->size() > 1);
+  *overridden = &((*Vec)[1]);
+  *num_overridden = Vec->size() - 1;
+}
+
+void clang_disposeOverriddenCursors(CXCursor *overridden) {
+  if (!overridden)
+    return;
+  
+  // Use pointer arithmetic to get back the first faux entry
+  // which has a back-reference to the TU and the vector.
+  --overridden;
+  OverridenCursorsPool::CursorVec *Vec =
+    static_cast<OverridenCursorsPool::CursorVec*>(overridden->data[0]);
+  CXTranslationUnit TU = getCursorTU(*overridden);
+  
+  assert(Vec && TU);
+
+  OverridenCursorsPool &pool =
+    *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+  
+  pool.AvailableCursors.push_back(Vec);
+}
   
 } // end: extern "C"

Modified: cfe/trunk/tools/libclang/CXCursor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.h?rev=155841&r1=155840&r2=155841&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.h (original)
+++ cfe/trunk/tools/libclang/CXCursor.h Mon Apr 30 14:06:49 2012
@@ -55,7 +55,7 @@
 CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent,
                       CXTranslationUnit TU,
                       SourceRange RegionOfInterest = SourceRange());
-CXCursor MakeCXCursorInvalid(CXCursorKind K);
+CXCursor MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU = 0);
 
 /// \brief Create an Objective-C superclass reference at the given location.
 CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super, 
@@ -206,8 +206,15 @@
 CXTranslationUnit getCursorTU(CXCursor Cursor);
 
 void getOverriddenCursors(CXCursor cursor,
-                          SmallVectorImpl<CXCursor> &overridden); 
+                          SmallVectorImpl<CXCursor> &overridden);
+  
+/// \brief Create an opaque  pool used for fast generation of overriden
+/// CXCursor arrays.
+void *createOverridenCXCursorsPool();
 
+/// \brief Dispose of the overriden CXCursors pool.
+void disposeOverridenCXCursorsPool(void *pool);
+  
 /// \brief Returns a index/location pair for a selector identifier if the cursor
 /// points to one.
 std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);

Modified: cfe/trunk/tools/libclang/CXTranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTranslationUnit.h?rev=155841&r1=155840&r2=155841&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXTranslationUnit.h (original)
+++ cfe/trunk/tools/libclang/CXTranslationUnit.h Mon Apr 30 14:06:49 2012
@@ -20,6 +20,7 @@
   void *TUData;
   void *StringPool;
   void *Diagnostics;
+  void *OverridenCursorsPool;
 };
 }
 





More information about the cfe-commits mailing list