@@ -24,23 +24,8 @@ public enum SyntaxVisitorContinueKind {
2424open class SyntaxVisitor {
2525 public let viewMode : SyntaxTreeViewMode
2626
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 ( )
4429
4530 public init ( viewMode: SyntaxTreeViewMode ) {
4631 self . viewMode = viewMode
@@ -5267,60 +5252,11 @@ open class SyntaxVisitor {
52675252 #endif
52685253
52695254 /// - 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)
52865258 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)
53135260 }
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
53255261 }
53265262}
0 commit comments