summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-11-24 10:52:33 +0100
committerAndreas Rumpf <rumpf_a@web.de>2016-11-24 10:52:33 +0100
commit2316c71e09aef62f9f1a4897c47baccaea2623bf (patch)
tree39feb7a32476611d38511ddb18d2390b43067097 /lib/system
parent633dcca71bc85690ac7bea09bb452f5132c0f182 (diff)
downloadNim-2316c71e09aef62f9f1a4897c47baccaea2623bf.tar.gz
reverted deepcopy fix for now
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/deepcopy.nim106
1 files changed, 31 insertions, 75 deletions
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index b1609252c..38cc8cbf3 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -7,66 +7,18 @@
 #    distribution, for details about the copyright.
 #
 
-type
-  PtrTable = ptr object
-    counter, max: int
-    data: array[0..0xff_ffff, (pointer, pointer)]
-
-template hashPtr(key: pointer): int = cast[int](key) shr 8
-template allocPtrTable: untyped =
-  cast[PtrTable](alloc0(sizeof(int)*2 + sizeof(pointer)*2*cap))
-
-proc rehash(t: PtrTable): PtrTable =
-  let cap = (t.max+1) * 2
-  result = allocPtrTable()
-  result.counter = t.counter
-  result.max = cap-1
-  for i in 0..t.max:
-    let k = t.data[i][0]
-    if k != nil:
-      var h = hashPtr(k)
-      while result.data[h and result.max][0] != nil: inc h
-      result.data[h and result.max] = t.data[i]
-  dealloc t
-
-proc initPtrTable(): PtrTable =
-  const cap = 32
-  result = allocPtrTable()
-  result.counter = 0
-  result.max = cap-1
-
-template deinit(t: PtrTable) = dealloc(t)
-
-proc get(t: PtrTable; key: pointer): pointer =
-  var h = hashPtr(key)
-  while true:
-    let k = t.data[h and t.max][0]
-    if k == nil: break
-    if k == key:
-      return t.data[h and t.max][1]
-    inc h
-
-proc put(t: var PtrTable; key, val: pointer) =
-  if (t.max+1) * 2 < t.counter * 3: t = rehash(t)
-  var h = hashPtr(key)
-  while t.data[h and t.max][0] != nil: inc h
-  t.data[h and t.max] = (key, val)
-  inc t.counter
-
-proc genericDeepCopyAux(dest, src: pointer, mt: PNimType;
-                        tab: var PtrTable) {.benign.}
-proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode;
-                        tab: var PtrTable) {.benign.} =
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.benign.}
+proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} =
   var
     d = cast[ByteAddress](dest)
     s = cast[ByteAddress](src)
   case n.kind
   of nkSlot:
     genericDeepCopyAux(cast[pointer](d +% n.offset),
-                       cast[pointer](s +% n.offset), n.typ, tab)
+                       cast[pointer](s +% n.offset), n.typ)
   of nkList:
     for i in 0..n.len-1:
-      genericDeepCopyAux(dest, src, n.sons[i], tab)
+      genericDeepCopyAux(dest, src, n.sons[i])
   of nkCase:
     var dd = selectBranch(dest, n)
     var m = selectBranch(src, n)
@@ -77,10 +29,10 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode;
     copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
             n.typ.size)
     if m != nil:
-      genericDeepCopyAux(dest, src, m, tab)
+      genericDeepCopyAux(dest, src, m)
   of nkNone: sysAssert(false, "genericDeepCopyAux")
 
-proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
   var
     d = cast[ByteAddress](dest)
     s = cast[ByteAddress](src)
@@ -108,22 +60,22 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
         cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
         cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
                      GenericSeqSize),
-        mt.base, tab)
+        mt.base)
   of tyObject:
     # we need to copy m_type field for tyObject, as it could be empty for
     # sequence reallocations:
     if mt.base != nil:
-      genericDeepCopyAux(dest, src, mt.base, tab)
+      genericDeepCopyAux(dest, src, mt.base)
     else:
       var pint = cast[ptr PNimType](dest)
       pint[] = cast[ptr PNimType](src)[]
-    genericDeepCopyAux(dest, src, mt.node, tab)
+    genericDeepCopyAux(dest, src, mt.node)
   of tyTuple:
-    genericDeepCopyAux(dest, src, mt.node, tab)
+    genericDeepCopyAux(dest, src, mt.node)
   of tyArray, tyArrayConstr:
     for i in 0..(mt.size div mt.base.size)-1:
       genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
-                         cast[pointer](s +% i*% mt.base.size), mt.base, tab)
+                         cast[pointer](s +% i*% mt.base.size), mt.base)
   of tyRef:
     let s2 = cast[PPointer](src)[]
     if s2 == nil:
@@ -132,24 +84,30 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
       let z = mt.base.deepcopy(s2)
       unsureAsgnRef(cast[PPointer](dest), z)
     else:
-      let z = tab.get(s2)
-      if z == nil:
-        when declared(usrToCell) and false:
-          let x = usrToCell(s2)
-          let realType = x.typ
-          let z = newObj(realType, realType.base.size)
+      # 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.
+      when declared(usrToCell):
+        # unfortunately we only have cycle detection for our native GCs.
+        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:
+          let z = cast[pointer](forw and not 1)
           unsureAsgnRef(cast[PPointer](dest), z)
-          tab.put(s2, z)
-          genericDeepCopyAux(z, s2, realType.base, tab)
         else:
-          # this version should work for any possible GC:
-          let size = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[].size else: mt.base.size
-          let z = newObj(mt, size)
+          let realType = x.typ
+          let z = newObj(realType, realType.base.size)
           unsureAsgnRef(cast[PPointer](dest), z)
-          tab.put(s2, z)
-          genericDeepCopyAux(z, s2, mt.base, tab)
+          x.typ = cast[PNimType](cast[int](z) or 1)
+          genericDeepCopyAux(z, s2, realType.base)
+          x.typ = realType
       else:
+        let size = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[].size
+                   else: mt.base.size
+        let z = newObj(mt, size)
         unsureAsgnRef(cast[PPointer](dest), z)
+        genericDeepCopyAux(z, s2, mt.base)
   of tyPtr:
     # no cycle check here, but also not really required
     let s2 = cast[PPointer](src)[]
@@ -162,9 +120,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
 
 proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
   GC_disable()
-  var tab = initPtrTable()
-  genericDeepCopyAux(dest, src, mt, tab)
-  deinit tab
+  genericDeepCopyAux(dest, src, mt)
   GC_enable()
 
 proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =