diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2014-01-22 16:43:45 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2014-01-22 16:43:45 +0000 |
commit | b6082a3d44c85bcf6ee46fb75ab3ce4a6e780f68 (patch) | |
tree | 750467481e37095c9419a63f6fbd15e76fccd093 | |
parent | f5f23b09bfa646ad20b2733a211496d0933e3723 (diff) | |
download | bcm5719-llvm-b6082a3d44c85bcf6ee46fb75ab3ce4a6e780f68.tar.gz bcm5719-llvm-b6082a3d44c85bcf6ee46fb75ab3ce4a6e780f68.zip |
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.
llvm-svn: 199815
-rw-r--r-- | llvm/tools/llvm-ar/llvm-ar.cpp | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index d4fe7d789c8..b2081e1a7b0 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/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 <typename T> void addMember(std::vector<NewArchiveIterator> &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<MemoryBuffer> File; + failIfError(MemoryBuffer::getOpenFile(FD, Filename, File, + Status.getSize(), false), + Filename); + if (ErrorOr<object::ObjectFile *> 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<MemoryBuffer> File; failIfError(MemoryBuffer::getOpenFile(FD, FileName, File, |