Skip to content

Commit 56a9234

Browse files
committed
[libSyntax] Reference count SyntaxData
Instead of having a heap-allocated RefCountedBox to store a SyntaxData's parent, reference-count SyntaxData itself. This has a couple of advantages: - When passing SyntaxData around, only a pointer needs to be passed instead of the entire struct contents. This is faster. - We can later introduce a SyntaxDataRef, which behaves similar to SyntaxData, but delegates the responsibility that the parent stays alive to the user. While sacrificing guaranteed memory safety, this means that SyntaxData can then be stack-allocated without any ref-counting overhead.
1 parent 68877f9 commit 56a9234

File tree

11 files changed

+85
-110
lines changed

11 files changed

+85
-110
lines changed

include/swift/Syntax/Syntax.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ class Syntax {
5656
friend struct SyntaxFactory;
5757

5858
protected:
59-
SyntaxData Data;
59+
RC<const SyntaxData> Data;
6060

6161
public:
62-
explicit Syntax(const SyntaxData Data) : Data(Data) {}
62+
explicit Syntax(const RC<const SyntaxData> &Data) : Data(Data) {}
6363

6464
virtual ~Syntax() {}
6565

@@ -86,9 +86,7 @@ class Syntax {
8686
}
8787

8888
/// Get the Data for this Syntax node.
89-
const SyntaxData &getData() const {
90-
return Data;
91-
}
89+
const RC<const SyntaxData> &getData() const { return Data; }
9290

9391
/// Cast this Syntax node to a more specific type, asserting it's of the
9492
/// right kind.
@@ -113,7 +111,7 @@ class Syntax {
113111

114112
/// Returns the child index of this node in its parent,
115113
/// if it has one, otherwise 0.
116-
CursorIndex getIndexInParent() const { return getData().getIndexInParent(); }
114+
CursorIndex getIndexInParent() const { return getData()->getIndexInParent(); }
117115

118116
/// Return the number of bytes this node takes when spelled out in the source
119117
size_t getTextLength() const { return getRaw()->getTextLength(); }
@@ -157,8 +155,8 @@ class Syntax {
157155
SWIFT_DEBUG_DUMP;
158156

159157
bool hasSameIdentityAs(const Syntax &Other) const {
160-
return Data.getAbsoluteRaw().getNodeId() ==
161-
Other.Data.getAbsoluteRaw().getNodeId();
158+
return Data->getAbsoluteRaw().getNodeId() ==
159+
Other.Data->getAbsoluteRaw().getNodeId();
162160
}
163161

164162
static bool kindof(SyntaxKind Kind) {
@@ -180,23 +178,23 @@ class Syntax {
180178

181179
/// Get the offset at which the leading trivia of this node starts.
182180
AbsoluteOffsetPosition getAbsolutePositionBeforeLeadingTrivia() const {
183-
return Data.getAbsolutePositionBeforeLeadingTrivia();
181+
return Data->getAbsolutePositionBeforeLeadingTrivia();
184182
}
185183

186184
/// Get the offset at which the actual content (i.e. non-triva) of this node
187185
/// starts.
188186
AbsoluteOffsetPosition getAbsolutePositionAfterLeadingTrivia() const {
189-
return Data.getAbsolutePositionAfterLeadingTrivia();
187+
return Data->getAbsolutePositionAfterLeadingTrivia();
190188
}
191189

192190
/// Get the offset at which the trailing trivia of this node starts.
193191
AbsoluteOffsetPosition getAbsoluteEndPositionBeforeTrailingTrivia() const {
194-
return Data.getAbsoluteEndPositionBeforeTrailingTrivia();
192+
return Data->getAbsoluteEndPositionBeforeTrailingTrivia();
195193
}
196194

197195
/// Get the offset at which the trailing trivia of this node starts.
198196
AbsoluteOffsetPosition getAbsoluteEndPositionAfterTrailingTrivia() const {
199-
return Data.getAbsoluteEndPositionAfterTrailingTrivia();
197+
return Data->getAbsoluteEndPositionAfterTrailingTrivia();
200198
}
201199

202200
// TODO: hasSameStructureAs ?

include/swift/Syntax/SyntaxCollection.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ class SyntaxCollection : public Syntax {
5757
friend class Syntax;
5858

5959
private:
60-
static SyntaxData makeData(std::initializer_list<Element> &Elements,
61-
const RC<SyntaxArena> &Arena) {
60+
static RC<const SyntaxData> makeData(std::initializer_list<Element> &Elements,
61+
const RC<SyntaxArena> &Arena) {
6262
std::vector<const RawSyntax *> List;
6363
List.reserve(Elements.size());
6464
for (auto &Elt : Elements)
@@ -69,7 +69,7 @@ class SyntaxCollection : public Syntax {
6969
}
7070

7171
public:
72-
SyntaxCollection(const SyntaxData Data) : Syntax(Data) {}
72+
SyntaxCollection(const RC<const SyntaxData> &Data) : Syntax(Data) {}
7373

7474
SyntaxCollection(std::initializer_list<Element> list):
7575
SyntaxCollection(SyntaxCollection::makeData(list)) {}
@@ -105,7 +105,7 @@ class SyntaxCollection : public Syntax {
105105
Element operator[](const size_t Index) const {
106106
assert(Index < size());
107107
assert(!empty());
108-
return Element(*Data.getChild(Index));
108+
return Element(Data->getChild(Index));
109109
}
110110

111111
/// Return a new collection with the given element added to the end.
@@ -119,7 +119,7 @@ class SyntaxCollection : public Syntax {
119119
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
120120
getRaw()->getPresence(),
121121
getRaw()->getArena());
122-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
122+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
123123
}
124124

125125
/// Return a new collection with an element removed from the end.
@@ -131,7 +131,7 @@ class SyntaxCollection : public Syntax {
131131
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
132132
getRaw()->getPresence(),
133133
getRaw()->getArena());
134-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
134+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
135135
}
136136

137137
/// Return a new collection with the given element appended to the front.
@@ -144,7 +144,7 @@ class SyntaxCollection : public Syntax {
144144
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
145145
getRaw()->getPresence(),
146146
getRaw()->getArena());
147-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
147+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
148148
}
149149

150150
/// Return a new collection with an element removed from the end.
@@ -156,7 +156,7 @@ class SyntaxCollection : public Syntax {
156156
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
157157
getRaw()->getPresence(),
158158
getRaw()->getArena());
159-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
159+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
160160
}
161161

162162
/// Return a new collection with the Element inserted at index i.
@@ -177,7 +177,7 @@ class SyntaxCollection : public Syntax {
177177
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
178178
getRaw()->getPresence(),
179179
getRaw()->getArena());
180-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
180+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
181181
}
182182

183183
/// Return a new collection with the element removed at index i.
@@ -190,14 +190,14 @@ class SyntaxCollection : public Syntax {
190190
auto Raw = RawSyntax::makeAndCalcLength(CollectionKind, NewLayout,
191191
getRaw()->getPresence(),
192192
getRaw()->getArena());
193-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
193+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
194194
}
195195

196196
/// Return an empty syntax collection of this type.
197197
SyntaxCollection<CollectionKind, Element> cleared() const {
198198
auto Raw = RawSyntax::makeAndCalcLength(
199199
CollectionKind, {}, getRaw()->getPresence(), getRaw()->getArena());
200-
return SyntaxCollection<CollectionKind, Element>(Data.replacingSelf(Raw));
200+
return SyntaxCollection<CollectionKind, Element>(Data->replacingSelf(Raw));
201201
}
202202

203203
static bool kindof(SyntaxKind Kind) {

include/swift/Syntax/SyntaxData.h

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -51,39 +51,24 @@
5151
namespace swift {
5252
namespace syntax {
5353

54-
/// A reference counted box that can contain any type.
55-
template <typename T>
56-
class RefCountedBox final
57-
: public llvm::ThreadSafeRefCountedBase<RefCountedBox<T>> {
58-
public:
59-
const T Data;
60-
61-
RefCountedBox(const T Data) : Data(Data) {}
62-
63-
static RC<RefCountedBox<T>> make(const T &Data) {
64-
return RC<RefCountedBox<T>>{new RefCountedBox(Data)};
65-
}
66-
};
67-
6854
/// The class for holding parented syntax.
6955
///
7056
/// This structure should not contain significant public
7157
/// API or internal modification API.
7258
///
7359
/// It is essentially a wrapper around \c AbsoluteRawSyntax that also keeps
7460
/// track of the parent.
75-
class SyntaxData {
61+
class SyntaxData : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
7662
const AbsoluteRawSyntax AbsoluteRaw;
77-
RC<RefCountedBox<SyntaxData>> Parent;
63+
RC<const SyntaxData> Parent;
7864

7965
/// If this node is the root of a Syntax tree (i.e. \c Parent is \c nullptr ),
8066
/// the arena in which this node's \c RawSyntax node has been allocated.
8167
/// This keeps this \c RawSyntax nodes referenced by this tree alive.
8268
RC<SyntaxArena> Arena;
8369

8470
/// Create a intermediate node with a parent.
85-
SyntaxData(AbsoluteRawSyntax AbsoluteRaw,
86-
const RC<RefCountedBox<SyntaxData>> &Parent)
71+
SyntaxData(AbsoluteRawSyntax AbsoluteRaw, const RC<const SyntaxData> &Parent)
8772
: AbsoluteRaw(AbsoluteRaw), Parent(Parent), Arena(nullptr) {}
8873

8974
/// Create a new root node
@@ -94,36 +79,36 @@ class SyntaxData {
9479
public:
9580
/// With a new \c RawSyntax node, create a new node from this one and
9681
/// recursively rebuild the parental chain up to the root.
97-
SyntaxData replacingSelf(const RawSyntax *NewRaw) const;
82+
RC<const SyntaxData> replacingSelf(const RawSyntax *NewRaw) const;
9883

9984
/// Replace a child in the raw syntax and recursively rebuild the
10085
/// parental chain up to the root.
10186
template <typename CursorType>
102-
SyntaxData replacingChild(const RawSyntax *RawChild,
103-
CursorType ChildCursor) const {
87+
RC<const SyntaxData> replacingChild(const RawSyntax *RawChild,
88+
CursorType ChildCursor) const {
10489
auto NewRaw = AbsoluteRaw.getRaw()->replacingChild(ChildCursor, RawChild);
10590
return replacingSelf(NewRaw);
10691
}
10792

10893
/// Get the node immediately before this current node that does contain a
109-
/// non-missing token. Return \c None if we cannot find such node.
110-
Optional<SyntaxData> getPreviousNode() const;
94+
/// non-missing token. Return \c nullptr if we cannot find such node.
95+
RC<const SyntaxData> getPreviousNode() const;
11196

11297
/// Get the node immediately after this current node that does contain a
113-
/// non-missing token. Return \c None if we cannot find such node.
114-
Optional<SyntaxData> getNextNode() const;
98+
/// non-missing token. Return \c nullptr if we cannot find such node.
99+
RC<const SyntaxData> getNextNode() const;
115100

116-
/// Get the first non-missing token node in this tree. Return \c None if
101+
/// Get the first non-missing token node in this tree. Return \c nullptr if
117102
/// this node does not contain non-missing tokens.
118-
Optional<SyntaxData> getFirstToken() const;
103+
RC<const SyntaxData> getFirstToken() const;
119104

120-
/// Get the last non-missing token node in this tree. Return \c None if
105+
/// Get the last non-missing token node in this tree. Return \c nullptr if
121106
/// this node does not contain non-missing tokens.
122-
Optional<SyntaxData> getLastToken() const;
107+
RC<const SyntaxData> getLastToken() const;
123108

124109
/// Make a new \c SyntaxData node for the tree's root.
125-
static SyntaxData makeRoot(AbsoluteRawSyntax AbsoluteRaw) {
126-
return SyntaxData(AbsoluteRaw);
110+
static RC<const SyntaxData> makeRoot(AbsoluteRawSyntax AbsoluteRaw) {
111+
return RC<const SyntaxData>(new SyntaxData(AbsoluteRaw));
127112
}
128113

129114
const AbsoluteRawSyntax &getAbsoluteRaw() const { return AbsoluteRaw; }
@@ -135,13 +120,7 @@ class SyntaxData {
135120
SyntaxKind getKind() const { return AbsoluteRaw.getRaw()->getKind(); }
136121

137122
/// Return the parent syntax if there is one.
138-
Optional<SyntaxData> getParent() const {
139-
if (Parent) {
140-
return Parent->Data;
141-
} else {
142-
return None;
143-
}
144-
}
123+
RC<const SyntaxData> getParent() const { return Parent; }
145124

146125
/// Returns true if this syntax node has a parent.
147126
bool hasParent() const {
@@ -161,13 +140,13 @@ class SyntaxData {
161140

162141
/// Gets the child at the index specified by the provided cursor.
163142
template <typename CursorType>
164-
Optional<SyntaxData> getChild(CursorType Cursor) const {
143+
RC<const SyntaxData> getChild(CursorType Cursor) const {
165144
return getChild(
166145
(AbsoluteSyntaxPosition::IndexInParentType)cursorIndex(Cursor));
167146
}
168147

169148
/// Gets the child at the specified \p Index.
170-
Optional<SyntaxData>
149+
RC<const SyntaxData>
171150
getChild(AbsoluteSyntaxPosition::IndexInParentType Index) const;
172151

173152
/// Get the offset at which the leading trivia of this node starts.

include/swift/Syntax/SyntaxNodes.h.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public:
6969
};
7070
% end
7171

72-
${node.name}(const SyntaxData Data) : ${node.base_type}(Data) {
72+
${node.name}(const RC<const SyntaxData> &Data) : ${node.base_type}(Data) {
7373
% if node.requires_validation():
7474
this->validate();
7575
% end

include/swift/Syntax/TokenSyntax.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class TokenSyntax final : public Syntax {
3333
assert(getRaw()->isToken());
3434
}
3535
public:
36-
TokenSyntax(const SyntaxData Data) : Syntax(Data) {}
36+
TokenSyntax(const RC<const SyntaxData> &Data) : Syntax(Data) {}
3737

3838
static TokenSyntax missingToken(const tok Kind, StringRef Text,
3939
const RC<SyntaxArena> &Arena) {
@@ -50,12 +50,12 @@ class TokenSyntax final : public Syntax {
5050

5151
TokenSyntax withLeadingTrivia(StringRef Trivia) const {
5252
auto NewRaw = getRaw()->withLeadingTrivia(Trivia);
53-
return TokenSyntax(getData().replacingSelf(NewRaw));
53+
return TokenSyntax(getData()->replacingSelf(NewRaw));
5454
}
5555

5656
TokenSyntax withTrailingTrivia(StringRef Trivia) const {
5757
auto NewRaw = getRaw()->withTrailingTrivia(Trivia);
58-
return TokenSyntax(getData().replacingSelf(NewRaw));
58+
return TokenSyntax(getData()->replacingSelf(NewRaw));
5959
}
6060

6161
/* TODO: If we really need them.

include/swift/Syntax/UnknownSyntax.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace syntax {
2929
class UnknownSyntax : public Syntax {
3030
void validate() const;
3131
public:
32-
UnknownSyntax(const SyntaxData Data) : Syntax(Data) {}
32+
UnknownSyntax(const RC<const SyntaxData> &Data) : Syntax(Data) {}
3333

3434
static bool classof(const Syntax *S) {
3535
return S->isUnknown();

lib/Parse/SyntaxParsingCache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ bool SyntaxParsingCache::nodeCanBeReused(const Syntax &Node, size_t NodeStart,
4141
// StructDecl inside and `private struc Foo {}` parses as two CodeBlockItems
4242
// one for `private` and one for `struc Foo {}`
4343
size_t NextLeafNodeLength = 0;
44-
if (auto NextNode = Node.getData().getNextNode()) {
44+
if (auto NextNode = Node.getData()->getNextNode()) {
4545
auto NextLeafNode = NextNode->getFirstToken();
4646
auto NextRawNode = NextLeafNode->getRaw();
4747
assert(NextRawNode->isPresent());

lib/Syntax/Syntax.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
using namespace swift;
1818
using namespace swift::syntax;
1919

20-
const RawSyntax *Syntax::getRaw() const { return Data.getRaw(); }
20+
const RawSyntax *Syntax::getRaw() const { return Data->getRaw(); }
2121

2222
SyntaxKind Syntax::getKind() const {
2323
return getRaw()->getKind();
@@ -36,21 +36,21 @@ void Syntax::dump(llvm::raw_ostream &OS, unsigned Indent) const {
3636
getRaw()->dump(OS, 0);
3737
}
3838

39-
bool Syntax::isType() const { return Data.isType(); }
39+
bool Syntax::isType() const { return Data->isType(); }
4040

41-
bool Syntax::isDecl() const { return Data.isDecl(); }
41+
bool Syntax::isDecl() const { return Data->isDecl(); }
4242

43-
bool Syntax::isStmt() const { return Data.isStmt(); }
43+
bool Syntax::isStmt() const { return Data->isStmt(); }
4444

45-
bool Syntax::isExpr() const { return Data.isExpr(); }
45+
bool Syntax::isExpr() const { return Data->isExpr(); }
4646

4747
bool Syntax::isToken() const {
4848
return getRaw()->isToken();
4949
}
5050

51-
bool Syntax::isPattern() const { return Data.isPattern(); }
51+
bool Syntax::isPattern() const { return Data->isPattern(); }
5252

53-
bool Syntax::isUnknown() const { return Data.isUnknown(); }
53+
bool Syntax::isUnknown() const { return Data->isUnknown(); }
5454

5555
bool Syntax::isPresent() const {
5656
return getRaw()->isPresent();
@@ -61,19 +61,19 @@ bool Syntax::isMissing() const {
6161
}
6262

6363
llvm::Optional<Syntax> Syntax::getParent() const {
64-
auto ParentData = getData().getParent();
64+
auto ParentData = getData()->getParent();
6565
if (!ParentData) {
6666
return None;
6767
}
68-
return Syntax(*ParentData);
68+
return Syntax(ParentData);
6969
}
7070

71-
size_t Syntax::getNumChildren() const { return Data.getNumChildren(); }
71+
size_t Syntax::getNumChildren() const { return Data->getNumChildren(); }
7272

7373
llvm::Optional<Syntax> Syntax::getChild(const size_t N) const {
74-
auto ChildData = Data.getChild(N);
74+
auto ChildData = Data->getChild(N);
7575
if (!ChildData) {
7676
return None;
7777
}
78-
return Syntax(*ChildData);
78+
return Syntax(ChildData);
7979
}

0 commit comments

Comments
 (0)