@@ -57,12 +57,13 @@ namespace syntax {
57
57
// / This is only for holding a strong reference to the RawSyntax, a weak
58
58
// / reference to the parent, and, in subclasses, lazily created strong
59
59
// / references to non-terminal child nodes.
60
- class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
61
- using RootDataPair = std::pair<RC<SyntaxData>, RC<SyntaxData>>;
60
+ class SyntaxData final
61
+ : public llvm::ThreadSafeRefCountedBase<SyntaxData>,
62
+ private llvm::TrailingObjects<SyntaxData, AtomicCache<SyntaxData>> {
63
+ friend TrailingObjects;
62
64
63
- llvm::SmallVector<AtomicCache <SyntaxData>, 10 > Children ;
65
+ using RootDataPair = std::pair<RC <SyntaxData>, RC<SyntaxData>> ;
64
66
65
- public:
66
67
// / The shared raw syntax representing this syntax data node.
67
68
const RC<RawSyntax> Raw;
68
69
@@ -77,18 +78,16 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
77
78
// / If there is no parent, this is 0.
78
79
const CursorIndex IndexInParent;
79
80
81
+ size_t numTrailingObjects (OverloadToken<AtomicCache<SyntaxData>>) const {
82
+ return Raw->getNumChildren ();
83
+ }
84
+
80
85
SyntaxData (RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr ,
81
86
CursorIndex IndexInParent = 0 )
82
87
: Raw(Raw), Parent(Parent), IndexInParent(IndexInParent) {
83
- Children.resize (Raw ? Raw->getLayout ().size () : 0 );
84
- }
85
-
86
- // / Constructs a SyntaxNode by replacing `self` and recursively building
87
- // / the parent chain up to the root.
88
- template <typename SyntaxNode>
89
- SyntaxNode replaceSelf (const RC<RawSyntax> NewRaw) const {
90
- auto NewRootAndData = replaceSelf (NewRaw);
91
- return { NewRootAndData.first , NewRootAndData.second .get () };
88
+ auto *I = getTrailingObjects<AtomicCache<SyntaxData>>();
89
+ for (auto *E = I + getNumChildren (); I != E; ++I)
90
+ ::new (static_cast <void *>(I)) AtomicCache<SyntaxData>();
92
91
}
93
92
94
93
// / With a new RawSyntax node, create a new node from this one and
@@ -97,8 +96,7 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
97
96
// / DO NOT expose this as public API.
98
97
RootDataPair replaceSelf (const RC<RawSyntax> NewRaw) const {
99
98
if (hasParent ()) {
100
- auto NewRootAndParent =
101
- getParent ().getValue ()->replaceChild (NewRaw, IndexInParent);
99
+ auto NewRootAndParent = Parent->replaceChild (NewRaw, IndexInParent);
102
100
auto NewMe = NewRootAndParent.second ->getChild (IndexInParent);
103
101
return { NewRootAndParent.first , NewMe.get () };
104
102
} else {
@@ -116,6 +114,35 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
116
114
return nullptr ;
117
115
}
118
116
117
+ // / Replace a child in the raw syntax and recursively rebuild the
118
+ // / parental chain up to the root.
119
+ // /
120
+ // / DO NOT expose this as public API.
121
+ template <typename CursorType>
122
+ RootDataPair replaceChild (const RC<RawSyntax> RawChild,
123
+ CursorType ChildCursor) const {
124
+ auto NewRaw = Raw->replaceChild (ChildCursor, RawChild);
125
+ return replaceSelf (NewRaw);
126
+ }
127
+
128
+ ArrayRef<AtomicCache<SyntaxData>> getChildren () const {
129
+ return {getTrailingObjects<AtomicCache<SyntaxData>>(), getNumChildren ()};
130
+ }
131
+
132
+ public:
133
+ ~SyntaxData () {
134
+ for (auto &I : getChildren ())
135
+ I.~AtomicCache<SyntaxData>();
136
+ }
137
+
138
+ // / Constructs a SyntaxNode by replacing `self` and recursively building
139
+ // / the parent chain up to the root.
140
+ template <typename SyntaxNode>
141
+ SyntaxNode replaceSelf (const RC<RawSyntax> NewRaw) const {
142
+ auto NewRootAndData = replaceSelf (NewRaw);
143
+ return { NewRootAndData.first , NewRootAndData.second .get () };
144
+ }
145
+
119
146
// / Replace a child in the raw syntax and recursively rebuild the
120
147
// / parental chain up to the root.
121
148
// /
@@ -130,18 +157,6 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
130
157
};
131
158
}
132
159
133
- // / Replace a child in the raw syntax and recursively rebuild the
134
- // / parental chain up to the root.
135
- // /
136
- // / DO NOT expose this as public API.
137
- template <typename CursorType>
138
- RootDataPair replaceChild (const RC<RawSyntax> RawChild,
139
- CursorType ChildCursor) const {
140
- auto NewRaw = Raw->replaceChild (ChildCursor, RawChild);
141
- return replaceSelf (NewRaw);
142
- }
143
-
144
- public:
145
160
146
161
static RC<SyntaxData> make (RC<RawSyntax> Raw,
147
162
const SyntaxData *Parent = nullptr ,
@@ -158,11 +173,8 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
158
173
}
159
174
160
175
// / Return the parent syntax if there is one.
161
- llvm::Optional<const SyntaxData *> getParent () const {
162
- if (Parent != nullptr ) {
163
- return Parent;
164
- }
165
- return llvm::None;
176
+ const SyntaxData * getParent () const {
177
+ return Parent;
166
178
}
167
179
168
180
// / Returns true if this syntax node has a parent.
@@ -218,7 +230,7 @@ class SyntaxData final : public llvm::ThreadSafeRefCountedBase<SyntaxData> {
218
230
RC<SyntaxData> getChild (size_t Index) const {
219
231
if (!getRaw ()->getChild (Index))
220
232
return nullptr ;
221
- return Children [Index].getOrCreate ([&]() {
233
+ return getChildren () [Index].getOrCreate ([&]() {
222
234
return realizeSyntaxNode (Index);
223
235
});
224
236
}
@@ -262,8 +274,8 @@ namespace llvm {
262
274
}
263
275
static unsigned getHashValue (const RCSD Value) {
264
276
unsigned H = 0 ;
265
- H ^= DenseMapInfo<uintptr_t >::getHashValue (reinterpret_cast <const uintptr_t >(Value->Raw .get ()));
266
- H ^= DenseMapInfo<uintptr_t >::getHashValue (reinterpret_cast <const uintptr_t >(Value->Parent ));
277
+ H ^= DenseMapInfo<uintptr_t >::getHashValue (reinterpret_cast <const uintptr_t >(Value->getRaw () .get ()));
278
+ H ^= DenseMapInfo<uintptr_t >::getHashValue (reinterpret_cast <const uintptr_t >(Value->getParent () ));
267
279
H ^= DenseMapInfo<swift::syntax::CursorIndex>::getHashValue (Value->getIndexInParent ());
268
280
return H;
269
281
}
0 commit comments