From fa4a8f4f5a6de6e205f4685196d3d535a395c152 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 22 Jan 2014 16:43:45 +0000 Subject: Don't open or fstat files twice in llvm-ar. We still read/mmap them twice, but the fix for that is a bit more complex. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199815 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-ar/llvm-ar.cpp | 62 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index d4fe7d789c..b2081e1a7b 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -395,17 +395,25 @@ namespace { class NewArchiveIterator { bool IsNewMember; StringRef Name; + object::Archive::child_iterator OldI; + std::string NewFilename; + mutable int NewFD; + mutable sys::fs::file_status NewStatus; public: NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); NewArchiveIterator(std::string *I, StringRef Name); NewArchiveIterator(); bool isNewMember() const; + StringRef getName() const; + object::Archive::child_iterator getOld() const; + const char *getNew() const; - StringRef getName() const; + int getFD() const; + const sys::fs::file_status &getStatus() const; }; } @@ -416,7 +424,7 @@ NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I, : IsNewMember(false), Name(Name), OldI(I) {} NewArchiveIterator::NewArchiveIterator(std::string *NewFilename, StringRef Name) - : IsNewMember(true), Name(Name), NewFilename(*NewFilename) {} + : IsNewMember(true), Name(Name), NewFilename(*NewFilename), NewFD(-1) {} StringRef NewArchiveIterator::getName() const { return Name; } @@ -432,6 +440,31 @@ const char *NewArchiveIterator::getNew() const { return NewFilename.c_str(); } +int NewArchiveIterator::getFD() const { + assert(IsNewMember); + if (NewFD != -1) + return NewFD; + failIfError(sys::fs::openFileForRead(NewFilename, NewFD), NewFilename); + assert(NewFD != -1); + + failIfError(sys::fs::status(NewFD, NewStatus), NewFilename); + + // Opening a directory doesn't make sense. Let it fail. + // Linux cannot open directories with open(2), although + // cygwin and *bsd can. + if (NewStatus.type() == sys::fs::file_type::directory_file) + failIfError(error_code(errc::is_a_directory, posix_category()), + NewFilename); + + return NewFD; +} + +const sys::fs::file_status &NewArchiveIterator::getStatus() const { + assert(IsNewMember); + assert(NewFD != -1 && "Must call getFD first"); + return NewStatus; +} + template void addMember(std::vector &Members, T I, StringRef Name, int Pos = -1) { @@ -670,8 +703,16 @@ static void writeSymbolTable( object::ObjectFile *Obj; if (I->isNewMember()) { const char *Filename = I->getNew(); + int FD = I->getFD(); + const sys::fs::file_status &Status = I->getStatus(); + + OwningPtr File; + failIfError(MemoryBuffer::getOpenFile(FD, Filename, File, + Status.getSize(), false), + Filename); + if (ErrorOr ObjOrErr = - object::ObjectFile::createObjectFile(Filename)) + object::ObjectFile::createObjectFile(File.take())) Obj = ObjOrErr.get(); else Obj = NULL; @@ -786,19 +827,8 @@ static void performWriteOperation(ArchiveOperation Operation, if (I->isNewMember()) { const char *FileName = I->getNew(); - - int FD; - failIfError(sys::fs::openFileForRead(FileName, FD), FileName); - - sys::fs::file_status Status; - failIfError(sys::fs::status(FD, Status), FileName); - - // Opening a directory doesn't make sense. Let it failed. - // Linux cannot open directories with open(2), although - // cygwin and *bsd can. - if (Status.type() == sys::fs::file_type::directory_file) - failIfError(error_code(errc::is_a_directory, posix_category()), - FileName); + int FD = I->getFD(); + const sys::fs::file_status &Status = I->getStatus(); OwningPtr File; failIfError(MemoryBuffer::getOpenFile(FD, FileName, File, -- cgit v1.2.3