diff options
author | Araq <rumpf_a@web.de> | 2014-08-06 09:54:23 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-08-06 09:54:23 +0200 |
commit | a64d733029b1f8c76575f5d117399d587346b9cc (patch) | |
tree | b0da407036a22032376169fc1977e42f934b8b4d | |
parent | 1e8a9aead060d27099bdd8634cbab6b89ecd9995 (diff) | |
download | Nim-a64d733029b1f8c76575f5d117399d587346b9cc.tar.gz |
some bugfixes for 'deepCopy'
-rw-r--r-- | compiler/ccgexprs.nim | 11 | ||||
-rw-r--r-- | lib/system/deepcopy.nim | 33 |
2 files changed, 29 insertions, 15 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index b4beb5a7e..d480373d4 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -360,13 +360,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: internalError("genAssignment: " & $ty.kind) proc genDeepCopy(p: BProc; dest, src: TLoc) = - var ty = skipTypes(dest.t, abstractRange) + var ty = skipTypes(dest.t, abstractVarRange) case ty.kind - of tyPtr, tyRef, tyString, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr: + of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr: # XXX optimize this linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)) - of tySequence: + of tySequence, tyString: linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n", addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)) of tyOpenArray, tyVarargs: @@ -1687,9 +1687,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = expr(p, n, d) of mDeepCopy: 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) - genDeepCopy(p, a, b) + genDeepCopy(p, a, b) else: internalError(e.info, "genMagicExpr: " & $op) proc genConstExpr(p: BProc, n: PNode): PRope diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index d3f9c5d7c..5c10ef9ed 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -32,6 +32,12 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} = genericDeepCopyAux(dest, src, m) 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) = var d = cast[TAddress](dest) @@ -44,10 +50,10 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = if s2 == nil: unsureAsgnRef(x, s2) else: - unsureAsgnRef(x, copyString(cast[NimString](s2))) + unsureAsgnRef(x, copyDeepString(cast[NimString](s2))) of tySequence: var s2 = cast[PPointer](src)[] - var seq = cast[PGenericSeq](s2) + var seq = cast[PGenericSeq](s2) var x = cast[PPointer](dest) if s2 == nil: unsureAsgnRef(x, s2) @@ -76,25 +82,31 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size), cast[pointer](s +% i*% mt.base.size), mt.base) of tyRef: - var z: pointer 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: # 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 # 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) if (forw and 1) == 1: # 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: 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) - genericDeepCopyAux(dest, addr(z), realType) + genericDeepCopyAux(z, s2, realType.base) x.typ = realType - unsureAsgnRef(cast[PPointer](dest), z) of tyPtr: # no cycle check here, but also not really required if mt.base.deepCopy != nil: @@ -102,12 +114,13 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = else: cast[PPointer](dest)[] = cast[PPointer](s)[] else: - copyMem(dest, src, mt.size) # copy raw bits + copyMem(dest, src, mt.size) proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = genericDeepCopyAux(dest, src, mt) proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = + # also invoked for 'string' var src = src genericDeepCopy(dest, addr(src), mt) |