Skip to content

Commit e626965

Browse files
committed
AST: Request-ify ValueDecl::findImport().
To prevent performance regressions from calling `findImport()` more frequently, request-ify the computation. NFC. Prerequisite of rdar://16154294
1 parent 41f2504 commit e626965

File tree

5 files changed

+63
-19
lines changed

5 files changed

+63
-19
lines changed

include/swift/AST/SourceFile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,11 @@ class SourceFile final : public FileUnit {
418418
ImportedUnderlyingModule = module;
419419
}
420420

421+
/// Finds the import declaration that effectively imports a given module in
422+
/// this source file.
423+
std::optional<AttributedImport<ImportedModule>>
424+
findImport(const ModuleDecl *mod) const;
425+
421426
/// Whether the given import has used @preconcurrency.
422427
bool hasImportUsedPreconcurrency(
423428
AttributedImport<ImportedModule> import) const;

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4845,6 +4845,27 @@ class ObjCRequirementMapRequest
48454845
bool isCached() const { return true; }
48464846
};
48474847

4848+
/// Finds the import declaration that effectively imports a given module in a
4849+
/// source file.
4850+
class ImportDeclRequest
4851+
: public SimpleRequest<ImportDeclRequest,
4852+
std::optional<AttributedImport<ImportedModule>>(
4853+
const SourceFile *sf, const ModuleDecl *mod),
4854+
RequestFlags::Cached> {
4855+
public:
4856+
using SimpleRequest::SimpleRequest;
4857+
4858+
private:
4859+
friend SimpleRequest;
4860+
4861+
std::optional<AttributedImport<ImportedModule>>
4862+
evaluate(Evaluator &evaluator, const SourceFile *sf,
4863+
const ModuleDecl *mod) const;
4864+
4865+
public:
4866+
bool isCached() const { return true; }
4867+
};
4868+
48484869
#define SWIFT_TYPEID_ZONE TypeChecker
48494870
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
48504871
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,4 +562,7 @@ SWIFT_REQUEST(TypeChecker, LocalTypeDeclsRequest,
562562
SWIFT_REQUEST(TypeChecker, ObjCRequirementMapRequest,
563563
ObjCRequirementMap(const ProtocolDecl *proto),
564564
Cached, NoLocationInfo)
565-
565+
SWIFT_REQUEST(TypeChecker, ImportDeclRequest,
566+
std::optional<AttributedImport<ImportedModule>>(
567+
const SourceFile *sf, const ModuleDecl *mod),
568+
Cached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3853,24 +3853,7 @@ ValueDecl::findImport(const DeclContext *fromDC) {
38533853
if (!fromSourceFile)
38543854
return std::nullopt;
38553855

3856-
// Look to see if the owning module was directly imported.
3857-
for (const auto &import : fromSourceFile->getImports()) {
3858-
if (import.module.importedModule == module)
3859-
return import;
3860-
}
3861-
3862-
// Now look for transitive imports.
3863-
auto &importCache = getASTContext().getImportCache();
3864-
for (const auto &import : fromSourceFile->getImports()) {
3865-
auto &importSet = importCache.getImportSet(import.module.importedModule);
3866-
for (const auto &transitive : importSet.getTransitiveImports()) {
3867-
if (transitive.importedModule == module) {
3868-
return import;
3869-
}
3870-
}
3871-
}
3872-
3873-
return std::nullopt;
3856+
return fromSourceFile->findImport(module);
38743857
}
38753858

38763859
bool ValueDecl::isProtocolRequirement() const {

lib/AST/Module.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,38 @@ SourceFile::setImports(ArrayRef<AttributedImport<ImportedModule>> imports) {
25802580
Imports = getASTContext().AllocateCopy(imports);
25812581
}
25822582

2583+
std::optional<AttributedImport<ImportedModule>>
2584+
SourceFile::findImport(const ModuleDecl *module) const {
2585+
return evaluateOrDefault(getASTContext().evaluator,
2586+
ImportDeclRequest{this, module}, std::nullopt);
2587+
}
2588+
2589+
std::optional<AttributedImport<ImportedModule>>
2590+
ImportDeclRequest::evaluate(Evaluator &evaluator, const SourceFile *sf,
2591+
const ModuleDecl *module) const {
2592+
auto &ctx = sf->getASTContext();
2593+
auto imports = sf->getImports();
2594+
2595+
// Look to see if the owning module was directly imported.
2596+
for (const auto &import : imports) {
2597+
if (import.module.importedModule == module)
2598+
return import;
2599+
}
2600+
2601+
// Now look for transitive imports.
2602+
auto &importCache = ctx.getImportCache();
2603+
for (const auto &import : imports) {
2604+
auto &importSet = importCache.getImportSet(import.module.importedModule);
2605+
for (const auto &transitive : importSet.getTransitiveImports()) {
2606+
if (transitive.importedModule == module) {
2607+
return import;
2608+
}
2609+
}
2610+
}
2611+
2612+
return std::nullopt;
2613+
}
2614+
25832615
bool SourceFile::hasImportUsedPreconcurrency(
25842616
AttributedImport<ImportedModule> import) const {
25852617
return PreconcurrencyImportsUsed.count(import) != 0;

0 commit comments

Comments
 (0)