Skip to content

Commit bf23faa

Browse files
authored
Merge pull request #35112 from slavapestov/request-evaluator-caching-optimization
Hacks to avoid request evaluator caching overhead
2 parents 32c5941 + 008a97e commit bf23faa

File tree

7 files changed

+73
-29
lines changed

7 files changed

+73
-29
lines changed

include/swift/AST/Decl.h

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ class alignas(1 << DeclAlignInBits) Decl {
418418
HasNestedTypeDeclarations : 1
419419
);
420420

421-
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+1,
421+
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+1+1+1,
422422
/// Whether we've computed the 'static' flag yet.
423423
IsStaticComputed : 1,
424424

@@ -437,21 +437,28 @@ class alignas(1 << DeclAlignInBits) Decl {
437437
/// Backing bits for 'self' access kind.
438438
SelfAccess : 2,
439439

440+
/// Whether we've computed the IsAsyncHandlerRequest.
441+
IsAsyncHandlerComputed : 1,
442+
443+
/// The value of IsAsyncHandlerRequest.
444+
IsAsyncHandler : 1,
445+
440446
/// Whether this is a top-level function which should be treated
441447
/// as if it were in local context for the purposes of capture
442448
/// analysis.
443449
HasTopLevelLocalContextCaptures : 1
444450
);
445451

446452
SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4 + 1 + 1,
447-
/// The kind of accessor this is.
448-
AccessorKind : 4,
453+
/// The kind of accessor this is.
454+
AccessorKind : 4,
449455

450-
/// Whether the accessor is transparent.
451-
IsTransparent : 1,
456+
/// Whether the accessor is transparent.
457+
IsTransparent : 1,
452458

453-
/// Whether we have computed the above.
454-
IsTransparentComputed : 1);
459+
/// Whether we have computed the above.
460+
IsTransparentComputed : 1
461+
);
455462

456463
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 1+1,
457464
/// Whether this constructor can fail, by building an Optional type.
@@ -5926,6 +5933,7 @@ class FuncDecl : public AbstractFunctionDecl {
59265933
friend class SelfAccessKindRequest;
59275934
friend class IsStaticRequest;
59285935
friend class ResultTypeRequest;
5936+
friend class IsAsyncHandlerRequest;
59295937

59305938
SourceLoc StaticLoc; // Location of the 'static' token or invalid.
59315939
SourceLoc FuncLoc; // Location of the 'func' token.
@@ -5957,6 +5965,8 @@ class FuncDecl : public AbstractFunctionDecl {
59575965
Bits.FuncDecl.SelfAccessComputed = false;
59585966
Bits.FuncDecl.IsStaticComputed = false;
59595967
Bits.FuncDecl.IsStatic = false;
5968+
Bits.FuncDecl.IsAsyncHandlerComputed = false;
5969+
Bits.FuncDecl.IsAsyncHandler = false;
59605970
Bits.FuncDecl.HasTopLevelLocalContextCaptures = false;
59615971
}
59625972

@@ -5987,6 +5997,18 @@ class FuncDecl : public AbstractFunctionDecl {
59875997
return None;
59885998
}
59895999

6000+
Optional<bool> getCachedIsAsyncHandler() const {
6001+
if (Bits.FuncDecl.IsAsyncHandlerComputed)
6002+
return Bits.FuncDecl.IsAsyncHandler;
6003+
6004+
return None;
6005+
}
6006+
6007+
void setIsAsyncHandler(bool value) {
6008+
Bits.FuncDecl.IsAsyncHandlerComputed = true;
6009+
Bits.FuncDecl.IsAsyncHandler = value;
6010+
}
6011+
59906012
public:
59916013
/// Factory function only for use by deserialization.
59926014
static FuncDecl *createDeserialized(ASTContext &Context,

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ class SelfAccessKindRequest :
802802
class IsAsyncHandlerRequest :
803803
public SimpleRequest<IsAsyncHandlerRequest,
804804
bool(FuncDecl *),
805-
RequestFlags::Cached> {
805+
RequestFlags::SeparatelyCached> {
806806
public:
807807
using SimpleRequest::SimpleRequest;
808808

@@ -812,8 +812,10 @@ class IsAsyncHandlerRequest :
812812
bool evaluate(Evaluator &evaluator, FuncDecl *func) const;
813813

814814
public:
815-
// Caching
815+
// Separate caching.
816816
bool isCached() const { return true; }
817+
Optional<bool> getCachedResult() const;
818+
void cacheResult(bool value) const;
817819
};
818820

819821
/// Determine whether the given function can be an @asyncHandler, without

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5910,6 +5910,11 @@ void VarDecl::visitAuxiliaryDecls(llvm::function_ref<void(VarDecl *)> visit) con
59105910
if (getDeclContext()->isTypeContext())
59115911
return;
59125912

5913+
// Avoid request evaluator overhead in the common case where there's
5914+
// no wrapper.
5915+
if (!getAttrs().hasAttribute<CustomAttr>())
5916+
return;
5917+
59135918
if (auto *backingVar = getPropertyWrapperBackingProperty())
59145919
visit(backingVar);
59155920

lib/AST/TypeCheckRequests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,20 @@ void SelfAccessKindRequest::cacheResult(SelfAccessKind value) const {
616616
funcDecl->setSelfAccessKind(value);
617617
}
618618

619+
//----------------------------------------------------------------------------//
620+
// IsAsyncHandlerRequest computation.
621+
//----------------------------------------------------------------------------//
622+
623+
Optional<bool> IsAsyncHandlerRequest::getCachedResult() const {
624+
auto *funcDecl = std::get<0>(getStorage());
625+
return funcDecl->getCachedIsAsyncHandler();
626+
}
627+
628+
void IsAsyncHandlerRequest::cacheResult(bool value) const {
629+
auto *funcDecl = std::get<0>(getStorage());
630+
funcDecl->setIsAsyncHandler(value);
631+
}
632+
619633
//----------------------------------------------------------------------------//
620634
// IsGetterMutatingRequest computation.
621635
//----------------------------------------------------------------------------//

lib/SILGen/SILGenDecl.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,17 +1220,21 @@ void SILGenFunction::visitPatternBindingDecl(PatternBindingDecl *PBD) {
12201220
void SILGenFunction::visitVarDecl(VarDecl *D) {
12211221
// We handle emitting the variable storage when we see the pattern binding.
12221222

1223-
// Emit the property wrapper backing initializer if necessary.
1224-
auto wrapperInfo = D->getPropertyWrapperBackingPropertyInfo();
1225-
if (wrapperInfo && wrapperInfo.initializeFromOriginal)
1226-
SGM.emitPropertyWrapperBackingInitializer(D);
1223+
// Avoid request evaluator overhead in the common case where there's
1224+
// no wrapper.
1225+
if (D->getAttrs().hasAttribute<CustomAttr>()) {
1226+
// Emit the property wrapper backing initializer if necessary.
1227+
auto wrapperInfo = D->getPropertyWrapperBackingPropertyInfo();
1228+
if (wrapperInfo && wrapperInfo.initializeFromOriginal)
1229+
SGM.emitPropertyWrapperBackingInitializer(D);
12271230

1228-
D->visitAuxiliaryDecls([&](VarDecl *var) {
1229-
if (auto *patternBinding = var->getParentPatternBinding())
1230-
visitPatternBindingDecl(patternBinding);
1231+
D->visitAuxiliaryDecls([&](VarDecl *var) {
1232+
if (auto *patternBinding = var->getParentPatternBinding())
1233+
visitPatternBindingDecl(patternBinding);
12311234

1232-
visit(var);
1233-
});
1235+
visit(var);
1236+
});
1237+
}
12341238

12351239
// Emit the variable's accessors.
12361240
D->visitEmittedAccessors([&](AccessorDecl *accessor) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,14 +2144,6 @@ std::pair<Type, bool> ConstraintSystem::adjustTypeOfOverloadReference(
21442144
llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
21452145
}
21462146

2147-
/// Whether the declaration is considered 'async'.
2148-
static bool isDeclAsync(ValueDecl *value) {
2149-
if (auto func = dyn_cast<AbstractFunctionDecl>(value))
2150-
return func->isAsyncContext();
2151-
2152-
return false;
2153-
}
2154-
21552147
/// Walk a closure AST to determine its effects.
21562148
///
21572149
/// \returns a function's extended info describing the effects, as
@@ -2374,7 +2366,7 @@ FunctionType::ExtInfo ConstraintSystem::closureEffects(ClosureExpr *expr) {
23742366

23752367
bool ConstraintSystem::isAsynchronousContext(DeclContext *dc) {
23762368
if (auto func = dyn_cast<AbstractFunctionDecl>(dc))
2377-
return isDeclAsync(func);
2369+
return func->isAsyncContext();
23782370

23792371
if (auto closure = dyn_cast<ClosureExpr>(dc))
23802372
return closureEffects(closure).isAsync();
@@ -2708,8 +2700,10 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
27082700
if (auto *decl = choice.getDeclOrNull()) {
27092701
// If we're choosing an asynchronous declaration within a synchronous
27102702
// context, or vice-versa, increase the async/async mismatch score.
2711-
if (isAsynchronousContext(useDC) != isDeclAsync(decl))
2712-
increaseScore(SK_AsyncSyncMismatch);
2703+
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
2704+
if (func->isAsyncContext() != isAsynchronousContext(useDC))
2705+
increaseScore(SK_AsyncSyncMismatch);
2706+
}
27132707

27142708
// If we're binding to an init member, the 'throws' need to line up
27152709
// between the bound and reference types.

lib/Sema/PreCheckExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,9 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) {
19261926
/// expression and folding sequence expressions.
19271927
bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc,
19281928
bool replaceInvalidRefsWithErrors) {
1929+
auto &ctx = dc->getASTContext();
1930+
FrontendStatsTracer StatsTracer(ctx.Stats, "precheck-expr", expr);
1931+
19291932
PreCheckExpression preCheck(dc, expr, replaceInvalidRefsWithErrors);
19301933
// Perform the pre-check.
19311934
if (auto result = expr->walk(preCheck)) {

0 commit comments

Comments
 (0)