mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
If a module was first read using the adjacent swiftmodule and then reloaded using the swiftinterface, we would do an up to date check on the adjacent module but write out the unit using the swiftinterface. This would cause the same modules to be indexed repeatedly for the first invocation using a new SDK. On the next run we would instead raad the swiftmodule from the cache and thus the out of date check would match up. The impact of this varies depending on the size of the module graph in the initial compilation and the number of jobs started at the same time. Each SDK dependency is re-indexed *and* reloaded, which is a drain on both CPU and memory. Thus, if many jobs are initially started and they're all going down this path, it can cause the system to run out of memory very quickly. Resolves rdar://103119964.
134 lines
5.7 KiB
C++
134 lines
5.7 KiB
C++
//===--- ModuleDependencyScanner.h - Import Swift modules --------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2020 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/Frontend/ModuleInterfaceLoader.h"
|
|
#include "swift/Serialization/SerializedModuleLoader.h"
|
|
|
|
namespace swift {
|
|
/// A module "loader" that looks for .swiftinterface and .swiftmodule files
|
|
/// for the purpose of determining dependencies, but does not attempt to
|
|
/// load the module files.
|
|
class ModuleDependencyScanner : public SerializedModuleLoaderBase {
|
|
public:
|
|
enum ScannerKind {
|
|
MDS_plain,
|
|
MDS_placeholder
|
|
};
|
|
|
|
private:
|
|
/// The kind of scanner this is (LLVM-style RTTI)
|
|
const ScannerKind kind;
|
|
|
|
/// The module we're scanning dependencies of.
|
|
Identifier moduleName;
|
|
|
|
/// Scan the given interface file to determine dependencies.
|
|
llvm::ErrorOr<ModuleDependencyInfo> scanInterfaceFile(
|
|
Twine moduleInterfacePath, bool isFramework);
|
|
|
|
InterfaceSubContextDelegate &astDelegate;
|
|
|
|
/// Location where pre-built moduels are to be built into.
|
|
std::string moduleCachePath;
|
|
public:
|
|
Optional<ModuleDependencyInfo> dependencies;
|
|
|
|
ModuleDependencyScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
|
|
Identifier moduleName,
|
|
InterfaceSubContextDelegate &astDelegate,
|
|
ScannerKind kind = MDS_plain)
|
|
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
|
|
/*IgnoreSwiftSourceInfoFile=*/true),
|
|
kind(kind), moduleName(moduleName), astDelegate(astDelegate),
|
|
moduleCachePath(getModuleCachePathFromClang(
|
|
ctx.getClangModuleLoader()->getClangInstance())) {}
|
|
|
|
std::error_code findModuleFilesInDirectory(
|
|
ImportPath::Element ModuleID,
|
|
const SerializedModuleBaseName &BaseName,
|
|
SmallVectorImpl<char> *ModuleInterfacePath,
|
|
SmallVectorImpl<char> *ModuleInterfaceSourcePath,
|
|
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
|
|
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
|
|
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
|
|
bool skipBuildingInterface, bool IsFramework) override;
|
|
|
|
virtual void collectVisibleTopLevelModuleNames(
|
|
SmallVectorImpl<Identifier> &names) const override {
|
|
llvm_unreachable("Not used");
|
|
}
|
|
|
|
ScannerKind getKind() const { return kind; }
|
|
static bool classof(const ModuleDependencyScanner *MDS) {
|
|
return MDS->getKind() == MDS_plain;
|
|
}
|
|
};
|
|
|
|
/// A ModuleLoader that loads placeholder dependency module stubs specified in
|
|
/// -placeholder-dependency-module-map-file
|
|
/// This loader is used only in dependency scanning to inform the scanner that a
|
|
/// set of modules constitute placeholder dependencies that are not visible to the
|
|
/// scanner but will nevertheless be provided by the scanner's clients.
|
|
/// This "loader" will not attempt to load any module files.
|
|
class PlaceholderSwiftModuleScanner : public ModuleDependencyScanner {
|
|
/// Scan the given placeholder module map
|
|
void parsePlaceholderModuleMap(StringRef fileName) {
|
|
ExplicitModuleMapParser parser(Allocator);
|
|
auto result =
|
|
parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap);
|
|
if (result == std::errc::invalid_argument) {
|
|
Ctx.Diags.diagnose(SourceLoc(),
|
|
diag::placeholder_dependency_module_map_corrupted,
|
|
fileName);
|
|
}
|
|
else if (result == std::errc::no_such_file_or_directory) {
|
|
Ctx.Diags.diagnose(SourceLoc(),
|
|
diag::placeholder_dependency_module_map_missing,
|
|
fileName);
|
|
}
|
|
}
|
|
|
|
llvm::StringMap<ExplicitModuleInfo> PlaceholderDependencyModuleMap;
|
|
llvm::BumpPtrAllocator Allocator;
|
|
|
|
public:
|
|
PlaceholderSwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
|
|
Identifier moduleName,
|
|
StringRef PlaceholderDependencyModuleMap,
|
|
InterfaceSubContextDelegate &astDelegate)
|
|
: ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate,
|
|
MDS_placeholder) {
|
|
|
|
// FIXME: Find a better place for this map to live, to avoid
|
|
// doing the parsing on every module.
|
|
if (!PlaceholderDependencyModuleMap.empty()) {
|
|
parsePlaceholderModuleMap(PlaceholderDependencyModuleMap);
|
|
}
|
|
}
|
|
|
|
virtual bool
|
|
findModule(ImportPath::Element moduleID,
|
|
SmallVectorImpl<char> *moduleInterfacePath,
|
|
SmallVectorImpl<char> *moduleInterfaceSourcePath,
|
|
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
|
|
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
|
|
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
|
|
bool skipBuildingInterface, bool &isFramework,
|
|
bool &isSystemModule) override;
|
|
|
|
static bool classof(const ModuleDependencyScanner *MDS) {
|
|
return MDS->getKind() == MDS_placeholder;
|
|
}
|
|
};
|
|
}
|