mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-06 07:38:24 +00:00
@@ -139,7 +139,7 @@
|
||||
|
||||
import
|
||||
ast, msgs, idents,
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos, trees
|
||||
|
||||
import std/tables
|
||||
|
||||
@@ -1390,18 +1390,34 @@ proc optimizeStates(ctx: var Ctx) =
|
||||
for i in 0 .. ctx.states.high:
|
||||
ctx.states[i].label.intVal = i
|
||||
|
||||
proc detectCapturedSym(c: var Ctx, s: PSym, stateIdx: int) =
|
||||
if s.kind in {skResult, skVar, skLet, skForVar, skTemp} and sfGlobal notin s.flags and s.owner == c.fn and s != c.externExcSym:
|
||||
let vs = c.varStates.getOrDefault(s.itemId, localNotSeen)
|
||||
if vs == localNotSeen: # First seing this variable
|
||||
c.varStates[s.itemId] = stateIdx
|
||||
elif vs == localRequiresLifting:
|
||||
discard # Sym already marked
|
||||
elif vs != stateIdx:
|
||||
c.captureVar(s)
|
||||
|
||||
proc isClosureIterLocal(c: Ctx, s: PSym): bool =
|
||||
s.kind in {skResult, skVar, skLet, skForVar, skTemp} and
|
||||
sfGlobal notin s.flags and s.owner == c.fn and s != c.externExcSym
|
||||
|
||||
proc detectCapturedVars(c: var Ctx, n: PNode, stateIdx: int) =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
let s = n.sym
|
||||
if s.kind in {skResult, skVar, skLet, skForVar, skTemp} and sfGlobal notin s.flags and s.owner == c.fn and s != c.externExcSym:
|
||||
let vs = c.varStates.getOrDefault(s.itemId, localNotSeen)
|
||||
if vs == localNotSeen: # First seing this variable
|
||||
c.varStates[s.itemId] = stateIdx
|
||||
elif vs == localRequiresLifting:
|
||||
discard # Sym already marked
|
||||
elif vs != stateIdx:
|
||||
c.captureVar(s)
|
||||
detectCapturedSym(c, s, stateIdx)
|
||||
of nkAddr, nkHiddenAddr:
|
||||
let s = getRoot(n)
|
||||
if s != nil and isClosureIterLocal(c, s):
|
||||
detectCapturedSym(c, s, stateIdx)
|
||||
# bug #25596; lifetime extension for `addr`-taken locals as
|
||||
# we claim ARC/ORC do destruction based on scopes, not on last-usages.
|
||||
c.captureVar(s)
|
||||
for i in 0 ..< n.safeLen:
|
||||
detectCapturedVars(c, n[i], stateIdx)
|
||||
of nkReturnStmt:
|
||||
if n[0].kind in {nkAsgn, nkFastAsgn, nkSinkAsgn}:
|
||||
# we have a `result = result` expression produced by the closure
|
||||
|
||||
@@ -559,17 +559,21 @@ block: # void iterator
|
||||
discard
|
||||
var a = it
|
||||
|
||||
block: # Locals present in only 1 state should be on the stack
|
||||
block:
|
||||
# Locals present in only 1 state should be on the stack
|
||||
proc checkOnStack(a: pointer, shouldBeOnStack: bool) =
|
||||
# Quick and dirty way to check if a points to stack
|
||||
var dummy = 0
|
||||
let dummyAddr = addr dummy
|
||||
let distance = abs(cast[int](dummyAddr) - cast[int](a))
|
||||
const requiredDistance = 300
|
||||
if shouldBeOnStack:
|
||||
doAssert(distance <= requiredDistance, "a is not on stack, but should")
|
||||
else:
|
||||
doAssert(distance > requiredDistance, "a is on stack, but should not")
|
||||
# bug #25596: the very fact we take the address prevents the local
|
||||
# from being on the stack
|
||||
when false:
|
||||
# Quick and dirty way to check if a points to stack
|
||||
var dummy = 0
|
||||
let dummyAddr = addr dummy
|
||||
let distance = abs(cast[int](dummyAddr) - cast[int](a))
|
||||
const requiredDistance = 300
|
||||
if shouldBeOnStack:
|
||||
doAssert(distance <= requiredDistance, "a is not on stack, but should")
|
||||
else:
|
||||
doAssert(distance > requiredDistance, "a is on stack, but should not")
|
||||
|
||||
iterator it(): int {.closure.} =
|
||||
var a = 1
|
||||
|
||||
Reference in New Issue
Block a user