[pypy-svn] r27667 - in pypy/dist/pypy/rpython/memory: . test

arigo at codespeak.net arigo at codespeak.net
Thu May 25 16:16:02 CEST 2006


Author: arigo
Date: Thu May 25 16:16:00 2006
New Revision: 27667

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Cloning of varsized structures.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Thu May 25 16:16:00 2006
@@ -529,22 +529,47 @@
             newhdr = oldhdr.next      # abused to point to the copy
             if not newhdr:
                 typeid >>= 1
+                size = self.fixed_size(typeid)
+                # XXX! collect() at the beginning if the free heap is low
                 if self.is_varsize(typeid):
-                    raise NotImplementedError
+                    itemsize = self.varsize_item_sizes(typeid)
+                    offset_to_length = self.varsize_offset_to_length(typeid)
+                    length = (oldobj_addr +
+                              self.varsize_offset_to_length(typeid)).signed[0]
+                    newobj = self.malloc_varsize(typeid, length, size,
+                                                 itemsize, offset_to_length,
+                                                 False)
                 else:
-                    size = self.fixed_size(typeid)
-                    # XXX! collect() at the beginning if the free heap is low
                     newobj = self.malloc_fixedsize(typeid, size, False)
-                    newobj_addr = llmemory.cast_ptr_to_adr(newobj)
-                    newhdr_addr = newobj_addr - size_gc_header
-                    newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR)
-                    raw_memcopy(oldobj_addr, newobj_addr, size)
-                    offsets = self.offsets_to_gc_pointers(typeid)
+                    length = -1
+
+                newobj_addr = llmemory.cast_ptr_to_adr(newobj)
+                newhdr_addr = newobj_addr - size_gc_header
+                newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR)
+                raw_memcopy(oldobj_addr, newobj_addr, size)
+                offsets = self.offsets_to_gc_pointers(typeid)
+                i = 0
+                while i < len(offsets):
+                    pointer_addr = newobj_addr + offsets[i]
+                    stack.append(pointer_addr)
+                    i += 1
+
+                if length > 0:
+                    offsets = self.varsize_offsets_to_gcpointers_in_var_part(
+                        typeid)
+                    itemlength = self.varsize_item_sizes(typeid)
+                    offset = self.varsize_offset_to_variable_part(typeid)
+                    itembaseaddr = newobj_addr + offset
                     i = 0
-                    while i < len(offsets):
-                        pointer_addr = newobj_addr + offsets[i]
-                        stack.append(pointer_addr)
+                    while i < length:
+                        item = itembaseaddr + itemlength * i
+                        j = 0
+                        while j < len(offsets):
+                            pointer_addr = item + offsets[j]
+                            stack.append(pointer_addr)
+                            j += 1
                         i += 1
+
                 oldhdr.next = newhdr
             newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
             gcptr_addr.address[0] = newobj_addr

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Thu May 25 16:16:00 2006
@@ -448,6 +448,41 @@
         res = run([])
         assert res == 111222333
 
+    def test_cloning_varsize(self):
+        B = lltype.GcStruct('B', ('x', lltype.Signed))
+        A = lltype.GcStruct('A', ('b', lltype.Ptr(B)),
+                                 ('more', lltype.Array(lltype.Ptr(B))))
+        def make(n):
+            b = lltype.malloc(B)
+            b.x = n
+            a = lltype.malloc(A, 2)
+            a.b = b
+            a.more[0] = lltype.malloc(B)
+            a.more[0].x = n*10
+            a.more[1] = lltype.malloc(B)
+            a.more[1].x = n*10+1
+            return a
+        def func():
+            oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL))
+            a2 = make(22)
+            newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool)
+            # clone a2
+            a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2)
+            clonedata = lltype.malloc(X_CLONE)
+            clonedata.gcobjectptr = a2ref
+            clonedata.pool = newpool
+            llop.gc_x_clone(lltype.Void, clonedata)
+            a2copyref = clonedata.gcobjectptr
+            a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref)
+            a2copy.b.x = 44
+            a2copy.more[0].x = 440
+            a2copy.more[1].x = 441
+            return a2.b.x * 1000000 + a2.more[0].x * 1000 + a2.more[1].x
+
+        run = self.runner(func)
+        res = run([])
+        assert res == 22220221
+
     def test_cloning_highlevel(self):
         from pypy.rpython import rgc
         class A:
@@ -482,6 +517,33 @@
         res = run([7, 0])
         assert res == 1
 
+    def test_cloning_highlevel_varsize(self):
+        from pypy.rpython import rgc
+        class A:
+            pass
+        def func(n, dummy):
+            lst = [A() for i in range(n)]
+            for a in lst:
+                a.value = 1
+            lst2, newpool = rgc.gc_clone(lst, None)
+            for i in range(n):
+                a = A()
+                a.value = i
+                lst.append(a)
+                lst[i].value = 4 + i
+                lst2[i].value = 7 + i
+
+            n = 0
+            for a in lst:
+                n = n*10 + a.value
+            for a in lst2:
+                n = n*10 + a.value
+            return n
+
+        run = self.runner(func, nbargs=2)
+        res = run([3, 0])
+        assert res == 456012789
+
     def test_tree_cloning(self):
         import os
         # this makes a tree of calls.  Each leaf stores its path (a linked



More information about the Pypy-commit mailing list