[pypy-commit] pypy jit-targets: hg merge default

hakanardo noreply at buildbot.pypy.org
Sat Nov 5 10:23:58 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48776:88580873fdfd
Date: 2011-11-05 10:10 +0100
http://bitbucket.org/pypy/pypy/changeset/88580873fdfd/

Log:	hg 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
@@ -2224,13 +2224,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)
@@ -7493,7 +7493,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)
@@ -7520,7 +7520,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,7 +106,12 @@
         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):
@@ -114,11 +119,20 @@
     _lengthbox = None     # cache only
 
     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:
@@ -126,42 +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):
         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_virtual() and targetbox is not self.box:
-            lengthbox = self.getstrlen(string_optimizer, mode)
-            srcbox = self.force_box(string_optimizer)
-            return copy_str_content(string_optimizer, srcbox, targetbox,
-                                CONST_0, offsetbox, lengthbox, mode)
+        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):
-            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)
@@ -277,6 +315,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],
@@ -287,6 +326,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)
@@ -373,6 +413,7 @@
 
     def optimize_STRSETITEM(self, op):
         value = self.getvalue(op.getarg(0))
+        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:
@@ -406,11 +447,20 @@
         #
         if isinstance(value, VStringPlainValue):  # even if no longer virtual
             if vindex.is_constant():
-                res = value.getitem(vindex.box.getint())
-                # If it is uninitialized we can't return it, it was set by a
-                # COPYSTRCONTENT, not a STRSETITEM
-                if res is not optimizer.CVAL_UNINITIALIZED_ZERO:
-                    return res
+                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)
@@ -432,6 +482,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))
@@ -503,19 +558,12 @@
         vstart = self.getvalue(op.getarg(2))
         vstop = self.getvalue(op.getarg(3))
         #
-        if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
-            and vstop.is_constant()):
-            # slicing with constant bounds of a VStringPlainValue, if any of
-            # the characters is unitialized we don't do this special slice, we
-            # do the regular copy contents.
-            for i in range(vstart.box.getint(), vstop.box.getint()):
-                if vstr.getitem(i) is optimizer.CVAL_UNINITIALIZED_ZERO:
-                    break
-            else:
-                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/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/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -206,24 +206,28 @@
     @unwrap_spec(size=int)
     def direct_readlines(self, size=0):
         stream = self.getstream()
-        # NB. this implementation is very inefficient for unbuffered
-        # streams, but ok if stream.readline() is efficient.
+        # this is implemented as: .read().split('\n')
+        # except that it keeps the \n in the resulting strings
         if size <= 0:
-            result = []
-            while True:
-                line = stream.readline()
-                if not line:
-                    break
-                result.append(line)
-                size -= len(line)
+            data = stream.readall()
         else:
-            result = []
-            while size > 0:
-                line = stream.readline()
-                if not line:
-                    break
-                result.append(line)
-                size -= len(line)
+            data = stream.read(size)
+        result = []
+        splitfrom = 0
+        for i in range(len(data)):
+            if data[i] == '\n':
+                result.append(data[splitfrom : i + 1])
+                splitfrom = i + 1
+        #
+        if splitfrom < len(data):
+            # there is a partial line at the end.  If size > 0, it is likely
+            # to be because the 'read(size)' returned data up to the middle
+            # of a line.  In that case, use 'readline()' to read until the
+            # end of the current line.
+            data = data[splitfrom:]
+            if size > 0:
+                data += stream.readline()
+            result.append(data)
         return result
 
     @unwrap_spec(offset=r_longlong, whence=int)
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/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -283,17 +283,9 @@
     return space.wrap(''.join(w_bytearray.data))
 
 def _convert_idx_params(space, w_self, w_start, w_stop):
-    start = slicetype.eval_slice_index(space, w_start)
-    stop = slicetype.eval_slice_index(space, w_stop)
     length = len(w_self.data)
-    if start < 0:
-        start += length
-        if start < 0:
-            start = 0
-    if stop < 0:
-        stop += length
-        if stop < 0:
-            stop = 0
+    start, stop = slicetype.unwrap_start_stop(
+            space, length, w_start, w_stop, False)
     return start, stop, length
 
 def str_count__Bytearray_Int_ANY_ANY(space, w_bytearray, w_char, w_start, w_stop):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -419,8 +419,8 @@
     # needs to be safe against eq_w() mutating the w_list behind our back
     items = w_list.wrappeditems
     size = len(items)
-    i = slicetype.adapt_bound(space, size, w_start)
-    stop = slicetype.adapt_bound(space, size, w_stop)
+    i, stop = slicetype.unwrap_start_stop(
+            space, size, w_start, w_stop, True)
     while i < stop and i < len(items):
         if space.eq_w(items[i], w_any):
             return space.wrap(i)
diff --git a/pypy/objspace/std/ropeobject.py b/pypy/objspace/std/ropeobject.py
--- a/pypy/objspace/std/ropeobject.py
+++ b/pypy/objspace/std/ropeobject.py
@@ -357,16 +357,8 @@
     self = w_self._node
     sub = w_sub._node
 
-    if space.is_w(w_start, space.w_None):
-        w_start = space.wrap(0)
-    if space.is_w(w_end, space.w_None):
-        w_end = space.len(w_self)
-    if upper_bound:
-        start = slicetype.adapt_bound(space, self.length(), w_start)
-        end = slicetype.adapt_bound(space, self.length(), w_end)
-    else:
-        start = slicetype.adapt_lower_bound(space, self.length(), w_start)
-        end = slicetype.adapt_lower_bound(space, self.length(), w_end)
+    start, end = slicetype.unwrap_start_stop(
+            space, self.length(), w_start, w_end, upper_bound)
 
     return (self, sub, start, end)
 _convert_idx_params._annspecialcase_ = 'specialize:arg(5)'
diff --git a/pypy/objspace/std/sliceobject.py b/pypy/objspace/std/sliceobject.py
--- a/pypy/objspace/std/sliceobject.py
+++ b/pypy/objspace/std/sliceobject.py
@@ -4,7 +4,7 @@
 from pypy.interpreter import gateway
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.slicetype import eval_slice_index
+from pypy.objspace.std.slicetype import _eval_slice_index
 
 class W_SliceObject(W_Object):
     from pypy.objspace.std.slicetype import slice_typedef as typedef
@@ -25,7 +25,7 @@
         if space.is_w(w_slice.w_step, space.w_None):
             step = 1
         else:
-            step = eval_slice_index(space, w_slice.w_step)
+            step = _eval_slice_index(space, w_slice.w_step)
             if step == 0:
                 raise OperationError(space.w_ValueError,
                                      space.wrap("slice step cannot be zero"))
@@ -35,7 +35,7 @@
             else:
                 start = 0
         else:
-            start = eval_slice_index(space, w_slice.w_start)
+            start = _eval_slice_index(space, w_slice.w_start)
             if start < 0:
                 start += length
                 if start < 0:
@@ -54,7 +54,7 @@
             else:
                 stop = length
         else:
-            stop = eval_slice_index(space, w_slice.w_stop)
+            stop = _eval_slice_index(space, w_slice.w_stop)
             if stop < 0:
                 stop += length
                 if stop < 0:
diff --git a/pypy/objspace/std/slicetype.py b/pypy/objspace/std/slicetype.py
--- a/pypy/objspace/std/slicetype.py
+++ b/pypy/objspace/std/slicetype.py
@@ -3,6 +3,7 @@
 from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
 from pypy.objspace.std.register_all import register_all
 from pypy.interpreter.error import OperationError
+from pypy.rlib.objectmodel import specialize
 
 # indices multimehtod
 slice_indices = SMM('indices', 2,
@@ -14,7 +15,9 @@
                         ' normal slices.')
 
 # utility functions
-def eval_slice_index(space, w_int):
+def _eval_slice_index(space, w_int):
+    # note that it is the *callers* responsibility to check for w_None
+    # otherwise you can get funny error messages
     try:
         return space.getindex_w(w_int, None) # clamp if long integer too large
     except OperationError, err:
@@ -25,7 +28,7 @@
                                         "None or have an __index__ method"))
 
 def adapt_lower_bound(space, size, w_index):
-    index = eval_slice_index(space, w_index)
+    index = _eval_slice_index(space, w_index)
     if index < 0:
         index = index + size
         if index < 0:
@@ -34,16 +37,29 @@
     return index
 
 def adapt_bound(space, size, w_index):
-    index = eval_slice_index(space, w_index)
-    if index < 0:
-        index = index + size
-        if index < 0:
-            index = 0
+    index = adapt_lower_bound(space, size, w_index)
     if index > size:
         index = size
     assert index >= 0
     return index
 
+ at specialize.arg(4)
+def unwrap_start_stop(space, size, w_start, w_end, upper_bound=False):
+    if space.is_w(w_start, space.w_None):
+        start = 0
+    elif upper_bound:
+        start = adapt_bound(space, size, w_start)
+    else:
+        start = adapt_lower_bound(space, size, w_start)
+
+    if space.is_w(w_end, space.w_None):
+        end = size
+    elif upper_bound:
+        end = adapt_bound(space, size, w_end)
+    else:
+        end = adapt_lower_bound(space, size, w_end)
+    return start, end
+
 register_all(vars(), globals())
 
 # ____________________________________________________________
diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py
--- a/pypy/objspace/std/smalltupleobject.py
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -68,10 +68,10 @@
             raise IndexError
 
         def eq(self, space, w_other):
-            if self.length() != w_other.length():
+            if n != w_other.length():
                 return space.w_False
             for i in iter_n:
-                item1 = self.getitem(i)
+                item1 = getattr(self,'w_value%s' % i)
                 item2 = w_other.getitem(i)
                 if not space.eq_w(item1, item2):
                     return space.w_False
@@ -80,9 +80,9 @@
         def hash(self, space):
             mult = 1000003
             x = 0x345678
-            z = self.length()
+            z = n
             for i in iter_n:
-                w_item = self.getitem(i)
+                w_item = getattr(self, 'w_value%s' % i)
                 y = space.int_w(space.hash(w_item))
                 x = (x ^ y) * mult
                 z -= 1
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -4,7 +4,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter import gateway
 from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.objectmodel import we_are_translated, compute_hash
+from pypy.rlib.objectmodel import we_are_translated, compute_hash, specialize
 from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype, newformat
@@ -47,6 +47,7 @@
 W_StringObject.PREBUILT = [W_StringObject(chr(i)) for i in range(256)]
 del i
 
+ at specialize.arg(2)
 def _is_generic(space, w_self, fun):
     v = w_self._value
     if len(v) == 0:
@@ -56,14 +57,13 @@
         return space.newbool(fun(c))
     else:
         return _is_generic_loop(space, v, fun)
-_is_generic._annspecialcase_ = "specialize:arg(2)"
 
+ at specialize.arg(2)
 def _is_generic_loop(space, v, fun):
     for idx in range(len(v)):
         if not fun(v[idx]):
             return space.w_False
     return space.w_True
-_is_generic_loop._annspecialcase_ = "specialize:arg(2)"
 
 def _upper(ch):
     if ch.islower():
@@ -420,22 +420,14 @@
 
     return space.wrap(u_self)
 
-def _convert_idx_params(space, w_self, w_sub, w_start, w_end, upper_bound=False):
+ at specialize.arg(4)
+def _convert_idx_params(space, w_self, w_start, w_end, upper_bound=False):
     self = w_self._value
-    sub = w_sub._value
+    lenself = len(self)
 
-    if space.is_w(w_start, space.w_None):
-        w_start = space.wrap(0)
-    if space.is_w(w_end, space.w_None):
-        w_end = space.len(w_self)
-    if upper_bound:
-        start = slicetype.adapt_bound(space, len(self), w_start)
-        end = slicetype.adapt_bound(space, len(self), w_end)
-    else:
-        start = slicetype.adapt_lower_bound(space, len(self), w_start)
-        end = slicetype.adapt_lower_bound(space, len(self), w_end)
-    return (self, sub, start, end)
-_convert_idx_params._annspecialcase_ = 'specialize:arg(5)'
+    start, end = slicetype.unwrap_start_stop(
+            space, lenself, w_start, w_end, upper_bound=upper_bound)
+    return (self, start, end)
 
 def contains__String_String(space, w_self, w_sub):
     self = w_self._value
@@ -443,13 +435,13 @@
     return space.newbool(self.find(sub) >= 0)
 
 def str_find__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
-    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.find(sub, start, end)
+    (self, start, end) =  _convert_idx_params(space, w_self, w_start, w_end)
+    res = self.find(w_sub._value, start, end)
     return space.wrap(res)
 
 def str_rfind__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
-    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.rfind(sub, start, end)
+    (self, start, end) =  _convert_idx_params(space, w_self, w_start, w_end)
+    res = self.rfind(w_sub._value, start, end)
     return space.wrap(res)
 
 def str_partition__String_String(space, w_self, w_sub):
@@ -483,8 +475,8 @@
 
 
 def str_index__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
-    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.find(sub, start, end)
+    (self, start, end) =  _convert_idx_params(space, w_self, w_start, w_end)
+    res = self.find(w_sub._value, start, end)
     if res < 0:
         raise OperationError(space.w_ValueError,
                              space.wrap("substring not found in string.index"))
@@ -493,8 +485,8 @@
 
 
 def str_rindex__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
-    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.rfind(sub, start, end)
+    (self, start, end) =  _convert_idx_params(space, w_self, w_start, w_end)
+    res = self.rfind(w_sub._value, start, end)
     if res < 0:
         raise OperationError(space.w_ValueError,
                              space.wrap("substring not found in string.rindex"))
@@ -636,20 +628,17 @@
     return wrapstr(space, u_centered)
 
 def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end):
-    u_self, u_arg, u_start, u_end = _convert_idx_params(space, w_self, w_arg,
-                                                        w_start, w_end)
-    return wrapint(space, u_self.count(u_arg, u_start, u_end))
+    u_self, u_start, u_end = _convert_idx_params(space, w_self, w_start, w_end)
+    return wrapint(space, u_self.count(w_arg._value, u_start, u_end))
 
 def str_endswith__String_String_ANY_ANY(space, w_self, w_suffix, w_start, w_end):
-    (u_self, suffix, start, end) = _convert_idx_params(space, w_self,
-                                                       w_suffix, w_start,
-                                                       w_end, True)
-    return space.newbool(stringendswith(u_self, suffix, start, end))
+    (u_self, start, end) = _convert_idx_params(space, w_self, w_start,
+                                               w_end, True)
+    return space.newbool(stringendswith(u_self, w_suffix._value, start, end))
 
 def str_endswith__String_Tuple_ANY_ANY(space, w_self, w_suffixes, w_start, w_end):
-    (u_self, _, start, end) = _convert_idx_params(space, w_self,
-                                                  space.wrap(''), w_start,
-                                                  w_end, True)
+    (u_self, start, end) = _convert_idx_params(space, w_self, w_start,
+                                               w_end, True)
     for w_suffix in space.fixedview(w_suffixes):
         if space.isinstance_w(w_suffix, space.w_unicode):
             w_u = space.call_function(space.w_unicode, w_self)
@@ -661,14 +650,13 @@
     return space.w_False
 
 def str_startswith__String_String_ANY_ANY(space, w_self, w_prefix, w_start, w_end):
-    (u_self, prefix, start, end) = _convert_idx_params(space, w_self,
-                                                       w_prefix, w_start,
-                                                       w_end, True)
-    return space.newbool(stringstartswith(u_self, prefix, start, end))
+    (u_self, start, end) = _convert_idx_params(space, w_self, w_start,
+                                               w_end, True)
+    return space.newbool(stringstartswith(u_self, w_prefix._value, start, end))
 
 def str_startswith__String_Tuple_ANY_ANY(space, w_self, w_prefixes, w_start, w_end):
-    (u_self, _, start, end) = _convert_idx_params(space, w_self, space.wrap(''),
-                                                  w_start, w_end, True)
+    (u_self, start, end) = _convert_idx_params(space, w_self,
+                                               w_start, w_end, True)
     for w_prefix in space.fixedview(w_prefixes):
         if space.isinstance_w(w_prefix, space.w_unicode):
             w_u = space.call_function(space.w_unicode, w_self)
diff --git a/pypy/objspace/std/strsliceobject.py b/pypy/objspace/std/strsliceobject.py
--- a/pypy/objspace/std/strsliceobject.py
+++ b/pypy/objspace/std/strsliceobject.py
@@ -60,8 +60,8 @@
 def _convert_idx_params(space, w_self, w_sub, w_start, w_end):
     length = w_self.stop - w_self.start
     sub = w_sub._value
-    start = slicetype.adapt_bound(space, length, w_start)
-    end = slicetype.adapt_bound(space, length, w_end)
+    start, end = slicetype.unwrap_start_stop(
+            space, length, w_start, w_end, True)
 
     assert start >= 0
     assert end >= 0
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -2,11 +2,10 @@
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.interpreter.error import OperationError
 
-from pypy.conftest import gettestobjspace
+from pypy.conftest import gettestobjspace, option
 
 
 class TestW_ListObject(object):
-
     def test_is_true(self):
         w = self.space.wrap
         w_list = W_ListObject([])
@@ -343,6 +342,13 @@
 
 
 class AppTestW_ListObject(object):
+    def setup_class(cls):
+        import sys
+        on_cpython = (option.runappdirect and
+                            not hasattr(sys, 'pypy_translation_info'))
+
+        cls.w_on_cpython = cls.space.wrap(on_cpython)
+
     def test_call_list(self):
         assert list('') == []
         assert list('abc') == ['a', 'b', 'c']
@@ -616,6 +622,14 @@
         assert c.index(0) == 0
         raises(ValueError, c.index, 3)
 
+    def test_index_cpython_bug(self):
+        if self.on_cpython:
+            skip("cpython has a bug here")
+        c = list('hello world')
+        assert c.index('l', None, None) == 2
+        assert c.index('l', 3, None) == 3
+        assert c.index('l', None, 4) == 2
+
     def test_ass_slice(self):
         l = range(6)
         l[1:3] = 'abc'
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):
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -167,17 +167,8 @@
     return space.wrap(count)
 
 def tuple_index__Tuple_ANY_ANY_ANY(space, w_tuple, w_obj, w_start, w_stop):
-    start = slicetype.eval_slice_index(space, w_start)
-    stop = slicetype.eval_slice_index(space, w_stop)
     length = len(w_tuple.wrappeditems)
-    if start < 0:
-        start += length
-        if start < 0:
-            start = 0
-    if stop < 0:
-        stop += length
-        if stop < 0:
-            stop = 0
+    start, stop = slicetype.unwrap_start_stop(space, length, w_start, w_stop)
     for i in range(start, min(stop, length)):
         w_item = w_tuple.wrappeditems[i]
         if space.eq_w(w_item, w_obj):
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -10,7 +10,7 @@
 from pypy.objspace.std import slicetype, newformat
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
-from pypy.rlib.objectmodel import compute_hash
+from pypy.rlib.objectmodel import compute_hash, specialize
 from pypy.rlib.rstring import UnicodeBuilder
 from pypy.rlib.runicode import unicode_encode_unicode_escape
 from pypy.module.unicodedata import unicodedb
@@ -475,42 +475,29 @@
         index = length
     return index
 
-def _convert_idx_params(space, w_self, w_sub, w_start, w_end, upper_bound=False):
-    assert isinstance(w_sub, W_UnicodeObject)
+ at specialize.arg(4)
+def _convert_idx_params(space, w_self, w_start, w_end, upper_bound=False):
     self = w_self._value
-    sub = w_sub._value
-
-    if space.is_w(w_start, space.w_None):
-        w_start = space.wrap(0)
-    if space.is_w(w_end, space.w_None):
-        w_end = space.len(w_self)
-
-    if upper_bound:
-        start = slicetype.adapt_bound(space, len(self), w_start)
-        end = slicetype.adapt_bound(space, len(self), w_end)
-    else:
-        start = slicetype.adapt_lower_bound(space, len(self), w_start)
-        end = slicetype.adapt_lower_bound(space, len(self), w_end)
-    return (self, sub, start, end)
-_convert_idx_params._annspecialcase_ = 'specialize:arg(5)'
+    start, end = slicetype.unwrap_start_stop(
+            space, len(self), w_start, w_end, upper_bound)
+    return (self, start, end)
 
 def unicode_endswith__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
+    self, start, end = _convert_idx_params(space, w_self,
                                                    w_start, w_end, True)
-    return space.newbool(stringendswith(self, substr, start, end))
+    return space.newbool(stringendswith(self, w_substr._value, start, end))
 
 def unicode_startswith__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                                   w_start, w_end, True)
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end, True)
     # XXX this stuff can be waaay better for ootypebased backends if
     #     we re-use more of our rpython machinery (ie implement startswith
     #     with additional parameters as rpython)
-    return space.newbool(stringstartswith(self, substr, start, end))
+    return space.newbool(stringstartswith(self, w_substr._value, start, end))
 
 def unicode_startswith__Unicode_Tuple_ANY_ANY(space, w_unistr, w_prefixes,
                                               w_start, w_end):
-    unistr, _, start, end = _convert_idx_params(space, w_unistr, space.wrap(u''),
-                                                w_start, w_end, True)
+    unistr, start, end = _convert_idx_params(space, w_unistr,
+                                             w_start, w_end, True)
     for w_prefix in space.fixedview(w_prefixes):
         prefix = space.unicode_w(w_prefix)
         if stringstartswith(unistr, prefix, start, end):
@@ -519,7 +506,7 @@
 
 def unicode_endswith__Unicode_Tuple_ANY_ANY(space, w_unistr, w_suffixes,
                                             w_start, w_end):
-    unistr, _, start, end = _convert_idx_params(space, w_unistr, space.wrap(u''),
+    unistr, start, end = _convert_idx_params(space, w_unistr,
                                              w_start, w_end, True)
     for w_suffix in space.fixedview(w_suffixes):
         suffix = space.unicode_w(w_suffix)
@@ -625,37 +612,32 @@
     return space.newlist(lines)
 
 def unicode_find__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                                   w_start, w_end)
-    return space.wrap(self.find(substr, start, end))
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end)
+    return space.wrap(self.find(w_substr._value, start, end))
 
 def unicode_rfind__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                                   w_start, w_end)
-    return space.wrap(self.rfind(substr, start, end))
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end)
+    return space.wrap(self.rfind(w_substr._value, start, end))
 
 def unicode_index__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                                   w_start, w_end)
-    index = self.find(substr, start, end)
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end)
+    index = self.find(w_substr._value, start, end)
     if index < 0:
         raise OperationError(space.w_ValueError,
                              space.wrap('substring not found'))
     return space.wrap(index)
 
 def unicode_rindex__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                           w_start, w_end)
-    index = self.rfind(substr, start, end)
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end)
+    index = self.rfind(w_substr._value, start, end)
     if index < 0:
         raise OperationError(space.w_ValueError,
                              space.wrap('substring not found'))
     return space.wrap(index)
 
 def unicode_count__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end):
-    self, substr, start, end = _convert_idx_params(space, w_self, w_substr,
-                                                   w_start, w_end)
-    return space.wrap(self.count(substr, start, end))
+    self, start, end = _convert_idx_params(space, w_self, w_start, w_end)
+    return space.wrap(self.count(w_substr._value, start, end))
 
 def unicode_split__Unicode_None_ANY(space, w_self, w_none, w_maxsplit):
     maxsplit = space.int_w(w_maxsplit)


More information about the pypy-commit mailing list