--gc:destructors improvements (#12626)
* do not cache the noDestructors transformation * liftdestructor: improvements * undo bugfix
This commit is contained in:
parent
144ad36974
commit
82e0765fc9
2 changed files with 18 additions and 14 deletions
|
|
@ -327,6 +327,14 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
|
||||||
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
createTypeBoundOps(c.g, c.c, t, body.info)
|
createTypeBoundOps(c.g, c.c, t, body.info)
|
||||||
|
# recursions are tricky, so we might need to forward the generated
|
||||||
|
# operation here:
|
||||||
|
var t = t
|
||||||
|
if t.assignment == nil or t.destructor == nil:
|
||||||
|
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
|
||||||
|
let canon = c.g.canonTypes.getOrDefault(h)
|
||||||
|
if canon != nil: t = canon
|
||||||
|
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedAsgn, attachedDeepCopy:
|
of attachedAsgn, attachedDeepCopy:
|
||||||
doAssert t.assignment != nil
|
doAssert t.assignment != nil
|
||||||
|
|
@ -682,24 +690,23 @@ template inst(field, t) =
|
||||||
else:
|
else:
|
||||||
localError(g.config, info, "unresolved generic parameter")
|
localError(g.config, info, "unresolved generic parameter")
|
||||||
|
|
||||||
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
|
proc isTrival(s: PSym): bool {.inline.} =
|
||||||
|
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
|
||||||
|
|
||||||
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
|
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
## The later 'injectdestructors' pass depends on it.
|
## The later 'injectdestructors' pass depends on it.
|
||||||
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.skipTypes({tyAlias}).flags != {}: return
|
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.flags != {}: return
|
||||||
incl orig.flags, tfCheckedForDestructor
|
incl orig.flags, tfCheckedForDestructor
|
||||||
|
|
||||||
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
|
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
|
|
||||||
|
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
|
||||||
var canon = g.canonTypes.getOrDefault(h)
|
var canon = g.canonTypes.getOrDefault(h)
|
||||||
var overwrite = false
|
|
||||||
if canon == nil:
|
if canon == nil:
|
||||||
let typ = orig.skipTypes({tyGenericInst, tyAlias, tySink})
|
g.canonTypes[h] = skipped
|
||||||
g.canonTypes[h] = typ
|
canon = skipped
|
||||||
canon = typ
|
|
||||||
if canon != orig:
|
|
||||||
overwrite = true
|
|
||||||
|
|
||||||
# multiple cases are to distinguish here:
|
# multiple cases are to distinguish here:
|
||||||
# 1. we don't know yet if 'typ' has a nontrival destructor.
|
# 1. we don't know yet if 'typ' has a nontrival destructor.
|
||||||
|
|
@ -714,9 +721,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||||
discard produceSym(g, c, canon, k, info)
|
discard produceSym(g, c, canon, k, info)
|
||||||
else:
|
else:
|
||||||
inst(canon.attachedOps[k], canon)
|
inst(canon.attachedOps[k], canon)
|
||||||
|
if canon != orig:
|
||||||
if overwrite:
|
|
||||||
for k in attachedDestructor..attachedSink:
|
|
||||||
orig.attachedOps[k] = canon.attachedOps[k]
|
orig.attachedOps[k] = canon.attachedOps[k]
|
||||||
|
|
||||||
if not isTrival(orig.destructor):
|
if not isTrival(orig.destructor):
|
||||||
|
|
|
||||||
|
|
@ -1137,8 +1137,7 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
|
||||||
|
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
||||||
let cache = cache or prc.typ.callConv == ccInline
|
if cache or prc.typ.callConv == ccInline:
|
||||||
if cache:
|
|
||||||
# genProc for inline procs will be called multiple times from different modules,
|
# genProc for inline procs will be called multiple times from different modules,
|
||||||
# it is important to transform exactly once to get sym ids and locations right
|
# it is important to transform exactly once to get sym ids and locations right
|
||||||
prc.transformedBody = result
|
prc.transformedBody = result
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue