[llvm] r199815 - Don't open or fstat files twice in llvm-ar.

Rafael Espindola rafael.espindola at gmail.com
Wed Jan 22 08:43:45 PST 2014


Author: rafael
Date: Wed Jan 22 10:43:45 2014
New Revision: 199815

URL: http://llvm.org/viewvc/llvm-project?rev=199815&view=rev
Log:
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.

Modified:
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

Modified: llvm/trunk/tools/llvm-ar/llvm-ar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-ar/llvm-ar.cpp?rev=199815&r1=199814&r2=199815&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Wed Jan 22 10:43:45 2014
@@ -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(o
     : 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()
   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(Archiv
 
     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,





More information about the llvm-commits mailing list