From 678b0934d657cb03016dff9c53e96bc2f830e675 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 15 Aug 2025 16:09:49 -0700 Subject: [PATCH] AST: Request-ify getting the AvailabilityDomain from a ValueDecl. Cache the result of turning a `ValueDecl` into an `AvailabilityDomain`. Use split caching to make the common case of the decl not representing an availability domain efficient. NFC. --- include/swift/AST/AvailabilityDomain.h | 3 +-- include/swift/AST/Decl.h | 5 +++++ include/swift/AST/TypeCheckRequests.h | 20 +++++++++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 4 ++++ lib/AST/AvailabilityDomain.cpp | 17 +++++++++++--- lib/AST/TypeCheckRequests.cpp | 25 +++++++++++++++++++++ lib/ClangImporter/ClangImporter.cpp | 2 +- lib/Serialization/Deserialization.cpp | 7 +++--- 8 files changed, 73 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/AvailabilityDomain.h b/include/swift/AST/AvailabilityDomain.h index ad054a4c47816..cc5b6e1941502 100644 --- a/include/swift/AST/AvailabilityDomain.h +++ b/include/swift/AST/AvailabilityDomain.h @@ -153,8 +153,7 @@ class AvailabilityDomain final { /// If `decl` represents an availability domain, returns the corresponding /// `AvailabilityDomain` value. Otherwise, returns `std::nullopt`. - static std::optional forCustom(ValueDecl *decl, - const ASTContext &ctx); + static std::optional forCustom(ValueDecl *decl); static AvailabilityDomain forCustom(const CustomAvailabilityDomain *domain) { return AvailabilityDomain(domain); diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 63d91361f0bbb..3f90673450792 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2925,6 +2925,10 @@ class ValueDecl : public Decl { /// Whether we've evaluated the ApplyAccessNoteRequest. unsigned accessNoteApplied : 1; + + /// Whether the AvailabilityDomainForDeclRequest request was evaluated and + /// yielded no availability domain. + unsigned noAvailabilityDomain : 1; } LazySemanticInfo = { }; friend class DynamicallyReplacedDeclRequest; @@ -2938,6 +2942,7 @@ class ValueDecl : public Decl { friend class ActorIsolationRequest; friend class OpaqueResultTypeRequest; friend class ApplyAccessNoteRequest; + friend class AvailabilityDomainForDeclRequest; friend class Decl; SourceLoc getLocFromSource() const { return NameLoc; } diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index ca631e3abd440..5cc78b9cf7168 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -5424,6 +5424,26 @@ class ModuleHasTypeCheckerPerformanceHacksEnabledRequest bool isCached() const { return true; } }; +class AvailabilityDomainForDeclRequest + : public SimpleRequest(ValueDecl *), + RequestFlags::Cached | RequestFlags::SplitCached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + std::optional evaluate(Evaluator &evaluator, + ValueDecl *decl) const; + +public: + bool isCached() const { return true; } + std::optional> getCachedResult() const; + void cacheResult(std::optional domain) const; +}; + #define SWIFT_TYPEID_ZONE TypeChecker #define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index cc07d9133b61e..3870fc714a092 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -648,3 +648,7 @@ SWIFT_REQUEST(TypeChecker, BindExtensionsForIDEInspectionRequest, SWIFT_REQUEST(TypeChecker, ModuleHasTypeCheckerPerformanceHacksEnabledRequest, bool(const ModuleDecl *), Cached, NoLocationInfo) + +SWIFT_REQUEST(TypeChecker, AvailabilityDomainForDeclRequest, + std::optional(ValueDecl *), + Cached | SplitCached, NoLocationInfo) diff --git a/lib/AST/AvailabilityDomain.cpp b/lib/AST/AvailabilityDomain.cpp index 853d234b95a0b..db245ac22f9b2 100644 --- a/lib/AST/AvailabilityDomain.cpp +++ b/lib/AST/AvailabilityDomain.cpp @@ -39,7 +39,7 @@ getCustomDomainKind(clang::FeatureAvailKind featureAvailKind) { } static const CustomAvailabilityDomain * -customDomainForClangDecl(ValueDecl *decl, const ASTContext &ctx) { +customDomainForClangDecl(ValueDecl *decl) { auto *clangDecl = decl->getClangDecl(); ASSERT(clangDecl); @@ -57,6 +57,7 @@ customDomainForClangDecl(ValueDecl *decl, const ASTContext &ctx) { if (featureInfo.second.Kind == clang::FeatureAvailKind::None) return nullptr; + auto &ctx = decl->getASTContext(); FuncDecl *predicate = nullptr; if (featureInfo.second.Kind == clang::FeatureAvailKind::Dynamic) predicate = @@ -68,12 +69,13 @@ customDomainForClangDecl(ValueDecl *decl, const ASTContext &ctx) { } std::optional -AvailabilityDomain::forCustom(ValueDecl *decl, const ASTContext &ctx) { +AvailabilityDomainForDeclRequest::evaluate(Evaluator &evaluator, + ValueDecl *decl) const { if (!decl) return std::nullopt; if (decl->hasClangNode()) { - if (auto *customDomain = customDomainForClangDecl(decl, ctx)) + if (auto *customDomain = customDomainForClangDecl(decl)) return AvailabilityDomain::forCustom(customDomain); } else { // FIXME: [availability] Handle Swift availability domains decls. @@ -82,6 +84,15 @@ AvailabilityDomain::forCustom(ValueDecl *decl, const ASTContext &ctx) { return std::nullopt; } +std::optional +AvailabilityDomain::forCustom(ValueDecl *decl) { + if (!decl) + return std::nullopt; + + return evaluateOrDefault(decl->getASTContext().evaluator, + AvailabilityDomainForDeclRequest{decl}, {}); +} + std::optional AvailabilityDomain::builtinDomainForString(StringRef string, const DeclContext *declContext) { diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 583eae48887f3..5e0e201737fff 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -2837,3 +2837,28 @@ void SemanticAvailableAttrRequest::cacheResult( if (!value) attr->setInvalid(); } + +//----------------------------------------------------------------------------// +// AvailabilityDomainForDeclRequest computation. +//----------------------------------------------------------------------------// + +std::optional> +AvailabilityDomainForDeclRequest::getCachedResult() const { + auto decl = std::get<0>(getStorage()); + + if (decl->LazySemanticInfo.noAvailabilityDomain) + return std::optional(); + return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this); +} + +void AvailabilityDomainForDeclRequest::cacheResult( + std::optional domain) const { + auto decl = std::get<0>(getStorage()); + + if (!domain) { + decl->LazySemanticInfo.noAvailabilityDomain = 1; + return; + } + + decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(domain)); +} diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index ebf22b009cbcf..f32996e7afa94 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -4103,7 +4103,7 @@ void ClangModuleUnit::lookupAvailabilityDomains( if (!imported) return; - auto customDomain = AvailabilityDomain::forCustom(imported, ctx); + auto customDomain = AvailabilityDomain::forCustom(imported); ASSERT(customDomain); results.push_back(*customDomain); } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index c71df81e84512..b915dbf22fbba 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -5824,8 +5824,7 @@ decodeDomainKind(uint8_t kind) { static std::optional decodeAvailabilityDomain(AvailabilityDomainKind domainKind, - PlatformKind platformKind, ValueDecl *decl, - const ASTContext &ctx) { + PlatformKind platformKind, ValueDecl *decl) { switch (domainKind) { case AvailabilityDomainKind::Universal: return AvailabilityDomain::forUniversal(); @@ -5838,7 +5837,7 @@ decodeAvailabilityDomain(AvailabilityDomainKind domainKind, case AvailabilityDomainKind::Platform: return AvailabilityDomain::forPlatform(platformKind); case AvailabilityDomainKind::Custom: - return AvailabilityDomain::forCustom(decl, ctx); + return AvailabilityDomain::forCustom(decl); } } @@ -5905,7 +5904,7 @@ DeclDeserializer::readAvailable_DECL_ATTR(SmallVectorImpl &scratch, } } - auto domain = decodeAvailabilityDomain(domainKind, platform, domainDecl, ctx); + auto domain = decodeAvailabilityDomain(domainKind, platform, domainDecl); if (!domain) return llvm::make_error();