destructors: do not produce strong backrefs in closure environments so that refcounting works
This commit is contained in:
parent
0c2c2dca2a
commit
0a628f36f0
1 changed files with 17 additions and 4 deletions
|
|
@ -320,17 +320,30 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
|
||||||
rawAddSon(result, obj)
|
rawAddSon(result, obj)
|
||||||
c.ownerToType[owner.id] = result
|
c.ownerToType[owner.id] = result
|
||||||
|
|
||||||
|
proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
|
||||||
|
info: TLineInfo): PType =
|
||||||
|
var r = c.getEnvTypeForOwner(owner, info)
|
||||||
|
result = newType(tyPtr, owner)
|
||||||
|
rawAddSon(result, r.base)
|
||||||
|
|
||||||
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||||
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
|
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
|
||||||
let obj = refObj.lastSon
|
let obj = refObj.lastSon
|
||||||
let fieldType = c.getEnvTypeForOwner(dep, info) #getHiddenParam(dep).typ
|
# The assumption here is that gcDestructors means we cannot deal
|
||||||
|
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
|
||||||
|
# This seems to be generally correct but since it's a bit risky it's only
|
||||||
|
# enabled for gcDestructors.
|
||||||
|
let fieldType = if c.graph.config.selectedGc == gcDestructors:
|
||||||
|
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
|
||||||
|
else:
|
||||||
|
c.getEnvTypeForOwner(dest, info)
|
||||||
if refObj == fieldType:
|
if refObj == fieldType:
|
||||||
localError(c.graph.config, dep.info, "internal error: invalid up reference computed")
|
localError(c.graph.config, dep.info, "internal error: invalid up reference computed")
|
||||||
|
|
||||||
let upIdent = getIdent(c.graph.cache, upName)
|
let upIdent = getIdent(c.graph.cache, upName)
|
||||||
let upField = lookupInRecord(obj.n, upIdent)
|
let upField = lookupInRecord(obj.n, upIdent)
|
||||||
if upField != nil:
|
if upField != nil:
|
||||||
if upField.typ != fieldType:
|
if upField.typ.base != fieldType.base:
|
||||||
localError(c.graph.config, dep.info, "internal error: up references do not agree")
|
localError(c.graph.config, dep.info, "internal error: up references do not agree")
|
||||||
else:
|
else:
|
||||||
let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
|
let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
|
||||||
|
|
@ -555,7 +568,7 @@ proc rawClosureCreation(owner: PSym;
|
||||||
let upField = lookupInRecord(env.typ.lastSon.n, getIdent(d.graph.cache, upName))
|
let upField = lookupInRecord(env.typ.lastSon.n, getIdent(d.graph.cache, upName))
|
||||||
if upField != nil:
|
if upField != nil:
|
||||||
let up = getUpViaParam(d.graph, owner)
|
let up = getUpViaParam(d.graph, owner)
|
||||||
if up != nil and upField.typ == up.typ:
|
if up != nil and upField.typ.base == up.typ.base:
|
||||||
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
||||||
up, env.info))
|
up, env.info))
|
||||||
#elif oldenv != nil and oldenv.typ == upField.typ:
|
#elif oldenv != nil and oldenv.typ == upField.typ:
|
||||||
|
|
@ -586,7 +599,7 @@ proc closureCreationForIter(iter: PNode;
|
||||||
let upField = lookupInRecord(v.typ.lastSon.n, getIdent(d.graph.cache, upName))
|
let upField = lookupInRecord(v.typ.lastSon.n, getIdent(d.graph.cache, upName))
|
||||||
if upField != nil:
|
if upField != nil:
|
||||||
let u = setupEnvVar(owner, d, c)
|
let u = setupEnvVar(owner, d, c)
|
||||||
if u.typ == upField.typ:
|
if u.typ.base == upField.typ.base:
|
||||||
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
|
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
|
||||||
u, iter.info))
|
u, iter.info))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue