From: Ted Kremenek Date: Tue, 6 Jan 2009 01:55:26 +0000 (+0000) Subject: Misc changes to SourceManager::ContentCache: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c16c208e8519476d838ad11fffc8e0ecea50550d;p=clang Misc changes to SourceManager::ContentCache: - 'Buffer' is now private and must be accessed via 'getBuffer()'. This paves the way for lazily mapping in source files on demand. - Added 'getSize()' (which gets the size of the content without necessarily accessing the MemBuffer) and 'getSizeBytesMapped()'. - Modifed SourceManager to use these new methods. This reduces the number of places that actually access the MemBuffer object for a file to those that actually look at the character data. These changes result in no performance change for -fsyntax-only on Cocoa.h. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61782 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 7d27a6ad59..175c40488c 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -48,16 +48,17 @@ namespace SrcMgr { /// ContentCache - Once instance of this struct is kept for every file /// loaded or used. This object owns the MemoryBuffer object. - struct ContentCache { + class ContentCache { + /// Buffer - The actual buffer containing the characters from the input + /// file. This is owned by the ContentCache object. + const llvm::MemoryBuffer* Buffer; + + public: /// Reference to the file entry. This reference does not own /// the FileEntry object. It is possible for this to be NULL if /// the ContentCache encapsulates an imaginary text buffer. const FileEntry* Entry; - /// Buffer - The actual buffer containing the characters from the input - /// file. This is owned by the ContentCache object. - const llvm::MemoryBuffer* Buffer; - /// SourceLineCache - A new[]'d array of offsets for each source line. This /// is lazily computed. This is owned by the ContentCache object. unsigned* SourceLineCache; @@ -65,9 +66,28 @@ namespace SrcMgr { /// NumLines - The number of lines in this ContentCache. This is only valid /// if SourceLineCache is non-null. unsigned NumLines; + + /// getBuffer - Returns the memory buffer for the associated content. + const llvm::MemoryBuffer* getBuffer() const; + + /// getSize - Returns the size of the content encapsulated by this + /// ContentCache. This can be the size of the source file or the size of an + /// arbitrary scratch buffer. If the ContentCache encapsulates a source + /// file this size is retrieved from the file's FileEntry. + unsigned getSize() const; + + /// getSizeBytesMapped - Returns the number of bytes actually mapped for + /// this ContentCache. This can be 0 if the MemBuffer was not actually + /// instantiated. + unsigned getSizeBytesMapped() const; + + void setBuffer(const llvm::MemoryBuffer* B) { + assert(!Buffer && "MemoryBuffer already set."); + Buffer = B; + } ContentCache(const FileEntry* e = NULL) - : Entry(e), Buffer(NULL), SourceLineCache(NULL), NumLines(0) {} + : Buffer(NULL), Entry(e), SourceLineCache(NULL), NumLines(0) {} ~ContentCache(); @@ -307,7 +327,7 @@ public: /// getBuffer - Return the buffer for the specified FileID. /// const llvm::MemoryBuffer *getBuffer(unsigned FileID) const { - return getContentCache(FileID)->Buffer; + return getContentCache(FileID)->getBuffer(); } /// getBufferData - Return a pointer to the start and end of the character @@ -506,7 +526,7 @@ private: /// getContentCache - Create or return a cached ContentCache for the specified /// file. This returns null on failure. const SrcMgr::ContentCache* getContentCache(const FileEntry* SourceFile); - + /// createMemBufferContentCache - Create a new ContentCache for the specified /// memory buffer. const SrcMgr::ContentCache* diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 44a6d66c1a..b040459e77 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -29,6 +29,26 @@ ContentCache::~ContentCache() { delete [] SourceLineCache; } +/// getSizeBytesMapped - Returns the number of bytes actually mapped for +/// this ContentCache. This can be 0 if the MemBuffer was not actually +/// instantiated. +unsigned ContentCache::getSizeBytesMapped() const { + return Buffer ? Buffer->getBufferSize() : 0; +} + +/// getSize - Returns the size of the content encapsulated by this ContentCache. +/// This can be the size of the source file or the size of an arbitrary +/// scratch buffer. If the ContentCache encapsulates a source file, that +/// file is not lazily brought in from disk to satisfy this query. +unsigned ContentCache::getSize() const { + return Entry ? Entry->getSize() : Buffer->getBufferSize(); +} + +const llvm::MemoryBuffer* ContentCache::getBuffer() const { + return Buffer; +} + + /// getFileInfo - Create or return a cached FileInfo for the specified file. /// const ContentCache* SourceManager::getContentCache(const FileEntry *FileEnt) { @@ -49,7 +69,9 @@ const ContentCache* SourceManager::getContentCache(const FileEntry *FileEnt) { ContentCache& Entry = const_cast(*FileInfos.insert(I,FileEnt)); - Entry.Buffer = File; + // FIXME: Shortly the above logic that creates a MemBuffer will be moved + // to ContentCache::getBuffer(). This way it can be done lazily. + Entry.setBuffer(File); Entry.SourceLineCache = 0; Entry.NumLines = 0; return &Entry; @@ -66,7 +88,7 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { // temporary we would use in the call to "push_back". MemBufferInfos.push_back(ContentCache()); ContentCache& Entry = const_cast(MemBufferInfos.back()); - Entry.Buffer = Buffer; + Entry.setBuffer(Buffer); return &Entry; } @@ -81,7 +103,7 @@ unsigned SourceManager::createFileID(const ContentCache *File, // to fit an arbitrary position in the file in the FilePos field. To handle // this, we create one FileID for each chunk of the file that fits in a // FilePos field. - unsigned FileSize = File->Buffer->getBufferSize(); + unsigned FileSize = File->getSize(); if (FileSize+1 < (1 << SourceLocation::FilePosBits)) { FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File, FileCharacter)); assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) && @@ -159,7 +181,8 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const { // heavily used by -E mode. SL = getPhysicalLoc(SL); - return getContentCache(SL.getFileID())->Buffer->getBufferStart() + + // Note that calling 'getBuffer()' may lazily page in a source file. + return getContentCache(SL.getFileID())->getBuffer()->getBufferStart() + getFullFilePos(SL); } @@ -187,12 +210,17 @@ unsigned SourceManager::getColumnNumber(SourceLocation Loc) const { const char *SourceManager::getSourceName(SourceLocation Loc) const { unsigned FileID = Loc.getFileID(); if (FileID == 0) return ""; - return getContentCache(FileID)->Buffer->getBufferIdentifier(); + + // To get the source name, first consult the FileEntry (if one exists) before + // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer. + const SrcMgr::ContentCache* C = getContentCache(FileID); + return C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); } static void ComputeLineNumbers(ContentCache* FI) DISABLE_INLINE; -static void ComputeLineNumbers(ContentCache* FI) { - const MemoryBuffer *Buffer = FI->Buffer; +static void ComputeLineNumbers(ContentCache* FI) { + // Note that calling 'getBuffer()' may lazily page in the file. + const MemoryBuffer *Buffer = FI->getBuffer(); // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. @@ -341,7 +369,7 @@ void SourceManager::PrintStats() const { for (std::set::const_iterator I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) { NumLineNumsComputed += I->SourceLineCache != 0; - NumFileBytesMapped += I->Buffer->getBufferSize(); + NumFileBytesMapped += I->getSizeBytesMapped(); } llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "