@@ -290,27 +290,26 @@ typedef struct {
290290 const char *start;
291291 size_t size;
292292} DeferredFile;
293+ typedef std::vector<DeferredFile> DeferredFiles;
294+
295+ #ifndef _WIN32
296+ typedef struct {
297+ DeferredFiles deferred;
298+ size_t counter, total, pageSize;
299+ pthread_mutex_t mutex;
300+ } PageInState;
293301
294302// Most input files have been mapped but not yet paged in.
295303// This code forces the page-ins on multiple threads so
296304// the process is not stalled waiting on disk buffer i/o.
297- static void multiThreadedPageIn (std::vector<DeferredFile> &deferred) {
298- #ifndef _WIN32
305+ static void multiThreadedPageInBackground (PageInState *state) {
299306#define MaxReadThreads 200
300- typedef struct {
301- std::vector<DeferredFile> &deferred;
302- size_t counter, total, pageSize;
303- pthread_mutex_t mutex;
304- } PageInState;
305- PageInState state = {deferred, 0 , 0 ,
306- llvm::sys::Process::getPageSizeEstimate (),
307- pthread_mutex_t ()};
308307 static size_t totalBytes;
309308
310309 pthread_t running[MaxReadThreads];
311310 if (config->readThreads > MaxReadThreads)
312311 config->readThreads = MaxReadThreads;
313- pthread_mutex_init (&state. mutex , NULL );
312+ pthread_mutex_init (&state-> mutex , nullptr );
314313
315314 for (int t = 0 ; t < config->readThreads ; t++)
316315 pthread_create (
@@ -336,20 +335,49 @@ static void multiThreadedPageIn(std::vector<DeferredFile> &deferred) {
336335 state.total += t; // Avoids the loop being optimised out.
337336 }
338337 },
339- & state);
338+ state);
340339
341340 for (int t = 0 ; t < config->readThreads ; t++)
342341 pthread_join (running[t], nullptr );
343342
344- pthread_mutex_destroy (&state. mutex );
343+ pthread_mutex_destroy (&state-> mutex );
345344 if (getenv (" LLD_MULTI_THREAD_PAGE" ))
346- printf (" multiThreadedPageIn %ld/%ld\n " , totalBytes, deferred.size ());
345+ printf (" multiThreadedPageIn %ld/%ld\n " , totalBytes, state->deferred .size ());
346+ }
347+ #endif
348+
349+ static void multiThreadedPageIn (DeferredFiles deferred) {
350+ #ifndef _WIN32
351+ static pthread_t running;
352+ static pthread_mutex_t busy;
353+
354+ if (running)
355+ pthread_join (running, nullptr );
356+ else
357+ pthread_mutex_init (&busy, nullptr );
358+
359+ PageInState *state =
360+ new PageInState{deferred, 0 , 0 , llvm::sys::Process::getPageSizeEstimate (),
361+ pthread_mutex_t ()};
362+
363+ pthread_mutex_lock (&busy);
364+ pthread_create (
365+ &running, nullptr ,
366+ [](void *ptr) -> void * {
367+ PageInState *state = (PageInState *)ptr;
368+ multiThreadedPageInBackground (state);
369+ pthread_mutex_unlock (&busy);
370+ delete state;
371+ return nullptr ;
372+ },
373+ state);
347374#endif
348375}
349376
350377static InputFile *processFile (std::optional<MemoryBufferRef> buffer,
351- StringRef path, LoadType loadType,
352- bool isLazy = false , bool isExplicit = true ,
378+ DeferredFiles *archiveContents, StringRef path,
379+ LoadType loadType, bool isLazy = false ,
380+ bool isExplicit = true ,
353381 bool isBundleLoader = false ,
354382 bool isForceHidden = false ) {
355383 if (!buffer)
@@ -431,7 +459,6 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
431459 // we already found that it contains an ObjC symbol.
432460 if (readFile (path)) {
433461 Error e = Error::success ();
434- std::vector<DeferredFile> deferredFiles;
435462 for (const object::Archive::Child &c : file->getArchive ().children (e)) {
436463 Expected<MemoryBufferRef> mb = c.getMemoryBufferRef ();
437464 if (!mb) {
@@ -445,9 +472,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
445472 continue ;
446473 }
447474
448- deferredFiles.push_back ({path, isLazy, std::nullopt ,
449- mb->getBuffer ().data (),
450- mb->getBuffer ().size ()});
475+ if (archiveContents)
476+ archiveContents->push_back ({path, isLazy, std::nullopt ,
477+ mb->getBuffer ().data (),
478+ mb->getBuffer ().size ()});
451479 if (!hasObjCSection (*mb))
452480 continue ;
453481 if (Error e = file->fetch (c, " -ObjC" ))
@@ -457,11 +485,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
457485 if (e)
458486 error (toString (file) +
459487 " : Archive::children failed: " + toString (std::move (e)));
460- if (config->readThreads && deferredFiles.size () > 1 )
461- multiThreadedPageIn (deferredFiles);
462488 }
463489 }
464- file->addLazySymbols ();
490+ if (!archiveContents || archiveContents->empty ())
491+ file->addLazySymbols ();
465492 loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
466493 newFile = file;
467494 break ;
@@ -516,18 +543,17 @@ static InputFile *addFile(StringRef path, LoadType loadType,
516543 bool isLazy = false , bool isExplicit = true ,
517544 bool isBundleLoader = false ,
518545 bool isForceHidden = false ) {
519- return processFile (readFile (path), path, loadType, isLazy, isExplicit ,
520- isBundleLoader, isForceHidden);
546+ return processFile (readFile (path), nullptr , path, loadType, isLazy,
547+ isExplicit, isBundleLoader, isForceHidden);
521548}
522549
523- static void deferFile (StringRef path, bool isLazy,
524- std::vector<DeferredFile> &deferred) {
550+ static void deferFile (StringRef path, bool isLazy, DeferredFiles &deferred) {
525551 std::optional<MemoryBufferRef> buffer = readFile (path);
526552 if (config->readThreads )
527553 deferred.push_back ({path, isLazy, buffer, buffer->getBuffer ().data (),
528554 buffer->getBuffer ().size ()});
529555 else
530- processFile (buffer, path, LoadType::CommandLine, isLazy);
556+ processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
531557}
532558
533559static std::vector<StringRef> missingAutolinkWarnings;
@@ -654,7 +680,7 @@ void macho::resolveLCLinkerOptions() {
654680}
655681
656682static void addFileList (StringRef path, bool isLazy,
657- std::vector<DeferredFile> &deferredFiles) {
683+ DeferredFiles &deferredFiles) {
658684 std::optional<MemoryBufferRef> buffer = readFile (path);
659685 if (!buffer)
660686 return ;
@@ -1312,7 +1338,7 @@ static void createFiles(const InputArgList &args) {
13121338 bool isLazy = false ;
13131339 // If we've processed an opening --start-lib, without a matching --end-lib
13141340 bool inLib = false ;
1315- std::vector<DeferredFile> deferredFiles;
1341+ DeferredFiles deferredFiles;
13161342
13171343 for (const Arg *arg : args) {
13181344 const Option &opt = arg->getOption ();
@@ -1390,8 +1416,24 @@ static void createFiles(const InputArgList &args) {
13901416
13911417 if (config->readThreads ) {
13921418 multiThreadedPageIn (deferredFiles);
1419+
1420+ DeferredFiles archiveContents;
1421+ std::vector<ArchiveFile *> archives;
13931422 for (auto &file : deferredFiles)
1394- processFile (file.buffer , file.path , LoadType::CommandLine, file.isLazy );
1423+ if (ArchiveFile *archive = dyn_cast<ArchiveFile>(
1424+ processFile (file.buffer , &archiveContents, file.path ,
1425+ LoadType::CommandLine, file.isLazy )))
1426+ archives.push_back (archive);
1427+
1428+ if (!archiveContents.empty ()) {
1429+ multiThreadedPageIn (archiveContents);
1430+ for (auto *archive : archives)
1431+ archive->addLazySymbols ();
1432+ }
1433+
1434+ // flush threads
1435+ deferredFiles.clear ();
1436+ multiThreadedPageIn (deferredFiles);
13951437 }
13961438}
13971439
0 commit comments