Skip to content

Commit 0d913e9

Browse files
authored
Merge pull request #36364 from ahoppen/pr/deferred-rawsyntax-nodes
[libSyntax] Don't create dedicated deferred nodes in SyntaxTreeCreator
2 parents 07823ab + a47bd70 commit 0d913e9

File tree

7 files changed

+294
-209
lines changed

7 files changed

+294
-209
lines changed

include/swift/Parse/SyntaxParseActions.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ struct DeferredNodeInfo {
8282
// MARK: - SyntaxParseActions
8383

8484
class SyntaxParseActions {
85-
llvm::BumpPtrAllocator DeferredNodeAllocator;
86-
8785
virtual void _anchor();
8886

8987
public:
@@ -111,24 +109,24 @@ class SyntaxParseActions {
111109
StringRef leadingTrivia,
112110
StringRef trailingTrivia,
113111
CharSourceRange range,
114-
bool isMissing);
112+
bool isMissing) = 0;
115113

116114
/// Create a deferred layout node that may or may not be recorded later using
117115
/// \c recordDeferredLayout. The \c SyntaxParseAction is responsible for
118116
/// keeping the deferred token alive until it is destructed.
119117
virtual OpaqueSyntaxNode
120118
makeDeferredLayout(syntax::SyntaxKind k, bool isMissing,
121-
const ArrayRef<RecordedOrDeferredNode> &children);
119+
const ArrayRef<RecordedOrDeferredNode> &children) = 0;
122120

123121
/// Record a deferred token node that was previously created using \c
124122
/// makeDeferredToken. The deferred data will never be used again, so it can
125123
/// be destroyed by this method. Note that not all deferred nodes will be
126124
/// recorded and that pending deferred nodes need to be freed when the \c
127125
/// SyntaxParseActions is destructed.
128-
virtual OpaqueSyntaxNode recordDeferredToken(OpaqueSyntaxNode deferred);
126+
virtual OpaqueSyntaxNode recordDeferredToken(OpaqueSyntaxNode deferred) = 0;
129127

130128
/// Record a deferred layout node. See recordDeferredToken.
131-
virtual OpaqueSyntaxNode recordDeferredLayout(OpaqueSyntaxNode deferred);
129+
virtual OpaqueSyntaxNode recordDeferredLayout(OpaqueSyntaxNode deferred) = 0;
132130

133131
/// Since most data of \c ParsedRawSyntax is described as opaque data, the
134132
/// \c ParsedRawSyntax node needs to reach out to the \c SyntaxParseAction,
@@ -140,11 +138,11 @@ class SyntaxParseActions {
140138
/// node starts at \p StartLoc.
141139
virtual DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
142140
size_t childIndex,
143-
SourceLoc startLoc);
141+
SourceLoc startLoc) = 0;
144142

145143
/// Return the number of children, \p node has. These can be retrieved using
146144
/// \c getDeferredChild.
147-
virtual size_t getDeferredNumChildren(OpaqueSyntaxNode node);
145+
virtual size_t getDeferredNumChildren(OpaqueSyntaxNode node) = 0;
148146

149147
/// Attempt to realize an opaque raw syntax node for a source file into a
150148
/// SourceFileSyntax node. This will return \c None if the parsing action

include/swift/SyntaxParse/SyntaxTreeCreator.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class SourceFileSyntax;
3333
///
3434
/// It also handles caching re-usable RawSyntax objects and skipping parsed
3535
/// nodes via consulting a \c SyntaxParsingCache.
36-
class SyntaxTreeCreator: public SyntaxParseActions {
36+
class SyntaxTreeCreator final : public SyntaxParseActions {
3737
SourceManager &SM;
3838
unsigned BufferID;
3939
RC<syntax::SyntaxArena> Arena;
@@ -48,6 +48,8 @@ class SyntaxTreeCreator: public SyntaxParseActions {
4848
/// tree.
4949
SyntaxParsingCache *SyntaxCache;
5050

51+
llvm::BumpPtrAllocator ScratchAlloc;
52+
5153
public:
5254
SyntaxTreeCreator(SourceManager &SM, unsigned bufferID,
5355
SyntaxParsingCache *syntaxCache,
@@ -70,6 +72,23 @@ class SyntaxTreeCreator: public SyntaxParseActions {
7072

7173
std::pair<size_t, OpaqueSyntaxNode>
7274
lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) override;
75+
76+
OpaqueSyntaxNode makeDeferredToken(tok tokenKind, StringRef leadingTrivia,
77+
StringRef trailingTrivia,
78+
CharSourceRange range,
79+
bool isMissing) override;
80+
81+
OpaqueSyntaxNode
82+
makeDeferredLayout(syntax::SyntaxKind k, bool IsMissing,
83+
const ArrayRef<RecordedOrDeferredNode> &children) override;
84+
85+
OpaqueSyntaxNode recordDeferredToken(OpaqueSyntaxNode deferred) override;
86+
OpaqueSyntaxNode recordDeferredLayout(OpaqueSyntaxNode deferred) override;
87+
88+
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node, size_t ChildIndex,
89+
SourceLoc StartLoc) override;
90+
91+
size_t getDeferredNumChildren(OpaqueSyntaxNode node) override;
7392
};
7493

7594
} // end namespace swift

lib/Parse/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ add_swift_host_library(swiftParse STATIC
2222
ParseStmt.cpp
2323
ParseType.cpp
2424
PersistentParserState.cpp
25-
SyntaxParseActions.cpp
2625
SyntaxParsingCache.cpp
2726
SyntaxParsingContext.cpp)
2827
_swift_gyb_target_sources(swiftParse PRIVATE

lib/Parse/SyntaxParseActions.cpp

Lines changed: 0 additions & 179 deletions
This file was deleted.

lib/SyntaxParse/SyntaxTreeCreator.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,92 @@ SyntaxTreeCreator::lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {
164164
size_t length = raw->getTextLength();
165165
return {length, static_cast<OpaqueSyntaxNode>(raw)};
166166
}
167+
168+
OpaqueSyntaxNode SyntaxTreeCreator::makeDeferredToken(tok tokenKind,
169+
StringRef leadingTrivia,
170+
StringRef trailingTrivia,
171+
CharSourceRange range,
172+
bool isMissing) {
173+
// Instead of creating dedicated deferred nodes that will be recorded only if
174+
// needed, the SyntaxTreeCreator always records all nodes and forms RawSyntax
175+
// nodes for them. This eliminates a bunch of copies that would otherwise
176+
// be required to record the deferred nodes.
177+
// Should a deferred node not be recorded, its data stays alive in the
178+
// SyntaxArena. This causes a small memory leak but since most nodes are
179+
// being recorded, it is acceptable.
180+
if (isMissing) {
181+
auto Node = recordMissingToken(tokenKind, range.getStart());
182+
return Node;
183+
} else {
184+
auto Node = recordToken(tokenKind, leadingTrivia, trailingTrivia, range);
185+
return Node;
186+
}
187+
}
188+
189+
OpaqueSyntaxNode SyntaxTreeCreator::makeDeferredLayout(
190+
syntax::SyntaxKind k, bool IsMissing,
191+
const ArrayRef<RecordedOrDeferredNode> &children) {
192+
SmallVector<OpaqueSyntaxNode, 16> opaqueChildren;
193+
opaqueChildren.reserve(children.size());
194+
195+
for (size_t i = 0; i < children.size(); ++i) {
196+
opaqueChildren.push_back(children[i].getOpaque());
197+
}
198+
199+
// Also see comment in makeDeferredToken
200+
return recordRawSyntax(k, opaqueChildren);
201+
}
202+
203+
OpaqueSyntaxNode
204+
SyntaxTreeCreator::recordDeferredToken(OpaqueSyntaxNode deferred) {
205+
// We don't diffirentiate between deferred and recorded nodes. See comment in
206+
// makeDeferredToken.
207+
return deferred;
208+
}
209+
210+
OpaqueSyntaxNode
211+
SyntaxTreeCreator::recordDeferredLayout(OpaqueSyntaxNode deferred) {
212+
// We don't diffirentiate between deferred and recorded nodes. See comment in
213+
// makeDeferredToken.
214+
return deferred;
215+
}
216+
217+
DeferredNodeInfo SyntaxTreeCreator::getDeferredChild(OpaqueSyntaxNode node,
218+
size_t ChildIndex,
219+
SourceLoc StartLoc) {
220+
const RawSyntax *raw = static_cast<const RawSyntax *>(node);
221+
222+
// Compute the start offset of the child node by advancing StartLoc by the
223+
// length of all previous child nodes.
224+
for (unsigned i = 0; i < ChildIndex; ++i) {
225+
const RawSyntax *child = raw->getChild(i);
226+
if (child) {
227+
StartLoc = StartLoc.getAdvancedLoc(child->getTextLength());
228+
}
229+
}
230+
231+
const RawSyntax *Child = raw->getChild(ChildIndex);
232+
if (Child == nullptr) {
233+
return DeferredNodeInfo(
234+
RecordedOrDeferredNode(nullptr, RecordedOrDeferredNode::Kind::Null),
235+
syntax::SyntaxKind::Unknown, tok::NUM_TOKENS, /*IsMissing=*/false,
236+
CharSourceRange(StartLoc, /*Length=*/0));
237+
} else if (Child->isToken()) {
238+
return DeferredNodeInfo(
239+
RecordedOrDeferredNode(Child,
240+
RecordedOrDeferredNode::Kind::DeferredToken),
241+
syntax::SyntaxKind::Token, Child->getTokenKind(), Child->isMissing(),
242+
CharSourceRange(StartLoc, Child->getTextLength()));
243+
} else {
244+
return DeferredNodeInfo(
245+
RecordedOrDeferredNode(Child,
246+
RecordedOrDeferredNode::Kind::DeferredLayout),
247+
Child->getKind(), tok::NUM_TOKENS,
248+
/*IsMissing=*/false, CharSourceRange(StartLoc, Child->getTextLength()));
249+
}
250+
}
251+
252+
size_t SyntaxTreeCreator::getDeferredNumChildren(OpaqueSyntaxNode node) {
253+
const syntax::RawSyntax *raw = static_cast<const syntax::RawSyntax *>(node);
254+
return raw->getNumChildren();
255+
}

0 commit comments

Comments
 (0)