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