forked from OSchip/llvm-project
				
			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:
		
							parent
							
								
									07c446baf4
								
							
						
					
					
						commit
						08037045f8
					
				| 
						 | 
					@ -447,7 +447,7 @@ public:
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// The cache structure is complex enough to be worth breaking out of
 | 
					/// The cache structure is complex enough to be worth breaking out of
 | 
				
			||||||
/// SourceManager.
 | 
					/// SourceManager.
 | 
				
			||||||
class IsBeforeInTranslationUnitCache {
 | 
					class InBeforeInTUCacheEntry {
 | 
				
			||||||
  /// \brief The FileID's of the cached query.
 | 
					  /// \brief The FileID's of the cached query.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// If these match up with a subsequent query, the result can be reused.
 | 
					  /// If these match up with a subsequent query, the result can be reused.
 | 
				
			||||||
| 
						 | 
					@ -469,7 +469,6 @@ class IsBeforeInTranslationUnitCache {
 | 
				
			||||||
  /// random token in the parent.
 | 
					  /// random token in the parent.
 | 
				
			||||||
  unsigned LCommonOffset, RCommonOffset;
 | 
					  unsigned LCommonOffset, RCommonOffset;
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// \brief Return true if the currently cached values match up with
 | 
					  /// \brief Return true if the currently cached values match up with
 | 
				
			||||||
  /// the specified LHS/RHS query.
 | 
					  /// the specified LHS/RHS query.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
| 
						 | 
					@ -647,8 +646,21 @@ class SourceManager : public RefCountedBase<SourceManager> {
 | 
				
			||||||
  // Statistics for -print-stats.
 | 
					  // Statistics for -print-stats.
 | 
				
			||||||
  mutable unsigned NumLinearScans, NumBinaryProbes;
 | 
					  mutable unsigned NumLinearScans, NumBinaryProbes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Cache results for the isBeforeInTranslationUnit method.
 | 
					  /// The key value into the IsBeforeInTUCache table.
 | 
				
			||||||
  mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache;
 | 
					  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.
 | 
					  // Cache for the "fake" buffer used for error-recovery purposes.
 | 
				
			||||||
  mutable llvm::MemoryBuffer *FakeBufferForRecovery;
 | 
					  mutable llvm::MemoryBuffer *FakeBufferForRecovery;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1856,6 +1856,31 @@ static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
 | 
				
			||||||
  return false;
 | 
					  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.
 | 
					/// \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)
 | 
					  if (LOffs.first == ROffs.first)
 | 
				
			||||||
    return LOffs.second < ROffs.second;
 | 
					    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
 | 
					  // If we are comparing a source location with multiple locations in the same
 | 
				
			||||||
  // file, we get a big win by caching the result.
 | 
					  // file, we get a big win by caching the result.
 | 
				
			||||||
  if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
 | 
					  if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue