forked from OSchip/llvm-project
Reduce malloc() traffic of clang_getOverridenCursors() by using a pool of SmallVector<CXCursor> objects
under the covers. Fixes <rdar://problem/11289160>. llvm-svn: 155841
This commit is contained in:
parent
5b7e08c9d8
commit
d77f6219de
|
@ -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<ASTUnit *>(CTUnit->TUData);
|
||||
disposeCXStringPool(CTUnit->StringPool);
|
||||
delete static_cast<CXDiagnosticSetImpl *>(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<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;
|
||||
|
|
|
@ -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<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"
|
||||
|
|
|
@ -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<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);
|
||||
|
|
|
@ -20,6 +20,7 @@ struct CXTranslationUnitImpl {
|
|||
void *TUData;
|
||||
void *StringPool;
|
||||
void *Diagnostics;
|
||||
void *OverridenCursorsPool;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue