@@ -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,47 @@ 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 ());
347
346
#endif
348
347
}
349
348
349
+ static void multiThreadedPageIn (DeferredFiles deferred) {
350
+ static pthread_t running;
351
+ static pthread_mutex_t busy;
352
+
353
+ if (running)
354
+ pthread_join (running, nullptr );
355
+ else
356
+ pthread_mutex_init (&busy, nullptr );
357
+
358
+ pthread_mutex_lock (&busy);
359
+ PageInState *state =
360
+ new PageInState{deferred, 0 , 0 , llvm::sys::Process::getPageSizeEstimate (),
361
+ pthread_mutex_t ()};
362
+
363
+ pthread_create (
364
+ &running, nullptr ,
365
+ [](void *ptr) -> void * {
366
+ PageInState *state = (PageInState *)ptr;
367
+ multiThreadedPageInBackground (state);
368
+ pthread_mutex_unlock (&busy);
369
+ delete state;
370
+ return nullptr ;
371
+ },
372
+ state);
373
+ }
374
+
350
375
static InputFile *processFile (std::optional<MemoryBufferRef> buffer,
351
- StringRef path, LoadType loadType,
352
- bool isLazy = false , bool isExplicit = true ,
376
+ DeferredFiles *archiveContents, StringRef path,
377
+ LoadType loadType, bool isLazy = false ,
378
+ bool isExplicit = true ,
353
379
bool isBundleLoader = false ,
354
380
bool isForceHidden = false ) {
355
381
if (!buffer)
@@ -431,7 +457,6 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
431
457
// we already found that it contains an ObjC symbol.
432
458
if (readFile (path)) {
433
459
Error e = Error::success ();
434
- std::vector<DeferredFile> deferredFiles;
435
460
for (const object::Archive::Child &c : file->getArchive ().children (e)) {
436
461
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef ();
437
462
if (!mb) {
@@ -445,9 +470,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
445
470
continue ;
446
471
}
447
472
448
- deferredFiles.push_back ({path, isLazy, std::nullopt,
449
- mb->getBuffer ().data (),
450
- mb->getBuffer ().size ()});
473
+ if (archiveContents)
474
+ archiveContents->push_back ({path, isLazy, std::nullopt,
475
+ mb->getBuffer ().data (),
476
+ mb->getBuffer ().size ()});
451
477
if (!hasObjCSection (*mb))
452
478
continue ;
453
479
if (Error e = file->fetch (c, " -ObjC" ))
@@ -457,11 +483,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
457
483
if (e)
458
484
error (toString (file) +
459
485
" : Archive::children failed: " + toString (std::move (e)));
460
- if (config->readThreads && deferredFiles.size () > 1 )
461
- multiThreadedPageIn (deferredFiles);
462
486
}
463
487
}
464
- file->addLazySymbols ();
488
+ if (!archiveContents || archiveContents->empty ())
489
+ file->addLazySymbols ();
465
490
loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
466
491
newFile = file;
467
492
break ;
@@ -516,18 +541,17 @@ static InputFile *addFile(StringRef path, LoadType loadType,
516
541
bool isLazy = false , bool isExplicit = true ,
517
542
bool isBundleLoader = false ,
518
543
bool isForceHidden = false ) {
519
- return processFile (readFile (path), path, loadType, isLazy, isExplicit ,
520
- isBundleLoader, isForceHidden);
544
+ return processFile (readFile (path), nullptr , path, loadType, isLazy,
545
+ isExplicit, isBundleLoader, isForceHidden);
521
546
}
522
547
523
- static void deferFile (StringRef path, bool isLazy,
524
- std::vector<DeferredFile> &deferred) {
548
+ static void deferFile (StringRef path, bool isLazy, DeferredFiles &deferred) {
525
549
std::optional<MemoryBufferRef> buffer = readFile (path);
526
550
if (config->readThreads )
527
551
deferred.push_back ({path, isLazy, buffer, buffer->getBuffer ().data (),
528
552
buffer->getBuffer ().size ()});
529
553
else
530
- processFile (buffer, path, LoadType::CommandLine, isLazy);
554
+ processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
531
555
}
532
556
533
557
static std::vector<StringRef> missingAutolinkWarnings;
@@ -654,7 +678,7 @@ void macho::resolveLCLinkerOptions() {
654
678
}
655
679
656
680
static void addFileList (StringRef path, bool isLazy,
657
- std::vector<DeferredFile> &deferredFiles) {
681
+ DeferredFiles &deferredFiles) {
658
682
std::optional<MemoryBufferRef> buffer = readFile (path);
659
683
if (!buffer)
660
684
return ;
@@ -1312,7 +1336,7 @@ static void createFiles(const InputArgList &args) {
1312
1336
bool isLazy = false ;
1313
1337
// If we've processed an opening --start-lib, without a matching --end-lib
1314
1338
bool inLib = false ;
1315
- std::vector<DeferredFile> deferredFiles;
1339
+ DeferredFiles deferredFiles;
1316
1340
1317
1341
for (const Arg *arg : args) {
1318
1342
const Option &opt = arg->getOption ();
@@ -1390,8 +1414,20 @@ static void createFiles(const InputArgList &args) {
1390
1414
1391
1415
if (config->readThreads ) {
1392
1416
multiThreadedPageIn (deferredFiles);
1417
+
1418
+ DeferredFiles archiveContents;
1419
+ std::vector<ArchiveFile *> archives;
1393
1420
for (auto &file : deferredFiles)
1394
- processFile (file.buffer , file.path , LoadType::CommandLine, file.isLazy );
1421
+ if (ArchiveFile *archive = dyn_cast<ArchiveFile>(
1422
+ processFile (file.buffer , &archiveContents, file.path ,
1423
+ LoadType::CommandLine, file.isLazy )))
1424
+ archives.push_back (archive);
1425
+
1426
+ if (!archiveContents.empty ()) {
1427
+ multiThreadedPageIn (archiveContents);
1428
+ for (auto *archive : archives)
1429
+ archive->addLazySymbols ();
1430
+ }
1395
1431
}
1396
1432
}
1397
1433
0 commit comments