Skip to content

Commit bd2fcf3

Browse files
authored
Merge pull request #75015 from slavapestov/split-caching
Request evaluator split caching
2 parents e2f8006 + 4c7ca3e commit bd2fcf3

14 files changed

+566
-44
lines changed

include/swift/AST/Decl.h

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
357357
// for the inline bitfields.
358358
union { uint64_t OpaqueBits;
359359

360-
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1,
360+
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1+1+1+1+1,
361361
Kind : bitmax(NumDeclKindBits,8),
362362

363363
/// Whether this declaration is invalid.
@@ -388,7 +388,23 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
388388
/// True if \c ObjCInterfaceAndImplementationRequest has been computed
389389
/// and did \em not find anything. This is the fast path where we can bail
390390
/// out without checking other caches or computing anything.
391-
LacksObjCInterfaceOrImplementation : 1
391+
LacksObjCInterfaceOrImplementation : 1,
392+
393+
/// True if we're in the common case where the ExpandMemberAttributeMacros
394+
/// request returned an empty array.
395+
NoMemberAttributeMacros : 1,
396+
397+
/// True if we're in the common case where the ExpandPeerMacroRequest
398+
/// request returned an empty array.
399+
NoPeerMacros : 1,
400+
401+
/// True if we're in the common case where the GlobalActorAttributeRequest
402+
/// request returned a pair of null pointers.
403+
NoGlobalActorAttribute : 1,
404+
405+
/// True if we're in the common case where the SPIGroupsRequest
406+
/// request returned an empty array of identifiers.
407+
NoSPIGroups : 1
392408
);
393409

394410
SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+1+2+16,
@@ -436,7 +452,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
436452
IsStatic : 1
437453
);
438454

439-
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 2+1+1+1+1+1,
455+
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 2+1+1+1+1+1+1+1,
440456
/// Encodes whether this is a 'let' binding.
441457
Introducer : 2,
442458

@@ -454,7 +470,13 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
454470
IsPropertyWrapperBackingProperty : 1,
455471

456472
/// Whether this is a lazily top-level global variable from the main file.
457-
IsTopLevelGlobal : 1
473+
IsTopLevelGlobal : 1,
474+
475+
/// Whether this variable has no attached property wrappers.
476+
NoAttachedPropertyWrappers : 1,
477+
478+
/// Whether this variable has no property wrapper auxiliary variables.
479+
NoPropertyWrapperAuxiliaryVariables : 1
458480
);
459481

460482
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits,
@@ -504,7 +526,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
504526

505527
/// Whether this function is a distributed thunk for a distributed
506528
/// function or computed property.
507-
DistributedThunk: 1
529+
DistributedThunk : 1
508530
);
509531

510532
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl,
@@ -827,6 +849,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
827849
friend class MemberLookupTable;
828850
friend class DeclDeserializer;
829851
friend class RawCommentRequest;
852+
friend class ExpandMemberAttributeMacros;
853+
friend class ExpandPeerMacroRequest;
854+
friend class GlobalActorAttributeRequest;
855+
friend class SPIGroupsRequest;
830856

831857
private:
832858
llvm::PointerUnion<DeclContext *, ASTContext *> Context;
@@ -845,6 +871,38 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
845871
/// Directly set the invalid bit
846872
void setInvalidBit();
847873

874+
bool hasNoMemberAttributeMacros() const {
875+
return Bits.Decl.NoMemberAttributeMacros;
876+
}
877+
878+
void setHasNoMemberAttributeMacros() {
879+
Bits.Decl.NoMemberAttributeMacros = true;
880+
}
881+
882+
bool hasNoPeerMacros() const {
883+
return Bits.Decl.NoPeerMacros;
884+
}
885+
886+
void setHasNoPeerMacros() {
887+
Bits.Decl.NoPeerMacros = true;
888+
}
889+
890+
bool hasNoGlobalActorAttribute() const {
891+
return Bits.Decl.NoGlobalActorAttribute;
892+
}
893+
894+
void setHasNoGlobalActorAttribute() {
895+
Bits.Decl.NoGlobalActorAttribute = true;
896+
}
897+
898+
bool hasNoSPIGroups() const {
899+
return Bits.Decl.NoSPIGroups;
900+
}
901+
902+
void setHasNoSPIGroups() {
903+
Bits.Decl.NoSPIGroups = true;
904+
}
905+
848906
protected:
849907

850908
Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
@@ -857,6 +915,9 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
857915
Bits.Decl.EscapedFromIfConfig = false;
858916
Bits.Decl.Hoisted = false;
859917
Bits.Decl.LacksObjCInterfaceOrImplementation = false;
918+
Bits.Decl.NoMemberAttributeMacros = false;
919+
Bits.Decl.NoGlobalActorAttribute = false;
920+
Bits.Decl.NoSPIGroups = false;
860921
}
861922

862923
/// Get the Clang node associated with this declaration.
@@ -2749,6 +2810,10 @@ class ValueDecl : public Decl {
27492810
/// allows the entity to be replaced at runtime.
27502811
unsigned isDynamic : 1;
27512812

2813+
/// Whether the DynamicallyReplacedDeclRequest request was evaluated and
2814+
/// output a null pointer.
2815+
unsigned noDynamicallyReplacedDecl : 1;
2816+
27522817
/// Whether the "isFinal" bit has been computed yet.
27532818
unsigned isFinalComputed : 1;
27542819

@@ -2762,6 +2827,13 @@ class ValueDecl : public Decl {
27622827
/// Whether this declaration produces an implicitly unwrapped
27632828
/// optional result.
27642829
unsigned isIUO : 1;
2830+
2831+
/// Whether we're in the common case where the ActorIsolationRequest
2832+
/// request returned ActorIsolation::forUnspecified().
2833+
unsigned noActorIsolation : 1;
2834+
2835+
/// Whether we've evaluated the ApplyAccessNoteRequest.
2836+
unsigned accessNoteApplied : 1;
27652837
} LazySemanticInfo = { };
27662838

27672839
friend class DynamicallyReplacedDeclRequest;
@@ -2772,6 +2844,9 @@ class ValueDecl : public Decl {
27722844
friend class IsImplicitlyUnwrappedOptionalRequest;
27732845
friend class InterfaceTypeRequest;
27742846
friend class CheckRedeclarationRequest;
2847+
friend class ActorIsolationRequest;
2848+
friend class DynamicallyReplacedDeclRequest;
2849+
friend class ApplyAccessNoteRequest;
27752850
friend class Decl;
27762851
SourceLoc getLocFromSource() const { return NameLoc; }
27772852
protected:
@@ -6090,8 +6165,27 @@ enum class PropertyWrapperSynthesizedPropertyKind {
60906165
/// VarDecl - 'var' and 'let' declarations.
60916166
class VarDecl : public AbstractStorageDecl {
60926167
friend class NamingPatternRequest;
6168+
friend class AttachedPropertyWrappersRequest;
6169+
friend class PropertyWrapperAuxiliaryVariablesRequest;
6170+
60936171
NamedPattern *NamingPattern = nullptr;
60946172

6173+
bool hasNoAttachedPropertyWrappers() const {
6174+
return Bits.VarDecl.NoAttachedPropertyWrappers;
6175+
}
6176+
6177+
void setHasNoAttachedPropertyWrappers() {
6178+
Bits.VarDecl.NoAttachedPropertyWrappers = true;
6179+
}
6180+
6181+
bool hasNoPropertyWrapperAuxiliaryVariables() const {
6182+
return Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables;
6183+
}
6184+
6185+
void setHasNoPropertyWrapperAuxiliaryVariables() {
6186+
Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables = true;
6187+
}
6188+
60956189
public:
60966190
enum class Introducer : uint8_t {
60976191
Let = 0,
@@ -7416,6 +7510,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
74167510
friend class ParseAbstractFunctionBodyRequest;
74177511
friend class TypeCheckFunctionBodyRequest;
74187512
friend class IsFunctionBodySkippedRequest;
7513+
friend class LifetimeDependenceInfoRequest;
74197514

74207515
CaptureInfo Captures;
74217516

@@ -7431,6 +7526,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
74317526
struct {
74327527
unsigned NeedsNewVTableEntryComputed : 1;
74337528
unsigned NeedsNewVTableEntry : 1;
7529+
unsigned NoLifetimeDependenceInfo : 1;
74347530
} LazySemanticInfo = { };
74357531

74367532
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,

include/swift/AST/Evaluator.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,31 @@ class Evaluator {
271271
recorder.clearRequest<Request>(request);
272272
}
273273

274+
/// Store a value in the request evaluator's cache for a split-cached request.
275+
/// The request chooses to do this itself for storing some suitable definition of
276+
/// "non-empty" value.
277+
template<typename Request,
278+
typename std::enable_if<Request::hasSplitCache>::type* = nullptr>
279+
void cacheNonEmptyOutput(const Request &request,
280+
typename Request::OutputType &&output) {
281+
bool inserted = cache.insert<Request>(request, std::move(output));
282+
assert(inserted && "Request result was already cached");
283+
(void) inserted;
284+
}
285+
286+
/// Consults the request evaluator's cache for a split-cached request.
287+
/// The request should perform this check after consulting it's own optimized
288+
/// representation for storing an empty value.
289+
template<typename Request,
290+
typename std::enable_if<Request::hasSplitCache>::type* = nullptr>
291+
std::optional<typename Request::OutputType>
292+
getCachedNonEmptyOutput(const Request &request) {
293+
auto found = cache.find_as(request);
294+
if (found == cache.end<Request>())
295+
return std::nullopt;
296+
return found->second;
297+
}
298+
274299
/// Clear the cache stored within this evaluator.
275300
///
276301
/// Note that this does not clear the caches of requests that use external
@@ -283,6 +308,8 @@ class Evaluator {
283308
return activeRequests.count(ActiveRequest(request));
284309
}
285310

311+
void dump(llvm::raw_ostream &out) { cache.dump(out); }
312+
286313
private:
287314
/// Diagnose a cycle detected in the evaluation of the given
288315
/// request.

include/swift/AST/Expr.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
266266
Kind : 2
267267
);
268268

269-
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1+1+1+1+1,
269+
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1+1+1+1+1+1,
270270
/// True if closure parameters were synthesized from anonymous closure
271271
/// variables.
272272
HasAnonymousClosureVars : 1,
@@ -284,7 +284,11 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
284284
IsolatedByPreconcurrency : 1,
285285

286286
/// True if this is a closure literal that is passed to a sending parameter.
287-
IsPassedToSendingParameter : 1
287+
IsPassedToSendingParameter : 1,
288+
289+
/// True if we're in the common case where the GlobalActorAttributeRequest
290+
/// request returned a pair of null pointers.
291+
NoGlobalActorAttribute : 1
288292
);
289293

290294
SWIFT_INLINE_BITFIELD_FULL(BindOptionalExpr, Expr, 16,
@@ -4124,6 +4128,16 @@ class ClosureExpr : public AbstractClosureExpr {
41244128
/// The body of the closure.
41254129
BraceStmt *Body;
41264130

4131+
friend class GlobalActorAttributeRequest;
4132+
4133+
bool hasNoGlobalActorAttribute() const {
4134+
return Bits.ClosureExpr.NoGlobalActorAttribute;
4135+
}
4136+
4137+
void setHasNoGlobalActorAttribute() {
4138+
Bits.ClosureExpr.NoGlobalActorAttribute = true;
4139+
}
4140+
41274141
public:
41284142
ClosureExpr(const DeclAttributes &attributes,
41294143
SourceRange bracketRange, VarDecl *capturedSelfDecl,
@@ -4143,6 +4157,7 @@ class ClosureExpr : public AbstractClosureExpr {
41434157
Bits.ClosureExpr.ImplicitSelfCapture = false;
41444158
Bits.ClosureExpr.InheritActorContext = false;
41454159
Bits.ClosureExpr.IsPassedToSendingParameter = false;
4160+
Bits.ClosureExpr.NoGlobalActorAttribute = false;
41464161
}
41474162

41484163
SourceRange getSourceRange() const;

include/swift/AST/RequestCache.h

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/DependencyCollector.h"
1919
#include "llvm/ADT/DenseMap.h"
2020
#include "llvm/ADT/StringRef.h"
21+
#include "llvm/Support/raw_ostream.h"
2122

2223
#ifndef SWIFT_AST_REQUEST_CACHE_H
2324
#define SWIFT_AST_REQUEST_CACHE_H
@@ -162,14 +163,22 @@ class RequestKey<Request, typename detail::TupleHasDenseMapInfo<
162163
class PerRequestCache {
163164
void *Storage;
164165
std::function<void(void *)> Deleter;
166+
std::function<void(llvm::raw_ostream &out, void *)> Dumper;
165167

166-
PerRequestCache(void *storage, std::function<void(void *)> deleter)
167-
: Storage(storage), Deleter(deleter) {}
168+
PerRequestCache(void *storage,
169+
std::function<void(void *)> deleter,
170+
std::function<void(llvm::raw_ostream &out, void *)> dumper)
171+
: Storage(storage), Deleter(deleter), Dumper(dumper) {}
168172

169173
public:
170-
PerRequestCache() : Storage(nullptr), Deleter([](void *) {}) {}
174+
PerRequestCache()
175+
: Storage(nullptr),
176+
Deleter([](void *) {}),
177+
Dumper([](llvm::raw_ostream &, void *) {}) {}
171178
PerRequestCache(PerRequestCache &&other)
172-
: Storage(other.Storage), Deleter(std::move(other.Deleter)) {
179+
: Storage(other.Storage),
180+
Deleter(std::move(other.Deleter)),
181+
Dumper(std::move(other.Dumper)) {
173182
other.Storage = nullptr;
174183
}
175184

@@ -190,7 +199,17 @@ class PerRequestCache {
190199
llvm::DenseMap<RequestKey<Request>,
191200
typename Request::OutputType>;
192201
return PerRequestCache(new Map(),
193-
[](void *ptr) { delete static_cast<Map *>(ptr); });
202+
[](void *ptr) { delete static_cast<Map *>(ptr); },
203+
[](llvm::raw_ostream &out, void *storage) {
204+
out << TypeID<Request>::getName() << "\t";
205+
if (auto *map = static_cast<Map *>(storage)) {
206+
out << map->size() << "\t"
207+
<< llvm::capacity_in_bytes(*map);
208+
} else {
209+
out << "0\t0";
210+
}
211+
out << "\n";
212+
});
194213
}
195214

196215
template <typename Request>
@@ -204,11 +223,28 @@ class PerRequestCache {
204223
return static_cast<Map *>(Storage);
205224
}
206225

226+
template <typename Request>
227+
std::pair<size_t, size_t>
228+
size() const {
229+
using Map =
230+
llvm::DenseMap<RequestKey<Request>,
231+
typename Request::OutputType>;
232+
if (!Storage)
233+
return std::make_pair(0, 0);
234+
235+
auto map = static_cast<Map *>(Storage);
236+
return std::make_pair(map.size(), llvm::capacity_in_bytes(map));
237+
}
238+
207239
bool isNull() const { return !Storage; }
208240
~PerRequestCache() {
209241
if (Storage)
210242
Deleter(Storage);
211243
}
244+
245+
void dump(llvm::raw_ostream &out) {
246+
Dumper(out, Storage);
247+
}
212248
};
213249

214250
/// Data structure for caching results of requests. Sharded by the type ID
@@ -275,6 +311,15 @@ class RequestCache {
275311
void clear() {
276312
#define SWIFT_TYPEID_ZONE(Name, Id) Name##ZoneCache.clear();
277313
#include "swift/Basic/TypeIDZones.def"
314+
#undef SWIFT_TYPEID_ZONE
315+
}
316+
317+
void dump(llvm::raw_ostream &out) {
318+
#define SWIFT_TYPEID_ZONE(Name, Id) \
319+
for (auto &entry : Name##ZoneCache) { \
320+
entry.dump(out); \
321+
}
322+
#include "swift/Basic/TypeIDZones.def"
278323
#undef SWIFT_TYPEID_ZONE
279324
}
280325
};

0 commit comments

Comments
 (0)