///
/// 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.
/// 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.
///
// 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;
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.
///
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))