Skip to content

Commit 57c1f72

Browse files
committed
[Parse] Optimize syntax parsing: Make ParsedRawSyntaxNode a POD type
This eliminates the overhead of ParsedRawSyntaxNode needing to do memory management. If ParsedRawSyntaxNode needs to point to some data the memory is allocated from a bump allocator. There are also some improvements on how the ParsedSyntaxBuilders work.
1 parent c7ac859 commit 57c1f72

17 files changed

+240
-192
lines changed

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 40 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
namespace swift {
2323

2424
typedef void *OpaqueSyntaxNode;
25+
class SyntaxParsingContext;
2526

2627
/// Represents a raw syntax node formed by the parser.
2728
///
@@ -50,12 +51,14 @@ class ParsedRawSyntaxNode {
5051
CharSourceRange Range;
5152
};
5253
struct DeferredLayoutNode {
53-
std::vector<ParsedRawSyntaxNode> Children;
54+
ArrayRef<ParsedRawSyntaxNode> Children;
5455
};
5556
struct DeferredTokenNode {
56-
Token Tok;
57-
ParsedTrivia LeadingTrivia;
58-
ParsedTrivia TrailingTrivia;
57+
const ParsedTriviaPiece *TriviaPieces;
58+
SourceLoc TokLoc;
59+
unsigned TokLength;
60+
uint16_t NumLeadingTrivia;
61+
uint16_t NumTrailingTrivia;
5962
};
6063

6164
union {
@@ -77,16 +80,22 @@ class ParsedRawSyntaxNode {
7780
assert(getKind() == k && "Syntax kind with too large value!");
7881
}
7982

80-
ParsedRawSyntaxNode(Token tok,
81-
ParsedTrivia leadingTrivia,
82-
ParsedTrivia trailingTrivia)
83-
: DeferredToken{std::move(tok),
84-
std::move(leadingTrivia),
85-
std::move(trailingTrivia)},
83+
ParsedRawSyntaxNode(tok tokKind, SourceLoc tokLoc, unsigned tokLength,
84+
const ParsedTriviaPiece *triviaPieces,
85+
unsigned numLeadingTrivia,
86+
unsigned numTrailingTrivia)
87+
: DeferredToken{triviaPieces,
88+
tokLoc, tokLength,
89+
uint16_t(numLeadingTrivia),
90+
uint16_t(numTrailingTrivia)},
8691
SynKind(uint16_t(syntax::SyntaxKind::Token)),
87-
TokKind(uint16_t(tok.getKind())),
92+
TokKind(uint16_t(tokKind)),
8893
DK(DataKind::DeferredToken) {
89-
assert(getTokenKind() == tok.getKind() && "Token kind is too large value!");
94+
assert(getTokenKind() == tokKind && "Token kind is too large value!");
95+
assert(DeferredToken.NumLeadingTrivia == numLeadingTrivia &&
96+
"numLeadingTrivia is too large value!");
97+
assert(DeferredToken.NumTrailingTrivia == numTrailingTrivia &&
98+
"numLeadingTrivia is too large value!");
9099
}
91100

92101
public:
@@ -106,63 +115,6 @@ class ParsedRawSyntaxNode {
106115
assert(getTokenKind() == tokKind && "Token kind with too large value!");
107116
}
108117

109-
ParsedRawSyntaxNode(const ParsedRawSyntaxNode &other) {
110-
switch (other.DK) {
111-
case DataKind::Null:
112-
break;
113-
case DataKind::Recorded:
114-
new(&this->RecordedData)RecordedSyntaxNode(other.RecordedData);
115-
break;
116-
case DataKind::DeferredLayout:
117-
new(&this->DeferredLayout)DeferredLayoutNode(other.DeferredLayout);
118-
break;
119-
case DataKind::DeferredToken:
120-
new(&this->DeferredToken)DeferredTokenNode(other.DeferredToken);
121-
break;
122-
}
123-
this->SynKind = other.SynKind;
124-
this->TokKind = other.TokKind;
125-
this->DK = other.DK;
126-
}
127-
128-
ParsedRawSyntaxNode(ParsedRawSyntaxNode &&other) {
129-
switch (other.DK) {
130-
case DataKind::Null:
131-
break;
132-
case DataKind::Recorded:
133-
new(&this->RecordedData)RecordedSyntaxNode(
134-
std::move(other.RecordedData));
135-
break;
136-
case DataKind::DeferredLayout:
137-
new(&this->DeferredLayout)DeferredLayoutNode(
138-
std::move(other.DeferredLayout));
139-
break;
140-
case DataKind::DeferredToken:
141-
new(&this->DeferredToken)DeferredTokenNode(
142-
std::move(other.DeferredToken));
143-
break;
144-
}
145-
this->SynKind = other.SynKind;
146-
this->TokKind = other.TokKind;
147-
this->DK = other.DK;
148-
}
149-
150-
~ParsedRawSyntaxNode() {
151-
releaseMemory();
152-
}
153-
154-
ParsedRawSyntaxNode &operator=(const ParsedRawSyntaxNode &other) {
155-
releaseMemory();
156-
new (this)ParsedRawSyntaxNode(other);
157-
return *this;
158-
}
159-
160-
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
161-
releaseMemory();
162-
new (this)ParsedRawSyntaxNode(std::move(other));
163-
return *this;
164-
}
165-
166118
syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); }
167119
tok getTokenKind() const { return tok(TokKind); }
168120

@@ -201,44 +153,44 @@ class ParsedRawSyntaxNode {
201153
assert(DK == DataKind::DeferredLayout);
202154
return DeferredLayout.Children;
203155
}
204-
void addDeferredChild(ParsedRawSyntaxNode subnode) {
205-
assert(DK == DataKind::DeferredLayout);
206-
DeferredLayout.Children.push_back(std::move(subnode));
207-
}
208156

209157
// Deferred Token Data =====================================================//
210158

211-
const Token &getToken() const {
159+
CharSourceRange getDeferredTokenRangeWithoutBackticks() const {
212160
assert(DK == DataKind::DeferredToken);
213-
return DeferredToken.Tok;
161+
return CharSourceRange{DeferredToken.TokLoc, DeferredToken.TokLength};
214162
}
215-
const ParsedTrivia &getLeadingTrivia() const {
163+
ArrayRef<ParsedTriviaPiece> getDeferredLeadingTriviaPieces() const {
216164
assert(DK == DataKind::DeferredToken);
217-
return DeferredToken.LeadingTrivia;
165+
return ArrayRef<ParsedTriviaPiece>(DeferredToken.TriviaPieces,
166+
DeferredToken.NumLeadingTrivia);
218167
}
219-
const ParsedTrivia &getTrailingTrivia() const {
168+
ArrayRef<ParsedTriviaPiece> getDeferredTrailingTriviaPieces() const {
220169
assert(DK == DataKind::DeferredToken);
221-
return DeferredToken.TrailingTrivia;
170+
return ArrayRef<ParsedTriviaPiece>(
171+
DeferredToken.TriviaPieces + DeferredToken.NumLeadingTrivia,
172+
DeferredToken.NumTrailingTrivia);
222173
}
223174

224175
//==========================================================================//
225176

226177
/// Form a deferred syntax layout node.
227178
static ParsedRawSyntaxNode makeDeferred(syntax::SyntaxKind k,
228-
ArrayRef<ParsedRawSyntaxNode> deferredNodes) {
229-
return ParsedRawSyntaxNode{k, deferredNodes};
230-
}
179+
ArrayRef<ParsedRawSyntaxNode> deferredNodes,
180+
SyntaxParsingContext &ctx);
231181

232182
/// Form a deferred token node.
233183
static ParsedRawSyntaxNode makeDeferred(Token tok,
234-
ParsedTrivia leadingTrivia,
235-
ParsedTrivia trailingTrivia) {
236-
return ParsedRawSyntaxNode{std::move(tok), std::move(leadingTrivia),
237-
std::move(trailingTrivia)};
238-
}
184+
const ParsedTrivia &leadingTrivia,
185+
const ParsedTrivia &trailingTrivia,
186+
SyntaxParsingContext &ctx);
239187

240188
/// Form a deferred missing token node.
241-
static ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc);
189+
static ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc) {
190+
auto raw = ParsedRawSyntaxNode(tokKind, loc, 0, nullptr, 0, 0);
191+
raw.IsMissing = true;
192+
return raw;
193+
}
242194

243195
/// Dump this piece of syntax recursively for debugging or testing.
244196
LLVM_ATTRIBUTE_DEPRECATED(
@@ -251,20 +203,6 @@ class ParsedRawSyntaxNode {
251203
static ParsedRawSyntaxNode null() {
252204
return ParsedRawSyntaxNode{};
253205
}
254-
255-
private:
256-
void releaseMemory() {
257-
switch (DK) {
258-
case DataKind::Null:
259-
break;
260-
case DataKind::Recorded:
261-
RecordedData.~RecordedSyntaxNode(); break;
262-
case DataKind::DeferredLayout:
263-
DeferredLayout.~DeferredLayoutNode(); break;
264-
case DataKind::DeferredToken:
265-
DeferredToken.~DeferredTokenNode(); break;
266-
}
267-
}
268206
};
269207

270208
} // end namespace swift

include/swift/Parse/ParsedRawSyntaxRecorder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424

2525
namespace swift {
2626

27+
class CharSourceRange;
2728
class ParsedRawSyntaxNode;
2829
struct ParsedTrivia;
30+
class ParsedTriviaPiece;
2931
class SyntaxParseActions;
3032
class SourceLoc;
3133
class Token;
@@ -46,6 +48,10 @@ class ParsedRawSyntaxRecorder {
4648
const ParsedTrivia &leadingTrivia,
4749
const ParsedTrivia &trailingTrivia);
4850

51+
ParsedRawSyntaxNode recordToken(tok tokenKind, CharSourceRange tokenRange,
52+
ArrayRef<ParsedTriviaPiece> leadingTrivia,
53+
ArrayRef<ParsedTriviaPiece> trailingTrivia);
54+
4955
/// Record a missing token. \p loc can be invalid or an approximate location
5056
/// of where the token would be if not missing.
5157
ParsedRawSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc);

include/swift/Parse/ParsedSyntaxBuilders.h.gyb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,20 @@ class SyntaxParsingContext;
3434
% if node.is_buildable():
3535
% child_count = len(node.children)
3636
class Parsed${node.name}Builder {
37-
ParsedRawSyntaxRecorder &Rec;
38-
bool IsBacktracking;
39-
ParsedRawSyntaxNode Layout[${child_count}] = {
37+
SyntaxParsingContext &SPCtx;
38+
ParsedRawSyntaxNode Layout[${child_count}];
4039
% for child in node.children:
41-
ParsedRawSyntaxNode::null(),
40+
% child_node = NODE_MAP.get(child.syntax_kind)
41+
% if child_node and child_node.is_syntax_collection():
42+
% child_elt = child_node.collection_element_name
43+
% child_elt_type = child_node.collection_element_type
44+
SmallVector<ParsedRawSyntaxNode, 8> ${child_elt}Nodes;
45+
% end
4246
% end
43-
};
4447

4548
public:
4649
explicit Parsed${node.name}Builder(SyntaxParsingContext &SPCtx)
47-
: Rec(SPCtx.getRecorder()), IsBacktracking(SPCtx.isBacktracking()) {}
50+
: SPCtx(SPCtx) {}
4851

4952
% for child in node.children:
5053
Parsed${node.name}Builder &use${child.name}(Parsed${child.type_name} ${child.name});
@@ -61,7 +64,7 @@ public:
6164

6265
private:
6366
Parsed${node.name} record();
64-
void finishLayout();
67+
void finishLayout(bool deferred);
6568
};
6669

6770
% end

include/swift/Parse/ParsedSyntaxRecorder.h.gyb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ private:
4646
static Parsed${node.name} record${node.syntax_kind}(${child_params},
4747
ParsedRawSyntaxRecorder &rec);
4848
public:
49-
static Parsed${node.name} defer${node.syntax_kind}(${child_params});
49+
static Parsed${node.name} defer${node.syntax_kind}(${child_params},
50+
SyntaxParsingContext &SPCtx);
5051
static Parsed${node.name} make${node.syntax_kind}(${child_params},
5152
SyntaxParsingContext &SPCtx);
5253
% elif node.is_syntax_collection():
@@ -57,7 +58,8 @@ private:
5758

5859
public:
5960
static Parsed${node.name} defer${node.syntax_kind}(
60-
ArrayRef<Parsed${node.collection_element_type}> elts);
61+
ArrayRef<Parsed${node.collection_element_type}> elts,
62+
SyntaxParsingContext &SPCtx);
6163
static Parsed${node.name} make${node.syntax_kind}(
6264
ArrayRef<Parsed${node.collection_element_type}> elts,
6365
SyntaxParsingContext &SPCtx);

include/swift/Parse/ParsedTrivia.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_PARSE_PARSEDTRIVIA_H
1515

1616
#include "swift/Basic/LLVM.h"
17+
#include "llvm/ADT/ArrayRef.h"
1718
#include "llvm/ADT/SmallVector.h"
1819

1920
namespace swift {
@@ -41,6 +42,17 @@ class ParsedTriviaPiece {
4142
void extendLength(unsigned len) {
4243
Length += len;
4344
}
45+
46+
static size_t getTotalLength(ArrayRef<ParsedTriviaPiece> pieces) {
47+
size_t Len = 0;
48+
for (auto &p : pieces)
49+
Len += p.getLength();
50+
return Len;
51+
}
52+
53+
static syntax::Trivia
54+
convertToSyntaxTrivia(ArrayRef<ParsedTriviaPiece> pieces, SourceLoc loc,
55+
const SourceManager &SM, unsigned bufferID);
4456
};
4557

4658
using ParsedTriviaList = SmallVector<ParsedTriviaPiece, 3>;
@@ -68,11 +80,13 @@ struct ParsedTrivia {
6880
return Pieces.empty();
6981
}
7082

83+
/// Return the number of pieces in this Trivia collection.
84+
size_t size() const {
85+
return Pieces.size();
86+
}
87+
7188
size_t getLength() const {
72-
size_t Len = 0;
73-
for (auto &P : Pieces)
74-
Len += P.getLength();
75-
return Len;
89+
return ParsedTriviaPiece::getTotalLength(Pieces);
7690
}
7791

7892
void push_back(syntax::TriviaKind kind, unsigned length) {

include/swift/Parse/SyntaxParseActions.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323
namespace swift {
2424

2525
class CharSourceRange;
26-
struct ParsedTrivia;
26+
class ParsedTriviaPiece;
2727
class SourceLoc;
28-
class Token;
2928
enum class tok;
3029

3130
namespace syntax {
@@ -40,10 +39,10 @@ class SyntaxParseActions {
4039
public:
4140
virtual ~SyntaxParseActions() = default;
4241

43-
virtual OpaqueSyntaxNode recordToken(const Token &tok,
44-
const ParsedTrivia &leadingTrivia,
45-
const ParsedTrivia &trailingTrivia,
46-
CharSourceRange range) = 0;
42+
virtual OpaqueSyntaxNode recordToken(tok tokenKind,
43+
ArrayRef<ParsedTriviaPiece> leadingTrivia,
44+
ArrayRef<ParsedTriviaPiece> trailingTrivia,
45+
CharSourceRange range) = 0;
4746

4847
/// Record a missing token. \c loc can be invalid or an approximate location
4948
/// of where the token would be if not missing.

include/swift/Parse/SyntaxParsingContext.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
9494

9595
ParsedRawSyntaxRecorder Recorder;
9696

97+
llvm::BumpPtrAllocator ScratchAlloc;
98+
9799
RootContextData(SourceFile &SF, DiagnosticEngine &Diags,
98100
SourceManager &SourceMgr, unsigned BufferID,
99101
std::shared_ptr<SyntaxParseActions> spActions)
@@ -242,12 +244,16 @@ class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
242244

243245
ParsedRawSyntaxRecorder &getRecorder() { return getRootData()->Recorder; }
244246

247+
llvm::BumpPtrAllocator &getScratchAlloc() {
248+
return getRootData()->ScratchAlloc;
249+
}
250+
245251
/// Add RawSyntax to the parts.
246252
void addRawSyntax(ParsedRawSyntaxNode Raw);
247253

248254
/// Add Token with Trivia to the parts.
249-
void addToken(Token &Tok, ParsedTrivia &LeadingTrivia,
250-
ParsedTrivia &TrailingTrivia);
255+
void addToken(Token &Tok, const ParsedTrivia &LeadingTrivia,
256+
const ParsedTrivia &TrailingTrivia);
251257

252258
/// Add Syntax to the parts.
253259
void addSyntax(ParsedSyntax Node);

include/swift/SyntaxParse/SyntaxTreeCreator.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ class SyntaxTreeCreator: public SyntaxParseActions {
5454
void acceptSyntaxRoot(OpaqueSyntaxNode root, SourceFile &SF);
5555

5656
private:
57-
OpaqueSyntaxNode recordToken(const Token &tok,
58-
const ParsedTrivia &leadingTrivia,
59-
const ParsedTrivia &trailingTrivia,
57+
OpaqueSyntaxNode recordToken(tok tokenKind,
58+
ArrayRef<ParsedTriviaPiece> leadingTrivia,
59+
ArrayRef<ParsedTriviaPiece> trailingTrivia,
6060
CharSourceRange range) override;
6161

6262
OpaqueSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc) override;

0 commit comments

Comments
 (0)