31
31
32
32
#include " swift/Basic/InlineBitfield.h"
33
33
#include " swift/Syntax/References.h"
34
+ #include " swift/Syntax/SyntaxArena.h"
34
35
#include " swift/Syntax/SyntaxKind.h"
35
36
#include " swift/Syntax/TokenKinds.h"
36
37
#include " swift/Syntax/Trivia.h"
@@ -218,8 +219,7 @@ typedef unsigned SyntaxNodeId;
218
219
// /
219
220
// / This is implementation detail - do not expose it in public API.
220
221
class RawSyntax final
221
- : public llvm::ThreadSafeRefCountedBase<RawSyntax>,
222
- private llvm::TrailingObjects<RawSyntax, RC<RawSyntax>, OwnedString,
222
+ : private llvm::TrailingObjects<RawSyntax, RC<RawSyntax>, OwnedString,
223
223
TriviaPiece> {
224
224
friend TrailingObjects;
225
225
@@ -230,18 +230,20 @@ class RawSyntax final
230
230
// / An ID of this node that is stable across incremental parses
231
231
SyntaxNodeId NodeId;
232
232
233
+ // / If this node was allocated using a \c SyntaxArena's bump allocator, a
234
+ // / reference to the arena to keep the underlying memory buffer of this node
235
+ // / alive. If this is a \c nullptr, the node owns its own memory buffer.
236
+ RC<SyntaxArena> Arena;
237
+
233
238
union {
234
239
uint64_t OpaqueBits;
235
240
struct {
236
241
// / The kind of syntax this node represents.
237
242
unsigned Kind : bitmax(NumSyntaxKindBits, 8 );
238
243
// / Whether this piece of syntax was actually present in the source.
239
244
unsigned Presence : 1 ;
240
- // / Whether this piece of syntax was constructed with manually managed
241
- // / memory.
242
- unsigned ManualMemory : 1 ;
243
245
} Common;
244
- enum { NumRawSyntaxBits = bitmax (NumSyntaxKindBits, 8 ) + 1 + 1 };
246
+ enum { NumRawSyntaxBits = bitmax (NumSyntaxKindBits, 8 ) + 1 };
245
247
246
248
// For "layout" nodes.
247
249
struct {
@@ -282,18 +284,23 @@ class RawSyntax final
282
284
: 0 ;
283
285
}
284
286
285
- // / Constructor for creating layout nodes
287
+ // / Constructor for creating layout nodes.
288
+ // / If the node has been allocated inside the bump allocator of a
289
+ // / \c SyntaxArena, that arena must be passed as \p Arena to retain the node's
290
+ // / underlying storage.
286
291
// / If \p NodeId is \c None, the next free NodeId is used, if it is passed,
287
292
// / the caller needs to assure that the node ID has not been used yet.
288
293
RawSyntax (SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
289
- SourcePresence Presence, bool ManualMemory ,
294
+ SourcePresence Presence, RC<SyntaxArena> Arena ,
290
295
llvm::Optional<SyntaxNodeId> NodeId);
291
296
// / Constructor for creating token nodes
297
+ // / \c SyntaxArena, that arena must be passed as \p Arena to retain the node's
298
+ // / underlying storage.
292
299
// / If \p NodeId is \c None, the next free NodeId is used, if it is passed,
293
300
// / the caller needs to assure that the NodeId has not been used yet.
294
301
RawSyntax (tok TokKind, OwnedString Text, ArrayRef<TriviaPiece> LeadingTrivia,
295
302
ArrayRef<TriviaPiece> TrailingTrivia, SourcePresence Presence,
296
- bool ManualMemory , llvm::Optional<SyntaxNodeId> NodeId);
303
+ RC<SyntaxArena> Arena , llvm::Optional<SyntaxNodeId> NodeId);
297
304
298
305
// / Compute the node's text length by summing up the length of its childern
299
306
size_t computeTextLength () {
@@ -307,18 +314,30 @@ class RawSyntax final
307
314
return TextLength;
308
315
}
309
316
317
+ mutable std::atomic<int > RefCount;
318
+
310
319
public:
311
320
~RawSyntax ();
312
321
322
+ // This is a copy-pased implementation of llvm::ThreadSafeRefCountedBase with
323
+ // the difference that we do not delete the RawSyntax node's memory if the
324
+ // node was allocated within a SyntaxArena and thus doesn't own its memory.
325
+ void Retain () const { RefCount.fetch_add (1 , std::memory_order_relaxed); }
326
+
313
327
void Release () const {
314
- if (Bits.Common .ManualMemory )
315
- return ;
316
- return llvm::ThreadSafeRefCountedBase<RawSyntax>::Release ();
317
- }
318
- void Retain () const {
319
- if (Bits.Common .ManualMemory )
320
- return ;
321
- return llvm::ThreadSafeRefCountedBase<RawSyntax>::Retain ();
328
+ int NewRefCount = RefCount.fetch_sub (1 , std::memory_order_acq_rel) - 1 ;
329
+ assert (NewRefCount >= 0 && " Reference count was already zero." );
330
+ if (NewRefCount == 0 ) {
331
+ if (Arena) {
332
+ // The node was allocated inside a SyntaxArena and thus doesn't own its
333
+ // own memory region. Hence we cannot free it. It will be deleted once
334
+ // the last RawSyntax node allocated with it will release its reference
335
+ // to the arena.
336
+ this ->~RawSyntax ();
337
+ } else {
338
+ delete this ;
339
+ }
340
+ }
322
341
}
323
342
324
343
// / \name Factory methods.
@@ -327,33 +346,29 @@ class RawSyntax final
327
346
// / Make a raw "layout" syntax node.
328
347
static RC<RawSyntax> make (SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
329
348
SourcePresence Presence,
330
- SyntaxArena * Arena = nullptr ,
349
+ RC< SyntaxArena> Arena = nullptr ,
331
350
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
332
351
333
352
// / Make a raw "token" syntax node.
334
353
static RC<RawSyntax> make (tok TokKind, OwnedString Text,
335
354
ArrayRef<TriviaPiece> LeadingTrivia,
336
355
ArrayRef<TriviaPiece> TrailingTrivia,
337
356
SourcePresence Presence,
338
- SyntaxArena * Arena = nullptr ,
357
+ RC< SyntaxArena> Arena = nullptr ,
339
358
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
340
359
341
360
// / Make a missing raw "layout" syntax node.
342
- static RC<RawSyntax> missing (SyntaxKind Kind, SyntaxArena *Arena = nullptr ) {
361
+ static RC<RawSyntax> missing (SyntaxKind Kind,
362
+ RC<SyntaxArena> Arena = nullptr ) {
343
363
return make (Kind, {}, SourcePresence::Missing, Arena);
344
364
}
345
365
346
366
// / Make a missing raw "token" syntax node.
347
367
static RC<RawSyntax> missing (tok TokKind, OwnedString Text,
348
- SyntaxArena * Arena = nullptr ) {
368
+ RC< SyntaxArena> Arena = nullptr ) {
349
369
return make (TokKind, Text, {}, {}, SourcePresence::Missing, Arena);
350
370
}
351
371
352
- static RC<RawSyntax> getToken (SyntaxArena &Arena, tok TokKind,
353
- OwnedString Text,
354
- ArrayRef<TriviaPiece> LeadingTrivia,
355
- ArrayRef<TriviaPiece> TrailingTrivia);
356
-
357
372
// / @}
358
373
359
374
SourcePresence getPresence () const {
0 commit comments