[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