[pypy-commit] pypy win64_gborg: merge default

ctismer noreply at buildbot.pypy.org
Sat Nov 5 18:33:29 CET 2011


Author: Christian Tismer <tismer at stackless.com>
Branch: win64_gborg
Changeset: r48799:9752b5362bec
Date: 2011-11-05 18:32 +0100
http://bitbucket.org/pypy/pypy/changeset/9752b5362bec/

Log:	merge default

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -247,7 +247,6 @@
 CONST_1      = ConstInt(1)
 CVAL_ZERO    = ConstantValue(CONST_0)
 CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
-CVAL_UNINITIALIZED_ZERO = ConstantValue(CONST_0)
 llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
 oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL)
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -4123,6 +4123,38 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_concat_constant_lengths(self):
+        ops = """
+        [i0]
+        p0 = newstr(1)
+        strsetitem(p0, 0, i0)
+        p1 = newstr(0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p0, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_str_concat_constant_lengths_2(self):
+        ops = """
+        [i0]
+        p0 = newstr(0)
+        p1 = newstr(1)
+        strsetitem(p1, 0, i0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p1, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     def test_str_slice_1(self):
         ops = """
         [p1, i1, i2]
@@ -4883,6 +4915,27 @@
 
     def test_plain_virtual_string_copy_content(self):
         ops = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = call(0, p0, s"abc123", descr=strconcatdescr)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        expected = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = newstr(12)
+        copystrcontent(p0, p1, 0, 0, 6)
+        copystrcontent(s"abc123", p1, 0, 6, 6)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_plain_virtual_string_copy_content_2(self):
+        ops = """
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
@@ -4894,10 +4947,7 @@
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
-        p1 = newstr(12)
-        copystrcontent(p0, p1, 0, 0, 6)
-        copystrcontent(s"abc123", p1, 0, 6, 6)
-        i0 = strgetitem(p1, 0)
+        i0 = strgetitem(p0, 0)
         finish(i0)
         """
         self.optimize_strunicode_loop(ops, expected)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -2168,13 +2168,13 @@
         ops = """
         [p0, i0, p1, i1, i2]
         setfield_gc(p0, i1, descr=valuedescr)
-        copystrcontent(p0, i0, p1, i1, i2)
+        copystrcontent(p0, p1, i0, i1, i2)
         escape()
         jump(p0, i0, p1, i1, i2)
         """
         expected = """
         [p0, i0, p1, i1, i2]
-        copystrcontent(p0, i0, p1, i1, i2)
+        copystrcontent(p0, p1, i0, i1, i2)
         setfield_gc(p0, i1, descr=valuedescr)
         escape()
         jump(p0, i0, p1, i1, i2)
@@ -7407,7 +7407,7 @@
         expected = """
         [p22, p18, i1, i2]
         call(i2, descr=nonwritedescr)
-        setfield_gc(p22, i1, descr=valuedescr)        
+        setfield_gc(p22, i1, descr=valuedescr)
         jump(p22, p18, i1, i1)
         """
         self.optimize_loop(ops, expected, preamble, expected_short=short)
@@ -7434,7 +7434,7 @@
     def test_cache_setarrayitem_across_loop_boundaries(self):
         ops = """
         [p1]
-        p2 = getarrayitem_gc(p1, 3, descr=arraydescr)        
+        p2 = getarrayitem_gc(p1, 3, descr=arraydescr)
         guard_nonnull_class(p2, ConstClass(node_vtable)) []
         call(p2, descr=nonwritedescr)
         p3 = new_with_vtable(ConstClass(node_vtable))
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -1,6 +1,6 @@
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.metainterp.history import (BoxInt, Const, ConstInt, ConstPtr,
-    get_const_ptr_for_string, get_const_ptr_for_unicode)
+    get_const_ptr_for_string, get_const_ptr_for_unicode, BoxPtr, REF, INT)
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
 from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1, llhelper
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
@@ -106,46 +106,33 @@
         if not we_are_translated():
             op.name = 'FORCE'
         optforce.emit_operation(op)
-        self.string_copy_parts(optforce, box, CONST_0, self.mode)
+        self.initialize_forced_string(optforce, box, CONST_0, self.mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
+        return self.string_copy_parts(string_optimizer, targetbox,
+                                      offsetbox, mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
     """A string built with newstr(const)."""
     _lengthbox = None     # cache only
 
-    # Warning: an issue with VStringPlainValue is that sometimes it is
-    # initialized unpredictably by some copystrcontent.  When this occurs
-    # we set self._chars to None.  Be careful to check for is_valid().
-
-    def is_valid(self):
-        return self._chars is not None
-
-    def _invalidate(self):
-        assert self.is_valid()
-        if self._lengthbox is None:
-            self._lengthbox = ConstInt(len(self._chars))
-        self._chars = None
-
-    def _really_force(self, optforce):
-        VAbstractStringValue._really_force(self, optforce)
-        assert self.box is not None
-        if self.is_valid():
-            for c in self._chars:
-                if c is optimizer.CVAL_UNINITIALIZED_ZERO:
-                    # the string has uninitialized null bytes in it, so
-                    # assume that it is forced for being further mutated
-                    # (e.g. by copystrcontent).  So it becomes invalid
-                    # as a VStringPlainValue: the _chars must not be used
-                    # any longer.
-                    self._invalidate()
-                    break
-
     def setup(self, size):
-        self._chars = [optimizer.CVAL_UNINITIALIZED_ZERO] * size
+        # in this list, None means: "it's probably uninitialized so far,
+        # but maybe it was actually filled."  So to handle this case,
+        # strgetitem cannot be virtual-ized and must be done as a residual
+        # operation.  By contrast, any non-None value means: we know it
+        # is initialized to this value; strsetitem() there makes no sense.
+        # Also, as long as self.is_virtual(), then we know that no-one else
+        # could have written to the string, so we know that in this case
+        # "None" corresponds to "really uninitialized".
+        self._chars = [None] * size
 
     def setup_slice(self, longerlist, start, stop):
         assert 0 <= start <= stop <= len(longerlist)
         self._chars = longerlist[start:stop]
+        # slice the 'longerlist', which may also contain Nones
 
     def getstrlen(self, _, mode):
         if self._lengthbox is None:
@@ -153,43 +140,66 @@
         return self._lengthbox
 
     def getitem(self, index):
-        return self._chars[index]
+        return self._chars[index]     # may return None!
 
     def setitem(self, index, charvalue):
         assert isinstance(charvalue, optimizer.OptValue)
+        assert self._chars[index] is None, (
+            "setitem() on an already-initialized location")
         self._chars[index] = charvalue
 
+    def is_completely_initialized(self):
+        for c in self._chars:
+            if c is None:
+                return False
+        return True
+
     @specialize.arg(1)
     def get_constant_string_spec(self, mode):
-        if not self.is_valid():
-            return None
         for c in self._chars:
-            if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
+            if c is None or not c.is_constant():
                 return None
         return mode.emptystr.join([mode.chr(c.box.getint())
                                    for c in self._chars])
 
     def string_copy_parts(self, string_optimizer, targetbox, offsetbox, mode):
-        if not self.is_valid():
+        if not self.is_virtual() and not self.is_completely_initialized():
             return VAbstractStringValue.string_copy_parts(
                 self, string_optimizer, targetbox, offsetbox, mode)
+        else:
+            return self.initialize_forced_string(string_optimizer, targetbox,
+                                                 offsetbox, mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
         for i in range(len(self._chars)):
-            charbox = self._chars[i].force_box(string_optimizer)
-            if not (isinstance(charbox, Const) and charbox.same_constant(CONST_0)):
-                string_optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
-                                                                               offsetbox,
-                                                                               charbox],
-                                                  None))
+            assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
+            charvalue = self.getitem(i)
+            if charvalue is not None:
+                charbox = charvalue.force_box(string_optimizer)
+                if not (isinstance(charbox, Const) and
+                        charbox.same_constant(CONST_0)):
+                    op = ResOperation(mode.STRSETITEM, [targetbox,
+                                                        offsetbox,
+                                                        charbox],
+                                      None)
+                    string_optimizer.emit_operation(op)
             offsetbox = _int_add(string_optimizer, offsetbox, CONST_1)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            assert self.is_valid()
-            charboxes = [value.get_key_box() for value in self._chars]
+            charboxes = []
+            for value in self._chars:
+                if value is not None:
+                    box = value.get_key_box()
+                else:
+                    box = None
+                charboxes.append(box)
             modifier.register_virtual_fields(self.keybox, charboxes)
             for value in self._chars:
-                value.get_args_for_fail(modifier)
+                if value is not None:
+                    value.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
         return modifier.make_vstrplain(self.mode is mode_unicode)
@@ -197,6 +207,7 @@
 
 class VStringConcatValue(VAbstractStringValue):
     """The concatenation of two other strings."""
+    _attrs_ = ('left', 'right', 'lengthbox')
 
     lengthbox = None     # or the computed length
 
@@ -305,6 +316,7 @@
         for i in range(lengthbox.value):
             charbox = _strgetitem(string_optimizer, srcbox, srcoffsetbox, mode)
             srcoffsetbox = _int_add(string_optimizer, srcoffsetbox, CONST_1)
+            assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
             string_optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
                                                                            offsetbox,
                                                                            charbox],
@@ -315,6 +327,7 @@
             nextoffsetbox = _int_add(string_optimizer, offsetbox, lengthbox)
         else:
             nextoffsetbox = None
+        assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
         op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
                                                 srcoffsetbox, offsetbox,
                                                 lengthbox], None)
@@ -401,8 +414,8 @@
 
     def optimize_STRSETITEM(self, op):
         value = self.getvalue(op.getarg(0))
-        if (value.is_virtual() and isinstance(value, VStringPlainValue)
-            and value.is_valid()):
+        assert not value.is_constant() # strsetitem(ConstPtr) never makes sense
+        if value.is_virtual() and isinstance(value, VStringPlainValue):
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
                 value.setitem(indexbox.getint(), self.getvalue(op.getarg(2)))
@@ -433,10 +446,22 @@
             value = value.vstr
             vindex = self.getvalue(fullindexbox)
         #
-        if (isinstance(value, VStringPlainValue)  # even if no longer virtual
-            and value.is_valid()):                # but make sure it is valid
+        if isinstance(value, VStringPlainValue):  # even if no longer virtual
             if vindex.is_constant():
-                return value.getitem(vindex.box.getint())
+                result = value.getitem(vindex.box.getint())
+                if result is not None:
+                    return result
+        #
+        if isinstance(value, VStringConcatValue) and vindex.is_constant():
+            len1box = value.left.getstrlen(self, mode)
+            if isinstance(len1box, ConstInt):
+                index = vindex.box.getint()
+                len1 = len1box.getint()
+                if index < len1:
+                    return self.strgetitem(value.left, vindex, mode)
+                else:
+                    vindex = optimizer.ConstantValue(ConstInt(index - len1))
+                    return self.strgetitem(value.right, vindex, mode)
         #
         resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode)
         return self.getvalue(resbox)
@@ -458,6 +483,11 @@
 
     def _optimize_COPYSTRCONTENT(self, op, mode):
         # args: src dst srcstart dststart length
+        assert op.getarg(0).type == REF
+        assert op.getarg(1).type == REF
+        assert op.getarg(2).type == INT
+        assert op.getarg(3).type == INT
+        assert op.getarg(4).type == INT
         src = self.getvalue(op.getarg(0))
         dst = self.getvalue(op.getarg(1))
         srcstart = self.getvalue(op.getarg(2))
@@ -529,12 +559,12 @@
         vstart = self.getvalue(op.getarg(2))
         vstop = self.getvalue(op.getarg(3))
         #
-        if (isinstance(vstr, VStringPlainValue) and vstr.is_valid()
-            and vstart.is_constant() and vstop.is_constant()):
-            value = self.make_vstring_plain(op.result, op, mode)
-            value.setup_slice(vstr._chars, vstart.box.getint(),
-                              vstop.box.getint())
-            return True
+        #if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
+        #    and vstop.is_constant()):
+        #    value = self.make_vstring_plain(op.result, op, mode)
+        #    value.setup_slice(vstr._chars, vstart.box.getint(),
+        #                      vstop.box.getint())
+        #    return True
         #
         vstr.ensure_nonnull()
         lengthbox = _int_sub(self, vstop.force_box(self),
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -126,6 +126,7 @@
 UNASSIGNED = tag(-1<<13, TAGBOX)
 UNASSIGNEDVIRTUAL = tag(-1<<13, TAGVIRTUAL)
 NULLREF = tag(-1, TAGCONST)
+UNINITIALIZED = tag(-2, TAGCONST)   # used for uninitialized string characters
 
 
 class ResumeDataLoopMemo(object):
@@ -439,6 +440,8 @@
         self.storage.rd_pendingfields = rd_pendingfields
 
     def _gettagged(self, box):
+        if box is None:
+            return UNINITIALIZED
         if isinstance(box, Const):
             return self.memo.getconst(box)
         else:
@@ -572,7 +575,9 @@
         string = decoder.allocate_string(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.string_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.string_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
@@ -625,7 +630,9 @@
         string = decoder.allocate_unicode(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.unicode_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.unicode_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
diff --git a/pypy/jit/metainterp/test/test_virtualstate.py b/pypy/jit/metainterp/test/test_virtualstate.py
--- a/pypy/jit/metainterp/test/test_virtualstate.py
+++ b/pypy/jit/metainterp/test/test_virtualstate.py
@@ -847,7 +847,8 @@
         i5 = arraylen_gc(p2, descr=arraydescr)
         i6 = int_ge(i5, 1)
         guard_true(i6) []
-        jump(p0, p1, p2)
+        p3 = getarrayitem_gc(p2, 0, descr=arraydescr)
+        jump(p0, p1, p3, p2)
         """
         self.optimize_bridge(loop, bridge, expected, p0=self.myptr)
 
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -312,11 +312,10 @@
 
 
 class W_XRange(Wrappable):
-    def __init__(self, space, start, stop, step):
+    def __init__(self, space, start, len, step):
         self.space = space
         self.start = start
-        self.stop = stop
-        self.len = get_len_of_range(space, start, stop, step)
+        self.len   = len
         self.step  = step
 
     def descr_new(space, w_subtype, w_start, w_stop=None, w_step=1):
@@ -326,8 +325,9 @@
             start, stop = 0, start
         else:
             stop = _toint(space, w_stop)
+        howmany = get_len_of_range(space, start, stop, step)
         obj = space.allocate_instance(W_XRange, w_subtype)
-        W_XRange.__init__(obj, space, start, stop, step)
+        W_XRange.__init__(obj, space, start, howmany, step)
         return space.wrap(obj)
 
     def descr_repr(self):
@@ -357,12 +357,12 @@
 
     def descr_iter(self):
         return self.space.wrap(W_XRangeIterator(self.space, self.start,
-                                                self.stop, self.step))
+                                                self.len, self.step))
 
     def descr_reversed(self):
         lastitem = self.start + (self.len-1) * self.step
         return self.space.wrap(W_XRangeIterator(self.space, lastitem,
-                                                self.start, -self.step, True))
+                                                self.len, -self.step))
 
     def descr_reduce(self):
         space = self.space
@@ -389,29 +389,25 @@
 )
 
 class W_XRangeIterator(Wrappable):
-    def __init__(self, space, start, stop, step, inclusive=False):
+    def __init__(self, space, current, remaining, step):
         self.space = space
-        self.current = start
-        self.stop = stop
+        self.current = current
+        self.remaining = remaining
         self.step = step
-        self.inclusive = inclusive
 
     def descr_iter(self):
         return self.space.wrap(self)
 
     def descr_next(self):
-        if self.inclusive:
-            if not ((self.step > 0 and self.current <= self.stop) or (self.step < 0 and self.current >= self.stop)):
-                raise OperationError(self.space.w_StopIteration, self.space.w_None)
-        else:
-            if not ((self.step > 0 and self.current < self.stop) or (self.step < 0 and self.current > self.stop)):
-                raise OperationError(self.space.w_StopIteration, self.space.w_None)
-        item = self.current
-        self.current = item + self.step
-        return self.space.wrap(item)
+        if self.remaining > 0:
+            item = self.current
+            self.current = item + self.step
+            self.remaining -= 1
+            return self.space.wrap(item)
+        raise OperationError(self.space.w_StopIteration, self.space.w_None)
 
-    #def descr_len(self):
-    #    return self.space.wrap(self.remaining)
+    def descr_len(self):
+        return self.space.wrap(self.remaining)
 
     def descr_reduce(self):
         from pypy.interpreter.mixedmodule import MixedModule
@@ -422,7 +418,7 @@
         w        = space.wrap
         nt = space.newtuple
 
-        tup = [w(self.current), w(self.stop), w(self.step)]
+        tup = [w(self.current), w(self.remaining), w(self.step)]
         return nt([new_inst, nt(tup)])
 
 W_XRangeIterator.typedef = TypeDef("rangeiterator",
diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -157,8 +157,7 @@
        raises(OverflowError, xrange, a)
        raises(OverflowError, xrange, 0, a)
        raises(OverflowError, xrange, 0, 1, a)
-       assert list(reversed(xrange(-sys.maxint-1, -sys.maxint-1, -2))) == []
-       
+
    def test_xrange_reduce(self):
       x = xrange(2, 9, 3)
       callable, args = x.__reduce__()
diff --git a/pypy/module/_pickle_support/maker.py b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -66,10 +66,10 @@
     new_generator.running = running
     return space.wrap(new_generator)
 
- at unwrap_spec(current=int, stop=int, step=int)
-def xrangeiter_new(space, current, stop, step):
+ at unwrap_spec(current=int, remaining=int, step=int)
+def xrangeiter_new(space, current, remaining, step):
     from pypy.module.__builtin__.functional import W_XRangeIterator
-    new_iter = W_XRangeIterator(space, current, stop, step)
+    new_iter = W_XRangeIterator(space, current, remaining, step)
     return space.wrap(new_iter)
 
 @unwrap_spec(identifier=str)
diff --git a/pypy/objspace/std/boolobject.py b/pypy/objspace/std/boolobject.py
--- a/pypy/objspace/std/boolobject.py
+++ b/pypy/objspace/std/boolobject.py
@@ -27,11 +27,7 @@
 
     def uint_w(w_self, space):
         intval = int(w_self.boolval)
-        if intval < 0:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("cannot convert negative integer to unsigned"))
-        else:
-            return r_uint(intval)
+        return r_uint(intval)
 
     def bigint_w(w_self, space):
         return rbigint.fromint(int(w_self.boolval))
diff --git a/pypy/objspace/std/test/test_sliceobject.py b/pypy/objspace/std/test/test_sliceobject.py
--- a/pypy/objspace/std/test/test_sliceobject.py
+++ b/pypy/objspace/std/test/test_sliceobject.py
@@ -42,6 +42,23 @@
                             getslice(length, mystart, mystop))
 
 
+    def test_indexes4(self):
+        space = self.space
+        w = space.wrap
+
+        def getslice(length, start, stop, step):
+            return [i for i in range(0, length, step) if start <= i < stop]
+
+        for step in [-5, -4, -3, -2, -1, 1, 2, 3, 4, 5, None]:
+            for length in range(5):
+                for start in range(-2*length-2, 2*length+3) + [None]:
+                    for stop in range(-2*length-2, 2*length+3) + [None]:
+                        sl = space.newslice(w(start), w(stop), w(step))
+                        mystart, mystop, mystep, slicelength = sl.indices4(space, length)
+                        assert len(range(length)[start:stop:step]) == slicelength
+                        assert slice(start, stop, step).indices(length) == (
+                                mystart, mystop, mystep)
+
 class AppTest_SliceObject:
     def test_new(self):
         def cmp_slice(sl1, sl2):


More information about the pypy-commit mailing list