Skip to content

Commit 9e1b206

Browse files
committed
[Serialization] Collapse indirection in DeclContextID
...by making it a tagged union of either a DeclID or a LocalDeclContextID. This should lead to smaller module files and be slightly more efficient to deserialize, and also means that every AST entity kind is serialized in exactly one way, which allows for the following commit's refactoring.
1 parent e56743e commit 9e1b206

File tree

7 files changed

+116
-161
lines changed

7 files changed

+116
-161
lines changed

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ PATTERN(VAR)
149149
OTHER(PARAMETERLIST, 210)
150150
// 211 is unused
151151
OTHER(FOREIGN_ERROR_CONVENTION, 212)
152-
OTHER(DECL_CONTEXT, 213)
152+
// 213 is unused
153153
OTHER(XREF_TYPE_PATH_PIECE, 214)
154154
OTHER(XREF_VALUE_PATH_PIECE, 215)
155155
OTHER(XREF_EXTENSION_PATH_PIECE, 216)

include/swift/Serialization/ModuleFile.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,6 @@ class ModuleFile
305305
/// Decls referenced by this module.
306306
MutableArrayRef<Serialized<Decl*>> Decls;
307307

308-
/// DeclContexts referenced by this module.
309-
MutableArrayRef<Serialized<DeclContext*>> DeclContexts;
310-
311308
/// Local DeclContexts referenced by this module.
312309
MutableArrayRef<Serialized<DeclContext*>> LocalDeclContexts;
313310

@@ -862,7 +859,7 @@ class ModuleFile
862859
DeclContext *getDeclContext(serialization::DeclContextID DID);
863860

864861
/// Returns the local decl context with the given ID, deserializing it if needed.
865-
DeclContext *getLocalDeclContext(serialization::DeclContextID DID);
862+
DeclContext *getLocalDeclContext(serialization::LocalDeclContextID DID);
866863

867864
/// Returns the appropriate module for the given ID.
868865
ModuleDecl *getModule(serialization::ModuleID MID);

include/swift/Serialization/ModuleFormat.h

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 514; // specialize attr
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 515; // remove DeclContext indirection
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -66,9 +66,58 @@ using TypeIDWithBitField = BCFixed<32>;
6666
using IdentifierID = DeclID;
6767
using IdentifierIDField = DeclIDField;
6868

69-
// DeclContextID must be the same as DeclID because it is stored in the same way.
70-
using DeclContextID = DeclID;
71-
using DeclContextIDField = DeclIDField;
69+
// LocalDeclContextID must be the same as DeclID because it is stored in the
70+
// same way.
71+
using LocalDeclContextID = DeclID;
72+
using LocalDeclContextIDField = DeclIDField;
73+
74+
/// Stores either a DeclID or a LocalDeclContextID, using 32 bits.
75+
class DeclContextID {
76+
int32_t rawValue;
77+
explicit DeclContextID(int32_t rawValue) : rawValue(rawValue) {}
78+
public:
79+
DeclContextID() : DeclContextID(0) {}
80+
81+
static DeclContextID forDecl(DeclID value) {
82+
assert(value && "should encode null using DeclContextID()");
83+
assert(llvm::isUInt<31>(value) && "too many DeclIDs");
84+
return DeclContextID(static_cast<int32_t>(value));
85+
}
86+
static DeclContextID forLocalDeclContext(LocalDeclContextID value) {
87+
assert(value && "should encode null using DeclContextID()");
88+
assert(llvm::isUInt<31>(value) && "too many LocalDeclContextIDs");
89+
return DeclContextID(-static_cast<int32_t>(value));
90+
}
91+
92+
explicit operator bool() const {
93+
return rawValue != 0;
94+
}
95+
96+
Optional<DeclID> getAsDeclID() const {
97+
if (rawValue > 0)
98+
return DeclID(rawValue);
99+
return None;
100+
}
101+
102+
Optional<LocalDeclContextID> getAsLocalDeclContextID() const {
103+
if (rawValue < 0)
104+
return LocalDeclContextID(-rawValue);
105+
return None;
106+
}
107+
108+
static DeclContextID getFromOpaqueValue(uint32_t opaqueValue) {
109+
return DeclContextID(opaqueValue);
110+
}
111+
uint32_t getOpaqueValue() const { return rawValue; }
112+
};
113+
114+
class DeclContextIDField : public BCFixed<32> {
115+
public:
116+
static DeclContextID convert(uint64_t rawValue) {
117+
assert(llvm::isUInt<32>(rawValue));
118+
return DeclContextID::getFromOpaqueValue(rawValue);
119+
}
120+
};
72121

73122
// NormalConformanceID must be the same as DeclID because it is stored
74123
// in the same way.
@@ -1154,7 +1203,7 @@ namespace decls_block {
11541203
StaticSpellingKindField, // spelling of 'static' or 'class'
11551204
BCVBR<3>, // numpatterns
11561205
BCArray<DeclContextIDField> // init contexts
1157-
// The patterns and decl-contexts trail the record.
1206+
// The patterns trail the record.
11581207
>;
11591208

11601209
template <unsigned Code>
@@ -1520,16 +1569,6 @@ namespace decls_block {
15201569
BCFixed<2> // modref value
15211570
>;
15221571

1523-
using DeclContextLayout = BCRecordLayout<
1524-
DECL_CONTEXT,
1525-
// If this DeclContext is a local context, this is an
1526-
// index into the local decl context table.
1527-
// If this DeclContext is a Decl (and not a DeclContext
1528-
// *at all*, this is an index into the decl table.
1529-
DeclContextIDField,
1530-
BCFixed<1> // is a decl
1531-
>;
1532-
15331572
using ForeignErrorConventionLayout = BCRecordLayout<
15341573
FOREIGN_ERROR_CONVENTION,
15351574
ForeignErrorConventionKindField, // kind
@@ -1739,7 +1778,6 @@ namespace index_block {
17391778

17401779
ENTRY_POINT,
17411780
LOCAL_DECL_CONTEXT_OFFSETS,
1742-
DECL_CONTEXT_OFFSETS,
17431781
LOCAL_TYPE_DECLS,
17441782
OPAQUE_RETURN_TYPE_DECLS,
17451783
GENERIC_ENVIRONMENT_OFFSETS,

lib/Serialization/Deserialization.cpp

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,7 @@ StringRef ModuleFile::getIdentifierText(IdentifierID IID) {
18051805
return rawStrPtr.slice(0, terminatorOffset);
18061806
}
18071807

1808-
DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
1808+
DeclContext *ModuleFile::getLocalDeclContext(LocalDeclContextID DCID) {
18091809
assert(DCID != 0 && "invalid local DeclContext ID 0");
18101810
auto &declContextOrOffset = LocalDeclContexts[DCID-1];
18111811

@@ -1893,56 +1893,24 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
18931893
}
18941894

18951895
DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) {
1896-
if (DCID == 0)
1896+
if (!DCID)
18971897
return FileContext;
18981898

1899-
assert(DCID <= DeclContexts.size() && "invalid DeclContext ID");
1900-
auto &declContextOrOffset = DeclContexts[DCID-1];
1899+
if (Optional<LocalDeclContextID> contextID = DCID.getAsLocalDeclContextID())
1900+
return getLocalDeclContext(contextID.getValue());
19011901

1902-
if (declContextOrOffset.isComplete())
1903-
return declContextOrOffset;
1904-
1905-
BCOffsetRAII restoreOffset(DeclTypeCursor);
1906-
DeclTypeCursor.JumpToBit(declContextOrOffset);
1907-
auto entry = DeclTypeCursor.advance();
1902+
auto D = getDecl(DCID.getAsDeclID().getValue());
19081903

1909-
if (entry.Kind != llvm::BitstreamEntry::Record)
1910-
fatal();
1911-
1912-
SmallVector<uint64_t, 64> scratch;
1913-
StringRef blobData;
1904+
if (auto GTD = dyn_cast<GenericTypeDecl>(D))
1905+
return GTD;
1906+
if (auto ED = dyn_cast<ExtensionDecl>(D))
1907+
return ED;
1908+
if (auto AFD = dyn_cast<AbstractFunctionDecl>(D))
1909+
return AFD;
1910+
if (auto SD = dyn_cast<SubscriptDecl>(D))
1911+
return SD;
19141912

1915-
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
1916-
1917-
if (recordID != decls_block::DECL_CONTEXT)
1918-
llvm_unreachable("Expected a DECL_CONTEXT record");
1919-
1920-
DeclContextID declOrDeclContextId;
1921-
bool isDecl;
1922-
1923-
decls_block::DeclContextLayout::readRecord(scratch, declOrDeclContextId,
1924-
isDecl);
1925-
1926-
if (!isDecl)
1927-
return getLocalDeclContext(declOrDeclContextId);
1928-
1929-
auto D = getDecl(declOrDeclContextId);
1930-
1931-
if (auto ND = dyn_cast<NominalTypeDecl>(D)) {
1932-
declContextOrOffset = ND;
1933-
} else if (auto ED = dyn_cast<ExtensionDecl>(D)) {
1934-
declContextOrOffset = ED;
1935-
} else if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
1936-
declContextOrOffset = AFD;
1937-
} else if (auto SD = dyn_cast<SubscriptDecl>(D)) {
1938-
declContextOrOffset = SD;
1939-
} else if (auto TAD = dyn_cast<TypeAliasDecl>(D)) {
1940-
declContextOrOffset = TAD;
1941-
} else {
1942-
llvm_unreachable("Unknown Decl : DeclContext kind");
1943-
}
1944-
1945-
return declContextOrOffset;
1913+
llvm_unreachable("Unknown Decl : DeclContext kind");
19461914
}
19471915

19481916
ModuleDecl *ModuleFile::getModule(ModuleID MID) {
@@ -3195,8 +3163,10 @@ class swift::DeclDeserializer {
31953163
}
31963164

31973165
patterns.emplace_back(pattern.get(), DeclContextID());
3198-
if (!initContextIDs.empty())
3199-
patterns.back().second = initContextIDs[i];
3166+
if (!initContextIDs.empty()) {
3167+
patterns.back().second =
3168+
DeclContextID::getFromOpaqueValue(initContextIDs[i]);
3169+
}
32003170
}
32013171

32023172
auto binding =

lib/Serialization/ModuleFile.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -874,10 +874,6 @@ bool ModuleFile::readIndexBlock(llvm::BitstreamCursor &cursor) {
874874
assert(blobData.empty());
875875
allocateBuffer(Decls, scratch);
876876
break;
877-
case index_block::DECL_CONTEXT_OFFSETS:
878-
assert(blobData.empty());
879-
allocateBuffer(DeclContexts, scratch);
880-
break;
881877
case index_block::TYPE_OFFSETS:
882878
assert(blobData.empty());
883879
allocateBuffer(Types, scratch);

0 commit comments

Comments
 (0)