Skip to content

Commit a7de6ec

Browse files
authored
Merge pull request swiftlang#79761 from tshortli/availability-context-trailing-objects
AST: Reimplement `AvailabilityContext` storage using `TrailingObjects`
2 parents 98f4c1d + c6a5e6f commit a7de6ec

File tree

4 files changed

+223
-187
lines changed

4 files changed

+223
-187
lines changed

include/swift/AST/AvailabilityContext.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,9 @@ class Decl;
3737
class AvailabilityContext {
3838
public:
3939
class Storage;
40+
class DomainInfo;
4041

4142
private:
42-
class Info;
43-
4443
/// A non-null pointer to uniqued storage for this availability context.
4544
const Storage *storage;
4645

include/swift/AST/AvailabilityContextStorage.h

+59-40
Original file line numberDiff line numberDiff line change
@@ -19,64 +19,83 @@
1919

2020
#include "swift/AST/AvailabilityContext.h"
2121
#include "llvm/ADT/FoldingSet.h"
22-
#include <optional>
22+
#include "llvm/Support/TrailingObjects.h"
2323

2424
namespace swift {
2525

2626
class DeclAvailabilityConstraints;
2727

28-
/// Summarizes availability the constraints contained by an AvailabilityContext.
29-
class AvailabilityContext::Info {
30-
public:
31-
/// The introduction version.
32-
AvailabilityRange PlatformRange;
28+
/// A wrapper for storing an `AvailabilityDomain` and its associated information
29+
/// in `AvailabilityContext::Storage`.
30+
class AvailabilityContext::DomainInfo final {
31+
AvailabilityDomain domain;
32+
AvailabilityRange range;
3333

34-
/// A sorted collection of disjoint domains that are known to be
35-
/// unavailable in this context.
36-
llvm::SmallVector<AvailabilityDomain, 1> UnavailableDomains;
34+
public:
35+
DomainInfo(AvailabilityDomain domain, const AvailabilityRange &range)
36+
: domain(domain), range(range) {};
3737

38-
/// Whether or not the context is considered deprecated on the current
39-
/// platform.
40-
unsigned IsDeprecated : 1;
41-
42-
/// Sets each field to the value of the corresponding field in `other` if the
43-
/// other is more restrictive. Returns true if any field changed as a result
44-
/// of adding this constraint.
45-
bool constrainWith(const Info &other);
46-
47-
/// Constrains each field using the given constraints if they are more
48-
/// restrictive than the current values. Returns true if any field was
49-
/// updated.
50-
bool constrainWith(const DeclAvailabilityConstraints &constraints,
51-
const ASTContext &ctx);
52-
53-
bool constrainUnavailability(
54-
const llvm::SmallVectorImpl<AvailabilityDomain> &domains);
55-
bool constrainUnavailability(AvailabilityDomain domain) {
56-
return constrainUnavailability(
57-
llvm::SmallVector<AvailabilityDomain>{domain});
38+
static DomainInfo unavailable(AvailabilityDomain domain) {
39+
return DomainInfo(domain, AvailabilityRange::neverAvailable());
5840
}
5941

60-
/// Returns true if `other` is as available or is more available.
61-
bool isContainedIn(const Info &other) const;
62-
63-
void Profile(llvm::FoldingSetNodeID &ID) const;
42+
AvailabilityDomain getDomain() const { return domain; }
43+
AvailabilityRange getRange() const { return range; }
44+
bool isUnavailable() const { return range.isKnownUnreachable(); }
6445

65-
/// Returns true if all internal invariants are satisfied.
66-
bool verify(const ASTContext &ctx) const;
46+
void Profile(llvm::FoldingSetNodeID &ID) const {
47+
ID.AddPointer(domain.getOpaqueValue());
48+
range.getRawVersionRange().Profile(ID);
49+
}
6750
};
6851

6952
/// As an implementation detail, the values that make up an `Availability`
7053
/// context are uniqued and stored as folding set nodes.
71-
class AvailabilityContext::Storage final : public llvm::FoldingSetNode {
72-
Storage(const Info &info) : info(info){};
54+
class AvailabilityContext::Storage final
55+
: public llvm::FoldingSetNode,
56+
public llvm::TrailingObjects<Storage, DomainInfo> {
57+
friend TrailingObjects;
58+
59+
Storage(const AvailabilityRange &platformRange, bool isDeprecated,
60+
unsigned domainInfoCount)
61+
: platformRange(platformRange), isDeprecated(isDeprecated),
62+
domainInfoCount(domainInfoCount) {};
7363

7464
public:
75-
Info info;
65+
/// The introduction version for the current platform.
66+
const AvailabilityRange platformRange;
7667

77-
static const Storage *get(const Info &info, const ASTContext &ctx);
68+
/// Whether or not the context is considered deprecated on the current
69+
/// platform.
70+
const unsigned isDeprecated : 1;
7871

79-
void Profile(llvm::FoldingSetNodeID &ID) const { info.Profile(ID); }
72+
/// The number of `DomainInfo` objects in trailing storage.
73+
const unsigned domainInfoCount;
74+
75+
/// Retrieves the unique storage instance from the `ASTContext` for the given
76+
/// parameters.
77+
static const Storage *get(const AvailabilityRange &platformRange,
78+
bool isDeprecated,
79+
llvm::ArrayRef<DomainInfo> domainInfos,
80+
const ASTContext &ctx);
81+
82+
llvm::ArrayRef<DomainInfo> getDomainInfos() const {
83+
return llvm::ArrayRef(getTrailingObjects<DomainInfo>(), domainInfoCount);
84+
}
85+
86+
llvm::SmallVector<DomainInfo, 4> copyDomainInfos() const {
87+
return llvm::SmallVector<DomainInfo, 4>{getDomainInfos()};
88+
}
89+
90+
/// Uniquing for `ASTContext`.
91+
static void Profile(llvm::FoldingSetNodeID &ID,
92+
const AvailabilityRange &platformRange, bool isDeprecated,
93+
llvm::ArrayRef<DomainInfo> domainInfos);
94+
95+
void Profile(llvm::FoldingSetNodeID &ID) const {
96+
Profile(ID, platformRange, static_cast<bool>(isDeprecated),
97+
getDomainInfos());
98+
}
8099
};
81100

82101
} // end namespace swift

lib/AST/ASTContext.cpp

+14-6
Original file line numberDiff line numberDiff line change
@@ -5713,10 +5713,12 @@ SubstitutionMap::Storage *SubstitutionMap::Storage::get(
57135713
return result;
57145714
}
57155715

5716-
const AvailabilityContext::Storage *
5717-
AvailabilityContext::Storage::get(const Info &info, const ASTContext &ctx) {
5716+
const AvailabilityContext::Storage *AvailabilityContext::Storage::get(
5717+
const AvailabilityRange &platformRange, bool isDeprecated,
5718+
llvm::ArrayRef<DomainInfo> domainInfos, const ASTContext &ctx) {
57185719
llvm::FoldingSetNodeID id;
5719-
info.Profile(id);
5720+
AvailabilityContext::Storage::Profile(id, platformRange, isDeprecated,
5721+
domainInfos);
57205722

57215723
auto &foldingSet =
57225724
ctx.getImpl().getArena(AllocationArena::Permanent).AvailabilityContexts;
@@ -5725,9 +5727,15 @@ AvailabilityContext::Storage::get(const Info &info, const ASTContext &ctx) {
57255727
if (existing)
57265728
return existing;
57275729

5728-
void *mem = ctx.Allocate(sizeof(AvailabilityContext::Storage),
5729-
alignof(AvailabilityContext::Storage));
5730-
auto *newNode = ::new (mem) AvailabilityContext::Storage(info);
5730+
size_t storageToAlloc = AvailabilityContext::Storage::totalSizeToAlloc<
5731+
AvailabilityContext::DomainInfo>(domainInfos.size());
5732+
void *mem =
5733+
ctx.Allocate(storageToAlloc, alignof(AvailabilityContext::Storage));
5734+
auto *newNode = ::new (mem) AvailabilityContext::Storage(
5735+
platformRange, isDeprecated, domainInfos.size());
5736+
std::uninitialized_copy(
5737+
domainInfos.begin(), domainInfos.end(),
5738+
newNode->getTrailingObjects<AvailabilityContext::DomainInfo>());
57315739
foldingSet.InsertNode(newNode, insertPos);
57325740

57335741
return newNode;

0 commit comments

Comments
 (0)