Skip to content

[Dependency Scanning] Have the scanner cache answer queries relevant to current search paths only. #38703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
Expand Down Expand Up @@ -853,6 +854,13 @@ class ASTContext final {
ModuleDependenciesCache &cache,
InterfaceSubContextDelegate &delegate);

/// Compute the extra implicit framework search paths on Apple platforms:
/// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/.
std::vector<std::string> getDarwinImplicitFrameworkSearchPaths() const;

/// Return a set of all possible filesystem locations where modules can be found.
llvm::StringSet<> getAllModuleSearchPathsSet() const;

/// Load extensions to the given nominal type from the external
/// module loaders.
///
Expand Down
35 changes: 27 additions & 8 deletions include/swift/AST/ModuleDependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ enum class ModuleDependenciesKind : int8_t {
Clang,
};

/// Details of a given module used for dependency scanner cache queries.
struct ModuleLookupSpecifics {
Optional<ModuleDependenciesKind> kind;
llvm::StringSet<> currentSearchPaths;
};

/// Base class for the variant storage of ModuleDependencies.
///
/// This class is mostly an implementation detail for \c ModuleDependencies.
Expand Down Expand Up @@ -407,21 +413,25 @@ using ModuleDependencyID = std::pair<std::string, ModuleDependenciesKind>;
/// A cache describing the set of module dependencies that has been queried
/// thus far.
class ModuleDependenciesCache {
using ModuleDependenciesVector = llvm::SmallVector<ModuleDependencies, 1>;

/// All cached module dependencies, in the order in which they were
/// encountered.
std::vector<ModuleDependencyID> AllModules;

/// Dependencies for Textual Swift modules that have already been computed.
llvm::StringMap<ModuleDependencies> SwiftTextualModuleDependencies;
/// This maps a module's id (name, kind) to a vector of Dependency objects, which correspond
/// to instances of the same module that may have been found in different sets of search paths.
llvm::StringMap<ModuleDependenciesVector> SwiftTextualModuleDependencies;

/// Dependencies for Binary Swift modules that have already been computed.
llvm::StringMap<ModuleDependencies> SwiftBinaryModuleDependencies;
llvm::StringMap<ModuleDependenciesVector> SwiftBinaryModuleDependencies;

/// Dependencies for Swift placeholder dependency modules that have already been computed.
llvm::StringMap<ModuleDependencies> SwiftPlaceholderModuleDependencies;
llvm::StringMap<ModuleDependenciesVector> SwiftPlaceholderModuleDependencies;

/// Dependencies for Clang modules that have already been computed.
llvm::StringMap<ModuleDependencies> ClangModuleDependencies;
llvm::StringMap<ModuleDependenciesVector> ClangModuleDependencies;

/// Additional information needed for Clang dependency scanning.
ClangModuleDependenciesCacheImpl *clangImpl = nullptr;
Expand All @@ -437,9 +447,9 @@ class ModuleDependenciesCache {

/// Retrieve the dependencies map that corresponds to the given dependency
/// kind.
llvm::StringMap<ModuleDependencies> &getDependenciesMap(
llvm::StringMap<ModuleDependenciesVector> &getDependenciesMap(
ModuleDependenciesKind kind);
const llvm::StringMap<ModuleDependencies> &getDependenciesMap(
const llvm::StringMap<ModuleDependenciesVector> &getDependenciesMap(
ModuleDependenciesKind kind) const;

public:
Expand Down Expand Up @@ -469,12 +479,21 @@ class ModuleDependenciesCache {

/// Whether we have cached dependency information for the given module.
bool hasDependencies(StringRef moduleName,
Optional<ModuleDependenciesKind> kind) const;
ModuleLookupSpecifics details) const;

/// Look for module dependencies for a module with the given name.
/// Look for module dependencies for a module with the given name given current search paths.
///
/// \returns the cached result, or \c None if there is no cached entry.
Optional<ModuleDependencies> findDependencies(
StringRef moduleName,
ModuleLookupSpecifics details) const;

/// Look for module dependencies for a module with the given name.
/// This method has a deliberately-obtuse name to indicate that it is not to be used for general
/// queries.
///
/// \returns the cached result, or \c None if there is no cached entry.
Optional<ModuleDependenciesVector> findAllDependenciesIrrespectiveOfSearchPaths(
StringRef moduleName,
Optional<ModuleDependenciesKind> kind) const;

Expand Down
83 changes: 73 additions & 10 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/RawComment.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/SILLayout.h"
#include "swift/AST/SemanticAttrs.h"
#include "swift/AST/SourceFile.h"
Expand Down Expand Up @@ -1641,29 +1642,32 @@ Optional<ModuleDependencies> ASTContext::getModuleDependencies(
bool cacheOnly) {
// Retrieve the dependencies for this module.
if (cacheOnly) {
auto searchPathSet = getAllModuleSearchPathsSet();
// Check whether we've cached this result.
if (!isUnderlyingClangModule) {
if (auto found = cache.findDependencies(moduleName,
ModuleDependenciesKind::SwiftTextual))
if (auto found = cache.findDependencies(
moduleName,
{ModuleDependenciesKind::SwiftTextual, searchPathSet}))
return found;
if (auto found = cache.findDependencies(moduleName,
ModuleDependenciesKind::SwiftTextual))
if (auto found = cache.findDependencies(
moduleName, {ModuleDependenciesKind::SwiftBinary, searchPathSet}))
return found;
if (auto found = cache.findDependencies(moduleName,
ModuleDependenciesKind::SwiftPlaceholder))
if (auto found = cache.findDependencies(
moduleName,
{ModuleDependenciesKind::SwiftPlaceholder, searchPathSet}))
return found;
}
if (auto found = cache.findDependencies(moduleName,
ModuleDependenciesKind::Clang))
if (auto found = cache.findDependencies(
moduleName, {ModuleDependenciesKind::Clang, searchPathSet}))
return found;
} else {
for (auto &loader : getImpl().ModuleLoaders) {
if (isUnderlyingClangModule &&
loader.get() != getImpl().TheClangModuleLoader)
continue;

if (auto dependencies = loader->getModuleDependencies(moduleName, cache,
delegate))
if (auto dependencies =
loader->getModuleDependencies(moduleName, cache, delegate))
return dependencies;
}
}
Expand All @@ -1686,6 +1690,65 @@ ASTContext::getSwiftModuleDependencies(StringRef moduleName,
return None;
}

namespace {
static StringRef
pathStringFromFrameworkSearchPath(const SearchPathOptions::FrameworkSearchPath &next) {
return next.Path;
};
}

std::vector<std::string> ASTContext::getDarwinImplicitFrameworkSearchPaths()
const {
assert(LangOpts.Target.isOSDarwin());
SmallString<128> systemFrameworksScratch;
systemFrameworksScratch = SearchPathOpts.SDKPath;
llvm::sys::path::append(systemFrameworksScratch, "System", "Library", "Frameworks");

SmallString<128> frameworksScratch;
frameworksScratch = SearchPathOpts.SDKPath;
llvm::sys::path::append(frameworksScratch, "Library", "Frameworks");
return {systemFrameworksScratch.str().str(), frameworksScratch.str().str()};
}

llvm::StringSet<> ASTContext::getAllModuleSearchPathsSet()
const {
llvm::StringSet<> result;
result.insert(SearchPathOpts.ImportSearchPaths.begin(),
SearchPathOpts.ImportSearchPaths.end());

// Framework paths are "special", they contain more than path strings,
// but path strings are all we care about here.
using FrameworkPathView = ArrayRefView<SearchPathOptions::FrameworkSearchPath,
StringRef,
pathStringFromFrameworkSearchPath>;
FrameworkPathView frameworkPathsOnly{SearchPathOpts.FrameworkSearchPaths};
result.insert(frameworkPathsOnly.begin(), frameworkPathsOnly.end());

if (LangOpts.Target.isOSDarwin()) {
auto implicitFrameworkSearchPaths = getDarwinImplicitFrameworkSearchPaths();
result.insert(implicitFrameworkSearchPaths.begin(),
implicitFrameworkSearchPaths.end());
}
result.insert(SearchPathOpts.RuntimeLibraryImportPaths.begin(),
SearchPathOpts.RuntimeLibraryImportPaths.end());

// ClangImporter special-cases the path for SwiftShims, so do the same here
// If there are no shims in the resource dir, add a search path in the SDK.
SmallString<128> shimsPath(SearchPathOpts.RuntimeResourcePath);
llvm::sys::path::append(shimsPath, "shims");
if (!llvm::sys::fs::exists(shimsPath)) {
shimsPath = SearchPathOpts.SDKPath;
llvm::sys::path::append(shimsPath, "usr", "lib", "swift", "shims");
}
result.insert(shimsPath.str());

// Clang system modules are found in the SDK root
SmallString<128> clangSysRootPath(SearchPathOpts.SDKPath);
llvm::sys::path::append(clangSysRootPath, "usr", "include");
result.insert(clangSysRootPath.str());
return result;
}

void ASTContext::loadExtensions(NominalTypeDecl *nominal,
unsigned previousGeneration) {
PrettyStackTraceDecl stackTrace("loading extensions for", nominal);
Expand Down
Loading