some bugfixes for 'deepCopy'
This commit is contained in:
parent
1e8a9aead0
commit
a64d733029
2 changed files with 29 additions and 15 deletions
|
|
@ -360,13 +360,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else: internalError("genAssignment: " & $ty.kind)
|
else: internalError("genAssignment: " & $ty.kind)
|
||||||
|
|
||||||
proc genDeepCopy(p: BProc; dest, src: TLoc) =
|
proc genDeepCopy(p: BProc; dest, src: TLoc) =
|
||||||
var ty = skipTypes(dest.t, abstractRange)
|
var ty = skipTypes(dest.t, abstractVarRange)
|
||||||
case ty.kind
|
case ty.kind
|
||||||
of tyPtr, tyRef, tyString, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
|
of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
|
||||||
# XXX optimize this
|
# XXX optimize this
|
||||||
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
|
||||||
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
of tySequence:
|
of tySequence, tyString:
|
||||||
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
|
||||||
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
|
|
@ -1687,7 +1687,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
expr(p, n, d)
|
expr(p, n, d)
|
||||||
of mDeepCopy:
|
of mDeepCopy:
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
initLocExpr(p, e.sons[1], a)
|
let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
|
||||||
|
initLocExpr(p, x, a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
genDeepCopy(p, a, b)
|
genDeepCopy(p, a, b)
|
||||||
else: internalError(e.info, "genMagicExpr: " & $op)
|
else: internalError(e.info, "genMagicExpr: " & $op)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
|
||||||
genericDeepCopyAux(dest, src, m)
|
genericDeepCopyAux(dest, src, m)
|
||||||
of nkNone: sysAssert(false, "genericDeepCopyAux")
|
of nkNone: sysAssert(false, "genericDeepCopyAux")
|
||||||
|
|
||||||
|
proc copyDeepString(src: NimString): NimString {.inline.} =
|
||||||
|
if src != nil:
|
||||||
|
result = rawNewString(src.space)
|
||||||
|
result.len = src.len
|
||||||
|
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
|
||||||
|
|
||||||
proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
|
proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[TAddress](dest)
|
||||||
|
|
@ -44,7 +50,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
|
||||||
if s2 == nil:
|
if s2 == nil:
|
||||||
unsureAsgnRef(x, s2)
|
unsureAsgnRef(x, s2)
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
|
||||||
of tySequence:
|
of tySequence:
|
||||||
var s2 = cast[PPointer](src)[]
|
var s2 = cast[PPointer](src)[]
|
||||||
var seq = cast[PGenericSeq](s2)
|
var seq = cast[PGenericSeq](s2)
|
||||||
|
|
@ -76,25 +82,31 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
|
||||||
genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
|
genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
|
||||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
cast[pointer](s +% i*% mt.base.size), mt.base)
|
||||||
of tyRef:
|
of tyRef:
|
||||||
var z: pointer
|
|
||||||
if mt.base.deepCopy != nil:
|
if mt.base.deepCopy != nil:
|
||||||
z = mt.base.deepCopy(cast[PPointer](s)[])
|
let z = mt.base.deepCopy(cast[PPointer](src)[])
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
else:
|
else:
|
||||||
# we modify the header of the cell temporarily; instead of the type
|
# we modify the header of the cell temporarily; instead of the type
|
||||||
# field we store a forwarding pointer. XXX This is bad when the cloning
|
# field we store a forwarding pointer. XXX This is bad when the cloning
|
||||||
# fails due to OOM etc.
|
# fails due to OOM etc.
|
||||||
let x = usrToCell(cast[PPointer](s)[])
|
let s2 = cast[PPointer](src)[]
|
||||||
|
if s2 == nil:
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), s2)
|
||||||
|
return
|
||||||
|
let x = usrToCell(s2)
|
||||||
let forw = cast[int](x.typ)
|
let forw = cast[int](x.typ)
|
||||||
if (forw and 1) == 1:
|
if (forw and 1) == 1:
|
||||||
# we stored a forwarding pointer, so let's use that:
|
# we stored a forwarding pointer, so let's use that:
|
||||||
z = cast[pointer](forw and not 1)
|
let z = cast[pointer](forw and not 1)
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
else:
|
else:
|
||||||
let realType = x.typ
|
let realType = x.typ
|
||||||
z = newObj(realType, realType.base.size)
|
let z = newObj(realType, realType.base.size)
|
||||||
|
|
||||||
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
x.typ = cast[PNimType](cast[int](z) or 1)
|
x.typ = cast[PNimType](cast[int](z) or 1)
|
||||||
genericDeepCopyAux(dest, addr(z), realType)
|
genericDeepCopyAux(z, s2, realType.base)
|
||||||
x.typ = realType
|
x.typ = realType
|
||||||
unsureAsgnRef(cast[PPointer](dest), z)
|
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
# no cycle check here, but also not really required
|
# no cycle check here, but also not really required
|
||||||
if mt.base.deepCopy != nil:
|
if mt.base.deepCopy != nil:
|
||||||
|
|
@ -102,12 +114,13 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
|
||||||
else:
|
else:
|
||||||
cast[PPointer](dest)[] = cast[PPointer](s)[]
|
cast[PPointer](dest)[] = cast[PPointer](s)[]
|
||||||
else:
|
else:
|
||||||
copyMem(dest, src, mt.size) # copy raw bits
|
copyMem(dest, src, mt.size)
|
||||||
|
|
||||||
proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
||||||
genericDeepCopyAux(dest, src, mt)
|
genericDeepCopyAux(dest, src, mt)
|
||||||
|
|
||||||
proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
||||||
|
# also invoked for 'string'
|
||||||
var src = src
|
var src = src
|
||||||
genericDeepCopy(dest, addr(src), mt)
|
genericDeepCopy(dest, addr(src), mt)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue