[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