From bbf66ca1dad17773cc682d69b8482c4e179aeaeb Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 30 Apr 2012 19:06:49 +0000 Subject: [PATCH] Reduce malloc() traffic of clang_getOverridenCursors() by using a pool of SmallVector objects under the covers. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155841 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndex.cpp | 30 +-------- tools/libclang/CXCursor.cpp | 103 ++++++++++++++++++++++++++++- tools/libclang/CXCursor.h | 11 ++- tools/libclang/CXTranslationUnit.h | 1 + 4 files changed, 113 insertions(+), 32 deletions(-) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 605cc8bdee..0beb32d6c9 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -61,6 +61,7 @@ CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *TU) { D->TUData = TU; D->StringPool = createCXStringPool(); D->Diagnostics = 0; + D->OverridenCursorsPool = createOverridenCXCursorsPool(); return D; } @@ -2734,6 +2735,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) { delete static_cast(CTUnit->TUData); disposeCXStringPool(CTUnit->StringPool); delete static_cast(CTUnit->Diagnostics); + disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool); delete CTUnit; } } @@ -5549,34 +5551,6 @@ CXCursor clang_getCursorLexicalParent(CXCursor cursor) { 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 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; diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 678798f9aa..7d38802796 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -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 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) { } return NULL; } + +namespace { + struct OverridenCursorsPool { + typedef llvm::SmallVector CursorVec; + std::vector AllCursors; + std::vector AvailableCursors; + + ~OverridenCursorsPool() { + for (std::vector::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(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(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(overridden->data[0]); + CXTranslationUnit TU = getCursorTU(*overridden); + + assert(Vec && TU); + + OverridenCursorsPool &pool = + *static_cast(TU->OverridenCursorsPool); + + pool.AvailableCursors.push_back(Vec); +} } // end: extern "C" diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h index 947b0a3eed..120b881069 100644 --- a/tools/libclang/CXCursor.h +++ b/tools/libclang/CXCursor.h @@ -55,7 +55,7 @@ CXCursor MakeCXCursor(clang::Decl *D, CXTranslationUnit TU, 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 @@ ASTUnit *getCursorASTUnit(CXCursor Cursor); CXTranslationUnit getCursorTU(CXCursor Cursor); void getOverriddenCursors(CXCursor cursor, - SmallVectorImpl &overridden); + SmallVectorImpl &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 getSelectorIdentifierIndexAndLoc(CXCursor); diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h index 3ad867ca8b..37789aafb9 100644 --- a/tools/libclang/CXTranslationUnit.h +++ b/tools/libclang/CXTranslationUnit.h @@ -20,6 +20,7 @@ struct CXTranslationUnitImpl { void *TUData; void *StringPool; void *Diagnostics; + void *OverridenCursorsPool; }; } -- 2.40.0