Skip to content

Commit d421f55

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 0e2234f commit d421f55

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
@@ -3851,24 +3851,7 @@ ValueDecl::findImport(const DeclContext *fromDC) {
38513851
if (!fromSourceFile)
38523852
return std::nullopt;
38533853

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

38743857
bool ValueDecl::isProtocolRequirement() const {

lib/AST/Module.cpp

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

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

0 commit comments

Comments
 (0)