[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