Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: 
Changeset: r59779:99da6b4f5a3f
Date: 2013-01-05 22:25 +0200
http://bitbucket.org/pypy/pypy/changeset/99da6b4f5a3f/

Log:    merge

diff --git a/pypy/rlib/rgc.py b/pypy/rlib/rgc.py
--- a/pypy/rlib/rgc.py
+++ b/pypy/rlib/rgc.py
@@ -139,6 +139,40 @@
         hop.exception_cannot_occur()
         return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype)
 
+def copy_struct_item(source, dest, si, di):
+    TP = lltype.typeOf(source)
+    i = 0
+    while i < len(TP._names):
+        setattr(dest[di], TP._names[i], getattr(source[si], TP._names[i]))
+
+class CopyStructEntry(ExtRegistryEntry):
+    _about_ = copy_struct_item
+
+    def compute_result_annotation(self, s_source, s_dest, si, di):
+        pass
+
+    def specialize_call(self, hop):
+        v_source, v_dest, v_si, v_di = hop.inputargs(hop.args_r[0],
+                                                     hop.args_r[1],
+                                                     lltype.Signed,
+                                                     lltype.Signed)
+        hop.exception_cannot_occur()
+        TP = v_source.concretetype.TO.OF
+        for name, TP in TP._flds.iteritems():
+            c_name = hop.inputconst(lltype.Void, name)
+            v_fld = hop.genop('getinteriorfield', [v_source, v_si, c_name],
+                              resulttype=TP)
+            hop.genop('setinteriorfield', [v_dest, v_di, c_name, v_fld])
+
+
+@specialize.ll()
+def copy_item(source, dest, si, di):
+    TP = lltype.typeOf(source)
+    if isinstance(TP.TO.OF, lltype.Struct):
+        copy_struct_item(source, dest, si, di)
+    else:
+        dest[di] = source[si]
+
 @jit.oopspec('list.ll_arraycopy(source, dest, source_start, dest_start, 
length)')
 @enforceargs(None, None, int, int, int)
 @specialize.ll()
@@ -150,7 +184,7 @@
     # and also, maybe, speed up very small cases
     if length <= 1:
         if length == 1:
-            dest[dest_start] = source[source_start]
+            copy_item(source, dest, source_start, dest_start)
         return
 
     # supports non-overlapping copies only
@@ -170,7 +204,7 @@
             # if the write barrier is not supported, copy by hand
             i = 0
             while i < length:
-                dest[i + dest_start] = source[i + source_start]
+                copy_item(source, dest, i + source_start, i + dest_start)
                 i += 1
             return
     source_addr = llmemory.cast_ptr_to_adr(source)
diff --git a/pypy/rlib/test/test_rgc.py b/pypy/rlib/test/test_rgc.py
--- a/pypy/rlib/test/test_rgc.py
+++ b/pypy/rlib/test/test_rgc.py
@@ -134,6 +134,24 @@
 
     assert check.called
 
+def test_ll_arraycopy_array_of_structs():
+    TP = lltype.GcArray(lltype.Struct('x', ('x', lltype.Signed),
+                                      ('y', lltype.Signed)))
+    def f():
+        a1 = lltype.malloc(TP, 3)
+        a2 = lltype.malloc(TP, 3)
+        for i in range(3):
+            a1[i].x = 2 * i
+            a1[i].y = 2 * i + 1
+        rgc.ll_arraycopy(a1, a2, 0, 0, 3)
+        for i in range(3):
+            assert a2[i].x == 2 * i
+            assert a2[i].y == 2 * i + 1
+
+
+    interpret(f, [])
+    f()
+
 def test_ll_arraycopy_small():
     TYPE = lltype.GcArray(lltype.Signed)
     for length in range(5):
diff --git a/pypy/rpython/lltypesystem/test/test_lltype.py 
b/pypy/rpython/lltypesystem/test/test_lltype.py
--- a/pypy/rpython/lltypesystem/test/test_lltype.py
+++ b/pypy/rpython/lltypesystem/test/test_lltype.py
@@ -808,7 +808,6 @@
     assert F.RESULT == Signed
     assert F.ARGS == (Signed,)
 
-
 class TestTrackAllocation:
     def test_automatic_tracking(self):
         # calls to start_tracking_allocations/stop_tracking_allocations
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to