This commit is contained in:
ringabout
2023-12-07 12:53:06 +00:00
committed by GitHub
parent f7bdec6f0d
commit 9af21cf719
8 changed files with 123 additions and 101 deletions

View File

@@ -194,11 +194,11 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareF
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind in {tyVar} and not compileToCpp(p.module):
result = ("(($5) ? (($4*)(*$1)$3+($2)) : NIM_NIL)" %
[rdLoc(a), rdLoc(b), dataField(p), dest, dataFieldAccessor(p, "*" & rdLoc(a))],
[rdLoc(a), rdLoc(b), dataField(p, ty.kind == tyString), dest, dataFieldAccessor(p, "*" & rdLoc(a))],
lengthExpr)
else:
result = ("(($5) ? (($4*)$1$3+($2)) : NIM_NIL)" %
[rdLoc(a), rdLoc(b), dataField(p), dest, dataFieldAccessor(p, rdLoc(a))],
[rdLoc(a), rdLoc(b), dataField(p, ty.kind == tyString), dest, dataFieldAccessor(p, rdLoc(a))],
lengthExpr)
else:
result = ("", "")
@@ -222,7 +222,8 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
result.add x & ", " & y
else:
var a = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n)
case skipTypes(a.t, abstractVar+{tyStatic}).kind
let typKind = skipTypes(a.t, abstractVar+{tyStatic}).kind
case typKind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(n):
if a.t.kind in {tyVar, tyLent}:
@@ -240,11 +241,11 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result.add "($4) ? ((*$1)$3) : NIM_NIL, $2" %
[a.rdLoc, lenExpr(p, t), dataField(p),
[a.rdLoc, lenExpr(p, t), dataField(p, typKind == tyString),
dataFieldAccessor(p, "*" & a.rdLoc)]
else:
result.add "($4) ? ($1$3) : NIM_NIL, $2" %
[a.rdLoc, lenExpr(p, a), dataField(p), dataFieldAccessor(p, a.rdLoc)]
[a.rdLoc, lenExpr(p, a), dataField(p, typKind == tyString), dataFieldAccessor(p, a.rdLoc)]
of tyArray:
result.add "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
of tyPtr, tyRef:
@@ -253,7 +254,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result.add "($4) ? ((*$1)$3) : NIM_NIL, $2" %
[a.rdLoc, lenExpr(p, t), dataField(p),
[a.rdLoc, lenExpr(p, t), dataField(p, typKind == tyString),
dataFieldAccessor(p, "*" & a.rdLoc)]
of tyArray:
result.add "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]

View File

@@ -309,7 +309,7 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
linefmt(p, cpsStmts, "$1.Field0 = ($5) ? ($2$3) : NIM_NIL; $1.Field1 = $4;$n",
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
[rdLoc(d), a.rdLoc, dataField(p, isString = true), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
else:
internalError(p.config, a.lode.info, "cannot handle " & $a.t.kind)
@@ -1098,7 +1098,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
putIntoDest(p, d, n,
ropecg(p.module, "$1$3[$2]", [rdLoc(a), rdCharLoc(b), dataField(p)]), a.storage)
ropecg(p.module, "$1$3[$2]", [rdLoc(a), rdCharLoc(b), dataField(p, ty.kind == tyString)]), a.storage)
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
var ty = skipTypes(n[0].typ, abstractVarRange + tyUserTypeClasses)
@@ -1199,6 +1199,7 @@ proc genEcho(p: BProc, n: PNode) =
a = initLocExpr(p, it)
if i > 0:
args.add(", ")
## TODO: fixme nimseqsv3 needs to be treated as well
case detectStrVersion(p.module)
of 2:
args.add(ropecg(p.module, "Genode::Cstring($1.p->data, $1.len)", [a.rdLoc]))
@@ -1754,13 +1755,14 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
addrLoc(p.config, a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
of tyOpenArray, tyVarargs:
var b: TLoc = default(TLoc)
case skipTypes(a.t, abstractVarRange).kind
let typKind = skipTypes(a.t, abstractVarRange).kind
case typKind
of tyOpenArray, tyVarargs:
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
of tyString, tySequence:
putIntoDest(p, b, e,
"($4) ? ($1$3) : NIM_NIL, $2" %
[rdLoc(a), lenExpr(p, a), dataField(p), dataFieldAccessor(p, a.rdLoc)],
[rdLoc(a), lenExpr(p, a), dataField(p, typKind == tyString), dataFieldAccessor(p, a.rdLoc)],
a.storage)
of tyArray:
putIntoDest(p, b, e,
@@ -2342,14 +2344,18 @@ proc genDestroy(p: BProc; n: PNode) =
case t.kind
of tyString:
var a: TLoc = initLocExpr(p, arg)
if optThreads in p.config.globalOptions:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #deallocShared($1.p);$n" &
"}$n", [rdLoc(a)])
if p.config.isDefined("nimSeqsV3"):
linefmt(p, cpsStmts, "#nimDestroyStrV1($1);$n",
[rdLoc(a)])
else:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #dealloc($1.p);$n" &
"}$n", [rdLoc(a)])
if optThreads in p.config.globalOptions:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #deallocShared($1.p);$n" &
"}$n", [rdLoc(a)])
else:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #dealloc($1.p);$n" &
"}$n", [rdLoc(a)])
of tySequence:
var a: TLoc = initLocExpr(p, arg)
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &

View File

@@ -350,7 +350,10 @@ proc lenField(p: BProc): Rope {.inline.} =
proc lenExpr(p: BProc; a: TLoc): Rope =
if optSeqDestructors in p.config.globalOptions:
result = rdLoc(a) & ".len"
if p.config.isDefined("nimSeqsV3"):
result = ropecg(p.module, "(#nimStrLenV3($1))", [rdLoc(a)])
else:
result = rdLoc(a) & ".len"
else:
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
@@ -360,9 +363,13 @@ proc dataFieldAccessor(p: BProc, sym: Rope): Rope =
else:
result = sym
proc dataField(p: BProc): Rope =
proc dataField(p: BProc; isString: bool = false): Rope =
# TODO: revisit this after unify strings and seqs
if optSeqDestructors in p.config.globalOptions:
result = rope".p->data"
if isString and p.config.isDefined("nimSeqsV3"):
result = rope".p"
else:
result = rope".p->data"
else:
result = rope"->data"

View File

@@ -165,3 +165,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasWarnStdPrefix")
defineSymbol("nimHasVtables")
defineSymbol("nimHasSeqsV3")

View File

@@ -1616,7 +1616,7 @@ when not defined(js) and defined(nimV2):
proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
when notJSnotNims and defined(nimSeqsV2):
when defined(nimSeqsV3):
when defined(nimHasSeqsV3) and defined(nimSeqsV3):
include "system/strs_v3"
else:
include "system/strs_v2"
@@ -1682,15 +1682,16 @@ when not defined(js):
result = newString(len)
else:
result = newStringOfCap(len)
when defined(nimSeqsV3):
let s = cast[ptr NimStringV3](addr result)
if len > 0:
s.len = len
elif defined(nimSeqsV2):
let s = cast[ptr NimStringV2](addr result)
if len > 0:
s.len = len
s.p.data[len] = '\0'
when defined(nimSeqsV2):
when defined(nimHasSeqsV3) and defined(nimSeqsV3):
let s = cast[ptr NimStringV3](addr result)
if len > 0:
setRawLen(s[], len)
else:
let s = cast[ptr NimStringV2](addr result)
if len > 0:
s.len = len
s.p.data[len] = '\0'
else:
let s = cast[NimString](result)
s.len = len

View File

@@ -61,14 +61,15 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
sysAssert(mt != nil, "genericAssignAux 2")
case mt.kind
of tyString:
when defined(nimSeqsV3):
var x = cast[ptr NimStringV3](dest)
var s2 = cast[ptr NimStringV3](s)[]
nimAsgnStrV2(x[], s2)
elif defined(nimSeqsV2):
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
when defined(nimSeqsV2):
when defined(nimHasSeqsV3) and defined(nimSeqsV3):
var x = cast[ptr NimStringV3](dest)
var s2 = cast[ptr NimStringV3](s)[]
nimAsgnStrV2(x[], s2)
else:
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
else:
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]
@@ -248,14 +249,15 @@ proc genericReset(dest: pointer, mt: PNimType) =
of tyRef:
unsureAsgnRef(cast[PPointer](dest), nil)
of tyString:
when defined(nimSeqsV3):
var s = cast[ptr NimStringV3](dest)
frees(s[])
zeroMem(dest, mt.size)
elif defined(nimSeqsV2):
var s = cast[ptr NimStringV2](dest)
frees(s[])
zeroMem(dest, mt.size)
when defined(nimSeqsV2):
when defined(nimHasSeqsV3) and defined(nimSeqsV3):
var s = cast[ptr NimStringV3](dest)
frees(s[])
zeroMem(dest, mt.size)
else:
var s = cast[ptr NimStringV2](dest)
frees(s[])
zeroMem(dest, mt.size)
else:
unsureAsgnRef(cast[PPointer](dest), nil)
of tySequence:

View File

@@ -90,14 +90,15 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
sysAssert(mt != nil, "genericDeepCopyAux 2")
case mt.kind
of tyString:
when defined(nimSeqsV3):
var x = cast[ptr NimStringV3](dest)
var s2 = cast[ptr NimStringV3](s)[]
nimAsgnStrV2(x[], s2)
elif defined(nimSeqsV2):
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
when defined(nimSeqsV2):
when defined(nimHasSeqsV3) and defined(nimSeqsV3):
var x = cast[ptr NimStringV3](dest)
var s2 = cast[ptr NimStringV3](s)[]
nimAsgnStrV2(x[], s2)
else:
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
else:
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]

View File

@@ -25,22 +25,25 @@ const nimStrVersion {.core.} = 3
template isLiteral(s): bool = (s.rawlen and 1) == 1
template head(p: pointer): pointer =
template strHead(p: pointer): pointer =
cast[pointer](cast[int](p) -% sizeof(NimStrPayloadBase))
template cap(p: pointer): int =
cast[ptr NimStrPayloadBase](head(p))[].cap
template strCap(p: pointer): int =
cast[ptr NimStrPayloadBase](strHead(p))[].cap
template `cap=`(p: pointer, size: int) =
cast[ptr NimStrPayloadBase](head(p))[].cap = size
template `strCap=`(p: pointer, size: int) =
cast[ptr NimStrPayloadBase](strHead(p))[].cap = size
template len(s: NimStringV3): int = s.rawlen shr 1
proc nimStrLenV3(s: NimStringV3): int {.compilerRtl, inl.} = s.rawlen shr 1
template toRawLen(len: int): int = len shl 1
template incRawLen(s: var NimStringV3, value: int = 1) =
s.rawlen = s.rawlen + value shl 1
template setRawLen(s: var NimStringV3, len: int) =
s.rawLen = toRawLen(len)
proc markIntern(s: var NimStringV3): bool =
s.rawlen = s.rawlen or 1
result = not isLiteral(s)
@@ -48,18 +51,18 @@ proc markIntern(s: var NimStringV3): bool =
proc unsafeUnmarkIntern(s: var NimStringV3) =
s.rawlen = s.rawlen and (not 1) # unmark?
when compileOption("threads"):
deallocShared(head(s.p))
deallocShared(strHead(s.p))
else:
dealloc(head(s.p))
dealloc(strHead(s.p))
template contentSize(cap): int = cap + sizeof(NimStrPayloadBase)
template frees(s) =
if not isLiteral(s):
when compileOption("threads"):
deallocShared(head(s.p))
deallocShared(strHead(s.p))
else:
dealloc(head(s.p))
dealloc(strHead(s.p))
template allocPayload(newLen: int): ptr UncheckedArray[char] =
when compileOption("threads"):
@@ -91,28 +94,28 @@ proc resize(old: int): int {.inline.} =
else: result = old * 3 div 2 # for large arrays * 3/2 is better
proc prepareAdd(s: var NimStringV3; addLen: int) {.compilerRtl.} =
let newLen = s.len + addLen
let newLen = s.nimStrLenV3 + addLen
if isLiteral(s):
let oldP = s.p
# can't mutate a literal, so we need a fresh copy here:
s.p = allocPayload(newLen)
s.p.cap = newLen
if s.len > 0:
s.p.strCap = newLen
if s.nimStrLenV3 > 0:
# we are about to append
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], min(s.len, newLen))
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], min(s.nimStrLenV3, newLen))
else:
let oldCap = s.p.cap
let oldCap = s.p.strCap
if newLen > oldCap:
let newCap = max(newLen, resize(oldCap))
s.p = reallocPayload(head(s.p), newCap)
s.p.cap = newCap
s.p = reallocPayload(strHead(s.p), newCap)
s.p.strCap = newCap
if newLen < newCap:
zeroMem(cast[pointer](addr s.p[newLen]), newCap - newLen)
proc nimAddCharV1(s: var NimStringV3; c: char) {.compilerRtl, inl.} =
#if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag):
prepareAdd(s, 1)
s.p[s.len] = c
s.p[s.nimStrLenV3] = c
incRawLen s
proc toNimStr(str: cstring, len: int): NimStringV3 {.compilerproc.} =
@@ -120,7 +123,7 @@ proc toNimStr(str: cstring, len: int): NimStringV3 {.compilerproc.} =
result = NimStringV3(rawlen: 0, p: nil)
else:
var p = allocPayload(len)
p.cap = len
p.strCap = len
copyMem(unsafeAddr p[0], str, len)
result = NimStringV3(rawlen: toRawLen(len), p: p)
@@ -129,20 +132,20 @@ proc cstrToNimstr(str: cstring): NimStringV3 {.compilerRtl.} =
else: toNimStr(str, str.len)
proc nimToCStringConv(s: NimStringV3): cstring {.compilerproc, nonReloadable, inline.} =
if s.len == 0: result = cstring""
if s.nimStrLenV3 == 0: result = cstring""
else:
## TODO: fixme: inject conversions somewhere else and be cleaned up
## but let it leak for now
result = cast[cstring](allocPayload0(s.len+1))
copyMem(result, unsafeAddr s.p[0], s.len)
result = cast[cstring](allocPayload0(s.nimStrLenV3+1))
copyMem(result, unsafeAddr s.p[0], s.nimStrLenV3)
proc appendString(dest: var NimStringV3; src: NimStringV3) {.compilerproc, inline.} =
if src.len > 0:
copyMem(unsafeAddr dest.p[dest.len], unsafeAddr src.p[0], src.len)
incRawLen(dest, src.len)
if src.nimStrLenV3 > 0:
copyMem(unsafeAddr dest.p[dest.nimStrLenV3], unsafeAddr src.p[0], src.nimStrLenV3)
incRawLen(dest, src.nimStrLenV3)
proc appendChar(dest: var NimStringV3; c: char) {.compilerproc, inline.} =
dest.p[dest.len] = c
dest.p[dest.nimStrLenV3] = c
incRawLen(dest)
proc rawNewString(space: int): NimStringV3 {.compilerproc.} =
@@ -151,7 +154,7 @@ proc rawNewString(space: int): NimStringV3 {.compilerproc.} =
result = NimStringV3(rawlen: 0, p: nil)
else:
var p = allocPayload(space)
p.cap = space
p.strCap = space
result = NimStringV3(rawlen: 0, p: p)
proc mnewString(len: int): NimStringV3 {.compilerproc.} =
@@ -159,7 +162,7 @@ proc mnewString(len: int): NimStringV3 {.compilerproc.} =
result = NimStringV3(rawlen: 0, p: nil)
else:
var p = allocPayload0(len)
p.cap = len
p.strCap = len
result = NimStringV3(rawlen: toRawLen(len), p: p)
proc setLengthStrV2(s: var NimStringV3, newLen: int) {.compilerRtl.} =
@@ -169,21 +172,21 @@ proc setLengthStrV2(s: var NimStringV3, newLen: int) {.compilerRtl.} =
if isLiteral(s):
let oldP = s.p
s.p = allocPayload(newLen)
s.p.cap = newLen
if s.len > 0:
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], min(s.len, newLen))
if newLen > s.len:
zeroMem(cast[pointer](addr s.p[s.len]), newLen - s.len)
s.p.strCap = newLen
if s.nimStrLenV3 > 0:
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], min(s.nimStrLenV3, newLen))
if newLen > s.nimStrLenV3:
zeroMem(cast[pointer](addr s.p[s.nimStrLenV3]), newLen - s.nimStrLenV3)
else:
zeroMem(cast[pointer](addr s.p[0]), newLen)
elif newLen > s.len:
let oldCap = s.p.cap
elif newLen > s.nimStrLenV3:
let oldCap = s.p.strCap
if newLen > oldCap:
let newCap = max(newLen, resize(oldCap))
s.p = reallocPayload0(head(s.p), oldCap, newCap)
s.p.cap = newCap
s.p = reallocPayload0(strHead(s.p), oldCap, newCap)
s.p.strCap = newCap
s.rawlen = toRawLen(newLen)
setRawLen(s, newLen)
proc nimAsgnStrV2(a: var NimStringV3, b: NimStringV3) {.compilerRtl.} =
if a.p == b.p: return
@@ -193,22 +196,22 @@ proc nimAsgnStrV2(a: var NimStringV3, b: NimStringV3) {.compilerRtl.} =
a.rawlen = b.rawlen
a.p = b.p
else:
if isLiteral(a) or a.p.cap < b.len:
if isLiteral(a) or a.p.strCap < b.nimStrLenV3:
# we have to allocate the 'cap' here, consider
# 'let y = newStringOfCap(); var x = y'
# on the other hand... These get turned into moves now.
frees(a)
a.p = allocPayload(b.len)
a.p.cap = b.len
a.p = allocPayload(b.nimStrLenV3)
a.p.strCap = b.nimStrLenV3
a.rawlen = b.rawlen
copyMem(unsafeAddr a.p[0], unsafeAddr b.p[0], b.len)
copyMem(unsafeAddr a.p[0], unsafeAddr b.p[0], b.nimStrLenV3)
proc nimPrepareStrMutationImpl(s: var NimStringV3) =
let oldP = s.p
# can't mutate a literal, so we need a fresh copy here:
s.p = allocPayload(s.len)
s.p.cap = s.len
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], s.len)
s.p = allocPayload(s.nimStrLenV3)
s.p.strCap = s.nimStrLenV3
copyMem(unsafeAddr s.p[0], unsafeAddr oldP[0], s.nimStrLenV3)
proc nimPrepareStrMutationV2(s: var NimStringV3) {.compilerRtl, inl.} =
if isLiteral(s):
@@ -223,7 +226,7 @@ proc prepareMutation*(s: var string) {.inline.} =
proc nimAddStrV1(s: var NimStringV3; src: NimStringV3) {.compilerRtl, inl.} =
#if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag):
prepareAdd(s, src.len)
prepareAdd(s, src.nimStrLenV3)
appendString s, src
proc nimDestroyStrV1(s: NimStringV3) {.compilerRtl, inl.} =
@@ -245,4 +248,4 @@ func capacity*(self: string): int {.inline.} =
if isLiteral(str):
result = 0
else:
result = if str.p != nil: str.p.cap else: 0
result = if str.p != nil: str.p.strCap else: 0