optimize the 'StoredDeclsMap' for the common case where there is

exactly one decl with a specific name in a specific context.  This
avoids a bunch of malloc traffic and shrinks StoredDeclsMap to hold
one pointer instead of 3 words (for a std::vector).

This speeds up -fsyntax-only on cocoa.h with PTH by ~7.3%.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65103 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-02-20 01:44:05 +00:00
Родитель 15423b066d
Коммит 67762a35dc
1 изменённых файлов: 121 добавлений и 44 удалений

Просмотреть файл

@ -268,15 +268,119 @@ bool DeclContext::classof(const Decl *D) {
}
}
// FIXME: We really want to use a DenseSet here to eliminate the
// redundant storage of the declaration names, but (1) it doesn't give
// us the ability to search based on DeclarationName, (2) we really
// need something more like a DenseMultiSet, and (3) it's
// implemented in terms of DenseMap anyway. However, this data
// structure is really space-inefficient, so we'll have to do
// something.
typedef llvm::DenseMap<DeclarationName, std::vector<NamedDecl*> >
StoredDeclsMap;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
/// Data - If the integer is 0, then the pointer is a NamedDecl*. If the
/// integer is 1, then it is a VectorTy;
llvm::PointerIntPair<void*, 1, bool> Data;
/// VectorTy - When in vector form, this is what the Data pointer points to.
typedef llvm::SmallVector<NamedDecl*, 4> VectorTy;
public:
StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (isVector())
Data.setPointer(new VectorTy(getVector()));
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
if (isVector())
delete &getVector();
}
bool isVector() const { return Data.getInt() != 0; }
bool isInline() const { return Data.getInt() == 0; }
bool isNull() const { return Data.getPointer() == 0; }
void setOnlyValue(NamedDecl *ND) {
assert(isInline() && "Not inline");
Data.setPointer(ND);
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
DeclContext::lookup_result getLookupResult() {
// If we have a single inline unit, return it.
if (isInline()) {
assert(!isNull() && "Empty list isn't allowed");
// Data is a raw pointer to a NamedDecl*, return it.
void *Ptr = &Data;
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
}
// Otherwise, we have a range result.
VectorTy &V = getVector();
return DeclContext::lookup_result(&V[0], &V[0]+V.size());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(NamedDecl *D) {
// Most decls only have one entry in their list, special case it.
if (isInline()) {
if (!D->declarationReplaces(getInlineValue()))
return false;
setOnlyValue(D);
return true;
}
// Determine if this declaration is actually a redeclaration.
VectorTy &Vec = getVector();
VectorTy::iterator RDI
= std::find_if(Vec.begin(), Vec.end(),
std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
D));
if (RDI == Vec.end())
return false;
*RDI = D;
return true;
}
/// AddSubsequentDecl - This is called on the second and later decl when it is
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
// If this is the second decl added to the list, convert this to vector
// form.
if (isInline()) {
NamedDecl *OldD = getInlineValue();
Data.setInt(1);
VectorTy *VT = new VectorTy();
VT->push_back(OldD);
Data.setPointer(VT);
}
VectorTy &Vec = getVector();
if (isa<UsingDirectiveDecl>(D) ||
D->getIdentifierNamespace() == Decl::IDNS_Tag)
Vec.push_back(D);
else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
NamedDecl *TagD = Vec.back();
Vec.back() = D;
Vec.push_back(TagD);
} else
Vec.push_back(D);
}
private:
VectorTy &getVector() const {
assert(isVector() && "Not in vector form");
return *static_cast<VectorTy*>(Data.getPointer());
}
NamedDecl *getInlineValue() const {
assert(isInline() && "Not in inline form");
return (NamedDecl*)Data.getPointer();
}
};
typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
DeclContext::~DeclContext() {
unsigned Size = LookupPtr.getInt();
@ -412,9 +516,7 @@ DeclContext::lookup(DeclarationName Name) {
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos == Map->end())
return lookup_result(0, 0);
return lookup_result(&Pos->second.front(),
&Pos->second.front() + Pos->second.size());
return Pos->second.getLookupResult();
}
// We have a small array. Look into it.
@ -559,46 +661,21 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
}
// Insert this declaration into the map.
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
std::vector<NamedDecl *> &DeclNameEntries = (*Map)[D->getDeclName()];
if (DeclNameEntries.empty()) {
DeclNameEntries.push_back(D);
StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
}
// If it is possible that this is a redeclaration, check to see if there is
// already a decl for which declarationReplaces returns true. If there is
// one, just replace it and return.
if (MayBeRedeclaration) {
// Most decls only have one entry in their list, special case it.
if (DeclNameEntries.size() == 1) {
if (D->declarationReplaces(DeclNameEntries[0])) {
DeclNameEntries[0] = D;
return;
}
} else {
// Determine if this declaration is actually a redeclaration.
std::vector<NamedDecl *>::iterator Redecl
= std::find_if(DeclNameEntries.begin(), DeclNameEntries.end(),
std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
D));
if (Redecl != DeclNameEntries.end()) {
*Redecl = D;
return;
}
}
}
if (MayBeRedeclaration && DeclNameEntries.HandleRedeclaration(D))
return;
// Put this declaration into the appropriate slot.
if (isa<UsingDirectiveDecl>(D) ||
D->getIdentifierNamespace() == Decl::IDNS_Tag)
DeclNameEntries.push_back(D);
else if (DeclNameEntries.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
NamedDecl *TagD = DeclNameEntries.back();
DeclNameEntries.back() = D;
DeclNameEntries.push_back(TagD);
} else
DeclNameEntries.push_back(D);
DeclNameEntries.AddSubsequentDecl(D);
}
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within