@@ -288,71 +288,72 @@ class DeferredFile {
288288public:
289289 StringRef path;
290290 bool isLazy;
291- std::optional<MemoryBufferRef> buffer;
292- const char *start;
293- size_t size;
291+ MemoryBufferRef buffer;
294292};
295293using DeferredFiles = std::vector<DeferredFile>;
296294
297- class PageInState {
298- DeferredFiles deferred;
299- size_t counter = 0 , total = 0 , pageSize;
300- std::mutex mutex, *busy;
295+ // Most input files have been mapped but not yet paged in.
296+ // This code forces the page-ins on multiple threads so
297+ // the process is not stalled waiting on disk buffer i/o.
298+ void multiThreadedPageInBackground (const DeferredFiles &deferred) {
299+ static size_t pageSize = Process::getPageSizeEstimate (), totalBytes;
300+ size_t index = 0 ;
301+ std::mutex mutex;
302+
303+ parallelFor (0 , config->readThreads , [&](size_t I) {
304+ while (true ) {
305+ mutex.lock ();
306+ if (index >= deferred.size ()) {
307+ mutex.unlock ();
308+ return ;
309+ }
310+ const StringRef &buff = deferred[index].buffer .getBuffer ();
311+ totalBytes += buff.size ();
312+ index += 1 ;
313+ mutex.unlock ();
314+
315+ volatile int t = 0 ; // Reference each page to load it into memory.
316+ for (const char *page = buff.data (), *end = page + buff.size ();
317+ page < end; page += pageSize)
318+ t += *page;
319+ }
320+ });
301321
302- public:
303- PageInState (DeferredFiles &deferred, std::mutex *busy) {
304- this ->deferred = deferred;
305- this ->busy = busy;
306- pageSize = llvm::sys::Process::getPageSizeEstimate ();
307- }
322+ if (getenv (" LLD_MULTI_THREAD_PAGE" ))
323+ llvm::dbgs () << " multiThreadedPageIn " << totalBytes << " /"
324+ << deferred.size () << " \n " ;
325+ }
326+
327+ static void multiThreadedPageIn (const DeferredFiles &deferred) {
328+ static std::thread *running;
329+ static std::mutex mutex;
330+ static std::deque<DeferredFiles *> queue;
308331
309- // Most input files have been mapped but not yet paged in.
310- // This code forces the page-ins on multiple threads so
311- // the process is not stalled waiting on disk buffer i/o.
312- void multiThreadedPageInBackground () {
313- static size_t totalBytes;
332+ mutex.lock ();
333+ if (running) {
334+ running->join ();
335+ delete running;
336+ running = nullptr ;
337+ }
314338
315- parallelFor (0 , config->readThreads , [&](size_t I) {
339+ if (!deferred.empty ()) {
340+ queue.emplace_back (new DeferredFiles (deferred));
341+ running = new std::thread ([&]() {
316342 while (true ) {
317343 mutex.lock ();
318- if (counter >= deferred. size ()) {
344+ if (queue. empty ()) {
319345 mutex.unlock ();
320346 return ;
321347 }
322- DeferredFile &file = deferred[counter];
323- totalBytes += file.size ;
324- counter += 1 ;
348+ DeferredFiles *deferred = queue.front ();
349+ queue.pop_front ();
325350 mutex.unlock ();
326-
327- int t = 0 ; // Reference each page to load it into memory.
328- for (const char *page = file.start , *end = page + file.size ; page < end;
329- page += pageSize)
330- t += *page;
331- total += t; // Avoids the loop being optimised out.
351+ multiThreadedPageInBackground (*deferred);
352+ delete deferred;
332353 }
333354 });
334-
335- if (getenv (" LLD_MULTI_THREAD_PAGE" ))
336- llvm::dbgs () << " multiThreadedPageIn " << totalBytes << " /"
337- << deferred.size () << " \n " ;
338-
339- busy->unlock ();
340- delete this ;
341355 }
342- };
343-
344- static void multiThreadedPageIn (DeferredFiles deferred) {
345- static std::thread *running;
346- static std::mutex busy;
347-
348- busy.lock ();
349- if (running) {
350- running->join ();
351- delete running;
352- }
353-
354- running = new std::thread (&PageInState::multiThreadedPageInBackground,
355- new PageInState (deferred, &busy));
356+ mutex.unlock ();
356357}
357358
358359static InputFile *processFile (std::optional<MemoryBufferRef> buffer,
@@ -454,9 +455,7 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
454455 }
455456
456457 if (archiveContents)
457- archiveContents->push_back ({path, isLazy, std::nullopt ,
458- mb->getBuffer ().data (),
459- mb->getBuffer ().size ()});
458+ archiveContents->push_back ({path, isLazy, *mb});
460459 if (!hasObjCSection (*mb))
461460 continue ;
462461 if (Error e = file->fetch (c, " -ObjC" ))
@@ -530,9 +529,10 @@ static InputFile *addFile(StringRef path, LoadType loadType,
530529
531530static void deferFile (StringRef path, bool isLazy, DeferredFiles &deferred) {
532531 std::optional<MemoryBufferRef> buffer = readFile (path);
532+ if (!buffer)
533+ return ;
533534 if (config->readThreads )
534- deferred.push_back ({path, isLazy, buffer, buffer->getBuffer ().data (),
535- buffer->getBuffer ().size ()});
535+ deferred.push_back ({path, isLazy, *buffer});
536536 else
537537 processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
538538}
@@ -1400,11 +1400,12 @@ static void createFiles(const InputArgList &args) {
14001400
14011401 DeferredFiles archiveContents;
14021402 std::vector<ArchiveFile *> archives;
1403- for (auto &file : deferredFiles)
1404- if (ArchiveFile *archive = dyn_cast<ArchiveFile>(
1405- processFile (file. buffer , &archiveContents , file.path ,
1406- LoadType::CommandLine, file. isLazy ) ))
1403+ for (auto &file : deferredFiles) {
1404+ auto inputFile = processFile (file. buffer , &archiveContents, file. path ,
1405+ LoadType::CommandLine , file.isLazy );
1406+ if (ArchiveFile *archive = dyn_cast<ArchiveFile>(inputFile ))
14071407 archives.push_back (archive);
1408+ }
14081409
14091410 if (!archiveContents.empty ()) {
14101411 multiThreadedPageIn (archiveContents);
0 commit comments