added system.newSeqOfCap for improved efficiency

This commit is contained in:
Andreas Rumpf
2016-07-15 17:04:14 +02:00
parent 11b499f3ca
commit b7c1be03c8
7 changed files with 47 additions and 4 deletions

View File

@@ -545,7 +545,7 @@ type
mEcho, mShallowCopy, mSlurp, mStaticExec,
mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
mUnaryLt, mInc, mDec, mOrd,
mNew, mNewFinalize, mNewSeq,
mNew, mNewFinalize, mNewSeq, mNewSeqOfCap,
mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
mXLenStr, mXLenSeq,
mIncl, mExcl, mCard, mChr,

View File

@@ -1141,6 +1141,16 @@ proc genNewSeq(p: BProc, e: PNode) =
genNewSeqAux(p, a, b.rdLoc)
gcUsage(e)
proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
let seqtype = skipTypes(e.typ, abstractVarRange)
var a: TLoc
initLocExpr(p, e.sons[1], a)
putIntoDest(p, d, e.typ, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype), a.rdLoc]))
gcUsage(e)
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
var tmp: TLoc
var t = e.typ.skipTypes(abstractInst)
@@ -1712,6 +1722,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mNew: genNew(p, e)
of mNewFinalize: genNewFinalize(p, e)
of mNewSeq: genNewSeq(p, e)
of mNewSeqOfCap: genNewSeqOfCap(p, e, d)
of mSizeOf:
let t = e.sons[1].typ.skipTypes({tyTypeDesc})
putIntoDest(p, d, e.typ, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])

View File

@@ -1755,6 +1755,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
else:
binaryExpr(p, n, r, "", "isset($1[$2])")
of mNewSeq: genNewSeq(p, n)
of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]" | "array()")
of mOf: genOf(p, n, r)
of mReset: genReset(p, n)
of mEcho: genEcho(p, n, r)

View File

@@ -597,16 +597,27 @@ proc genNew(c: PCtx; n: PNode) =
c.freeTemp(dest)
proc genNewSeq(c: PCtx; n: PNode) =
let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
let t = n.sons[1].typ
let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(t)
else: c.genx(n.sons[1])
let tmp = c.genx(n.sons[2])
c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(
c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
abstractVar-{tyTypeDesc})))
c.gABx(n, opcNewSeq, tmp, 0)
c.freeTemp(tmp)
c.genAsgnPatch(n.sons[1], dest)
c.freeTemp(dest)
proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
let t = n.typ
let tmp = c.getTemp(n.sons[1].typ)
c.gABx(n, opcLdNull, dest, c.genType(t))
c.gABx(n, opcLdImmInt, tmp, 0)
c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
abstractVar-{tyTypeDesc})))
c.gABx(n, opcNewSeq, tmp, 0)
c.freeTemp(tmp)
proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
let tmp = c.genx(n.sons[1])
if dest < 0: dest = c.getTemp(n.typ)
@@ -782,6 +793,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mNewSeq:
unused(n, dest)
c.genNewSeq(n)
of mNewSeqOfCap: c.genNewSeqOfCap(n, dest)
of mNewString:
genUnaryABC(c, n, dest, opcNewStr)
# XXX buggy

View File

@@ -669,6 +669,12 @@ proc newSeq*[T](len = 0.Natural): seq[T] =
## #inputStrings[3] = "out of bounds"
newSeq(result, len)
proc newSeqOfCap*[T](cap: Natural): seq[T] {.
magic: "NewSeqOfCap", noSideEffect.} =
## creates a new sequence of type ``seq[T]`` with length 0 and capacity
## ``cap``.
discard
proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.
magic: "LengthOpenArray", noSideEffect.}
proc len*(x: string): int {.magic: "LengthStr", noSideEffect.}

View File

@@ -354,6 +354,12 @@ elif defined(gogc):
cast[PGenericSeq](result).reserved = len
cast[PGenericSeq](result).elemSize = typ.base.size
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
result = newObj(typ, cap * typ.base.size + GenericSeqSize)
cast[PGenericSeq](result).len = 0
cast[PGenericSeq](result).reserved = cap
cast[PGenericSeq](result).elemSize = typ.base.size
proc growObj(old: pointer, newsize: int): pointer =
# the Go GC doesn't have a realloc
var
@@ -447,6 +453,7 @@ elif defined(nogc) and defined(useMalloc):
result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
cast[PGenericSeq](result).len = len
cast[PGenericSeq](result).reserved = len
proc newObjNoInit(typ: PNimType, size: int): pointer =
result = alloc(size)
@@ -506,6 +513,7 @@ elif defined(nogc):
result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
cast[PGenericSeq](result).len = len
cast[PGenericSeq](result).reserved = len
proc growObj(old: pointer, newsize: int): pointer =
result = realloc(old, newsize)
@@ -545,4 +553,10 @@ else:
else:
include "system/gc"
when not declared(nimNewSeqOfCap):
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
result = newObj(typ, addInt(mulInt(cap, typ.base.size), GenericSeqSize))
cast[PGenericSeq](result).len = 0
cast[PGenericSeq](result).reserved = cap
{.pop.}

View File

@@ -1,7 +1,6 @@
version 1.0 battle plan
=======================
- introduce newSeqOfCap(10)
- overloading of `()` and ``.`` needs to be in .experimental
- implement ``.delegate`` for .experimental
- find a solution for the x.f[T](y) gotcha