gc:destructors further progress

This commit is contained in:
Andreas Rumpf 2018-11-29 01:13:24 +01:00
commit 7d82df20be
6 changed files with 52 additions and 24 deletions

View file

@ -241,7 +241,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# (for objects, etc.): # (for objects, etc.):
if p.config.selectedGC == gcDestructors: if p.config.selectedGC == gcDestructors:
linefmt(p, cpsStmts, linefmt(p, cpsStmts,
"$1.len = $2.len; $1.p = $2.p;$n", "$1 = $2;$n",
rdLoc(dest), rdLoc(src)) rdLoc(dest), rdLoc(src))
elif needToCopy notin flags or elif needToCopy notin flags or
tfShallow in skipTypes(dest.t, abstractVarRange).flags: tfShallow in skipTypes(dest.t, abstractVarRange).flags:
@ -1339,9 +1339,17 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
getTemp(p, n.typ, tmp) getTemp(p, n.typ, tmp)
elif d.k == locNone: elif d.k == locNone:
getTemp(p, n.typ, d) getTemp(p, n.typ, d)
# generate call to newSeq before adding the elements per hand:
genNewSeqAux(p, dest[], intLiteral(sonsLen(n)), let l = intLiteral(sonsLen(n))
optNilSeqs notin p.options and n.len == 0) if p.config.selectedGC == gcDestructors:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
rdLoc dest[], l, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype))
else:
# generate call to newSeq before adding the elements per hand:
genNewSeqAux(p, dest[], l,
optNilSeqs notin p.options and n.len == 0)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
initLoc(arr, locExpr, n[i], OnHeap) initLoc(arr, locExpr, n[i], OnHeap)
arr.r = ropecg(p.module, "$1$3[$2]", rdLoc(dest[]), intLiteral(i), dataField(p)) arr.r = ropecg(p.module, "$1$3[$2]", rdLoc(dest[]), intLiteral(i), dataField(p))
@ -1364,7 +1372,13 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
getTemp(p, n.typ, d) getTemp(p, n.typ, d)
# generate call to newSeq before adding the elements per hand: # generate call to newSeq before adding the elements per hand:
let L = int(lengthOrd(p.config, n.sons[1].typ)) let L = int(lengthOrd(p.config, n.sons[1].typ))
genNewSeqAux(p, d, intLiteral(L), optNilSeqs notin p.options and L == 0) if p.config.selectedGC == gcDestructors:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
rdLoc d, rope L, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype))
else:
genNewSeqAux(p, d, intLiteral(L), optNilSeqs notin p.options and L == 0)
initLocExpr(p, n.sons[1], a) initLocExpr(p, n.sons[1], a)
# bug #5007; do not produce excessive C source code: # bug #5007; do not produce excessive C source code:
if L < 10: if L < 10:

View file

@ -54,7 +54,7 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope = proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope =
result = getTempName(m) result = getTempName(m)
addf(m.s[cfsData], "static const struct {$n" & addf(m.s[cfsData], "static const struct {$n" &
" NI cap; void* allocator; NIM_CHAR data[$2];$n" & " NI cap; void* allocator; NIM_CHAR data[$2+1];$n" &
"} $1 = { $2, NIM_NIL, $3 };$n", "} $1 = { $2, NIM_NIL, $3 };$n",
[result, rope(len(s)), makeCString(s)]) [result, rope(len(s)), makeCString(s)])

View file

@ -117,7 +117,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
import import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
strutils, options, dfa, lowerings, tables, modulegraphs, strutils, options, dfa, lowerings, tables, modulegraphs,
lineinfos lineinfos, parampatterns
const const
InterestingSyms = {skVar, skResult, skLet} InterestingSyms = {skVar, skResult, skLet}
@ -402,9 +402,10 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
var m = genCopy(c, n.typ, tmp, n) var m = genCopy(c, n.typ, tmp, n)
m.add p(n, c) m.add p(n, c)
result.add m result.add m
message(c.graph.config, n.info, hintPerformance, if isLValue(n):
("passing '$1' to a sink parameter introduces an implicit copy; " & message(c.graph.config, n.info, hintPerformance,
"use 'move($1)' to prevent it") % $n) ("passing '$1' to a sink parameter introduces an implicit copy; " &
"use 'move($1)' to prevent it") % $n)
else: else:
result.add newTree(nkAsgn, tmp, p(n, c)) result.add newTree(nkAsgn, tmp, p(n, c))
result.add tmp result.add tmp

View file

@ -1758,28 +1758,28 @@ proc processMagicType(c: PContext, m: PSym) =
of mVoidType: of mVoidType:
setMagicType(c.config, m, tyVoid, 0) setMagicType(c.config, m, tyVoid, 0)
of mArray: of mArray:
setMagicType(c.config, m, tyArray, 0) setMagicType(c.config, m, tyArray, szUncomputedSize)
of mOpenArray: of mOpenArray:
setMagicType(c.config, m, tyOpenArray, 0) setMagicType(c.config, m, tyOpenArray, szUncomputedSize)
of mVarargs: of mVarargs:
setMagicType(c.config, m, tyVarargs, 0) setMagicType(c.config, m, tyVarargs, szUncomputedSize)
of mRange: of mRange:
setMagicType(c.config, m, tyRange, 0) setMagicType(c.config, m, tyRange, szUncomputedSize)
rawAddSon(m.typ, newTypeS(tyNone, c)) rawAddSon(m.typ, newTypeS(tyNone, c))
of mSet: of mSet:
setMagicType(c.config, m, tySet, 0) setMagicType(c.config, m, tySet, szUncomputedSize)
of mUncheckedArray: of mUncheckedArray:
setMagicType(c.config, m, tyUncheckedArray, 0) setMagicType(c.config, m, tyUncheckedArray, szUncomputedSize)
of mSeq: of mSeq:
setMagicType(c.config, m, tySequence, 0) setMagicType(c.config, m, tySequence, szUncomputedSize)
if c.config.selectedGc == gcDestructors: if c.config.selectedGc == gcDestructors:
incl m.typ.flags, tfHasAsgn incl m.typ.flags, tfHasAsgn
assert c.graph.sysTypes[tySequence] == nil assert c.graph.sysTypes[tySequence] == nil
c.graph.sysTypes[tySequence] = m.typ c.graph.sysTypes[tySequence] = m.typ
of mOpt: of mOpt:
setMagicType(c.config, m, tyOpt, 0) setMagicType(c.config, m, tyOpt, szUncomputedSize)
of mOrdinal: of mOrdinal:
setMagicType(c.config, m, tyOrdinal, 0) setMagicType(c.config, m, tyOrdinal, szUncomputedSize)
rawAddSon(m.typ, newTypeS(tyNone, c)) rawAddSon(m.typ, newTypeS(tyNone, c))
of mPNimrodNode: of mPNimrodNode:
incl m.typ.flags, tfTriggersCompileTime incl m.typ.flags, tfTriggersCompileTime
@ -1787,7 +1787,7 @@ proc processMagicType(c: PContext, m: PSym) =
of mBuiltinType: of mBuiltinType:
case m.name.s case m.name.s
of "lent": setMagicType(c.config, m, tyLent, c.config.target.ptrSize) of "lent": setMagicType(c.config, m, tyLent, c.config.target.ptrSize)
of "sink": setMagicType(c.config, m, tySink, 0) of "sink": setMagicType(c.config, m, tySink, szUncomputedSize)
else: localError(c.config, m.info, errTypeExpected) else: localError(c.config, m.info, errTypeExpected)
else: localError(c.config, m.info, errTypeExpected) else: localError(c.config, m.info, errTypeExpected)

View file

@ -11,7 +11,8 @@ type
AllocatorFlag* {.pure.} = enum ## flags describing the properties of the allocator AllocatorFlag* {.pure.} = enum ## flags describing the properties of the allocator
ThreadLocal ## the allocator is thread local only. ThreadLocal ## the allocator is thread local only.
ZerosMem ## the allocator always zeros the memory on an allocation ZerosMem ## the allocator always zeros the memory on an allocation
Allocator* = ptr object {.inheritable.} Allocator* = ptr AllocatorObj
AllocatorObj* {.inheritable.} = object
alloc*: proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall.} alloc*: proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall.}
dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall.} dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall.}
realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.} realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.}
@ -21,9 +22,21 @@ type
var var
localAllocator {.threadvar.}: Allocator localAllocator {.threadvar.}: Allocator
sharedAllocator: Allocator sharedAllocator: Allocator
allocatorStorage {.threadvar.}: AllocatorObj
proc getLocalAllocator*(): Allocator = proc getLocalAllocator*(): Allocator =
result = localAllocator result = localAllocator
if result == nil:
result = addr allocatorStorage
result.alloc = proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall.} =
result = system.alloc(size)
result.dealloc = proc (a: Allocator; p: pointer; size: int) {.nimcall.} =
system.dealloc(p)
result.realloc = proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.} =
result = system.realloc(p, newSize)
result.deallocAll = nil
result.flags = {ThreadLocal}
localAllocator = result
proc setLocalAllocator*(a: Allocator) = proc setLocalAllocator*(a: Allocator) =
localAllocator = a localAllocator = a

View file

@ -85,7 +85,7 @@ type
proc newSeqPayload(cap, elemSize: int): pointer {.compilerRtl.} = proc newSeqPayload(cap, elemSize: int): pointer {.compilerRtl.} =
# we have to use type erasure here as Nim does not support generic # we have to use type erasure here as Nim does not support generic
# compilerProcs. Oh well, this will all be inlined anyway. # compilerProcs. Oh well, this will all be inlined anyway.
if cap <= 0: if cap > 0:
let region = getLocalAllocator() let region = getLocalAllocator()
var p = cast[ptr PayloadBase](region.alloc(region, cap * elemSize + sizeof(int) + sizeof(Allocator))) var p = cast[ptr PayloadBase](region.alloc(region, cap * elemSize + sizeof(int) + sizeof(Allocator)))
p.region = region p.region = region