diff options
author | Ted Kremenek <kremenek@apple.com> | 2013-02-27 00:00:26 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2013-02-27 00:00:26 +0000 |
commit | 2564f811ba107cb314a594d730aa3357b6181b62 (patch) | |
tree | e82cc70e40dcf889803e8139973354ffee87b637 | |
parent | b58f810669d9c17bcc025b7560de01d162856f34 (diff) |
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>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176142 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/SourceManager.h | 20 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 32 |
2 files changed, 47 insertions, 5 deletions
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index d7c71a7632..00c96c3da0 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -447,7 +447,7 @@ public: /// /// The cache structure is complex enough to be worth breaking out of /// SourceManager. -class IsBeforeInTranslationUnitCache { +class InBeforeInTUCacheEntry { /// \brief The FileID's of the cached query. /// /// If these match up with a subsequent query, the result can be reused. @@ -469,7 +469,6 @@ class IsBeforeInTranslationUnitCache { /// random token in the parent. unsigned LCommonOffset, RCommonOffset; public: - /// \brief Return true if the currently cached values match up with /// the specified LHS/RHS query. /// @@ -647,8 +646,21 @@ class SourceManager : public RefCountedBase<SourceManager> { // Statistics for -print-stats. mutable unsigned NumLinearScans, NumBinaryProbes; - // Cache results for the isBeforeInTranslationUnit method. - mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; + /// The key value into the IsBeforeInTUCache table. + typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey; + + /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs + /// to cache results. + typedef llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry> + InBeforeInTUCache; + + /// Cache results for the isBeforeInTranslationUnit method. + mutable InBeforeInTUCache IBTUCache; + mutable InBeforeInTUCacheEntry IBTUCacheOverflow; + + /// Return the cache entry for comparing the given file IDs + /// for isBeforeInTranslationUnit. + InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const; // Cache for the "fake" buffer used for error-recovery purposes. mutable llvm::MemoryBuffer *FakeBufferForRecovery; diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index c5d275ab54..ea9565006c 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -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. /// @@ -1875,6 +1900,11 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, // 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)) return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); |