Author: Armin Rigo <[email protected]>
Branch: fix-2198
Changeset: r81385:e9ae1b34a1f6
Date: 2015-12-18 21:06 +0100
http://bitbucket.org/pypy/pypy/changeset/e9ae1b34a1f6/

Log:    Fix the tests (writing tons of comments)

diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -271,11 +271,16 @@
             copy_item(source, dest, source_start, dest_start)
         return
 
-    # supports non-overlapping copies only
+    # supports non-overlapping copies only, or as a very special case,
+    # copies that are identical and so don't need to do anything
+    # (this is needed to make one case of ll_listsetslice() easier)
+    # xxx I suppose that the C function memcpy(p,q,r), in practice, is
+    # always fine and doing nothing if called with p == q...
     if not we_are_translated():
         if source == dest:
             assert (source_start + length <= dest_start or
-                    dest_start + length <= source_start)
+                    dest_start + length <= source_start or
+                    source_start == dest_start)
 
     TP = lltype.typeOf(source).TO
     assert TP == lltype.typeOf(dest).TO
diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py
--- a/rpython/rtyper/rlist.py
+++ b/rpython/rtyper/rlist.py
@@ -968,22 +968,52 @@
     len1 = l1.ll_length()
     len2 = l2.ll_length()
     ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start")
-    ll_assert(start <= len1, "l[start:x] = l with start > len(l)")
     ll_assert(stop <= len1, "stop cannot be past the end of l1")
-    if len2 == stop - start:
+    ll_assert(start <= stop, "l[start:stop] with start > stop")
+    len_replace = stop - start
+    if len2 == len_replace:
         ll_arraycopy(l2, l1, 0, start, len2)
-    elif len2 < stop - start:
+    else:
+        _ll_listsetslice_resize(l1, start, len_replace, l2)
+
+def _ll_listsetslice_resize(l1, start, len_replace, l2):
+    # a separate function, so that ll_listsetslice() can be JITted
+    len1 = l1.ll_length()
+    len2 = l2.ll_length()
+    delta = len2 - len_replace
+    #
+    if delta < 0:      # len2 < len_replace
         ll_arraycopy(l2, l1, 0, start, len2)
-        ll_arraycopy(l1, l1, stop, start + len2, len1 - stop)
-        l1._ll_resize_le(len1 + len2 - (stop - start))
-    else: # len2 > stop - start:
+        # Shift the items left from l1[start+len_replace:] to l1[start+len2:].
+        # Usually the ranges overlap, so can't use ll_arraycopy.  Instead
+        # we will proceed item-by-item from left to right.  'j' is the
+        # source item to copy.
+        j = start + len_replace
+        while j < len1:
+            l1.ll_setitem_fast(j + delta, l1.ll_getitem_fast(j))
+            j += 1
+        l1._ll_resize_le(len1 + delta)   # this is < len1
+    #
+    else: # len2 > len_replace:
         try:
-            newlength = ovfcheck(len1 + len2)
+            newlength = ovfcheck(len1 + delta)
         except OverflowError:
             raise MemoryError
         l1._ll_resize_ge(newlength)
-        ll_arraycopy(l1, l1, stop, start + len2, len1 - stop)
-        ll_arraycopy(l2, l1, 0, start, len2)
+        # Shift the items right from l1[start+len_replace:] to l1[start+len2:].
+        # Usually the ranges overlap, so can't use ll_arraycopy.  Instead
+        # we will proceed item-by-item from right to left.  Here, 'j' is
+        # the target position to fill.
+        j_min = start + len2
+        j = newlength - 1
+        while j >= j_min:
+            l1.ll_setitem_fast(j, l1.ll_getitem_fast(j - delta))
+            j -= 1
+        # We could usually use ll_arraycopy() for the rest, but not if
+        # l1 == l2...  so instead we just continue to copy item-by-item.
+        while j >= start:
+            l1.ll_setitem_fast(j, l2.ll_getitem_fast(j - start))
+            j -= 1
 
 
 # ____________________________________________________________
diff --git a/rpython/rtyper/test/test_rlist.py 
b/rpython/rtyper/test/test_rlist.py
--- a/rpython/rtyper/test/test_rlist.py
+++ b/rpython/rtyper/test/test_rlist.py
@@ -92,14 +92,14 @@
 
 
 class TestListImpl(BaseTestListImpl):
-    def sample_list(self):    # [42, 43, 44, 45]
+    def sample_list(self, factor=1):    # [42, 43, 44, 45]
         rlist = ListRepr(None, signed_repr)
         rlist.setup()
         l = ll_newlist(rlist.lowleveltype.TO, 3)
-        ll_setitem(l, 0, 42)
-        ll_setitem(l, -2, 43)
-        ll_setitem_nonneg(l, 2, 44)
-        ll_append(l, 45)
+        ll_setitem(l, 0, 42 * factor)
+        ll_setitem(l, -2, 43 * factor)
+        ll_setitem_nonneg(l, 2, 44 * factor)
+        ll_append(l, 45 * factor)
         return l
 
     def test_rlist_del(self):
@@ -141,11 +141,11 @@
             for stop in range(start, 5):
                 for len2 in range(5):
                     l1 = self.sample_list()    # [42, 43, 44, 45]
-                    l2 = self.sample_list()
+                    l2 = self.sample_list(10)  # [420, 430, 440, 450]
                     ll_listdelslice_startonly(l2, len2)   # initial slice
                     ll_listsetslice(l1, start, stop, l2)
                     expected = [42, 43, 44, 45]
-                    expected[start:stop] = [42, 43, 44, 45][:len2]
+                    expected[start:stop] = [420, 430, 440, 450][:len2]
                     self.check_list(l1, expected)
 
     def test_rlist_setslice_overlapping(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to