Refine SourceManager's isBeforeInTranslationUnit() cache to have more entries.

isBeforeInTranslationUnit() uses a cache to reduce the expensive work
to compute a common ancestor for two FileIDs.  This work is very
expensive, so even caching the latest used FileIDs was a big win.
A closer analysis of the cache before, however, shows that the cache
access pattern would oscillate between a working set of FileIDs, and
thus caching more pairs would be profitable.

This patch adds a side table for extending caching.  This side table
is bounded in size (experimentally determined in this case from
a simple Objective-C project), and when the table gets too large
we fall back to the single entry caching before as before.

On Sketch (a small example Objective-C project), this optimization
reduces -fsyntax-only time on SKTGraphicView.m by 5%.  This is
for a project that is already using PCH.

Fixes <rdar://problem/13299847>

llvm-svn: 176142
This commit is contained in:
Ted Kremenek
2013-02-27 00:00:26 +00:00
parent 07c446baf4
commit 08037045f8
2 changed files with 47 additions and 5 deletions

View File

@@ -1855,7 +1855,32 @@ static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
Loc = SM.getDecomposedLoc(UpperLoc);
return false;
}
/// Return the cache entry for comparing the given file IDs
/// for isBeforeInTranslationUnit.
InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
FileID RFID) const {
// This is a magic number for limiting the cache size. It was experimentally
// derived from a small Objective-C project (where the cache filled
// out to ~250 items). We can make it larger if necessary.
enum { MagicCacheSize = 300 };
IsBeforeInTUCacheKey Key(LFID, RFID);
// If the cache size isn't too large, do a lookup and if necessary default
// construct an entry. We can then return it to the caller for direct
// use. When they update the value, the cache will get automatically
// updated as well.
if (IBTUCache.size() < MagicCacheSize)
return IBTUCache[Key];
// Otherwise, do a lookup that will not construct a new value.
InBeforeInTUCache::iterator I = IBTUCache.find(Key);
if (I != IBTUCache.end())
return I->second;
// Fall back to the overflow value.
return IBTUCacheOverflow;
}
/// \brief Determines the order of 2 source locations in the translation unit.
///
@@ -1873,6 +1898,11 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
if (LOffs.first == ROffs.first)
return LOffs.second < ROffs.second;
// If we are comparing a source location with multiple locations in the same
// file, we get a big win by caching the result.
InBeforeInTUCacheEntry &IsBeforeInTUCache =
getInBeforeInTUCache(LOffs.first, ROffs.first);
// If we are comparing a source location with multiple locations in the same
// file, we get a big win by caching the result.
if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))