gc:destructors further progress

This commit is contained in:
Andreas Rumpf
2018-11-29 01:13:24 +01:00
parent ab38c075f8
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.):
if p.config.selectedGC == gcDestructors:
linefmt(p, cpsStmts,
"$1.len = $2.len; $1.p = $2.p;$n",
"$1 = $2;$n",
rdLoc(dest), rdLoc(src))
elif needToCopy notin flags or
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)
elif d.k == locNone:
getTemp(p, n.typ, d)
# generate call to newSeq before adding the elements per hand:
genNewSeqAux(p, dest[], intLiteral(sonsLen(n)),
optNilSeqs notin p.options and n.len == 0)
let l = intLiteral(sonsLen(n))
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):
initLoc(arr, locExpr, n[i], OnHeap)
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)
# generate call to newSeq before adding the elements per hand:
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)
# bug #5007; do not produce excessive C source code:
if L < 10:

View File

@@ -54,7 +54,7 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope =
result = getTempName(m)
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",
[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
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
strutils, options, dfa, lowerings, tables, modulegraphs,
lineinfos
lineinfos, parampatterns
const
InterestingSyms = {skVar, skResult, skLet}
@@ -262,7 +262,7 @@ template interestingSym(s: PSym): bool =
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)
template isUnpackedTuple(s: PSym): bool =
## we move out all elements of unpacked tuples,
## we move out all elements of unpacked tuples,
## hence unpacked tuples themselves don't need to be destroyed
s.kind == skTemp and s.typ.kind == tyTuple
@@ -402,9 +402,10 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
var m = genCopy(c, n.typ, tmp, n)
m.add p(n, c)
result.add m
message(c.graph.config, n.info, hintPerformance,
("passing '$1' to a sink parameter introduces an implicit copy; " &
"use 'move($1)' to prevent it") % $n)
if isLValue(n):
message(c.graph.config, n.info, hintPerformance,
("passing '$1' to a sink parameter introduces an implicit copy; " &
"use 'move($1)' to prevent it") % $n)
else:
result.add newTree(nkAsgn, tmp, p(n, c))
result.add tmp
@@ -453,7 +454,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
result.add ri2
of nkBracketExpr:
if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym):
# unpacking of tuple: move out the elements
# unpacking of tuple: move out the elements
result = genSink(c, dest.typ, dest, ri)
else:
result = genCopy(c, dest.typ, dest, ri)

View File

@@ -1758,28 +1758,28 @@ proc processMagicType(c: PContext, m: PSym) =
of mVoidType:
setMagicType(c.config, m, tyVoid, 0)
of mArray:
setMagicType(c.config, m, tyArray, 0)
setMagicType(c.config, m, tyArray, szUncomputedSize)
of mOpenArray:
setMagicType(c.config, m, tyOpenArray, 0)
setMagicType(c.config, m, tyOpenArray, szUncomputedSize)
of mVarargs:
setMagicType(c.config, m, tyVarargs, 0)
setMagicType(c.config, m, tyVarargs, szUncomputedSize)
of mRange:
setMagicType(c.config, m, tyRange, 0)
setMagicType(c.config, m, tyRange, szUncomputedSize)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mSet:
setMagicType(c.config, m, tySet, 0)
setMagicType(c.config, m, tySet, szUncomputedSize)
of mUncheckedArray:
setMagicType(c.config, m, tyUncheckedArray, 0)
setMagicType(c.config, m, tyUncheckedArray, szUncomputedSize)
of mSeq:
setMagicType(c.config, m, tySequence, 0)
setMagicType(c.config, m, tySequence, szUncomputedSize)
if c.config.selectedGc == gcDestructors:
incl m.typ.flags, tfHasAsgn
assert c.graph.sysTypes[tySequence] == nil
c.graph.sysTypes[tySequence] = m.typ
of mOpt:
setMagicType(c.config, m, tyOpt, 0)
setMagicType(c.config, m, tyOpt, szUncomputedSize)
of mOrdinal:
setMagicType(c.config, m, tyOrdinal, 0)
setMagicType(c.config, m, tyOrdinal, szUncomputedSize)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mPNimrodNode:
incl m.typ.flags, tfTriggersCompileTime
@@ -1787,7 +1787,7 @@ proc processMagicType(c: PContext, m: PSym) =
of mBuiltinType:
case m.name.s
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)

View File

@@ -11,7 +11,8 @@ type
AllocatorFlag* {.pure.} = enum ## flags describing the properties of the allocator
ThreadLocal ## the allocator is thread local only.
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.}
dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall.}
realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.}
@@ -21,9 +22,21 @@ type
var
localAllocator {.threadvar.}: Allocator
sharedAllocator: Allocator
allocatorStorage {.threadvar.}: AllocatorObj
proc getLocalAllocator*(): Allocator =
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) =
localAllocator = a

View File

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