Skip to content

Commit 95acf4d

Browse files
committed
[libSyntax] Inline commonly called methods in RawSyntax and AbsoluteRawSyntax
These methods are super small and setting up the stack frame etc. takes up the majority (or at least a significant amount) of their execution time. So let's inline them.
1 parent ffaf867 commit 95acf4d

File tree

4 files changed

+131
-160
lines changed

4 files changed

+131
-160
lines changed

include/swift/Syntax/AbsoluteRawSyntax.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,29 @@ class SyntaxIndexInTree {
3232

3333
/// Assuming that this index points to the start of \p Raw, advance it so that
3434
/// it points to the next sibling of \p Raw.
35-
SyntaxIndexInTree advancedBy(const RawSyntax *Raw) const;
35+
SyntaxIndexInTree advancedBy(const RawSyntax *Raw) const {
36+
auto NewIndexInTree = IndexInTree;
37+
if (Raw) {
38+
NewIndexInTree += Raw->getTotalNodes();
39+
}
40+
return SyntaxIndexInTree(NewIndexInTree);
41+
}
3642

3743
/// Assuming that this index points to the next sibling of \p Raw, reverse it
3844
/// so that it points to the start of \p Raw.
39-
SyntaxIndexInTree reversedBy(const RawSyntax *Raw) const;
45+
SyntaxIndexInTree reversedBy(const RawSyntax *Raw) const {
46+
auto NewIndexInTree = IndexInTree;
47+
if (Raw) {
48+
NewIndexInTree -= Raw->getTotalNodes();
49+
}
50+
return SyntaxIndexInTree(NewIndexInTree);
51+
}
4052

4153
/// Advance this index to point to its first immediate child.
42-
SyntaxIndexInTree advancedToFirstChild() const;
54+
SyntaxIndexInTree advancedToFirstChild() const {
55+
auto NewIndexInTree = IndexInTree + 1;
56+
return SyntaxIndexInTree(NewIndexInTree);
57+
}
4358

4459
bool operator==(SyntaxIndexInTree Other) const {
4560
return IndexInTree == Other.IndexInTree;
@@ -138,11 +153,25 @@ class AbsoluteSyntaxPosition {
138153

139154
/// Assuming that this position points to the start of \p Raw, advance it so
140155
/// that it points to the next sibling of \p Raw.
141-
AbsoluteSyntaxPosition advancedBy(const RawSyntax *Raw) const;
156+
AbsoluteSyntaxPosition advancedBy(const RawSyntax *Raw) const {
157+
OffsetType NewOffset = Offset;
158+
if (Raw) {
159+
NewOffset += Raw->getTextLength();
160+
}
161+
IndexInParentType NewIndexInParent = IndexInParent + 1;
162+
return AbsoluteSyntaxPosition(NewOffset, NewIndexInParent);
163+
}
142164

143165
/// Assuming that this position points to the next sibling of \p Raw, reverse
144166
/// it so that it points to the start of \p Raw.
145-
AbsoluteSyntaxPosition reversedBy(const RawSyntax *Raw) const;
167+
AbsoluteSyntaxPosition reversedBy(const RawSyntax *Raw) const {
168+
OffsetType NewOffset = Offset;
169+
if (Raw) {
170+
NewOffset -= Raw->getTextLength();
171+
}
172+
IndexInParentType NewIndexInParent = IndexInParent - 1;
173+
return AbsoluteSyntaxPosition(NewOffset, NewIndexInParent);
174+
}
146175

147176
/// Get the position of the node's first immediate child.
148177
AbsoluteSyntaxPosition advancedToFirstChild() const {

include/swift/Syntax/RawSyntax.h

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,27 @@ using llvm::StringRef;
120120
#define syntax_assert_token_is(Tok, Kind, Text)
121121
#endif
122122

123+
namespace {
124+
/// If the \p Str is not allocated in \p Arena, copy it to \p Arena and adjust
125+
/// \p Str to point to the string's copy in \p Arena.
126+
void copyToArenaIfNecessary(
127+
StringRef &Str, const swift::RC<swift::syntax::SyntaxArena> &Arena) {
128+
if (Str.empty()) {
129+
// Empty strings can live wherever they want. Nothing to do.
130+
return;
131+
}
132+
if (Arena->containsPointer(Str.data())) {
133+
// String already in arena. Nothing to do.
134+
return;
135+
}
136+
// Copy string to arena
137+
char *Data = (char *)Arena->Allocate(Str.size(), alignof(char *));
138+
std::uninitialized_copy(Str.begin(), Str.end(), Data);
139+
Str = StringRef(Data, Str.size());
140+
}
141+
} // namespace
142+
// end anonymous namespace
143+
123144
namespace swift {
124145
namespace syntax {
125146

@@ -223,7 +244,39 @@ class RawSyntax final
223244
/// the caller needs to assure that the node ID has not been used yet.
224245
RawSyntax(SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
225246
size_t TextLength, SourcePresence Presence,
226-
const RC<SyntaxArena> &Arena, llvm::Optional<SyntaxNodeId> NodeId);
247+
const RC<SyntaxArena> &Arena, llvm::Optional<SyntaxNodeId> NodeId)
248+
: Arena(Arena.get()),
249+
Bits({{unsigned(TextLength), unsigned(Presence), false}}) {
250+
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
251+
assert(
252+
Kind != SyntaxKind::Token &&
253+
"'token' syntax node must be constructed with dedicated constructor");
254+
255+
size_t TotalSubNodeCount = 0;
256+
for (auto Child : Layout) {
257+
if (Child) {
258+
TotalSubNodeCount += Child->getTotalSubNodeCount() + 1;
259+
// If the child is stored in a different arena, it needs to stay alive
260+
// as long as this node's arena is alive.
261+
Arena->addChildArena(Child->Arena);
262+
}
263+
}
264+
265+
if (NodeId.hasValue()) {
266+
this->NodeId = NodeId.getValue();
267+
NextFreeNodeId = std::max(this->NodeId + 1, NextFreeNodeId);
268+
} else {
269+
this->NodeId = NextFreeNodeId++;
270+
}
271+
Bits.Layout.NumChildren = Layout.size();
272+
Bits.Layout.TotalSubNodeCount = TotalSubNodeCount;
273+
Bits.Layout.Kind = unsigned(Kind);
274+
275+
// Initialize layout data.
276+
std::uninitialized_copy(Layout.begin(), Layout.end(),
277+
getTrailingObjects<const RawSyntax *>());
278+
}
279+
227280
/// Constructor for creating token nodes
228281
/// \c SyntaxArena, that arena must be passed as \p Arena to retain the node's
229282
/// underlying storage.
@@ -232,7 +285,35 @@ class RawSyntax final
232285
RawSyntax(tok TokKind, StringRef Text, size_t TextLength,
233286
StringRef LeadingTrivia, StringRef TrailingTrivia,
234287
SourcePresence Presence, const RC<SyntaxArena> &Arena,
235-
llvm::Optional<SyntaxNodeId> NodeId);
288+
llvm::Optional<SyntaxNodeId> NodeId)
289+
: Arena(Arena.get()),
290+
Bits({{unsigned(TextLength), unsigned(Presence), true}}) {
291+
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
292+
copyToArenaIfNecessary(LeadingTrivia, Arena);
293+
copyToArenaIfNecessary(Text, Arena);
294+
copyToArenaIfNecessary(TrailingTrivia, Arena);
295+
296+
if (Presence == SourcePresence::Missing) {
297+
assert(TextLength == 0);
298+
} else {
299+
assert(TextLength ==
300+
LeadingTrivia.size() + Text.size() + TrailingTrivia.size());
301+
}
302+
303+
if (NodeId.hasValue()) {
304+
this->NodeId = NodeId.getValue();
305+
NextFreeNodeId = std::max(this->NodeId + 1, NextFreeNodeId);
306+
} else {
307+
this->NodeId = NextFreeNodeId++;
308+
}
309+
Bits.Token.LeadingTrivia = LeadingTrivia.data();
310+
Bits.Token.TokenText = Text.data();
311+
Bits.Token.TrailingTrivia = TrailingTrivia.data();
312+
Bits.Token.LeadingTriviaLength = LeadingTrivia.size();
313+
Bits.Token.TokenLength = Text.size();
314+
Bits.Token.TrailingTriviaLength = TrailingTrivia.size();
315+
Bits.Token.TokenKind = unsigned(TokKind);
316+
}
236317

237318
/// Compute the node's text length by summing up the length of its childern
238319
size_t computeTextLength() {
@@ -254,7 +335,13 @@ class RawSyntax final
254335
static const RawSyntax *
255336
make(SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout, size_t TextLength,
256337
SourcePresence Presence, const RC<SyntaxArena> &Arena,
257-
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
338+
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
339+
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
340+
auto size = totalSizeToAlloc<const RawSyntax *>(Layout.size());
341+
void *data = Arena->Allocate(size, alignof(RawSyntax));
342+
return new (data)
343+
RawSyntax(Kind, Layout, TextLength, Presence, Arena, NodeId);
344+
}
258345

259346
static const RawSyntax *
260347
makeAndCalcLength(SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
@@ -274,7 +361,13 @@ class RawSyntax final
274361
make(tok TokKind, StringRef Text, size_t TextLength, StringRef LeadingTrivia,
275362
StringRef TrailingTrivia, SourcePresence Presence,
276363
const RC<SyntaxArena> &Arena,
277-
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
364+
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
365+
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
366+
auto size = totalSizeToAlloc<const RawSyntax *>(0);
367+
void *data = Arena->Allocate(size, alignof(RawSyntax));
368+
return new (data) RawSyntax(TokKind, Text, TextLength, LeadingTrivia,
369+
TrailingTrivia, Presence, Arena, NodeId);
370+
}
278371

279372
/// Make a raw "token" syntax node that was allocated in \p Arena.
280373
static const RawSyntax *

lib/Syntax/AbsoluteRawSyntax.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,6 @@ using namespace swift::syntax;
1717

1818
std::atomic<SyntaxIdentifier::RootIdType> SyntaxIdentifier::NextUnusedRootId(0);
1919

20-
SyntaxIndexInTree SyntaxIndexInTree::advancedBy(const RawSyntax *Raw) const {
21-
auto NewIndexInTree = IndexInTree;
22-
if (Raw) {
23-
NewIndexInTree += Raw->getTotalNodes();
24-
}
25-
return SyntaxIndexInTree(NewIndexInTree);
26-
}
27-
28-
SyntaxIndexInTree SyntaxIndexInTree::reversedBy(const RawSyntax *Raw) const {
29-
auto NewIndexInTree = IndexInTree;
30-
if (Raw) {
31-
NewIndexInTree -= Raw->getTotalNodes();
32-
}
33-
return SyntaxIndexInTree(NewIndexInTree);
34-
}
35-
36-
SyntaxIndexInTree SyntaxIndexInTree::advancedToFirstChild() const {
37-
auto NewIndexInTree = IndexInTree + 1;
38-
return SyntaxIndexInTree(NewIndexInTree);
39-
}
40-
41-
AbsoluteSyntaxPosition
42-
AbsoluteSyntaxPosition::advancedBy(const RawSyntax *Raw) const {
43-
OffsetType NewOffset = Offset;
44-
if (Raw) {
45-
NewOffset += Raw->getTextLength();
46-
}
47-
IndexInParentType NewIndexInParent = IndexInParent + 1;
48-
return AbsoluteSyntaxPosition(NewOffset, NewIndexInParent);
49-
}
50-
51-
AbsoluteSyntaxPosition
52-
AbsoluteSyntaxPosition::reversedBy(const RawSyntax *Raw) const {
53-
OffsetType NewOffset = Offset;
54-
if (Raw) {
55-
NewOffset -= Raw->getTextLength();
56-
}
57-
IndexInParentType NewIndexInParent = IndexInParent - 1;
58-
return AbsoluteSyntaxPosition(NewOffset, NewIndexInParent);
59-
}
60-
6120
raw_ostream &llvm::operator<<(raw_ostream &OS,
6221
swift::syntax::AbsoluteOffsetPosition Pos) {
6322
OS << "Offset " << Pos.getOffset();

lib/Syntax/RawSyntax.cpp

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -87,119 +87,9 @@ Trivia lexTrivia(StringRef TriviaStr) {
8787
return SyntaxTrivia;
8888
}
8989

90-
/// If the \p Str is not allocated in \p Arena, copy it to \p Arena and adjust
91-
/// \p Str to point to the string's copy in \p Arena.
92-
void copyToArenaIfNecessary(StringRef &Str, const RC<SyntaxArena> &Arena) {
93-
if (Str.empty()) {
94-
// Empty strings can live wherever they want. Nothing to do.
95-
return;
96-
}
97-
if (Arena->containsPointer(Str.data())) {
98-
// String already in arena. Nothing to do.
99-
return;
100-
}
101-
// Copy string to arena
102-
char *Data = (char *)Arena->Allocate(Str.size(), alignof(char *));
103-
std::uninitialized_copy(Str.begin(), Str.end(), Data);
104-
Str = StringRef(Data, Str.size());
105-
}
106-
10790
// FIXME: If we want thread-safety for tree creation, this needs to be atomic.
10891
unsigned RawSyntax::NextFreeNodeId = 1;
10992

110-
RawSyntax::RawSyntax(SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
111-
size_t TextLength, SourcePresence Presence,
112-
const RC<SyntaxArena> &Arena,
113-
llvm::Optional<unsigned> NodeId)
114-
: Arena(Arena.get()),
115-
Bits({{unsigned(TextLength), unsigned(Presence), false}}) {
116-
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
117-
assert(Kind != SyntaxKind::Token &&
118-
"'token' syntax node must be constructed with dedicated constructor");
119-
120-
size_t TotalSubNodeCount = 0;
121-
for (auto Child : Layout) {
122-
if (Child) {
123-
TotalSubNodeCount += Child->getTotalSubNodeCount() + 1;
124-
// If the child is stored in a different arena, it needs to stay alive
125-
// as long as this node's arena is alive.
126-
Arena->addChildArena(Child->Arena);
127-
}
128-
}
129-
130-
if (NodeId.hasValue()) {
131-
this->NodeId = NodeId.getValue();
132-
NextFreeNodeId = std::max(this->NodeId + 1, NextFreeNodeId);
133-
} else {
134-
this->NodeId = NextFreeNodeId++;
135-
}
136-
Bits.Layout.NumChildren = Layout.size();
137-
Bits.Layout.TotalSubNodeCount = TotalSubNodeCount;
138-
Bits.Layout.Kind = unsigned(Kind);
139-
140-
// Initialize layout data.
141-
std::uninitialized_copy(Layout.begin(), Layout.end(),
142-
getTrailingObjects<const RawSyntax *>());
143-
}
144-
145-
RawSyntax::RawSyntax(tok TokKind, StringRef Text, size_t TextLength,
146-
StringRef LeadingTrivia, StringRef TrailingTrivia,
147-
SourcePresence Presence, const RC<SyntaxArena> &Arena,
148-
llvm::Optional<unsigned> NodeId)
149-
: Arena(Arena.get()),
150-
Bits({{unsigned(TextLength), unsigned(Presence), true}}) {
151-
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
152-
copyToArenaIfNecessary(LeadingTrivia, Arena);
153-
copyToArenaIfNecessary(Text, Arena);
154-
copyToArenaIfNecessary(TrailingTrivia, Arena);
155-
156-
if (Presence == SourcePresence::Missing) {
157-
assert(TextLength == 0);
158-
} else {
159-
assert(TextLength ==
160-
LeadingTrivia.size() + Text.size() + TrailingTrivia.size());
161-
}
162-
163-
if (NodeId.hasValue()) {
164-
this->NodeId = NodeId.getValue();
165-
NextFreeNodeId = std::max(this->NodeId + 1, NextFreeNodeId);
166-
} else {
167-
this->NodeId = NextFreeNodeId++;
168-
}
169-
Bits.Token.LeadingTrivia = LeadingTrivia.data();
170-
Bits.Token.TokenText = Text.data();
171-
Bits.Token.TrailingTrivia = TrailingTrivia.data();
172-
Bits.Token.LeadingTriviaLength = LeadingTrivia.size();
173-
Bits.Token.TokenLength = Text.size();
174-
Bits.Token.TrailingTriviaLength = TrailingTrivia.size();
175-
Bits.Token.TokenKind = unsigned(TokKind);
176-
}
177-
178-
const RawSyntax *RawSyntax::make(SyntaxKind Kind,
179-
ArrayRef<const RawSyntax *> Layout,
180-
size_t TextLength, SourcePresence Presence,
181-
const RC<SyntaxArena> &Arena,
182-
llvm::Optional<unsigned> NodeId) {
183-
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
184-
auto size = totalSizeToAlloc<const RawSyntax *>(Layout.size());
185-
void *data = Arena->Allocate(size, alignof(RawSyntax));
186-
return new (data)
187-
RawSyntax(Kind, Layout, TextLength, Presence, Arena, NodeId);
188-
}
189-
190-
const RawSyntax *RawSyntax::make(tok TokKind, StringRef Text, size_t TextLength,
191-
StringRef LeadingTrivia,
192-
StringRef TrailingTrivia,
193-
SourcePresence Presence,
194-
const RC<SyntaxArena> &Arena,
195-
llvm::Optional<unsigned> NodeId) {
196-
assert(Arena && "RawSyntax nodes must always be allocated in an arena");
197-
auto size = totalSizeToAlloc<const RawSyntax *>(0);
198-
void *data = Arena->Allocate(size, alignof(RawSyntax));
199-
return new (data) RawSyntax(TokKind, Text, TextLength, LeadingTrivia,
200-
TrailingTrivia, Presence, Arena, NodeId);
201-
}
202-
20393
Trivia RawSyntax::getLeadingTriviaPieces() const {
20494
return lexTrivia(getLeadingTrivia());
20595
}

0 commit comments

Comments
 (0)