Skip to content

Commit

Permalink
Don't open or fstat files twice in llvm-ar.
Browse files Browse the repository at this point in the history
We still read/mmap them twice, but the fix for that is a bit more complex.

llvm-svn: 199815
  • Loading branch information
espindola committed Jan 22, 2014
1 parent f5f23b0 commit b6082a3
Showing 1 changed file with 46 additions and 16 deletions.
62 changes: 46 additions & 16 deletions llvm/tools/llvm-ar/llvm-ar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}

Expand All @@ -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; }

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit b6082a3

Please sign in to comment.