@@ -290,27 +290,26 @@ typedef struct {
290
290
const char *start;
291
291
size_t size;
292
292
} DeferredFile;
293
+ typedef std::vector<DeferredFile> DeferredFiles;
294
+
295
+ typedef struct {
296
+ DeferredFiles deferred;
297
+ size_t counter, total, pageSize;
298
+ pthread_mutex_t mutex;
299
+ } PageInState;
293
300
294
301
// Most input files have been mapped but not yet paged in.
295
302
// This code forces the page-ins on multiple threads so
296
303
// the process is not stalled waiting on disk buffer i/o.
297
- static void multiThreadedPageIn (std::vector<DeferredFile> &deferred ) {
304
+ static void multiThreadedPageInBackground (PageInState *state ) {
298
305
#ifndef _WIN32
299
306
#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 ()};
308
307
static size_t totalBytes;
309
308
310
309
pthread_t running[MaxReadThreads];
311
310
if (config->readThreads > MaxReadThreads)
312
311
config->readThreads = MaxReadThreads;
313
- pthread_mutex_init (&state. mutex , NULL );
312
+ pthread_mutex_init (&state-> mutex , nullptr );
314
313
315
314
for (int t = 0 ; t < config->readThreads ; t++)
316
315
pthread_create (
@@ -336,20 +335,49 @@ static void multiThreadedPageIn(std::vector<DeferredFile> &deferred) {
336
335
state.total += t; // Avoids the loop being optimised out.
337
336
}
338
337
},
339
- & state);
338
+ state);
340
339
341
340
for (int t = 0 ; t < config->readThreads ; t++)
342
341
pthread_join (running[t], nullptr );
343
342
344
- pthread_mutex_destroy (&state. mutex );
343
+ pthread_mutex_destroy (&state-> mutex );
345
344
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
+ #endif
347
+ }
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
+ pthread_mutex_lock (&busy);
360
+ PageInState *state =
361
+ new PageInState{deferred, 0 , 0 , llvm::sys::Process::getPageSizeEstimate (),
362
+ pthread_mutex_t ()};
363
+
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);
347
374
#endif
348
375
}
349
376
350
377
static 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 ,
353
381
bool isBundleLoader = false ,
354
382
bool isForceHidden = false ) {
355
383
if (!buffer)
@@ -431,7 +459,6 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
431
459
// we already found that it contains an ObjC symbol.
432
460
if (readFile (path)) {
433
461
Error e = Error::success ();
434
- std::vector<DeferredFile> deferredFiles;
435
462
for (const object::Archive::Child &c : file->getArchive ().children (e)) {
436
463
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef ();
437
464
if (!mb) {
@@ -445,9 +472,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
445
472
continue ;
446
473
}
447
474
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 ()});
451
479
if (!hasObjCSection (*mb))
452
480
continue ;
453
481
if (Error e = file->fetch (c, " -ObjC" ))
@@ -457,11 +485,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
457
485
if (e)
458
486
error (toString (file) +
459
487
" : Archive::children failed: " + toString (std::move (e)));
460
- if (config->readThreads && deferredFiles.size () > 1 )
461
- multiThreadedPageIn (deferredFiles);
462
488
}
463
489
}
464
- file->addLazySymbols ();
490
+ if (!archiveContents || archiveContents->empty ())
491
+ file->addLazySymbols ();
465
492
loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
466
493
newFile = file;
467
494
break ;
@@ -516,18 +543,17 @@ static InputFile *addFile(StringRef path, LoadType loadType,
516
543
bool isLazy = false , bool isExplicit = true ,
517
544
bool isBundleLoader = false ,
518
545
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);
521
548
}
522
549
523
- static void deferFile (StringRef path, bool isLazy,
524
- std::vector<DeferredFile> &deferred) {
550
+ static void deferFile (StringRef path, bool isLazy, DeferredFiles &deferred) {
525
551
std::optional<MemoryBufferRef> buffer = readFile (path);
526
552
if (config->readThreads )
527
553
deferred.push_back ({path, isLazy, buffer, buffer->getBuffer ().data (),
528
554
buffer->getBuffer ().size ()});
529
555
else
530
- processFile (buffer, path, LoadType::CommandLine, isLazy);
556
+ processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
531
557
}
532
558
533
559
static std::vector<StringRef> missingAutolinkWarnings;
@@ -654,7 +680,7 @@ void macho::resolveLCLinkerOptions() {
654
680
}
655
681
656
682
static void addFileList (StringRef path, bool isLazy,
657
- std::vector<DeferredFile> &deferredFiles) {
683
+ DeferredFiles &deferredFiles) {
658
684
std::optional<MemoryBufferRef> buffer = readFile (path);
659
685
if (!buffer)
660
686
return ;
@@ -1312,7 +1338,7 @@ static void createFiles(const InputArgList &args) {
1312
1338
bool isLazy = false ;
1313
1339
// If we've processed an opening --start-lib, without a matching --end-lib
1314
1340
bool inLib = false ;
1315
- std::vector<DeferredFile> deferredFiles;
1341
+ DeferredFiles deferredFiles;
1316
1342
1317
1343
for (const Arg *arg : args) {
1318
1344
const Option &opt = arg->getOption ();
@@ -1390,8 +1416,20 @@ static void createFiles(const InputArgList &args) {
1390
1416
1391
1417
if (config->readThreads ) {
1392
1418
multiThreadedPageIn (deferredFiles);
1419
+
1420
+ DeferredFiles archiveContents;
1421
+ std::vector<ArchiveFile *> archives;
1393
1422
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
+ }
1395
1433
}
1396
1434
}
1397
1435
0 commit comments