mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[AST] Use cached deserialized decl in getOpaqueResultTypeDecl
Mangling and looking up the opaque result type decl
for serialized decls is a fairly expensive
operation. Instead, fallthrough to the request
which will have a cached value set by deserialization.
This shaves ~30ms off the cached completion for:
```swift
import SwiftUI
struct V: View {
var body: some View {
Table(#^CC^#
}
}
```
This commit is contained in:
@@ -2758,6 +2758,10 @@ private:
|
|||||||
/// output a null pointer.
|
/// output a null pointer.
|
||||||
unsigned noDynamicallyReplacedDecl : 1;
|
unsigned noDynamicallyReplacedDecl : 1;
|
||||||
|
|
||||||
|
/// Whether the OpaqueResultTypeRequest request was evaluated and produced
|
||||||
|
/// a null pointer.
|
||||||
|
unsigned noOpaqueResultType : 1;
|
||||||
|
|
||||||
/// Whether the "isFinal" bit has been computed yet.
|
/// Whether the "isFinal" bit has been computed yet.
|
||||||
unsigned isFinalComputed : 1;
|
unsigned isFinalComputed : 1;
|
||||||
|
|
||||||
@@ -2785,7 +2789,7 @@ private:
|
|||||||
friend class InterfaceTypeRequest;
|
friend class InterfaceTypeRequest;
|
||||||
friend class CheckRedeclarationRequest;
|
friend class CheckRedeclarationRequest;
|
||||||
friend class ActorIsolationRequest;
|
friend class ActorIsolationRequest;
|
||||||
friend class DynamicallyReplacedDeclRequest;
|
friend class OpaqueResultTypeRequest;
|
||||||
friend class ApplyAccessNoteRequest;
|
friend class ApplyAccessNoteRequest;
|
||||||
|
|
||||||
friend class Decl;
|
friend class Decl;
|
||||||
|
|||||||
@@ -2295,21 +2295,22 @@ public:
|
|||||||
|
|
||||||
/// Builds an opaque result type for a declaration.
|
/// Builds an opaque result type for a declaration.
|
||||||
class OpaqueResultTypeRequest
|
class OpaqueResultTypeRequest
|
||||||
: public SimpleRequest<OpaqueResultTypeRequest,
|
: public SimpleRequest<
|
||||||
OpaqueTypeDecl *(ValueDecl *),
|
OpaqueResultTypeRequest, OpaqueTypeDecl *(ValueDecl *),
|
||||||
RequestFlags::Cached> {
|
RequestFlags::SeparatelyCached | RequestFlags::SplitCached> {
|
||||||
public:
|
public:
|
||||||
using SimpleRequest::SimpleRequest;
|
using SimpleRequest::SimpleRequest;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend SimpleRequest;
|
friend SimpleRequest;
|
||||||
|
|
||||||
OpaqueTypeDecl *
|
OpaqueTypeDecl *evaluate(Evaluator &evaluator, ValueDecl *VD) const;
|
||||||
evaluate(Evaluator &evaluator, ValueDecl *VD) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Caching.
|
// Split caching.
|
||||||
bool isCached() const { return true; }
|
bool isCached() const { return true; }
|
||||||
|
std::optional<OpaqueTypeDecl *> getCachedResult() const;
|
||||||
|
void cacheResult(OpaqueTypeDecl *result) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Determines if a function declaration is 'static'.
|
/// Determines if a function declaration is 'static'.
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest,
|
|||||||
NoLocationInfo)
|
NoLocationInfo)
|
||||||
SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest,
|
SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest,
|
||||||
OpaqueTypeDecl *(ValueDecl *),
|
OpaqueTypeDecl *(ValueDecl *),
|
||||||
Cached, NoLocationInfo)
|
SeparatelyCached | SplitCached, NoLocationInfo)
|
||||||
SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest,
|
SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest,
|
||||||
PrecedenceGroupDecl *(PrecedenceGroupDecl *),
|
PrecedenceGroupDecl *(PrecedenceGroupDecl *),
|
||||||
Cached, NoLocationInfo)
|
Cached, NoLocationInfo)
|
||||||
|
|||||||
@@ -3887,21 +3887,6 @@ TypeRepr *ValueDecl::getOpaqueResultTypeRepr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const {
|
OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const {
|
||||||
if (getOpaqueResultTypeRepr() == nullptr) {
|
|
||||||
if (!isa<VarDecl>(this) &&
|
|
||||||
!isa<FuncDecl>(this) &&
|
|
||||||
!isa<SubscriptDecl>(this))
|
|
||||||
return nullptr;
|
|
||||||
auto file = cast<FileUnit>(getDeclContext()->getModuleScopeContext());
|
|
||||||
// Don't look up when the decl is from source, otherwise a cycle will happen.
|
|
||||||
if (file->getKind() == FileUnitKind::SerializedAST) {
|
|
||||||
Mangle::ASTMangler mangler;
|
|
||||||
auto name = mangler.mangleOpaqueTypeDecl(this);
|
|
||||||
return file->lookupOpaqueResultType(name);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return evaluateOrDefault(getASTContext().evaluator,
|
return evaluateOrDefault(getASTContext().evaluator,
|
||||||
OpaqueResultTypeRequest{const_cast<ValueDecl *>(this)},
|
OpaqueResultTypeRequest{const_cast<ValueDecl *>(this)},
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|||||||
@@ -385,6 +385,28 @@ void DynamicallyReplacedDeclRequest::cacheResult(ValueDecl *result) const {
|
|||||||
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
|
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
// OpaqueResultTypeRequest caching.
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
std::optional<OpaqueTypeDecl *>
|
||||||
|
OpaqueResultTypeRequest::getCachedResult() const {
|
||||||
|
auto *decl = std::get<0>(getStorage());
|
||||||
|
if (decl->LazySemanticInfo.noOpaqueResultType)
|
||||||
|
return std::optional(nullptr);
|
||||||
|
|
||||||
|
return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpaqueResultTypeRequest::cacheResult(OpaqueTypeDecl *result) const {
|
||||||
|
auto *decl = std::get<0>(getStorage());
|
||||||
|
if (!result) {
|
||||||
|
decl->LazySemanticInfo.noOpaqueResultType = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
// ApplyAccessNoteRequest computation.
|
// ApplyAccessNoteRequest computation.
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ OpaqueTypeDecl *
|
|||||||
OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
|
OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
|
||||||
ValueDecl *originatingDecl) const {
|
ValueDecl *originatingDecl) const {
|
||||||
auto *repr = originatingDecl->getOpaqueResultTypeRepr();
|
auto *repr = originatingDecl->getOpaqueResultTypeRepr();
|
||||||
assert(repr && "Declaration does not have an opaque result type");
|
if (!repr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
auto *dc = originatingDecl->getInnermostDeclContext();
|
auto *dc = originatingDecl->getInnermostDeclContext();
|
||||||
auto &ctx = dc->getASTContext();
|
auto &ctx = dc->getASTContext();
|
||||||
|
|
||||||
|
|||||||
@@ -3936,14 +3936,17 @@ public:
|
|||||||
if (var->hasStorage())
|
if (var->hasStorage())
|
||||||
AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true));
|
AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true));
|
||||||
|
|
||||||
if (opaqueReturnTypeID) {
|
{
|
||||||
auto opaqueReturnType = MF.getDeclChecked(opaqueReturnTypeID);
|
OpaqueTypeDecl *opaqueDecl = nullptr;
|
||||||
if (!opaqueReturnType)
|
if (opaqueReturnTypeID) {
|
||||||
return opaqueReturnType.takeError();
|
auto opaqueReturnType = MF.getDeclChecked(opaqueReturnTypeID);
|
||||||
|
if (!opaqueReturnType)
|
||||||
|
return opaqueReturnType.takeError();
|
||||||
|
|
||||||
ctx.evaluator.cacheOutput(
|
opaqueDecl = cast<OpaqueTypeDecl>(opaqueReturnType.get());
|
||||||
OpaqueResultTypeRequest{var},
|
}
|
||||||
cast<OpaqueTypeDecl>(opaqueReturnType.get()));
|
ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{var},
|
||||||
|
std::move(opaqueDecl));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a lazy property, record its backing storage.
|
// If this is a lazy property, record its backing storage.
|
||||||
@@ -4357,14 +4360,17 @@ public:
|
|||||||
fn->setIsObjC(isObjC);
|
fn->setIsObjC(isObjC);
|
||||||
fn->setForcedStaticDispatch(hasForcedStaticDispatch);
|
fn->setForcedStaticDispatch(hasForcedStaticDispatch);
|
||||||
|
|
||||||
if (opaqueReturnTypeID) {
|
{
|
||||||
auto declOrError = MF.getDeclChecked(opaqueReturnTypeID);
|
OpaqueTypeDecl *opaqueDecl = nullptr;
|
||||||
if (!declOrError)
|
if (opaqueReturnTypeID) {
|
||||||
return declOrError.takeError();
|
auto declOrError = MF.getDeclChecked(opaqueReturnTypeID);
|
||||||
|
if (!declOrError)
|
||||||
|
return declOrError.takeError();
|
||||||
|
|
||||||
ctx.evaluator.cacheOutput(
|
opaqueDecl = cast<OpaqueTypeDecl>(declOrError.get());
|
||||||
OpaqueResultTypeRequest{fn},
|
}
|
||||||
cast<OpaqueTypeDecl>(declOrError.get()));
|
ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{fn},
|
||||||
|
std::move(opaqueDecl));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAccessor)
|
if (!isAccessor)
|
||||||
@@ -5204,16 +5210,19 @@ public:
|
|||||||
subscript->setOverriddenDecl(cast_or_null<SubscriptDecl>(overridden.get()));
|
subscript->setOverriddenDecl(cast_or_null<SubscriptDecl>(overridden.get()));
|
||||||
if (subscript->getOverriddenDecl())
|
if (subscript->getOverriddenDecl())
|
||||||
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
|
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
|
||||||
|
|
||||||
if (opaqueReturnTypeID) {
|
|
||||||
Decl *opaqueReturnType;
|
|
||||||
UNWRAP(MF.getDeclChecked(opaqueReturnTypeID), opaqueReturnType);
|
|
||||||
|
|
||||||
ctx.evaluator.cacheOutput(
|
{
|
||||||
OpaqueResultTypeRequest{subscript},
|
OpaqueTypeDecl *opaqueDecl = nullptr;
|
||||||
cast<OpaqueTypeDecl>(opaqueReturnType));
|
if (opaqueReturnTypeID) {
|
||||||
|
Decl *opaqueReturnType;
|
||||||
|
UNWRAP(MF.getDeclChecked(opaqueReturnTypeID), opaqueReturnType);
|
||||||
|
|
||||||
|
opaqueDecl = cast<OpaqueTypeDecl>(opaqueReturnType);
|
||||||
|
}
|
||||||
|
ctx.evaluator.cacheOutput(OpaqueResultTypeRequest{subscript},
|
||||||
|
std::move(opaqueDecl));
|
||||||
}
|
}
|
||||||
|
|
||||||
return subscript;
|
return subscript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user