@@ -126,16 +126,15 @@ type
126126 # # depends on the entity kind.
127127 a: array [2 , int ]
128128
129- EntityInfo = object
130- # # Information about a lifetime of an entity. The lifetime of an entity is
131- # # the time during which it can be *live* (i.e., store a value).
129+ Lifetime = object
130+ # # Describes a single lifetime of a location.
132131 def: NodePosition # # the position of the 'def' for the entity
133132 scope: Subgraph # # the data-flow subgraph during which the entity exists
134133
135- EntityDict = Table [EntityName , seq [EntityInfo ]]
134+ EntityDict = Table [EntityName , seq [Lifetime ]]
136135 # # Entity dictionary. Stores all entities relevant to destructor
137136 # # injection and the move analyser. A location may have more than one
138- # # lifetimes .
137+ # # lifetime .
139138
140139 Moves = PackedSet [OpValue ]
141140 # # A set storing the operands of all sinks that were collapsed into
@@ -165,22 +164,19 @@ func toName(n: MirNode): EntityName =
165164 else :
166165 unreachable (n.kind)
167166
168- func findScope (entities: EntityDict , name: EntityName , at: InstrPos ,
169- exists: var bool ): EntityInfo =
170- # # Returns the ``EntityInfo`` for `name` that encloses the data-flow
171- # # instruction at `at`. If `name` is present in `entities` but `at` is not
172- # # directly part of any lifetime, the ``EntityInfo`` for the lifetime
173- # # preceding `at` is returned.
174- # #
175- # # `exists` is updated to indicate whether a scope was found.
167+ func findLifetime (entities: EntityDict , name: EntityName , at: InstrPos ,
168+ exists: var bool ): Lifetime =
169+ # # Returns the lifetime for `name` the data-flow instruction at `at` is part
170+ # # of. `exists` is set to whether a lifetime was found.
176171 if name in entities:
177172 let lifetimes {.cursor .} = entities[name]
178- # search for the upper bound:
179- var i = 0
180- while i < lifetimes.len and at >= lifetimes[i].scope.a:
181- inc i
182-
183- if i - 1 >= 0 :
173+ if lifetimes[0 ].scope.a <= at:
174+ var i = 0
175+ while i < lifetimes.len and at >= lifetimes[i].scope.a:
176+ inc i
177+ while i > 1 and lifetimes[i - 1 ].scope.b < at:
178+ dec i
179+ # i now points to one past the best matching lifetime
184180 result = lifetimes[i - 1 ]
185181 exists = true
186182 else :
@@ -206,7 +202,7 @@ iterator nodesWithScope(tree: MirTree): (NodePosition, lent MirNode, Slice[NodeP
206202 # the logic relies on the assumption that there exists a scope around
207203 # every 'def'
208204
209- proc findScopeEnd (tree: MirTree , start: NodePosition ): NodePosition =
205+ proc End (tree: MirTree , start: NodePosition ): NodePosition =
210206 # # Searches for the position of the ``mnkScopeEnd`` node for the current
211207 # # scope.
212208 var
@@ -227,7 +223,7 @@ iterator nodesWithScope(tree: MirTree): (NodePosition, lent MirNode, Slice[NodeP
227223 of mnkScope:
228224 # start a new scope. The start and end node/token are not included in
229225 # the span
230- let fin = findScopeEnd (tree, i + 1 )
226+ let fin = End (tree, i + 1 )
231227 scopeStack.add tree.sibling (i).. (fin- 1 )
232228 of mnkEndScope:
233229 # leave the current scope:
@@ -257,7 +253,7 @@ func initEntityDict(tree: MirTree, dfg: DataFlowGraph, env: MirEnv): EntityDict
257253 if hasDestructor (env[entity.typ]):
258254 result .mgetOrPut (toName (entity), @ []).add:
259255 # don't include the data-flow operations preceding the def
260- EntityInfo (def: i, scope: subgraphFor (dfg, i .. scope.b))
256+ Lifetime (def: i, scope: subgraphFor (dfg, i .. scope.b))
261257 of mnkLocal:
262258 # there's no def for the result variable
263259 if n.local == resultId and hasDestructor (env[n.typ]):
@@ -266,7 +262,7 @@ func initEntityDict(tree: MirTree, dfg: DataFlowGraph, env: MirEnv): EntityDict
266262 # the result variable's location exists for the full duration
267263 # of the procedure
268264 let scope = subgraphFor (dfg, NodePosition (0 ).. NodePosition (tree.high))
269- result [name] = @ [EntityInfo (scope: scope)]
265+ result [name] = @ [Lifetime (scope: scope)]
270266 else :
271267 discard
272268
@@ -281,7 +277,7 @@ func computeOwnership(tree: MirTree, cfg: DataFlowGraph, entities: EntityDict,
281277 # can't reason about them or they're non-owning locations), so values
282278 # derived from them are treated as non-owning
283279 var exists = false
284- let info = entities.findScope (toName (tree[lval.root]), start, exists)
280+ let info = entities.findLifetime (toName (tree[lval.root]), start, exists)
285281 exists and isLastRead (tree, cfg, info.scope, lval, start)
286282 else :
287283 unreachable ()
@@ -328,7 +324,7 @@ func isAlive(tree: MirTree, cfg: DataFlowGraph,
328324 of mnkLocal, mnkParam, mnkGlobal, mnkTemp:
329325 let scope = block :
330326 var exists: bool
331- let info = entities.findScope (toName (tree[root]), at, exists)
327+ let info = entities.findLifetime (toName (tree[root]), at, exists)
332328 if exists: info.scope
333329 else : return true # not something we can analyse -> assume alive
334330
@@ -358,7 +354,7 @@ func needsReset(tree: MirTree, cfg: DataFlowGraph, ar: AnalysisResults,
358354 # # cause problems like, for example, double-frees), the location is
359355 # # explicitly reset (i.e. the value removed from it).
360356 var exists: bool
361- let info = findScope (ar.entities[], toName (tree[src.root]), at, exists)
357+ let info = findLifetime (ar.entities[], toName (tree[src.root]), at, exists)
362358
363359 if not exists:
364360 # the location is not local to the current context -> assume that it needs
0 commit comments