Skip to content

Commit 4e327f7

Browse files
authored
Merge pull request swiftlang#14330 from rintaro/syntax-arena
[Syntax] Bump allocate and cache/reuse RawSyntax
2 parents 354a76a + 057254d commit 4e327f7

20 files changed

+604
-231
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ namespace swift {
107107

108108
enum class KnownProtocolKind : uint8_t;
109109

110+
namespace syntax {
111+
class SyntaxArena;
112+
}
113+
110114
/// \brief The arena in which a particular ASTContext allocation will go.
111115
enum class AllocationArena {
112116
/// \brief The permanent arena, which is tied to the lifetime of
@@ -380,6 +384,9 @@ class ASTContext {
380384
setVector.size());
381385
}
382386

387+
/// Retrive the syntax node memory manager for this context.
388+
syntax::SyntaxArena &getSyntaxArena() const;
389+
383390
/// Retrieve the lazy resolver for this context.
384391
LazyResolver *getLazyResolver() const;
385392

include/swift/Syntax/RawSyntax.h

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "swift/Syntax/SyntaxKind.h"
3535
#include "swift/Syntax/TokenKinds.h"
3636
#include "swift/Syntax/Trivia.h"
37+
#include "llvm/ADT/FoldingSet.h"
3738
#include "llvm/ADT/IntrusiveRefCntPtr.h"
3839
#include "llvm/ADT/PointerUnion.h"
3940
#include "llvm/Support/Casting.h"
@@ -48,7 +49,7 @@ using llvm::StringRef;
4849
#ifndef NDEBUG
4950
#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind) \
5051
({ \
51-
if (auto &__Child = Raw->getChild(Cursor::CursorName)) \
52+
if (auto &__Child = Raw->getChild(Cursor)) \
5253
assert(__Child->getKind() == ExpectedKind); \
5354
})
5455
#else
@@ -113,7 +114,9 @@ using llvm::StringRef;
113114
namespace swift {
114115
namespace syntax {
115116

116-
using CursorIndex = uint32_t;
117+
class SyntaxArena;
118+
119+
using CursorIndex = size_t;
117120

118121
/// Get a numeric index suitable for array/vector indexing
119122
/// from a syntax node's Cursor enum value.
@@ -225,6 +228,9 @@ class RawSyntax final
225228
unsigned Kind : bitmax(NumSyntaxKindBits, 8);
226229
/// Whether this piece of syntax was actually present in the source.
227230
unsigned Presence : 1;
231+
/// Whether this piece of syntax was constructed with manually managed
232+
/// memory.
233+
unsigned ManualMemory : 1;
228234
};
229235
enum { NumRawSyntaxBits = bitmax(NumSyntaxKindBits, 8) + 1 };
230236

@@ -258,38 +264,57 @@ class RawSyntax final
258264
}
259265

260266
RawSyntax(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
261-
SourcePresence Presence);
262-
RawSyntax(tok TokKind, OwnedString Text, SourcePresence Presence,
267+
SourcePresence Presence, bool ManualMemory);
268+
RawSyntax(tok TokKind, OwnedString Text,
263269
ArrayRef<TriviaPiece> LeadingTrivia,
264-
ArrayRef<TriviaPiece> TrailingTrivia);
270+
ArrayRef<TriviaPiece> TrailingTrivia,
271+
SourcePresence Presence, bool ManualMemory);
265272

266273
public:
267274
~RawSyntax();
268275

276+
void Release() const {
277+
if (Bits.ManualMemory)
278+
return;
279+
return llvm::ThreadSafeRefCountedBase<RawSyntax>::Release();
280+
}
281+
void Retain() const {
282+
if (Bits.ManualMemory)
283+
return;
284+
return llvm::ThreadSafeRefCountedBase<RawSyntax>::Retain();
285+
}
286+
269287
/// \name Factory methods.
270288
/// @{
271289

272290
/// Make a raw "layout" syntax node.
273291
static RC<RawSyntax> make(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
274-
SourcePresence Presence);
292+
SourcePresence Presence,
293+
SyntaxArena *Arena = nullptr);
275294

276295
/// Make a raw "token" syntax node.
277296
static RC<RawSyntax> make(tok TokKind, OwnedString Text,
278-
SourcePresence Presence,
279297
ArrayRef<TriviaPiece> LeadingTrivia,
280-
ArrayRef<TriviaPiece> TrailingTrivia);
298+
ArrayRef<TriviaPiece> TrailingTrivia,
299+
SourcePresence Presence,
300+
SyntaxArena *Arena = nullptr);
281301

282302
/// Make a missing raw "layout" syntax node.
283-
static RC<RawSyntax> missing(SyntaxKind Kind) {
284-
return make(Kind, {}, SourcePresence::Missing);
303+
static RC<RawSyntax> missing(SyntaxKind Kind, SyntaxArena *Arena = nullptr) {
304+
return make(Kind, {}, SourcePresence::Missing, Arena);
285305
}
286306

287307
/// Make a missing raw "token" syntax node.
288-
static RC<RawSyntax> missing(tok TokKind, OwnedString Text) {
289-
return make(TokKind, Text, SourcePresence::Missing,
290-
ArrayRef<TriviaPiece>{}, ArrayRef<TriviaPiece>{});
308+
static RC<RawSyntax> missing(tok TokKind, OwnedString Text,
309+
SyntaxArena *Arena = nullptr) {
310+
return make(TokKind, Text, {}, {}, SourcePresence::Missing, Arena);
291311
}
292312

313+
static RC<RawSyntax> getToken(SyntaxArena &Arena, tok TokKind,
314+
OwnedString Text,
315+
ArrayRef<TriviaPiece> LeadingTrivia,
316+
ArrayRef<TriviaPiece> TrailingTrivia);
317+
293318
/// @}
294319

295320
SourcePresence getPresence() const {
@@ -365,8 +390,8 @@ class RawSyntax final
365390
/// trivia instead.
366391
RC<RawSyntax>
367392
withLeadingTrivia(ArrayRef<TriviaPiece> NewLeadingTrivia) const {
368-
return make(getTokenKind(), getTokenText(), getPresence(),
369-
NewLeadingTrivia, getTrailingTrivia());
393+
return make(getTokenKind(), getTokenText(), NewLeadingTrivia,
394+
getTrailingTrivia(), getPresence());
370395
}
371396

372397
RC<RawSyntax> withLeadingTrivia(Trivia NewLeadingTrivia) const {
@@ -377,8 +402,8 @@ class RawSyntax final
377402
/// trivia instead.
378403
RC<RawSyntax>
379404
withTrailingTrivia(ArrayRef<TriviaPiece> NewTrailingTrivia) const {
380-
return make(getTokenKind(), getTokenText(), getPresence(),
381-
getLeadingTrivia(), NewTrailingTrivia);
405+
return make(getTokenKind(), getTokenText(), getLeadingTrivia(),
406+
NewTrailingTrivia, getPresence());
382407
}
383408

384409
RC<RawSyntax> withTrailingTrivia(Trivia NewTrailingTrivia) const {
@@ -441,6 +466,10 @@ class RawSyntax final
441466

442467
/// Dump this piece of syntax recursively.
443468
void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
469+
470+
static void Profile(llvm::FoldingSetNodeID &ID, tok TokKind, OwnedString Text,
471+
ArrayRef<TriviaPiece> LeadingTrivia,
472+
ArrayRef<TriviaPiece> TrailingTrivia);
444473
};
445474

446475
} // end namespace syntax

include/swift/Syntax/SyntaxArena.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===--- SyntaxArena.h - Syntax Tree Memory Allocation ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines SyntaxArena that is Memory manager for Syntax nodes.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SYNTAX_SYNTAXARENA_H
18+
#define SWIFT_SYNTAX_SYNTAXARENA_H
19+
20+
#include "llvm/Support/Allocator.h"
21+
22+
namespace swift {
23+
namespace syntax {
24+
25+
/// Memory manager for Syntax nodes.
26+
class SyntaxArena {
27+
SyntaxArena(const SyntaxArena &) = delete;
28+
void operator=(const SyntaxArena &) = delete;
29+
30+
public:
31+
struct Implementation;
32+
Implementation &Impl;
33+
34+
SyntaxArena();
35+
~SyntaxArena();
36+
37+
llvm::BumpPtrAllocator &getAllocator() const;
38+
void *Allocate(size_t size, size_t alignment);
39+
void *AllocateRawSyntax(size_t size, size_t alignment);
40+
};
41+
42+
} // namespace syntax
43+
} // namespace swift
44+
45+
#endif

include/swift/Syntax/SyntaxBuilders.h.gyb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,23 @@
2727
namespace swift {
2828
namespace syntax {
2929

30+
class SyntaxArena;
31+
3032
% for node in SYNTAX_NODES:
3133
% if node.is_buildable():
34+
% child_count = len(node.children)
3235
class ${node.name}Builder {
33-
std::vector<RC<RawSyntax>> Layout = {
36+
SyntaxArena *Arena = nullptr;
37+
RC<RawSyntax> Layout[${child_count}] = {
3438
% for child in node.children:
3539
nullptr,
3640
% end
3741
};
3842

3943
public:
44+
${node.name}Builder() = default;
45+
${node.name}Builder(SyntaxArena &Arena) : Arena(&Arena) {}
46+
4047
% for child in node.children:
4148
${node.name}Builder &use${child.name}(${child.type_name} ${child.name});
4249
% child_node = NODE_MAP.get(child.syntax_kind)

include/swift/Syntax/SyntaxFactory.h.gyb

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,28 @@
4040
namespace swift {
4141
namespace syntax {
4242

43+
class SyntaxArena;
44+
4345
/// The Syntax factory - the one-stop shop for making new Syntax nodes.
4446
struct SyntaxFactory {
4547
/// Make any kind of token.
46-
static TokenSyntax
47-
makeToken(tok Kind, OwnedString Text, SourcePresence Presence,
48-
const Trivia &LeadingTrivia, const Trivia &TrailingTrivia);
48+
static TokenSyntax makeToken(tok Kind,
49+
OwnedString Text, const Trivia &LeadingTrivia,
50+
const Trivia &TrailingTrivia,
51+
SourcePresence Presence,
52+
SyntaxArena *Arena = nullptr);
4953

5054
/// Collect a list of tokens into a piece of "unknown" syntax.
51-
static UnknownSyntax
52-
makeUnknownSyntax(llvm::ArrayRef<TokenSyntax> Tokens);
55+
static UnknownSyntax makeUnknownSyntax(llvm::ArrayRef<TokenSyntax> Tokens,
56+
SyntaxArena *Arena = nullptr);
5357

5458
static Optional<Syntax> createSyntax(SyntaxKind Kind,
55-
llvm::ArrayRef<Syntax> Elements);
59+
llvm::ArrayRef<Syntax> Elements,
60+
SyntaxArena *Arena = nullptr);
5661

5762
static RC<RawSyntax> createRaw(SyntaxKind Kind,
58-
llvm::ArrayRef<RC<RawSyntax>> Elements);
63+
llvm::ArrayRef<RC<RawSyntax>> Elements,
64+
SyntaxArena *Arena = nullptr);
5965

6066
/// Count the number of children for a given syntax node kind,
6167
/// returning a pair of mininum and maximum count of children. The gap
@@ -76,74 +82,91 @@ struct SyntaxFactory {
7682
% child_params.append("%s %s" % (param_type, child.name))
7783
% end
7884
% child_params = ', '.join(child_params)
79-
static ${node.name} make${node.syntax_kind}(${child_params});
85+
static ${node.name} make${node.syntax_kind}(${child_params},
86+
SyntaxArena *Arena = nullptr);
8087
% elif node.is_syntax_collection():
8188
static ${node.name} make${node.syntax_kind}(
82-
const std::vector<${node.collection_element_type}> &elts);
89+
const std::vector<${node.collection_element_type}> &elts,
90+
SyntaxArena *Arena = nullptr);
8391
% end
8492

85-
static ${node.name} makeBlank${node.syntax_kind}();
93+
static ${node.name} makeBlank${node.syntax_kind}(SyntaxArena *Arena = nullptr);
8694
% end
8795

8896
% for token in SYNTAX_TOKENS:
8997
% if token.is_keyword:
9098
static TokenSyntax make${token.name}Keyword(const Trivia &LeadingTrivia,
91-
const Trivia &TrailingTrivia);
99+
const Trivia &TrailingTrivia,
100+
SyntaxArena *Arena = nullptr);
92101
% elif token.text:
93102
static TokenSyntax make${token.name}Token(const Trivia &LeadingTrivia,
94-
const Trivia &TrailingTrivia);
103+
const Trivia &TrailingTrivia,
104+
SyntaxArena *Arena = nullptr);
95105
% else:
96106
static TokenSyntax make${token.name}(OwnedString Text,
97107
const Trivia &LeadingTrivia,
98-
const Trivia &TrailingTrivia);
108+
const Trivia &TrailingTrivia,
109+
SyntaxArena *Arena = nullptr);
99110
% end
100111
% end
101112

102113
#pragma mark - Convenience APIs
103114

104-
static TupleTypeSyntax makeVoidTupleType();
115+
static TupleTypeSyntax makeVoidTupleType(SyntaxArena *Arena = nullptr);
105116

106117
/// Creates an labelled TupleTypeElementSyntax with the provided label,
107118
/// colon, type and optional trailing comma.
108119
static TupleTypeElementSyntax makeTupleTypeElement(
109-
llvm::Optional<TokenSyntax> Label,
110-
llvm::Optional<TokenSyntax> Colon, TypeSyntax Type,
111-
llvm::Optional<TokenSyntax> TrailingComma = llvm::None);
120+
llvm::Optional<TokenSyntax> Label,
121+
llvm::Optional<TokenSyntax> Colon, TypeSyntax Type,
122+
llvm::Optional<TokenSyntax> TrailingComma = llvm::None,
123+
SyntaxArena *Arena = nullptr);
112124

113125
/// Creates an unlabelled TupleTypeElementSyntax with the provided type and
114126
/// optional trailing comma.
115-
static TupleTypeElementSyntax makeTupleTypeElement(TypeSyntax Type,
116-
llvm::Optional<TokenSyntax> TrailingComma = llvm::None);
127+
static TupleTypeElementSyntax
128+
makeTupleTypeElement(TypeSyntax Type,
129+
llvm::Optional<TokenSyntax> TrailingComma = llvm::None,
130+
SyntaxArena *Arena = nullptr);
117131

118132
/// Creates a TypeIdentifierSyntax with the provided name and leading/trailing
119133
/// trivia.
120134
static TypeSyntax makeTypeIdentifier(OwnedString TypeName,
121-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
135+
const Trivia &LeadingTrivia = {},
136+
const Trivia &TrailingTrivia = {},
137+
SyntaxArena *Arena = nullptr);
122138

123139
/// Creates a GenericParameterSyntax with no inheritance clause and an
124140
/// optional trailing comma.
125-
static GenericParameterSyntax makeGenericParameter(TokenSyntax Name,
126-
llvm::Optional<TokenSyntax> TrailingComma);
141+
static GenericParameterSyntax
142+
makeGenericParameter(TokenSyntax Name,
143+
llvm::Optional<TokenSyntax> TrailingComma,
144+
SyntaxArena *Arena = nullptr);
127145

128146
/// Creates a TypeIdentifierSyntax for the `Any` type.
129-
static TypeSyntax makeAnyTypeIdentifier(
130-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
147+
static TypeSyntax makeAnyTypeIdentifier(const Trivia &LeadingTrivia = {},
148+
const Trivia &TrailingTrivia = {},
149+
SyntaxArena *Arena = nullptr);
131150

132151
/// Creates a TypeIdentifierSyntax for the `Self` type.
133-
static TypeSyntax makeSelfTypeIdentifier(
134-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
152+
static TypeSyntax makeSelfTypeIdentifier(const Trivia &LeadingTrivia = {},
153+
const Trivia &TrailingTrivia = {},
154+
SyntaxArena *Arena = nullptr);
135155

136156
/// Creates a TokenSyntax for the `Type` identifier.
137-
static TokenSyntax makeTypeToken(
138-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
157+
static TokenSyntax makeTypeToken(const Trivia &LeadingTrivia = {},
158+
const Trivia &TrailingTrivia = {},
159+
SyntaxArena *Arena = nullptr);
139160

140161
/// Creates a TokenSyntax for the `Protocol` identifier.
141-
static TokenSyntax makeProtocolToken(
142-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
162+
static TokenSyntax makeProtocolToken(const Trivia &LeadingTrivia = {},
163+
const Trivia &TrailingTrivia = {},
164+
SyntaxArena *Arena = nullptr);
143165

144166
/// Creates an `==` operator token.
145-
static TokenSyntax makeEqualityOperator(
146-
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
167+
static TokenSyntax makeEqualityOperator(const Trivia &LeadingTrivia = {},
168+
const Trivia &TrailingTrivia = {},
169+
SyntaxArena *Arena = nullptr);
147170

148171
/// Whether a raw node `Member` can serve as a member in a syntax collection
149172
/// of the given syntax collection kind.

0 commit comments

Comments
 (0)