Skip to content

Conversation

@artemcm
Copy link
Contributor

@artemcm artemcm commented Oct 15, 2025

Previously, with the change to bridge Clang dependency scanning results on-demand, the scanner would execute Clang dependency scanning queries for each unresolved import, in parallel, and aggregate all of the results to post-process (including on-demand bridging) later. As a consequence of that change, all of the Clang scanner queries' results (TranslationUnitDeps) got aggregated during a scan and had their lifetimes extended until a later point when they got processed and added to the scanner's cache.

This change refactors the Clang dependency scanner invocation to, upon query completion, accumulate only the ModuleDeps nodes which have not been registered by a prior scan, discarding the rest of the TranslationUnitDeps graph. The arrgegated ModuleDeps objects are still bridged on-demand downstream.

This change further splits up the resolveAllClangModuleDependencies method's functionality to improve readability and maintainability, into:

  • gatherUnresolvedImports method which collects all of collected Swift dependents' imports which did not get resolved to Swift dependencies
  • performParallelClangModuleLookup which actually executes the parallel queries and includes the new logic described above
  • cacheComputedClangModuleLookupResults method which takes the result of the parallel Clang scanner query and records in in the Swift scanner cache
  • reQueryMissedModulesFromCache method which covers the scenario where Clang scanner query returned no result because either the dependency can only be found transitively, or the query is for a dependency previously-queried.

@artemcm
Copy link
Contributor Author

artemcm commented Oct 15, 2025

@swift-ci test

struct BatchClangModuleLookupResult {
llvm::StringMap<clang::tooling::dependencies::ModuleDeps>
discoveredDependencyInfos;
llvm::StringMap<std::vector<std::string>> visibleModules;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StringMap is not thread-safe. A normal insert might be but it can expand when full. We need a lock for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have a lock for this, it is only ever modified in performParallelClangModuleLookup in a critical section guarded with a lock.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a helper function to the class to ensure the correct lock usage. It might even be cleaner to move the lock here to avoid introduce regression for future refactoring.

Copy link
Contributor

@cachemeifyoucan cachemeifyoucan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function wise, it looks good for me. Some comments inline for style and nits.

struct BatchClangModuleLookupResult {
llvm::StringMap<clang::tooling::dependencies::ModuleDeps>
discoveredDependencyInfos;
llvm::StringMap<std::vector<std::string>> visibleModules;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a helper function to the class to ensure the correct lock usage. It might even be cleaner to move the lock here to avoid introduce regression for future refactoring.

…ve only partial results

Previously, with the change to bridge Clang dependency scanning results on-demand, the scanner would execute Clang dependency scanning queries for each unresolved import, in parallel, and aggregate all of the results to post-process (including on-demand bridging) later. As a consequence of that change, all of the Clang scanner queries' results ('TranslationUnitDeps') got aggregated during a scan and had their lifetimes extended until a later point when they got processed and added to the scanner's cache.

This change refactors the Clang dependency scanner invocation to, upon query completion, accumulate only the 'ModuleDeps' nodes which have not been registered by a prior scan, discarding the rest of the 'TranslationUnitDeps' graph. The arrgegated 'ModuleDeps' objects are still bridged on-demand downstream.

This change further splits up the 'resolveAllClangModuleDependencies' method's functionality to improve readability and maintainability, into:
- 'gatherUnresolvedImports' method which collects all of collected Swift dependents' imports which did not get resolved to Swift dependencies
- 'performParallelClangModuleLookup' which actually executes the parallel queries and includes the new logic described above
- 'cacheComputedClangModuleLookupResults' method which takes the result of the parallel Clang scanner query and records in in the Swift scanner cache
- 'reQueryMissedModulesFromCache' method which covers the scenario where Clang scanner query returned no result because either the dependency can only be found transitively, or the query is for a dependency previously-queried.
@artemcm artemcm force-pushed the RevertRevertOnDemandBridging branch from 98fb1ff to 8335a03 Compare October 20, 2025 20:34
@artemcm
Copy link
Contributor Author

artemcm commented Oct 20, 2025

@swift-ci smoke test

@artemcm artemcm enabled auto-merge October 20, 2025 20:34
@artemcm
Copy link
Contributor Author

artemcm commented Oct 21, 2025

@swift-ci smoke test Windows platform

@artemcm artemcm merged commit f7d008e into swiftlang:main Oct 21, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants