@@ -496,42 +496,19 @@ bool FrameAnalysis::restoreFrameIndex(BinaryFunction &BF) {
496
496
void FrameAnalysis::cleanAnnotations () {
497
497
NamedRegionTimer T (" cleanannotations" , " clean annotations" , " FA" ,
498
498
" FA breakdown" , opts::TimeFA);
499
- auto cleanBlock = [&](std::map<uint64_t , BinaryFunction>::iterator BlockBegin,
500
- std::map<uint64_t , BinaryFunction>::iterator BlockEnd) {
501
- for (auto It = BlockBegin; It != BlockEnd; ++It) {
502
- auto &BF = It->second ;
503
-
504
- for (auto &BB : BF) {
505
- for (auto &Inst : BB) {
506
- BC.MIB ->removeAnnotation (Inst, " ArgAccessEntry" );
507
- BC.MIB ->removeAnnotation (Inst, " FrameAccessEntry" );
508
- }
499
+
500
+ ParallelUtilities::WorkFuncTy CleanFunction = [&](BinaryFunction &BF) {
501
+ for (auto &BB : BF) {
502
+ for (auto &Inst : BB) {
503
+ BC.MIB ->removeAnnotation (Inst, " ArgAccessEntry" );
504
+ BC.MIB ->removeAnnotation (Inst, " FrameAccessEntry" );
509
505
}
510
506
}
511
507
};
512
508
513
- if (opts::NoThreads) {
514
- cleanBlock (BC.getBinaryFunctions ().begin (), BC.getBinaryFunctions ().end ());
515
- return ;
516
- }
517
-
518
- ThreadPool ThPool (opts::ThreadCount);
519
- const unsigned TasksCount = 20 * opts::ThreadCount;
520
- const unsigned SingleTaskSize = BC.getBinaryFunctions ().size () / TasksCount;
521
-
522
- auto BlockBegin = BC.getBinaryFunctions ().begin ();
523
- unsigned CurSize = 0 ;
524
- for (auto It = BC.getBinaryFunctions ().begin ();
525
- It != BC.getBinaryFunctions ().end (); ++It) {
526
- CurSize++;
527
- if (CurSize >= SingleTaskSize) {
528
- ThPool.async (cleanBlock, BlockBegin, std::next (It));
529
- BlockBegin = std::next (It);
530
- CurSize = 0 ;
531
- }
532
- }
533
- ThPool.async (cleanBlock, BlockBegin, BC.getBinaryFunctions ().end ());
534
- ThPool.wait ();
509
+ ParallelUtilities::runOnEachFunction (
510
+ BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, CleanFunction,
511
+ ParallelUtilities::PredicateTy (nullptr ), " cleanAnnotations" );
535
512
}
536
513
537
514
FrameAnalysis::FrameAnalysis (BinaryContext &BC, BinaryFunctionCallGraph &CG)
@@ -613,127 +590,53 @@ void FrameAnalysis::clearSPTMap() {
613
590
return ;
614
591
}
615
592
616
- auto clearBlock = [&](std::map<uint64_t , BinaryFunction>::iterator BlockBegin,
617
- std::map<uint64_t , BinaryFunction>::iterator BlockEnd) {
618
- for (auto It = BlockBegin; It != BlockEnd; ++It) {
619
- auto &BF = It->second ;
620
-
621
- if (!BF.isSimple () || !BF.hasCFG ())
622
- continue ;
623
-
624
- auto &SPTPtr = SPTMap.find (&BF)->second ;
625
- SPTPtr.reset ();
626
- }
593
+ ParallelUtilities::WorkFuncTy ClearFunctionSPT = [&](BinaryFunction &BF) {
594
+ auto &SPTPtr = SPTMap.find (&BF)->second ;
595
+ SPTPtr.reset ();
627
596
};
628
597
629
- ThreadPool ThPool (opts::ThreadCount);
630
- unsigned CurId = 0 ;
631
- auto BlockBegin = BC.getBinaryFunctions ().begin ();
632
-
633
- // Functions that use the same allocator id are on the same task
634
- for (auto It = BC.getBinaryFunctions ().begin ();
635
- It != BC.getBinaryFunctions ().end (); ++It) {
636
- auto &BF = It->second ;
637
-
638
- if (BF.isSimple () && BF.hasCFG ()) {
639
- auto &SPT = getSPT (BF);
640
-
641
- // First valid allocator id is seen
642
- if (CurId == 0 ) {
643
- BlockBegin = It;
644
- CurId = SPT.getAllocatorId ();
645
- continue ;
646
- }
598
+ ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
599
+ return !BF.isSimple () || !BF.hasCFG ();
600
+ };
647
601
648
- if (CurId != SPT.getAllocatorId ()) {
649
- CurId = SPT.getAllocatorId ();
650
- ThPool.async (clearBlock, BlockBegin, It);
651
- BlockBegin = It;
652
- }
653
- }
654
- }
602
+ ParallelUtilities::runOnEachFunction (
603
+ BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, ClearFunctionSPT,
604
+ SkipFunc, " clearSPTMap" );
655
605
656
- ThPool.async (clearBlock, BlockBegin, BC.getBinaryFunctions ().end ());
657
- ThPool.wait ();
658
606
SPTMap.clear ();
659
607
}
660
608
661
609
void FrameAnalysis::preComputeSPT () {
662
- // Create a lock that postpone execution of tasks until all allocators are
663
- // initialized
664
- std::shared_timed_mutex Mutex;
665
- std::unique_lock<std::shared_timed_mutex> MainLock (Mutex);
666
-
667
- auto runBlock = [&](std::map<uint64_t , BinaryFunction>::iterator BlockBegin,
668
- std::map<uint64_t , BinaryFunction>::iterator BlockEnd,
669
- MCPlusBuilder::AllocatorIdTy AllocId) {
670
- // Wait until all tasks are created
671
- std::shared_lock<std::shared_timed_mutex> Lock (Mutex);
672
-
673
- Timer T (" preComputeSPT runBlock" , " preComputeSPT runBlock" );
674
- DEBUG (T.startTimer ());
675
- for (auto It = BlockBegin; It != BlockEnd; ++It) {
676
- auto &BF = It->second ;
677
-
678
- if (!BF.isSimple () || !BF.hasCFG ())
679
- continue ;
680
-
681
- auto &SPTPtr = SPTMap.find (&BF)->second ;
682
- SPTPtr = std::make_unique<StackPointerTracking>(BC, BF, AllocId);
683
- SPTPtr->run ();
684
- }
685
- DEBUG (T.stopTimer ());
686
- };
687
-
688
610
// Make sure that the SPTMap is empty
689
611
assert (SPTMap.size () == 0 );
690
612
691
613
// Create map entries to allow lock-free parallel execution
692
- unsigned TotalCost = 0 ;
693
614
for (auto &BFI : BC.getBinaryFunctions ()) {
694
615
auto &BF = BFI.second ;
695
616
if (!BF.isSimple () || !BF.hasCFG ())
696
617
continue ;
697
- TotalCost += BF.size () * BF.size ();
698
618
SPTMap.emplace (&BF, std::unique_ptr<StackPointerTracking>());
699
619
}
700
620
701
621
// Create an index for the SPT annotation to allow lock-free parallel
702
622
// execution
703
623
BC.MIB ->getOrCreateAnnotationIndex (" StackPointerTracking" );
704
624
705
- // The runtime cost of a single function is estimated by the square of its
706
- // size, the load distribution tries to create blocks of equal runtime.
707
- ThreadPool ThPool (opts::ThreadCount);
708
- const unsigned BlocksCount = 20 * opts::ThreadCount;
709
- const unsigned SingleBlockCost = TotalCost / BlocksCount;
710
-
711
- // Split functions into tasks and run them in parallel each using its own
712
- // allocator
713
- auto BlockBegin = BC.getBinaryFunctions ().begin ();
714
- unsigned CurBlockCost = 0 ;
715
- for (auto It = BC.getBinaryFunctions ().begin ();
716
- It != BC.getBinaryFunctions ().end (); ++It) {
717
- auto &BF = It->second ;
718
-
719
- if (BF.isSimple () && BF.hasCFG ())
720
- CurBlockCost += BF.size () * BF.size ();
721
-
722
- if (CurBlockCost >= SingleBlockCost) {
723
- auto AllocId = BC.MIB ->initializeNewAnnotationAllocator ();
724
- SPTAllocatorsId.push_back (AllocId);
725
- ThPool.async (runBlock, BlockBegin, std::next (It), AllocId);
726
- BlockBegin = std::next (It);
727
- CurBlockCost = 0 ;
728
- }
729
- }
730
- auto AllocId = BC.MIB ->initializeNewAnnotationAllocator ();
731
- SPTAllocatorsId.push_back (AllocId);
732
- ThPool.async (runBlock, BlockBegin, BC.getBinaryFunctions ().end (), AllocId);
625
+ // Run SPT in parallel
626
+ ParallelUtilities::WorkFuncWithAllocTy ProcessFunction =
627
+ [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {
628
+ auto &SPTPtr = SPTMap.find (&BF)->second ;
629
+ SPTPtr = std::make_unique<StackPointerTracking>(BC, BF, AllocId);
630
+ SPTPtr->run ();
631
+ };
632
+
633
+ ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {
634
+ return !BF.isSimple () || !BF.hasCFG ();
635
+ };
733
636
734
- // Start executing tasks
735
- MainLock. unlock ();
736
- ThPool. wait ( );
637
+ ParallelUtilities::runOnEachFunctionWithUniqueAllocId (
638
+ BC, ParallelUtilities::SchedulingPolicy::SP_BB_QUADRATIC, ProcessFunction,
639
+ SkipPredicate, " preComputeSPT " );
737
640
}
738
641
739
642
} // namespace bolt
0 commit comments