@@ -288,71 +288,72 @@ class DeferredFile {
288
288
public:
289
289
StringRef path;
290
290
bool isLazy;
291
- std::optional<MemoryBufferRef> buffer;
292
- const char *start;
293
- size_t size;
291
+ MemoryBufferRef buffer;
294
292
};
295
293
using DeferredFiles = std::vector<DeferredFile>;
296
294
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
+ });
301
321
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;
308
331
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
+ }
314
338
315
- parallelFor (0 , config->readThreads , [&](size_t I) {
339
+ if (!deferred.empty ()) {
340
+ queue.emplace_back (new DeferredFiles (deferred));
341
+ running = new std::thread ([&]() {
316
342
while (true ) {
317
343
mutex.lock ();
318
- if (counter >= deferred. size ()) {
344
+ if (queue. empty ()) {
319
345
mutex.unlock ();
320
346
return ;
321
347
}
322
- DeferredFile &file = deferred[counter];
323
- totalBytes += file.size ;
324
- counter += 1 ;
348
+ DeferredFiles *deferred = queue.front ();
349
+ queue.pop_front ();
325
350
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;
332
353
}
333
354
});
334
-
335
- if (getenv (" LLD_MULTI_THREAD_PAGE" ))
336
- llvm::dbgs () << " multiThreadedPageIn " << totalBytes << " /"
337
- << deferred.size () << " \n " ;
338
-
339
- busy->unlock ();
340
- delete this ;
341
355
}
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 ();
356
357
}
357
358
358
359
static InputFile *processFile (std::optional<MemoryBufferRef> buffer,
@@ -454,9 +455,7 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
454
455
}
455
456
456
457
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});
460
459
if (!hasObjCSection (*mb))
461
460
continue ;
462
461
if (Error e = file->fetch (c, " -ObjC" ))
@@ -530,9 +529,10 @@ static InputFile *addFile(StringRef path, LoadType loadType,
530
529
531
530
static void deferFile (StringRef path, bool isLazy, DeferredFiles &deferred) {
532
531
std::optional<MemoryBufferRef> buffer = readFile (path);
532
+ if (!buffer)
533
+ return ;
533
534
if (config->readThreads )
534
- deferred.push_back ({path, isLazy, buffer, buffer->getBuffer ().data (),
535
- buffer->getBuffer ().size ()});
535
+ deferred.push_back ({path, isLazy, *buffer});
536
536
else
537
537
processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
538
538
}
@@ -1400,11 +1400,12 @@ static void createFiles(const InputArgList &args) {
1400
1400
1401
1401
DeferredFiles archiveContents;
1402
1402
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 ))
1407
1407
archives.push_back (archive);
1408
+ }
1408
1409
1409
1410
if (!archiveContents.empty ()) {
1410
1411
multiThreadedPageIn (archiveContents);
0 commit comments