@@ -24,23 +24,8 @@ public enum SyntaxVisitorContinueKind {
24
24
open class SyntaxVisitor {
25
25
public let viewMode : SyntaxTreeViewMode
26
26
27
- /// `Syntax.Info` objects created in `visitChildren` but whose `Syntax` nodes were not retained by the `visit`
28
- /// functions implemented by a subclass of `SyntaxVisitor`.
29
- ///
30
- /// Instead of deallocating them and allocating memory for new syntax nodes, store the allocated memory in an array.
31
- /// We can then re-use them to create new syntax nodes.
32
- ///
33
- /// The array's size should be a typical nesting depth of a Swift file. That way we can store all allocated syntax
34
- /// nodes when unwinding the visitation stack.
35
- ///
36
- /// The actual `info` stored in the `Syntax.Info` objects is garbage. It needs to be set when any of the `Syntax.Info`
37
- /// objects get re-used.
38
- private var recyclableNodeInfos : ContiguousArray < Syntax . Info ? > = ContiguousArray ( repeating: nil , count: 64 )
39
-
40
- /// A bit is set to 1 if the corresponding index in `recyclableNodeInfos` is occupied and ready to be reused.
41
- ///
42
- /// The last bit in this UInt64 corresponds to index 0 in `recyclableNodeInfos`.
43
- private var recyclableNodeInfosUsageBitmap : UInt64 = 0
27
+ /// 'Syntax' object factory recycling 'Syntax.Info' instances.
28
+ private let nodeFactory : SyntaxNodeFactory = SyntaxNodeFactory ( )
44
29
45
30
public init ( viewMode: SyntaxTreeViewMode ) {
46
31
self . viewMode = viewMode
@@ -5267,60 +5252,11 @@ open class SyntaxVisitor {
5267
5252
#endif
5268
5253
5269
5254
/// - Note: `node` is `inout` to avoid reference counting. See comment in `visitImpl`.
5270
- private func visitChildren( _ syntaxNode: inout Syntax ) {
5271
- for childRaw in NonNilRawSyntaxChildren ( syntaxNode, viewMode: viewMode) {
5272
- // syntaxNode gets retained here. That seems unnecessary but I don't know how to remove it.
5273
- var childNode : Syntax
5274
- if let recycledInfoIndex = recyclableNodeInfosUsageBitmap. indexOfRightmostOne {
5275
- var recycledInfo : Syntax . Info ? = nil
5276
- // Use `swap` to extract the recyclable syntax node without incurring ref-counting.
5277
- swap ( & recycledInfo, & recyclableNodeInfos[ recycledInfoIndex] )
5278
- assert ( recycledInfo != nil , " Slot indicated by the bitmap did not contain a value " )
5279
- recyclableNodeInfosUsageBitmap. setBitToZero ( at: recycledInfoIndex)
5280
- // syntaxNode.info gets retained here. This is necessary because we build up the parent tree.
5281
- recycledInfo!. info = . nonRoot( . init( parent: syntaxNode, absoluteInfo: childRaw. info) )
5282
- childNode = Syntax ( childRaw. raw, info: recycledInfo!)
5283
- } else {
5284
- childNode = Syntax ( childRaw, parent: syntaxNode)
5285
- }
5255
+ private func visitChildren( _ node: inout Syntax ) {
5256
+ for case let ( child? , info) in RawSyntaxChildren ( node) where viewMode. shouldTraverse ( node: child) {
5257
+ var childNode = nodeFactory. create ( parent: node, raw: child, absoluteInfo: info)
5286
5258
visit ( & childNode)
5287
- if isKnownUniquelyReferenced ( & childNode. info) {
5288
- // The node didn't get stored by the subclass's visit method. We can re-use the memory of its `Syntax.Info`
5289
- // for future syntax nodes.
5290
- childNode. info. info = nil
5291
- if let emptySlot = recyclableNodeInfosUsageBitmap. indexOfRightmostZero {
5292
- // Use `swap` to store the recyclable syntax node without incurring ref-counting.
5293
- swap ( & recyclableNodeInfos[ emptySlot] , & childNode. info)
5294
- assert ( childNode. info == nil , " Slot should not have contained a value " )
5295
- recyclableNodeInfosUsageBitmap. setBitToOne ( at: emptySlot)
5296
- }
5297
- }
5298
- }
5299
- }
5300
- }
5301
-
5302
- fileprivate extension UInt64 {
5303
- var indexOfRightmostZero : Int ? {
5304
- return ( ~ self ) . indexOfRightmostOne
5305
- }
5306
-
5307
-
5308
- var indexOfRightmostOne : Int ? {
5309
- let trailingZeroCount = self . trailingZeroBitCount
5310
- if trailingZeroCount == Self . bitWidth {
5311
- // All indicies are 0
5312
- return nil
5259
+ nodeFactory. dispose ( & childNode)
5313
5260
}
5314
- return trailingZeroCount
5315
- }
5316
-
5317
-
5318
- mutating func setBitToZero( at index: Int ) {
5319
- self &= ~ ( 1 << index)
5320
- }
5321
-
5322
-
5323
- mutating func setBitToOne( at index: Int ) {
5324
- self |= 1 << index
5325
5261
}
5326
5262
}
0 commit comments