[cfe-commits] r103239 - /cfe/trunk/lib/Basic/SourceManager.cpp
Chris Lattner
sabre at nondot.org
Thu May 6 22:51:13 PDT 2010
Author: lattner
Date: Fri May 7 00:51:13 2010
New Revision: 103239
URL: http://llvm.org/viewvc/llvm-project?rev=103239&view=rev
Log:
reimplement the guts of SourceManager::isBeforeInTranslationUnit
to be algorithmically faster and avoid an std::map. This routine
basically boils down to finding the nearest common ancestor in a
tree, and we (implicitly) have information about nesting depth,
use it!
This wraps up rdar://7948633 - SourceManager::isBeforeInTranslationUnit has poor performance
Modified:
cfe/trunk/lib/Basic/SourceManager.cpp
Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=103239&r1=103238&r2=103239&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Fri May 7 00:51:13 2010
@@ -1179,74 +1179,77 @@
IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first);
// "Traverse" the include/instantiation stacks of both locations and try to
- // find a common "ancestor".
+ // find a common "ancestor". FileIDs build a tree-like structure that
+ // reflects the #include hierarchy, and this algorithm needs to find the
+ // nearest common ancestor between the two locations. For example, if you
+ // have a.c that includes b.h and c.h, and are comparing a location in b.h to
+ // a location in c.h, we need to find that their nearest common ancestor is
+ // a.c, and compare the locations of the two #includes to find their relative
+ // ordering.
//
- // First we traverse the stack of the right location and check each level
- // against the level of the left location, while collecting all levels in a
- // "stack map".
- std::map<FileID, unsigned> ROffsMap;
- ROffsMap[ROffs.first] = ROffs.second;
-
- while (1) {
- SourceLocation UpperLoc;
- const SrcMgr::SLocEntry &Entry = getSLocEntry(ROffs.first);
- if (Entry.isInstantiation())
- UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
- else
- UpperLoc = Entry.getFile().getIncludeLoc();
-
- if (UpperLoc.isInvalid())
- break; // We reached the top.
-
- ROffs = getDecomposedLoc(UpperLoc);
-
- // If we found a common file, cache and return our answer!
- if (LOffs.first == ROffs.first) {
- IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
- return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
+ // SourceManager assigns FileIDs in order of parsing. This means that an
+ // includee always has a larger FileID than an includer. While you might
+ // think that we could just compare the FileID's here, that doesn't work to
+ // compare a point at the end of a.c with a point within c.h. Though c.h has
+ // a larger FileID, we have to compare the include point of c.h to the
+ // location in a.c.
+ //
+ // Despite not being able to directly compare FileID's, we can tell that a
+ // larger FileID is necessarily more deeply nested than a lower one and use
+ // this information to walk up the tree to the nearest common ancestor.
+ do {
+ // If LOffs is larger than ROffs, then LOffs must be more deeply nested than
+ // ROffs, walk up the #include chain.
+ if (LOffs.first.ID > ROffs.first.ID) {
+ SourceLocation UpperLoc;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(LOffs.first);
+ if (Entry.isInstantiation())
+ UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+
+ if (UpperLoc.isInvalid())
+ break; // We reached the top.
+
+ LOffs = getDecomposedLoc(UpperLoc);
+ } else {
+ // Otherwise, ROffs is larger than LOffs, so ROffs must be more deeply
+ // nested than LOffs, walk up the #include chain.
+ SourceLocation UpperLoc;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(ROffs.first);
+ if (Entry.isInstantiation())
+ UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+
+ if (UpperLoc.isInvalid())
+ break; // We reached the top.
+
+ ROffs = getDecomposedLoc(UpperLoc);
}
+ } while (LOffs.first != ROffs.first);
- ROffsMap[ROffs.first] = ROffs.second;
- }
-
- // We didn't find a common ancestor. Now traverse the stack of the left
- // location, checking against the stack map of the right location.
- while (1) {
- SourceLocation UpperLoc;
- const SrcMgr::SLocEntry &Entry = getSLocEntry(LOffs.first);
- if (Entry.isInstantiation())
- UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
- else
- UpperLoc = Entry.getFile().getIncludeLoc();
-
- if (UpperLoc.isInvalid())
- break; // We reached the top.
-
- LOffs = getDecomposedLoc(UpperLoc);
-
- std::map<FileID, unsigned>::iterator I = ROffsMap.find(LOffs.first);
- if (I != ROffsMap.end()) {
- IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, I->second);
- return IsBeforeInTUCache.getCachedResult(LOffs.second, I->second);
- }
+ // If we exited because we found a nearest common ancestor, compare the
+ // locations within the common file and cache them.
+ if (LOffs.first == ROffs.first) {
+ IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
+ return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
}
// There is no common ancestor, most probably because one location is in the
// predefines buffer.
- //
+ IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
+
// FIXME: We should rearrange the external interface so this simply never
// happens; it can't conceptually happen. Also see PR5662.
-
+
// If exactly one location is a memory buffer, assume it preceeds the other.
bool LIsMB = !getSLocEntry(LOffs.first).getFile().getContentCache()->Entry;
bool RIsMB = !getSLocEntry(ROffs.first).getFile().getContentCache()->Entry;
- if (LIsMB != RIsMB) {
- IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
+ if (LIsMB != RIsMB)
return LIsMB;
- }
// Otherwise, just assume FileIDs were created in order.
- IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
return LOffs.first < ROffs.first;
}
More information about the cfe-commits
mailing list