@@ -146,8 +146,16 @@ namespace {
146
146
// / Imports which still need their scoped imports validated.
147
147
SmallVector<BoundImport, 16 > unvalidatedImports;
148
148
149
- // / All imported modules, including by re-exports.
150
- SmallSetVector<ImportedModuleDesc, 16 > visibleModules;
149
+ // crossImportableModules is usually relatively small (~hundreds max) and
150
+ // keeping it in order is convenient, so we use a SmallSetVector for it.
151
+ // visibleModules is much larger and we don't care about its order, so we
152
+ // use a DenseSet instead.
153
+
154
+ // / All imported modules, including by re-exports, and including submodules.
155
+ llvm::DenseSet<ImportedModuleDesc> visibleModules;
156
+
157
+ // / visibleModules but without the submoduless.
158
+ SmallSetVector<ImportedModuleDesc, 64 > crossImportableModules;
151
159
152
160
// / The index of the next module in \c visibleModules that should be
153
161
// / cross-imported.
@@ -815,14 +823,20 @@ void NameBinder::crossImport(ModuleDecl *M, UnboundImport &I) {
815
823
// FIXME: Should we warn if M doesn't reexport underlyingModule?
816
824
SF.addSeparatelyImportedOverlay (M, I.underlyingModule .get ());
817
825
818
- auto newImports = visibleModules.getArrayRef ().slice (nextModuleToCrossImport);
826
+ // FIXME: Most of the comparisons we do here are probably unnecessary. We
827
+ // only need to findCrossImports() on pairs where at least one of the two
828
+ // modules declares cross-imports, and most modules don't. This is low-hanging
829
+ // performance fruit.
830
+
831
+ auto newImports = crossImportableModules.getArrayRef ()
832
+ .slice (nextModuleToCrossImport);
819
833
for (auto &newImport : newImports) {
820
834
if (!canCrossImport (newImport))
821
835
continue ;
822
836
823
837
// Search imports up to, but not including or after, `newImport`.
824
838
auto oldImports =
825
- make_range (visibleModules .getArrayRef ().data (), &newImport);
839
+ make_range (crossImportableModules .getArrayRef ().data (), &newImport);
826
840
for (auto &oldImport : oldImports) {
827
841
if (!canCrossImport (oldImport))
828
842
continue ;
@@ -845,12 +859,13 @@ void NameBinder::crossImport(ModuleDecl *M, UnboundImport &I) {
845
859
846
860
// If findCrossImports() ever changed the visibleModules list, we'd see
847
861
// memory smashers here.
848
- assert (newImports.data () == &visibleModules[nextModuleToCrossImport] &&
862
+ assert (newImports.data () ==
863
+ &crossImportableModules[nextModuleToCrossImport] &&
849
864
" findCrossImports() should never mutate visibleModules" );
850
865
}
851
866
}
852
867
853
- nextModuleToCrossImport = visibleModules .size ();
868
+ nextModuleToCrossImport = crossImportableModules .size ();
854
869
}
855
870
856
871
void NameBinder::findCrossImports (UnboundImport &I,
@@ -864,10 +879,16 @@ void NameBinder::findCrossImports(UnboundImport &I,
864
879
<< declaringImport.module .second ->getName () << " ' -> '"
865
880
<< bystandingImport.module .second ->getName () << " '\n " );
866
881
882
+ if (ctx.Stats )
883
+ ctx.Stats ->getFrontendCounters ().NumCrossImportsChecked ++;
884
+
867
885
// Find modules we need to import.
868
886
declaringImport.module .second ->findDeclaredCrossImportOverlays (
869
887
bystandingImport.module .second ->getName (), names, I.importLoc );
870
888
889
+ if (ctx.Stats && !names.empty ())
890
+ ctx.Stats ->getFrontendCounters ().NumCrossImportsFound ++;
891
+
871
892
// Add import statements.
872
893
for (auto &name : names) {
873
894
// If we are actually compiling part of this overlay, don't try to load the
@@ -890,6 +911,11 @@ void NameBinder::findCrossImports(UnboundImport &I,
890
911
}
891
912
}
892
913
914
+ static bool isSubmodule (ModuleDecl* M) {
915
+ auto clangMod = M->findUnderlyingClangModule ();
916
+ return clangMod && clangMod->Parent ;
917
+ }
918
+
893
919
void NameBinder::addVisibleModules (ImportedModuleDesc importDesc) {
894
920
// FIXME: namelookup::getAllImports() doesn't quite do what we need (mainly
895
921
// w.r.t. scoped imports), but it seems like we could extend it to do so, and
@@ -903,7 +929,8 @@ void NameBinder::addVisibleModules(ImportedModuleDesc importDesc) {
903
929
// If they are both scoped, and they are *differently* scoped, this import
904
930
// cannot possibly expose anything new. Skip it.
905
931
if (!importDesc.module .first .empty () && !nextImport.first .empty () &&
906
- importDesc.module .first != nextImport.first )
932
+ !ModuleDecl::isSameAccessPath (importDesc.module .first ,
933
+ nextImport.first ))
907
934
continue ;
908
935
909
936
// Drop this module into the ImportDesc so we treat it as imported with the
@@ -912,9 +939,14 @@ void NameBinder::addVisibleModules(ImportedModuleDesc importDesc) {
912
939
913
940
// If we've already imported it, we've also already imported its
914
941
// imports.
915
- if (!visibleModules.insert (importDesc))
942
+ if (!visibleModules.insert (importDesc). second )
916
943
continue ;
917
944
945
+ // We don't cross-import submodules, so we shouldn't add them to the
946
+ // visibility set. (However, we do consider their reexports.)
947
+ if (!isSubmodule (importDesc.module .second ))
948
+ crossImportableModules.insert (importDesc);
949
+
918
950
// Add the module's re-exports to worklist.
919
951
nextImport.second ->getImportedModules (importsWorklist,
920
952
ModuleDecl::ImportFilterKind::Public);
0 commit comments