@@ -755,11 +755,244 @@ size_t ModuleList::GetIndexForModule(const Module *module) const {
755
755
}
756
756
757
757
namespace {
758
+ // / A wrapper around ModuleList for shared modules. Provides fast lookups for
759
+ // / file-based ModuleSpec queries.
760
+ class SharedModuleList {
761
+ public:
762
+ // / Finds all the modules matching the module_spec, and adds them to \p
763
+ // / matching_module_list.
764
+ void FindModules (const ModuleSpec &module_spec,
765
+ ModuleList &matching_module_list) const {
766
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
767
+ // Try map first for performance - if found, skip expensive full list
768
+ // search
769
+ if (FindModulesInMap (module_spec, matching_module_list))
770
+ return ;
771
+ m_list.FindModules (module_spec, matching_module_list);
772
+ // Assert that modules were found in the list but not the map, it's
773
+ // because the module_spec has no filename or the found module has a
774
+ // different filename. For example, when searching by UUID and finding a
775
+ // module with an alias.
776
+ assert ((matching_module_list.IsEmpty () ||
777
+ module_spec.GetFileSpec ().GetFilename ().IsEmpty () ||
778
+ module_spec.GetFileSpec ().GetFilename () !=
779
+ matching_module_list.GetModuleAtIndex (0 )
780
+ ->GetFileSpec ()
781
+ .GetFilename ()) &&
782
+ " Search by name not found in SharedModuleList's map" );
783
+ }
784
+
785
+ ModuleSP FindModule (const Module *module_ptr) {
786
+ if (!module_ptr)
787
+ return ModuleSP ();
788
+
789
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
790
+ if (ModuleSP result = FindModuleInMap (module_ptr))
791
+ return result;
792
+ return m_list.FindModule (module_ptr);
793
+ }
794
+
795
+ // UUID searches bypass map since UUIDs aren't indexed by filename.
796
+ ModuleSP FindModule (const UUID &uuid) const {
797
+ return m_list.FindModule (uuid);
798
+ }
799
+
800
+ void Append (const ModuleSP &module_sp, bool use_notifier) {
801
+ if (!module_sp)
802
+ return ;
803
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
804
+ m_list.Append (module_sp, use_notifier);
805
+ AddToMap (module_sp);
806
+ }
807
+
808
+ size_t RemoveOrphans (bool mandatory) {
809
+ std::unique_lock<std::recursive_mutex> lock (GetMutex (), std::defer_lock);
810
+ if (mandatory) {
811
+ lock.lock ();
812
+ } else {
813
+ if (!lock.try_lock ())
814
+ return 0 ;
815
+ }
816
+ size_t total_count = 0 ;
817
+ size_t run_count;
818
+ do {
819
+ // Remove indexed orphans first, then remove non-indexed orphans. This
820
+ // order is important because the shared count will be different if a
821
+ // module is indexed or not.
822
+ run_count = RemoveOrphansFromMapAndList ();
823
+ run_count += m_list.RemoveOrphans (mandatory);
824
+ total_count += run_count;
825
+ // Because removing orphans might make new orphans, remove from both
826
+ // containers until a fixed-point is reached.
827
+ } while (run_count != 0 );
828
+
829
+ return total_count;
830
+ }
831
+
832
+ bool Remove (const ModuleSP &module_sp, bool use_notifier = true ) {
833
+ if (!module_sp)
834
+ return false ;
835
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
836
+ RemoveFromMap (module_sp.get ());
837
+ return m_list.Remove (module_sp, use_notifier);
838
+ }
839
+
840
+ void ReplaceEquivalent (const ModuleSP &module_sp,
841
+ llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {
842
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
843
+ m_list.ReplaceEquivalent (module_sp, old_modules);
844
+ ReplaceEquivalentInMap (module_sp);
845
+ }
846
+
847
+ bool RemoveIfOrphaned (const Module *module_ptr) {
848
+ std::lock_guard<std::recursive_mutex> guard (GetMutex ());
849
+ RemoveFromMap (module_ptr, /* if_orphaned =*/ true );
850
+ return m_list.RemoveIfOrphaned (module_ptr);
851
+ }
852
+
853
+ std::recursive_mutex &GetMutex () const { return m_list.GetMutex (); }
854
+
855
+ private:
856
+ ModuleSP FindModuleInMap (const Module *module_ptr) {
857
+ if (!module_ptr->GetFileSpec ().GetFilename ())
858
+ return ModuleSP ();
859
+ ConstString name = module_ptr->GetFileSpec ().GetFilename ();
860
+ auto it = m_name_to_modules.find (name);
861
+ if (it == m_name_to_modules.end ())
862
+ return ModuleSP ();
863
+ const llvm::SmallVectorImpl<ModuleSP> &vector = it->second ;
864
+ for (auto &module_sp : vector) {
865
+ if (module_sp.get () == module_ptr)
866
+ return module_sp;
867
+ }
868
+ return ModuleSP ();
869
+ }
870
+
871
+ bool FindModulesInMap (const ModuleSpec &module_spec,
872
+ ModuleList &matching_module_list) const {
873
+ auto it = m_name_to_modules.find (module_spec.GetFileSpec ().GetFilename ());
874
+ if (it == m_name_to_modules.end ())
875
+ return false ;
876
+ const llvm::SmallVectorImpl<ModuleSP> &vector = it->second ;
877
+ bool found = false ;
878
+ for (auto &module_sp : vector) {
879
+ if (module_sp->MatchesModuleSpec (module_spec)) {
880
+ matching_module_list.Append (module_sp);
881
+ found = true ;
882
+ }
883
+ }
884
+ return found;
885
+ }
886
+
887
+ void AddToMap (const ModuleSP &module_sp) {
888
+ ConstString name = module_sp->GetFileSpec ().GetFilename ();
889
+ if (name.IsEmpty ())
890
+ return ;
891
+ llvm::SmallVectorImpl<ModuleSP> &vec = m_name_to_modules[name];
892
+ vec.push_back (module_sp);
893
+ }
894
+
895
+ void RemoveFromMap (const Module *module_ptr, bool if_orphaned = false ) {
896
+ ConstString name = module_ptr->GetFileSpec ().GetFilename ();
897
+ auto it = m_name_to_modules.find (name);
898
+ if (it == m_name_to_modules.end ())
899
+ return ;
900
+ llvm::SmallVectorImpl<ModuleSP> &vec = it->second ;
901
+ for (auto *it = vec.begin (); it != vec.end (); ++it) {
902
+ if (it->get () == module_ptr) {
903
+ // use_count == 2 means only held by map and list (orphaned)
904
+ if (!if_orphaned || it->use_count () == 2 )
905
+ vec.erase (it);
906
+ break ;
907
+ }
908
+ }
909
+ }
910
+
911
+ void ReplaceEquivalentInMap (const ModuleSP &module_sp) {
912
+ RemoveEquivalentModulesFromMap (module_sp);
913
+ AddToMap (module_sp);
914
+ }
915
+
916
+ void RemoveEquivalentModulesFromMap (const ModuleSP &module_sp) {
917
+ ConstString name = module_sp->GetFileSpec ().GetFilename ();
918
+ if (name.IsEmpty ())
919
+ return ;
920
+
921
+ auto it = m_name_to_modules.find (name);
922
+ if (it == m_name_to_modules.end ())
923
+ return ;
924
+
925
+ // First remove any equivalent modules. Equivalent modules are modules
926
+ // whose path, platform path and architecture match.
927
+ ModuleSpec equivalent_module_spec (module_sp->GetFileSpec (),
928
+ module_sp->GetArchitecture ());
929
+ equivalent_module_spec.GetPlatformFileSpec () =
930
+ module_sp->GetPlatformFileSpec ();
931
+
932
+ llvm::SmallVectorImpl<ModuleSP> &vec = it->second ;
933
+ // Iterate backwards to minimize element shifting during removal.
934
+ for (int i = vec.size () - 1 ; i >= 0 ; --i) {
935
+ auto *it = vec.begin () + i;
936
+ if ((*it)->MatchesModuleSpec (equivalent_module_spec))
937
+ vec.erase (it);
938
+ }
939
+ }
940
+
941
+ // / Remove orphans from the vector.
942
+ // /
943
+ // / Returns the removed orphans.
944
+ ModuleList RemoveOrphansFromVector (llvm::SmallVectorImpl<ModuleSP> &vec) {
945
+ ModuleList to_remove;
946
+ for (int i = vec.size () - 1 ; i >= 0 ; --i) {
947
+ ModuleSP module = vec[i];
948
+ long kUseCountOrphaned = 2 ;
949
+ long kUseCountLocalVariable = 1 ;
950
+ // use_count == 3: map + list + local variable = orphaned.
951
+ if (module .use_count () == kUseCountOrphaned + kUseCountLocalVariable ) {
952
+ to_remove.Append (module );
953
+ vec.erase (vec.begin () + i);
954
+ }
955
+ }
956
+ return to_remove;
957
+ }
958
+
959
+ // / Remove orphans that exist in both the map and list. This does not remove
960
+ // / any orphans that exist exclusively on the list.
961
+ // /
962
+ // / This assumes that the mutex is locked.
963
+ int RemoveOrphansFromMapAndList () {
964
+ // Modules might hold shared pointers to other modules, so removing one
965
+ // module might orphan other modules. Keep removing modules until
966
+ // there are no further modules that can be removed.
967
+ bool made_progress = true ;
968
+ int remove_count = 0 ;
969
+ while (made_progress) {
970
+ made_progress = false ;
971
+ for (auto &[name, vec] : m_name_to_modules) {
972
+ if (vec.empty ())
973
+ continue ;
974
+ ModuleList to_remove = RemoveOrphansFromVector (vec);
975
+ remove_count += to_remove.GetSize ();
976
+ made_progress = !to_remove.IsEmpty ();
977
+ m_list.Remove (to_remove);
978
+ }
979
+ }
980
+ return remove_count;
981
+ }
982
+
983
+ ModuleList m_list;
984
+
985
+ // / A hash map from a module's filename to all the modules that share that
986
+ // / filename, for fast module lookups by name.
987
+ llvm::DenseMap<ConstString, llvm::SmallVector<ModuleSP, 1 >> m_name_to_modules;
988
+ };
989
+
758
990
struct SharedModuleListInfo {
759
- ModuleList module_list;
991
+ SharedModuleList module_list;
760
992
ModuleListProperties module_list_properties;
761
993
};
762
- }
994
+ } // namespace
995
+
763
996
static SharedModuleListInfo &GetSharedModuleListInfo ()
764
997
{
765
998
static SharedModuleListInfo *g_shared_module_list_info = nullptr ;
@@ -774,7 +1007,7 @@ static SharedModuleListInfo &GetSharedModuleListInfo()
774
1007
return *g_shared_module_list_info;
775
1008
}
776
1009
777
- static ModuleList &GetSharedModuleList () {
1010
+ static SharedModuleList &GetSharedModuleList () {
778
1011
return GetSharedModuleListInfo ().module_list ;
779
1012
}
780
1013
@@ -784,7 +1017,7 @@ ModuleListProperties &ModuleList::GetGlobalModuleListProperties() {
784
1017
785
1018
bool ModuleList::ModuleIsInCache (const Module *module_ptr) {
786
1019
if (module_ptr) {
787
- ModuleList &shared_module_list = GetSharedModuleList ();
1020
+ SharedModuleList &shared_module_list = GetSharedModuleList ();
788
1021
return shared_module_list.FindModule (module_ptr).get () != nullptr ;
789
1022
}
790
1023
return false ;
@@ -808,9 +1041,8 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
808
1041
const FileSpecList *module_search_paths_ptr,
809
1042
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
810
1043
bool *did_create_ptr, bool always_create) {
811
- ModuleList &shared_module_list = GetSharedModuleList ();
812
- std::lock_guard<std::recursive_mutex> guard (
813
- shared_module_list.m_modules_mutex );
1044
+ SharedModuleList &shared_module_list = GetSharedModuleList ();
1045
+ std::lock_guard<std::recursive_mutex> guard (shared_module_list.GetMutex ());
814
1046
char path[PATH_MAX];
815
1047
816
1048
Status error;
0 commit comments