[pypy-commit] pypy guard-compatible: merge default
cfbolz
pypy.commits at gmail.com
Wed Jun 22 06:17:59 EDT 2016
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r85324:914cc74b5a8c
Date: 2016-06-20 15:49 +0200
http://bitbucket.org/pypy/pypy/changeset/914cc74b5a8c/
Log: merge default
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -26,3 +26,4 @@
40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
c09c19272c990a0611b17569a0085ad1ab00c8ff release-pypy2.7-v5.3
+7e8df3df96417c16c2d55b41352ec82c9c69c978 release-pypy2.7-v5.3.1
diff --git a/lib_pypy/greenlet.egg-info b/lib_pypy/greenlet.egg-info
--- a/lib_pypy/greenlet.egg-info
+++ b/lib_pypy/greenlet.egg-info
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: greenlet
-Version: 0.4.9
+Version: 0.4.10
Summary: Lightweight in-process concurrent programming
Home-page: https://github.com/python-greenlet/greenlet
Author: Ralf Schmitt (for CPython), PyPy team
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -1,7 +1,7 @@
import sys
import _continuation
-__version__ = "0.4.9"
+__version__ = "0.4.10"
# ____________________________________________________________
# Exceptions
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -315,13 +315,28 @@
- ``complex``
+ - ``str`` (empty or single-character strings only)
+
+ - ``unicode`` (empty or single-character strings only)
+
+ - ``tuple`` (empty tuples only)
+
+ - ``frozenset`` (empty frozenset only)
+
This change requires some changes to ``id`` as well. ``id`` fulfills the
following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
above types will return a value that is computed from the argument, and can
thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
-Notably missing from the list above are ``str`` and ``unicode``. If your
-code relies on comparing strings with ``is``, then it might break in PyPy.
+Note that strings of length 2 or greater can be equal without being
+identical. Similarly, ``x is (2,)`` is not necessarily true even if
+``x`` contains a tuple and ``x == (2,)``. The uniqueness rules apply
+only to the particular cases described above. The ``str``, ``unicode``,
+``tuple`` and ``frozenset`` rules were added in PyPy 5.4; before that, a
+test like ``if x is "?"`` or ``if x is ()`` could fail even if ``x`` was
+equal to ``"?"`` or ``()``. The new behavior added in PyPy 5.4 is
+closer to CPython's, which caches precisely the empty tuple/frozenset,
+and (generally but not always) the strings and unicodes of length <= 1.
Note that for floats there "``is``" only one object per "bit pattern"
of the float. So ``float('nan') is float('nan')`` is true on PyPy,
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
.. toctree::
+ release-pypy2.7-v5.3.1.rst
release-pypy2.7-v5.3.0.rst
release-5.1.1.rst
release-5.1.0.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
.. toctree::
whatsnew-head.rst
+ whatsnew-pypy2-5.3.1.rst
whatsnew-pypy2-5.3.0.rst
whatsnew-5.1.0.rst
whatsnew-5.0.0.rst
diff --git a/pypy/doc/release-pypy2.7-v5.3.1.rst b/pypy/doc/release-pypy2.7-v5.3.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy2.7-v5.3.1.rst
@@ -0,0 +1,41 @@
+==========
+PyPy 5.3.1
+==========
+
+We have released a bugfix for PyPy2.7-v5.3.0, released last week,
+due to issues_ reported by users.
+
+Thanks to those who reported the issues.
+
+.. _issues: http://doc.pypy.org/en/latest/whatsnew-pypy2-5.3.1.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other
+`dynamic languages`_ to see what RPython can do for them.
+
+This release supports:
+
+ * **x86** machines on most common operating systems
+ (Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, FreeBSD),
+
+ * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+ * big- and little-endian variants of **PPC64** running Linux,
+
+ * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,6 +5,10 @@
.. this is a revision shortly after release-pypy2.7-v5.3
.. startrev: 873218a739f1
+.. 418b05f95db5
+Improve CPython compatibility for ``is``. Now code like ``if x is ():``
+works the same way as it does on CPython. See http://pypy.readthedocs.io/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id .
+
.. pull request #455
Add sys.{get,set}dlopenflags, for cpyext extensions.
@@ -31,3 +35,5 @@
Simplify handling of interp-level tests and make it more forward-
compatible.
+.. branch: pyfile-tell
+Sync w_file with the c-level FILE* before returning FILE* in PyFile_AsFile
diff --git a/pypy/doc/whatsnew-pypy2-5.3.1.rst b/pypy/doc/whatsnew-pypy2-5.3.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.3.1.rst
@@ -0,0 +1,15 @@
+===========================
+What's new in PyPy2.7 5.3.1
+===========================
+
+.. this is a revision shortly after release-pypy2.7-v5.3.0
+.. startrev: f4d726d1a010
+
+
+A bug-fix release, merging these changes:
+
+ * Add include guards to pymem.h, fixes issue #2321
+
+ * Make vmprof build on OpenBSD, from pull request #456
+
+ * Fix ``bytearray('').replace('a', 'ab')``, issue #2324
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,8 +29,8 @@
#define PY_VERSION "2.7.10"
/* PyPy version as a string */
-#define PYPY_VERSION "5.3.1-alpha0"
-#define PYPY_VERSION_NUM 0x05030100
+#define PYPY_VERSION "5.3.2-alpha0"
+#define PYPY_VERSION_NUM 0x05030200
/* Defined to mean a PyPy where cpyext holds more regular references
to PyObjects, e.g. staying alive as long as the internal PyPy object
diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
--- a/pypy/module/cpyext/pyfile.py
+++ b/pypy/module/cpyext/pyfile.py
@@ -55,6 +55,7 @@
if not PyFile_Check(space, w_p):
raise oefmt(space.w_IOError, 'first argument must be an open file')
assert isinstance(w_p, W_File)
+ w_p.stream.flush_buffers()
try:
fd = space.int_w(space.call_method(w_p, 'fileno'))
mode = w_p.mode
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -43,15 +43,6 @@
/* foo methods */
-static void
-foo_dealloc(fooobject *foop)
-{
- PyObject_Del(foop);
-}
-
-
-/* foo methods-as-attributes */
-
static PyObject *
foo_copy(fooobject *self)
{
@@ -195,7 +186,7 @@
sizeof(fooobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
- (destructor)foo_dealloc, /*tp_dealloc*/
+ 0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -463,9 +454,9 @@
PyTypeObject InitErrType = {
PyObject_HEAD_INIT(NULL)
0,
- "foo.InitErr",
- sizeof(PyObject),
- 0,
+ "foo.InitErrType",
+ sizeof(PyObject),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
@@ -508,12 +499,12 @@
0, /*tp_dictoffset*/
initerrtype_init, /*tp_init*/
- 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
+ 0, /*tp_alloc*/
0, /*tp_new*/
- 0, /*tp_free Low-level free-memory routine */
- 0, /*tp_is_gc For PyObject_IS_GC */
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
0, /*tp_bases*/
- 0, /*tp_mro method resolution order */
+ 0, /*tp_mro*/
0, /*tp_cache*/
0, /*tp_subclasses*/
0 /*tp_weaklist*/
diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py
--- a/pypy/module/cpyext/test/test_pyfile.py
+++ b/pypy/module/cpyext/test/test_pyfile.py
@@ -1,5 +1,7 @@
+from pypy.conftest import option
from pypy.module.cpyext.api import fopen, fclose, fwrite
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.object import Py_PRINT_RAW
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.tool.udir import udir
@@ -111,3 +113,34 @@
out, err = capfd.readouterr()
out = out.replace('\r\n', '\n')
assert out == " 1 23\n"
+
+
+class AppTestPyFile(AppTestCpythonExtensionBase):
+
+ def setup_class(cls):
+ from rpython.tool.udir import udir
+ if option.runappdirect:
+ cls.w_udir = str(udir)
+ else:
+ cls.w_udir = cls.space.wrap(str(udir))
+
+ def test_file_tell(self):
+ module = self.import_extension('foo', [
+ ("get_c_tell", "METH_O",
+ """
+ FILE * fp = PyFile_AsFile(args);
+ if (fp == NULL)
+ return PyLong_FromLong(0);
+ return PyLong_FromLong(ftell(fp));
+ """),
+ ])
+ filename = self.udir + "/_test_file"
+ with open(filename, 'w') as fid:
+ fid.write('3' * 122)
+ with open(filename, 'r') as fid:
+ s = fid.read(80)
+ t_py = fid.tell()
+ assert t_py == 80
+ t_c = module.get_c_tell(fid)
+ assert t_c == t_py
+
diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -142,6 +142,7 @@
ref = rffi.cast(PyTupleObject, ref)
size = ref.c_ob_size
if index < 0 or index >= size:
+ decref(space, py_obj)
raise oefmt(space.w_IndexError, "tuple assignment index out of range")
old_ref = ref.c_ob_item[index]
ref.c_ob_item[index] = py_obj # consumes a reference
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -163,14 +163,10 @@
guard_not_invalidated(descr=...)
i32 = float_ne(f31, 0.000000)
guard_true(i32, descr=...)
- i34 = getarrayitem_raw_i(#, #, descr=<ArrayU 1>) # XXX what are these?
- guard_value(i34, #, descr=...) # XXX don't appear in
- i35 = getarrayitem_raw_i(#, #, descr=<ArrayU 1>) # XXX equiv test_zjit
i36 = int_add(i24, 1)
i37 = int_add(i29, 8)
i38 = int_ge(i36, i30)
guard_false(i38, descr=...)
- guard_value(i35, #, descr=...) # XXX
jump(..., descr=...)
""")
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
#XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h
-PYPY_VERSION = (5, 3, 1, "alpha", 0) #XXX # sync patchlevel.h
+PYPY_VERSION = (5, 3, 2, "alpha", 0) #XXX # sync patchlevel.h
import pypy
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -17,6 +17,7 @@
from pypy.objspace.std.unicodeobject import (
decode_object, unicode_from_encoded_object,
unicode_from_string, getdefaultencoding)
+from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
class W_AbstractBytesObject(W_Root):
@@ -29,12 +30,26 @@
return True
if self.user_overridden_class or w_other.user_overridden_class:
return False
- return space.str_w(self) is space.str_w(w_other)
+ s1 = space.str_w(self)
+ s2 = space.str_w(w_other)
+ if len(s2) > 1:
+ return s1 is s2
+ else: # strings of len <= 1 are unique-ified
+ return s1 == s2
def immutable_unique_id(self, space):
if self.user_overridden_class:
return None
- return space.wrap(compute_unique_id(space.str_w(self)))
+ s = space.str_w(self)
+ if len(s) > 1:
+ uid = compute_unique_id(s)
+ else: # strings of len <= 1 are unique-ified
+ if len(s) == 1:
+ base = ord(s[0]) # base values 0-255
+ else:
+ base = 256 # empty string: base value 256
+ uid = (base << IDTAG_SHIFT) | IDTAG_SPECIAL
+ return space.wrap(uid)
def unicode_w(self, space):
# Use the default encoding.
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -6,6 +6,7 @@
from pypy.objspace.std.bytesobject import W_BytesObject
from pypy.objspace.std.intobject import W_IntObject
from pypy.objspace.std.unicodeobject import W_UnicodeObject
+from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
from rpython.rlib.objectmodel import r_dict
from rpython.rlib.objectmodel import iterkeys_with_hash, contains_with_hash
@@ -575,6 +576,23 @@
class W_FrozensetObject(W_BaseSetObject):
hash = 0
+ def is_w(self, space, w_other):
+ if not isinstance(w_other, W_FrozensetObject):
+ return False
+ if self is w_other:
+ return True
+ if self.user_overridden_class or w_other.user_overridden_class:
+ return False
+ # empty frozensets are unique-ified
+ return 0 == w_other.length() == self.length()
+
+ def immutable_unique_id(self, space):
+ if self.user_overridden_class or self.length() > 0:
+ return None
+ # empty frozenset: base value 259
+ uid = (259 << IDTAG_SHIFT) | IDTAG_SPECIAL
+ return space.wrap(uid)
+
def _newobj(self, space, w_iterable):
"""Make a new frozenset by taking ownership of 'w_iterable'."""
if type(self) is W_FrozensetObject:
diff --git a/pypy/objspace/std/stringmethods.py b/pypy/objspace/std/stringmethods.py
--- a/pypy/objspace/std/stringmethods.py
+++ b/pypy/objspace/std/stringmethods.py
@@ -162,7 +162,8 @@
buffer = _get_buffer(space, w_sub)
res = count(value, buffer, start, end)
- return space.wrap(max(res, 0))
+ assert res >= 0
+ return space.wrap(res)
def descr_decode(self, space, w_encoding=None, w_errors=None):
from pypy.objspace.std.unicodeobject import (
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -211,6 +211,7 @@
check(bytearray('abc').replace('b', bytearray('d')), 'adc')
check(bytearray('abc').replace('b', 'd'), 'adc')
+ check(bytearray('').replace('a', 'ab'), '')
check(bytearray('abc').upper(), 'ABC')
check(bytearray('ABC').lower(), 'abc')
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -186,17 +186,36 @@
def test_id_on_strs(self):
if self.appdirect:
skip("cannot run this test as apptest")
- u = u"a"
- assert id(self.unwrap_wrap_unicode(u)) == id(u)
- s = "a"
- assert id(self.unwrap_wrap_str(s)) == id(s)
+ for u in [u"", u"a", u"aa"]:
+ assert id(self.unwrap_wrap_unicode(u)) == id(u)
+ s = str(u)
+ assert id(self.unwrap_wrap_str(s)) == id(s)
+ #
+ assert id('') == (256 << 4) | 11 # always
+ assert id(u'') == (257 << 4) | 11
+ assert id('a') == (ord('a') << 4) | 11
+ assert id(u'\u1234') == ((~0x1234) << 4) | 11
+
+ def test_id_of_tuples(self):
+ l = []
+ x = (l,)
+ assert id(x) != id((l,)) # no caching at all
+ if self.appdirect:
+ skip("cannot run this test as apptest")
+ assert id(()) == (258 << 4) | 11 # always
+
+ def test_id_of_frozensets(self):
+ x = frozenset([4])
+ assert id(x) != id(frozenset([4])) # no caching at all
+ if self.appdirect:
+ skip("cannot run this test as apptest")
+ assert id(frozenset()) == (259 << 4) | 11 # always
+ assert id(frozenset([])) == (259 << 4) | 11 # always
def test_identity_vs_id_primitives(self):
- if self.cpython_apptest:
- skip("cpython behaves differently")
import sys
- l = range(-10, 10)
- for i in range(10):
+ l = range(-10, 10, 2)
+ for i in [0, 1, 3]:
l.append(float(i))
l.append(i + 0.1)
l.append(long(i))
@@ -206,18 +225,15 @@
l.append(i - 1j)
l.append(1 + i * 1j)
l.append(1 - i * 1j)
- s = str(i)
- l.append(s)
- u = unicode(s)
- l.append(u)
+ l.append((i,))
+ l.append(frozenset([i]))
l.append(-0.0)
l.append(None)
l.append(True)
l.append(False)
- s = "s"
- l.append(s)
- s = u"s"
- l.append(s)
+ l.append(())
+ l.append(tuple([]))
+ l.append(frozenset())
for i, a in enumerate(l):
for b in l[i:]:
@@ -228,21 +244,18 @@
def test_identity_vs_id_str(self):
if self.appdirect:
skip("cannot run this test as apptest")
- import sys
- l = range(-10, 10)
- for i in range(10):
- s = str(i)
+ l = []
+ def add(s, u):
l.append(s)
l.append(self.unwrap_wrap_str(s))
- u = unicode(s)
+ l.append(s[:1] + s[1:])
l.append(u)
l.append(self.unwrap_wrap_unicode(u))
- s = "s"
- l.append(s)
- l.append(self.unwrap_wrap_str(s))
- s = u"s"
- l.append(s)
- l.append(self.unwrap_wrap_unicode(s))
+ l.append(u[:1] + u[1:])
+ for i in range(3, 18):
+ add(str(i), unicode(i))
+ add("s", u"s")
+ add("", u"")
for i, a in enumerate(l):
for b in l[i:]:
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
@@ -9,7 +9,7 @@
from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.sliceobject import (W_SliceObject, unwrap_start_stop,
normalize_simple_slice)
-from pypy.objspace.std.util import negate
+from pypy.objspace.std.util import negate, IDTAG_SPECIAL, IDTAG_SHIFT
from rpython.rlib import jit
from rpython.rlib.debug import make_sure_not_resized
from rpython.rlib.rarithmetic import intmask
@@ -38,6 +38,23 @@
class W_AbstractTupleObject(W_Root):
__slots__ = ()
+ def is_w(self, space, w_other):
+ if not isinstance(w_other, W_AbstractTupleObject):
+ return False
+ if self is w_other:
+ return True
+ if self.user_overridden_class or w_other.user_overridden_class:
+ return False
+ # empty tuples are unique-ified
+ return 0 == w_other.length() == self.length()
+
+ def immutable_unique_id(self, space):
+ if self.user_overridden_class or self.length() > 0:
+ return None
+ # empty tuple: base value 258
+ uid = (258 << IDTAG_SHIFT) | IDTAG_SPECIAL
+ return space.wrap(uid)
+
def __repr__(self):
"""representation for debugging purposes"""
reprlist = [repr(w_item) for w_item in self.tolist()]
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
@@ -18,6 +18,7 @@
from pypy.objspace.std.basestringtype import basestring_typedef
from pypy.objspace.std.formatting import mod_format
from pypy.objspace.std.stringmethods import StringMethods
+from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
__all__ = ['W_UnicodeObject', 'wrapunicode', 'plain_str2unicode',
'encode_object', 'decode_object', 'unicode_from_object',
@@ -52,12 +53,26 @@
return True
if self.user_overridden_class or w_other.user_overridden_class:
return False
- return space.unicode_w(self) is space.unicode_w(w_other)
+ s1 = space.unicode_w(self)
+ s2 = space.unicode_w(w_other)
+ if len(s2) > 1:
+ return s1 is s2
+ else: # strings of len <= 1 are unique-ified
+ return s1 == s2
def immutable_unique_id(self, space):
if self.user_overridden_class:
return None
- return space.wrap(compute_unique_id(space.unicode_w(self)))
+ s = space.unicode_w(self)
+ if len(s) > 1:
+ uid = compute_unique_id(s)
+ else: # strings of len <= 1 are unique-ified
+ if len(s) == 1:
+ base = ~ord(s[0]) # negative base values
+ else:
+ base = 257 # empty unicode string: base value 257
+ uid = (base << IDTAG_SHIFT) | IDTAG_SPECIAL
+ return space.wrap(uid)
def str_w(self, space):
return space.str_w(space.str(self))
diff --git a/pypy/objspace/std/util.py b/pypy/objspace/std/util.py
--- a/pypy/objspace/std/util.py
+++ b/pypy/objspace/std/util.py
@@ -9,6 +9,12 @@
IDTAG_FLOAT = 5
IDTAG_COMPLEX = 7
IDTAG_METHOD = 9
+IDTAG_SPECIAL = 11 # -1 - (-maxunicode-1): unichar
+ # 0 - 255: char
+ # 256: empty string
+ # 257: empty unicode
+ # 258: empty tuple
+ # 259: empty frozenset
CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=')
BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>',
diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh
--- a/pypy/tool/release/repackage.sh
+++ b/pypy/tool/release/repackage.sh
@@ -1,9 +1,9 @@
# Edit these appropriately before running this script
maj=5
min=3
-rev=0
+rev=1
branchname=release-$maj.x # ==OR== release-$maj.$min.x
-tagname=release-pypy2.7-v$maj.$min # ==OR== release-$maj.$min
+tagname=release-pypy2.7-v$maj.$min.$rev # ==OR== release-$maj.$min
echo checking hg log -r $branchname
hg log -r $branchname || exit 1
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
@@ -2,7 +2,7 @@
import py
from rpython.jit.metainterp.optimizeopt.virtualstate import VirtualStateInfo,\
VStructStateInfo, LEVEL_CONSTANT,\
- VArrayStateInfo, NotVirtualStateInfo, VirtualState,\
+ VArrayStateInfo, not_virtual, VirtualState,\
GenerateGuardState, VirtualStatesCantMatch, VArrayStructStateInfo
from rpython.jit.metainterp.history import ConstInt, ConstPtr, TargetToken
from rpython.jit.metainterp.resoperation import InputArgInt, InputArgRef,\
@@ -31,10 +31,10 @@
def setup_class(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- self.knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ self.knownclass_info = not_virtual(self.cpu, 'r', value)
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- self.knownclass_info2 = NotVirtualStateInfo(self.cpu, 'r', value)
+ self.knownclass_info2 = not_virtual(self.cpu, 'r', value)
def guards(self, info1, info2, box, runtime_box, expected, inputargs=None):
if inputargs is None:
@@ -80,7 +80,7 @@
def test_make_inputargs(self):
optimizer = FakeOptimizer(self.cpu)
args = [InputArgInt()]
- info0 = NotVirtualStateInfo(self.cpu, args[0].type, None)
+ info0 = not_virtual(self.cpu, args[0].type, None)
vs = VirtualState([info0])
assert vs.make_inputargs(args, optimizer) == args
info0.level = LEVEL_CONSTANT
@@ -108,8 +108,8 @@
assert info1 in state.bad and info2 in state.bad
for BoxType in (InputArgInt, InputArgFloat, InputArgRef):
- info1 = NotVirtualStateInfo(self.cpu, BoxType.type, None)
- info2 = NotVirtualStateInfo(self.cpu, BoxType.type, None)
+ info1 = not_virtual(self.cpu, BoxType.type, None)
+ info2 = not_virtual(self.cpu, BoxType.type, None)
postest(info1, info2)
info1, info2 = VArrayStateInfo(42), VArrayStateInfo(42)
@@ -126,9 +126,9 @@
def test_NotVirtualStateInfo_generalization(self):
def isgeneral(tp1, info1, tp2, info2):
- info1 = NotVirtualStateInfo(self.cpu, tp1, info1)
+ info1 = not_virtual(self.cpu, tp1, info1)
info1.position = 0
- info2 = NotVirtualStateInfo(self.cpu, tp2, info2)
+ info2 = not_virtual(self.cpu, tp2, info2)
info2.position = 0
return VirtualState([info1]).generalization_of(VirtualState([info2]), FakeOptimizer(self.cpu))
@@ -166,8 +166,8 @@
assert not isgeneral('r', value1, 'r', value2)
def test_field_matching_generalization(self):
- const1 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(1))
- const2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(2))
+ const1 = not_virtual(self.cpu, 'i', ConstIntBound(1))
+ const2 = not_virtual(self.cpu, 'i', ConstIntBound(2))
const1.position = const2.position = 1
self.check_invalid(const1, const2)
self.check_invalid(const2, const1)
@@ -192,16 +192,16 @@
def test_known_class_generalization(self):
knownclass1 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
- info1 = NotVirtualStateInfo(self.cpu, 'r', knownclass1)
+ info1 = not_virtual(self.cpu, 'r', knownclass1)
info1.position = 0
knownclass2 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
- info2 = NotVirtualStateInfo(self.cpu, 'r', knownclass2)
+ info2 = not_virtual(self.cpu, 'r', knownclass2)
info2.position = 0
self.check_no_guards(info1, info2)
self.check_no_guards(info2, info1)
knownclass3 = info.InstancePtrInfo(None, ConstPtr(self.myptr2))
- info3 = NotVirtualStateInfo(self.cpu, 'r', knownclass3)
+ info3 = not_virtual(self.cpu, 'r', knownclass3)
info3.position = 0
self.check_invalid(info1, info3)
self.check_invalid(info2, info3)
@@ -222,26 +222,26 @@
#unknown_val = PtrOptValue(self.nodebox)
#unknownnull_val = PtrOptValue(BoxPtr(self.nullptr))
opt = FakeOptimizer(self.cpu)
- unknown_info = NotVirtualStateInfo(self.cpu, 'r', None)
+ unknown_info = not_virtual(self.cpu, 'r', None)
- nonnull_info = NotVirtualStateInfo(self.cpu, 'r', info.NonNullPtrInfo())
+ nonnull_info = not_virtual(self.cpu, 'r', info.NonNullPtrInfo())
classbox1 = self.cpu.ts.cls_of_box(ConstPtr(self.nodeaddr))
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r',
- info.InstancePtrInfo(None, classbox1))
+ knownclass_info = not_virtual(self.cpu, 'r',
+ info.InstancePtrInfo(None, classbox1))
classbox2 = self.cpu.ts.cls_of_box(ConstPtr(self.node2addr))
- knownclass2_info = NotVirtualStateInfo(self.cpu, 'r',
- info.InstancePtrInfo(None, classbox2))
+ knownclass2_info = not_virtual(self.cpu, 'r',
+ info.InstancePtrInfo(None, classbox2))
- constant_info = NotVirtualStateInfo(self.cpu, 'i',
- ConstIntBound(1))
- constant_ptr_info = NotVirtualStateInfo(self.cpu, 'r',
+ constant_info = not_virtual(self.cpu, 'i',
+ ConstIntBound(1))
+ constant_ptr_info = not_virtual(self.cpu, 'r',
info.ConstPtrInfo(ConstPtr(self.nodeaddr)))
constclass_val = info.ConstPtrInfo(ConstPtr(self.nodeaddr))
- constclass_info = NotVirtualStateInfo(self.cpu, 'r', constclass_val)
- constclass2_info = NotVirtualStateInfo(self.cpu, 'r',
+ constclass_info = not_virtual(self.cpu, 'r', constclass_val)
+ constclass2_info = not_virtual(self.cpu, 'r',
info.ConstPtrInfo(ConstPtr(self.node2addr)))
- constantnull_info = NotVirtualStateInfo(self.cpu, 'r',
+ constantnull_info = not_virtual(self.cpu, 'r',
info.ConstPtrInfo(ConstPtr(self.nullptr)))
# unknown unknown
@@ -260,9 +260,10 @@
self.check_no_guards(unknown_info, knownclass_info)
# unknown constant
- self.check_no_guards(unknown_info, constant_info,
+ unknown_info_int = not_virtual(self.cpu, 'i', None)
+ self.check_no_guards(unknown_info_int, constant_info,
ConstInt(1), ConstIntBound(1))
- self.check_no_guards(unknown_info, constant_info)
+ self.check_no_guards(unknown_info_int, constant_info)
# nonnull unknown
@@ -293,11 +294,11 @@
const_nonnull = ConstPtr(self.nodeaddr)
const_nonnull2 = ConstPtr(self.node2addr)
const_null = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
- self.check_no_guards(nonnull_info, constant_info, const_nonnull,
+ self.check_no_guards(nonnull_info, constant_ptr_info, const_nonnull,
info.ConstPtrInfo(const_nonnull))
self.check_invalid(nonnull_info, constantnull_info, const_null,
info.ConstPtrInfo(const_null))
- self.check_no_guards(nonnull_info, constant_info)
+ self.check_no_guards(nonnull_info, constant_ptr_info)
self.check_invalid(nonnull_info, constantnull_info)
@@ -392,8 +393,8 @@
value1 = IntUnbounded()
value1.make_ge(IntBound(0, 10))
value1.make_le(IntBound(20, 30))
- info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
- info2 = NotVirtualStateInfo(self.cpu, 'i', IntUnbounded())
+ info1 = not_virtual(self.cpu, 'i', value1)
+ info2 = not_virtual(self.cpu, 'i', IntUnbounded())
expected = """
[i0]
i1 = int_ge(i0, 0)
@@ -408,18 +409,18 @@
value1 = IntUnbounded()
value1.make_ge(IntBound(0, 10))
value1.make_le(IntBound(20, 30))
- info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
- info2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(10000))
+ info1 = not_virtual(self.cpu, 'i', value1)
+ info2 = not_virtual(self.cpu, 'i', ConstIntBound(10000))
self.check_invalid(info1, info2)
- info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
- info2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(11))
+ info1 = not_virtual(self.cpu, 'i', value1)
+ info2 = not_virtual(self.cpu, 'i', ConstIntBound(11))
self.check_no_guards(info1, info2)
def test_known_class(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value1 = info.InstancePtrInfo(None, classbox)
- info1 = NotVirtualStateInfo(self.cpu, 'r', value1)
- info2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ info1 = not_virtual(self.cpu, 'r', value1)
+ info2 = not_virtual(self.cpu, 'r', None)
expected = """
[p0]
guard_nonnull_class(p0, ConstClass(node_vtable)) []
@@ -456,18 +457,18 @@
def test_equal_inputargs(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
vstate1 = VirtualState([knownclass_info, knownclass_info])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
- unknown_info1 = NotVirtualStateInfo(self.cpu, 'r', None)
+ unknown_info1 = not_virtual(self.cpu, 'r', None)
vstate2 = VirtualState([unknown_info1, unknown_info1])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
- unknown_info1 = NotVirtualStateInfo(self.cpu, 'r', None)
- unknown_info2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ unknown_info1 = not_virtual(self.cpu, 'r', None)
+ unknown_info2 = not_virtual(self.cpu, 'r', None)
vstate3 = VirtualState([unknown_info1, unknown_info2])
assert vstate3.generalization_of(vstate2, FakeOptimizer(self.cpu))
assert vstate3.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -494,9 +495,9 @@
def test_generate_guards_on_virtual_fields_matches_array(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
innervalue1 = info.InstancePtrInfo(None, classbox)
- innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
+ innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
innerinfo1.position = 1
- innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ innerinfo2 = not_virtual(self.cpu, 'r', None)
innerinfo2.position = 1
descr = ArrayDescr(lltype.GcArray(llmemory.GCREF), self.cpu)
@@ -524,9 +525,9 @@
def test_generate_guards_on_virtual_fields_matches_instance(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
innervalue1 = info.InstancePtrInfo(None, classbox)
- innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
+ innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
innerinfo1.position = 1
- innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ innerinfo2 = not_virtual(self.cpu, 'r', None)
innerinfo2.position = 1
info1 = VirtualStateInfo(ConstInt(42), [self.nextdescr])
@@ -552,9 +553,9 @@
def test_generate_guards_on_virtual_fields_matches_struct(self):
constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
innervalue1 = info.InstancePtrInfo(None, constclassbox)
- innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
+ innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
innerinfo1.position = 1
- innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ innerinfo2 = not_virtual(self.cpu, 'r', None)
innerinfo2.position = 1
structdescr = self.nodesize
@@ -583,9 +584,9 @@
def test_generate_guards_on_virtual_fields_matches_arraystruct(self):
constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
innervalue1 = info.InstancePtrInfo(None, constclassbox)
- innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
+ innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
innerinfo1.position = 1
- innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
+ innerinfo2 = not_virtual(self.cpu, 'r', None)
innerinfo2.position = 1
NODE = lltype.Struct('NODE', ('x', llmemory.GCREF))
@@ -627,7 +628,7 @@
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
info2 = VirtualStateInfo(ConstInt(42), [1, 2])
- unknown_info1 = NotVirtualStateInfo(self.cpu, 'r',
+ unknown_info1 = not_virtual(self.cpu, 'r',
info.InstancePtrInfo())
info2.fieldstate = [unknown_info1, unknown_info1]
vstate2 = VirtualState([info2])
@@ -636,9 +637,9 @@
assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
info3 = VirtualStateInfo(ConstInt(42), [1, 2])
- unknown_info1 = NotVirtualStateInfo(self.cpu, 'r',
+ unknown_info1 = not_virtual(self.cpu, 'r',
info.InstancePtrInfo())
- unknown_info2 = NotVirtualStateInfo(self.cpu, 'r',
+ unknown_info2 = not_virtual(self.cpu, 'r',
info.InstancePtrInfo())
info3.fieldstate = [unknown_info1, unknown_info2]
vstate3 = VirtualState([info3])
@@ -651,7 +652,7 @@
info1 = VirtualStateInfo(ConstInt(42), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -659,7 +660,7 @@
info2 = VirtualStateInfo(ConstInt(42), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info2.fieldstate = [knownclass_info, knownclass_info]
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
@@ -671,7 +672,7 @@
info1 = VirtualStateInfo(ConstInt(42), [10, 20])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -679,7 +680,7 @@
info2 = VirtualStateInfo(ConstInt(42), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info2.fieldstate = [knownclass_info, knownclass_info]
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
@@ -691,7 +692,7 @@
info1 = VirtualStateInfo(ConstInt(42), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -699,24 +700,24 @@
info2 = VirtualStateInfo(ConstInt(7), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info2.fieldstate = [knownclass_info, knownclass_info]
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
-
+
def test_nonvirtual_is_not_virtual(self):
info1 = VirtualStateInfo(ConstInt(42), [1, 2])
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
- info2 = NotVirtualStateInfo(self.cpu, 'r', value)
+ info2 = not_virtual(self.cpu, 'r', value)
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
@@ -727,7 +728,7 @@
info1 = VArrayStateInfo(42)
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -735,7 +736,7 @@
info2 = VArrayStateInfo(42)
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info2.fieldstate = [knownclass_info, knownclass_info]
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
@@ -747,7 +748,7 @@
info1 = VArrayStateInfo(42)
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info1.fieldstate = [knownclass_info, knownclass_info]
vstate1 = VirtualState([info1])
assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
@@ -755,7 +756,7 @@
info2 = VArrayStateInfo(42)
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
value = info.InstancePtrInfo(None, classbox)
- knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
+ knownclass_info = not_virtual(self.cpu, 'r', value)
info2.fieldstate = [knownclass_info]
vstate2 = VirtualState([info2])
assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
@@ -793,7 +794,7 @@
def test_crash_varay_clear(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
innervalue1 = info.InstancePtrInfo(None, classbox)
- innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
+ innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
innerinfo1.position = 1
innerinfo1.position_in_notvirtuals = 0
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -350,40 +350,23 @@
def debug_header(self, indent):
debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position)
+
+def not_virtual(cpu, type, info):
+ if type == 'i':
+ return NotVirtualStateInfoInt(cpu, type, info)
+ if type == 'r':
+ return NotVirtualStateInfoPtr(cpu, type, info)
+ return NotVirtualStateInfo(cpu, type, info)
+
+
class NotVirtualStateInfo(AbstractVirtualStateInfo):
- lenbound = None
- intbound = None
level = LEVEL_UNKNOWN
constbox = None
- known_class = None
-
+
def __init__(self, cpu, type, info):
if info and info.is_constant():
self.level = LEVEL_CONSTANT
self.constbox = info.getconst()
- if type == 'r':
- self.known_class = info.get_known_class(cpu)
- elif type == 'i':
- self.intbound = info
- elif type == 'r':
- if info:
- self.known_class = info.get_known_class(cpu)
- if self.known_class:
- self.level = LEVEL_KNOWNCLASS
- elif info.is_nonnull():
- self.level = LEVEL_NONNULL
- self.lenbound = info.getlenbound(None)
- elif type == 'i':
- if isinstance(info, IntBound):
- if info.lower < MININT / 2:
- info.lower = MININT
- if info.upper > MAXINT / 2:
- info.upper = MAXINT
- self.intbound = info
- elif type == 'f':
- if info and info.is_constant():
- self.level = LEVEL_CONSTANT
- self.constbox = info.getconst()
def is_const(self):
return self.constbox is not None
@@ -394,84 +377,15 @@
def _generate_guards(self, other, box, runtime_box, state):
# XXX This will always retrace instead of forcing anything which
# might be what we want sometimes?
- if not isinstance(other, NotVirtualStateInfo):
- raise VirtualStatesCantMatch(
- 'The VirtualStates does not match as a ' +
- 'virtual appears where a pointer is needed ' +
- 'and it is too late to force it.')
-
-
extra_guards = state.extra_guards
- cpu = state.cpu
- if self.lenbound:
- if other.lenbound is None:
- other_bound = IntLowerBound(0)
- else:
- other_bound = other.lenbound
- if not self.lenbound.contains_bound(other_bound):
- raise VirtualStatesCantMatch("length bound does not match")
-
if self.level == LEVEL_UNKNOWN:
- # confusingly enough, this is done also for pointers
- # which have the full range as the "bound", so it always works
- return self._generate_guards_intbounds(other, box, runtime_box,
- extra_guards,
- state.optimizer)
-
- # the following conditions often peek into the runtime value that the
- # box had when tracing. This value is only used as an educated guess.
- # It is used here to choose between either emitting a guard and jumping
- # to an existing compiled loop or retracing the loop. Both alternatives
- # will always generate correct behaviour, but performance will differ.
- elif self.level == LEVEL_NONNULL:
- if other.level == LEVEL_UNKNOWN:
- if runtime_box is not None and runtime_box.nonnull():
- op = ResOperation(rop.GUARD_NONNULL, [box])
- extra_guards.append(op)
- return
- else:
- raise VirtualStatesCantMatch("other not known to be nonnull")
- elif other.level == LEVEL_NONNULL:
- return
- elif other.level == LEVEL_KNOWNCLASS:
- return # implies nonnull
- else:
- assert other.level == LEVEL_CONSTANT
- assert other.constbox
- if not other.constbox.nonnull():
- raise VirtualStatesCantMatch("constant is null")
- return
-
- elif self.level == LEVEL_KNOWNCLASS:
- if other.level == LEVEL_UNKNOWN:
- if (runtime_box and runtime_box.nonnull() and
- self.known_class.same_constant(cpu.ts.cls_of_box(runtime_box))):
- op = ResOperation(rop.GUARD_NONNULL_CLASS, [box, self.known_class])
- extra_guards.append(op)
- return
- else:
- raise VirtualStatesCantMatch("other's class is unknown")
- elif other.level == LEVEL_NONNULL:
- if (runtime_box and self.known_class.same_constant(
- cpu.ts.cls_of_box(runtime_box))):
- op = ResOperation(rop.GUARD_CLASS, [box, self.known_class])
- extra_guards.append(op)
- return
- else:
- raise VirtualStatesCantMatch("other's class is unknown")
- elif other.level == LEVEL_KNOWNCLASS:
- if self.known_class.same_constant(other.known_class):
- return
- raise VirtualStatesCantMatch("classes don't match")
- else:
- assert other.level == LEVEL_CONSTANT
- if (other.constbox.nonnull() and
- self.known_class.same_constant(cpu.ts.cls_of_box(other.constbox))):
- return
- else:
- raise VirtualStatesCantMatch("classes don't match")
-
+ return self._generate_guards_unkown(other, box, runtime_box,
+ extra_guards,
+ state)
else:
+ if not isinstance(other, NotVirtualStateInfo):
+ raise VirtualStatesCantMatch(
+ 'comparing a constant against something that is a virtual')
assert self.level == LEVEL_CONSTANT
if other.level == LEVEL_CONSTANT:
if self.constbox.same_constant(other.constbox):
@@ -485,19 +399,9 @@
raise VirtualStatesCantMatch("other not constant")
assert 0, "unreachable"
- def _generate_guards_intbounds(self, other, box, runtime_box, extra_guards,
- optimizer):
- if self.intbound is None:
- return
- if self.intbound.contains_bound(other.intbound):
- return
- if (runtime_box is not None and
- self.intbound.contains(runtime_box.getint())):
- # this may generate a few more guards than needed, but they are
- # optimized away when emitting them
- self.intbound.make_guards(box, extra_guards, optimizer)
- return
- raise VirtualStatesCantMatch("intbounds don't match")
+ def _generate_guards_unkown(self, other, box, runtime_box, extra_guards,
+ state):
+ return
def enum_forced_boxes(self, boxes, box, optimizer, force_boxes=False):
if self.level == LEVEL_CONSTANT:
@@ -553,8 +457,145 @@
if self.lenbound:
lb = ', ' + self.lenbound.bound.__repr__()
- debug_print(indent + mark + 'NotVirtualInfo(%d' % self.position +
- ', ' + l + ', ' + self.intbound.__repr__() + lb + ')')
+ result = indent + mark + 'NotVirtualStateInfo(%d' % self.position + ', ' + l
+ extra = self._extra_repr()
+ if extra:
+ result += ', ' + extra
+ result += lb + ')'
+ debug_print(result)
+
+class NotVirtualStateInfoInt(NotVirtualStateInfo):
+ intbound = None
+
+ def __init__(self, cpu, type, info):
+ NotVirtualStateInfo.__init__(self, cpu, type, info)
+ assert type == 'i'
+ if isinstance(info, IntBound):
+ if info.lower < MININT / 2:
+ info.lower = MININT
+ if info.upper > MAXINT / 2:
+ info.upper = MAXINT
+ self.intbound = info
+
+ def _generate_guards_unkown(self, other, box, runtime_box, extra_guards,
+ optimizer):
+ other_intbound = None
+ if isinstance(other, NotVirtualStateInfoInt):
+ other_intbound = other.intbound
+ if self.intbound is None:
+ return
+ if self.intbound.contains_bound(other_intbound):
+ return
+ if (runtime_box is not None and
+ self.intbound.contains(runtime_box.getint())):
+ # this may generate a few more guards than needed, but they are
+ # optimized away when emitting them
+ self.intbound.make_guards(box, extra_guards, optimizer)
+ return
+ raise VirtualStatesCantMatch("intbounds don't match")
+
+ def _extra_repr(self):
+ return self.intbound.__repr__()
+
+
+class NotVirtualStateInfoPtr(NotVirtualStateInfo):
+ lenbound = None
+ known_class = None
+
+ def __init__(self, cpu, type, info):
+ if info:
+ self.known_class = info.get_known_class(cpu)
+ if self.known_class:
+ self.level = LEVEL_KNOWNCLASS
+ elif info.is_nonnull():
+ self.level = LEVEL_NONNULL
+ self.lenbound = info.getlenbound(None)
+ # might set it to LEVEL_CONSTANT
+ NotVirtualStateInfo.__init__(self, cpu, type, info)
+
+ def _generate_guards(self, other, box, runtime_box, state):
+ if not isinstance(other, NotVirtualStateInfoPtr):
+ raise VirtualStatesCantMatch(
+ 'The VirtualStates does not match as a ' +
+ 'virtual appears where a pointer is needed ' +
+ 'and it is too late to force it.')
+ extra_guards = state.extra_guards
+ if self.lenbound:
+ if other.lenbound is None:
+ other_bound = IntLowerBound(0)
+ else:
+ other_bound = other.lenbound
+ if not self.lenbound.contains_bound(other_bound):
+ raise VirtualStatesCantMatch("length bound does not match")
+ if self.level == LEVEL_NONNULL:
+ return self._generate_guards_nonnull(other, box, runtime_box,
+ extra_guards,
+ state)
+ elif self.level == LEVEL_KNOWNCLASS:
+ return self._generate_guards_knownclass(other, box, runtime_box,
+ extra_guards,
+ state)
+ return NotVirtualStateInfo._generate_guards(self, other, box,
+ runtime_box, state)
+
+
+ # the following methods often peek into the runtime value that the
+ # box had when tracing. This value is only used as an educated guess.
+ # It is used here to choose between either emitting a guard and jumping
+ # to an existing compiled loop or retracing the loop. Both alternatives
+ # will always generate correct behaviour, but performance will differ.
+
+ def _generate_guards_nonnull(self, other, box, runtime_box, extra_guards,
+ state):
+ if not isinstance(other, NotVirtualStateInfoPtr):
+ raise VirtualStatesCantMatch('trying to match ptr with non-ptr??!')
+ if other.level == LEVEL_UNKNOWN:
+ if runtime_box is not None and runtime_box.nonnull():
+ op = ResOperation(rop.GUARD_NONNULL, [box])
+ extra_guards.append(op)
+ return
+ else:
+ raise VirtualStatesCantMatch("other not known to be nonnull")
+ elif other.level == LEVEL_NONNULL:
+ pass
+ elif other.level == LEVEL_KNOWNCLASS:
+ pass # implies nonnull
+ else:
+ assert other.level == LEVEL_CONSTANT
+ assert other.constbox
+ if not other.constbox.nonnull():
+ raise VirtualStatesCantMatch("constant is null")
+
+ def _generate_guards_knownclass(self, other, box, runtime_box, extra_guards,
+ state):
+ cpu = state.cpu
+ if not isinstance(other, NotVirtualStateInfoPtr):
+ raise VirtualStatesCantMatch('trying to match ptr with non-ptr??!')
+ if other.level == LEVEL_UNKNOWN:
+ if (runtime_box and runtime_box.nonnull() and
+ self.known_class.same_constant(cpu.ts.cls_of_box(runtime_box))):
+ op = ResOperation(rop.GUARD_NONNULL_CLASS, [box, self.known_class])
+ extra_guards.append(op)
+ else:
+ raise VirtualStatesCantMatch("other's class is unknown")
+ elif other.level == LEVEL_NONNULL:
+ if (runtime_box and self.known_class.same_constant(
+ cpu.ts.cls_of_box(runtime_box))):
+ op = ResOperation(rop.GUARD_CLASS, [box, self.known_class])
+ extra_guards.append(op)
+ else:
+ raise VirtualStatesCantMatch("other's class is unknown")
+ elif other.level == LEVEL_KNOWNCLASS:
+ if self.known_class.same_constant(other.known_class):
+ return
+ raise VirtualStatesCantMatch("classes don't match")
+ else:
+ assert other.level == LEVEL_CONSTANT
+ if (other.constbox.nonnull() and
+ self.known_class.same_constant(cpu.ts.cls_of_box(other.constbox))):
+ pass
+ else:
+ raise VirtualStatesCantMatch("classes don't match")
class VirtualState(object):
@@ -678,8 +719,8 @@
return VirtualState(state)
def visit_not_virtual(self, box):
- return NotVirtualStateInfo(self.optimizer.cpu, box.type,
- self.optimizer.getinfo(box))
+ return not_virtual(self.optimizer.cpu, box.type,
+ self.optimizer.getinfo(box))
def visit_virtual(self, descr, fielddescrs):
known_class = ConstInt(descr.get_vtable())
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -291,6 +291,7 @@
return _search(value, other, start, end, SEARCH_COUNT)
# -------------- substring searching helper ----------------
+# XXX a lot of code duplication with lltypesystem.rstr :-(
SEARCH_COUNT = 0
SEARCH_FIND = 1
@@ -309,6 +310,8 @@
if end > len(value):
end = len(value)
if start > end:
+ if mode == SEARCH_COUNT:
+ return 0
return -1
count = 0
@@ -326,6 +329,8 @@
w = n - m
if w < 0:
+ if mode == SEARCH_COUNT:
+ return 0
return -1
mlast = m - 1
@@ -570,18 +575,20 @@
class ByteListBuilder(object):
def __init__(self, init_size=INIT_SIZE):
+ assert init_size >= 0
self.l = newlist_hint(init_size)
@specialize.argtype(1)
def append(self, s):
+ l = self.l
for c in s:
- self.l.append(c)
+ l.append(c)
@specialize.argtype(1)
def append_slice(self, s, start, end):
- assert 0 <= start <= end <= len(s)
- for c in s[start:end]:
- self.l.append(c)
+ l = self.l
+ for i in xrange(start, end):
+ l.append(s[i])
def append_multiple_char(self, c, times):
assert isinstance(c, str)
@@ -589,8 +596,9 @@
def append_charpsize(self, s, size):
assert size >= 0
+ l = self.l
for i in xrange(size):
- self.l.append(s[i])
+ l.append(s[i])
def build(self):
return self.l
diff --git a/rpython/rlib/test/test_rstring.py b/rpython/rlib/test/test_rstring.py
--- a/rpython/rlib/test/test_rstring.py
+++ b/rpython/rlib/test/test_rstring.py
@@ -231,6 +231,10 @@
check_search(count, 'one two three', 'e', 0, 1, res=0)
check_search(count, 'one two three', '', 0, 13, res=14)
+ check_search(count, '', 'ab', 0, 0, res=0)
+ check_search(count, 'a', 'ab', 0, 1, res=0)
+ check_search(count, 'ac', 'ab', 0, 2, res=0)
+
class TestTranslates(BaseRtypingTest):
def test_split_rsplit(self):
diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py
--- a/rpython/rtyper/test/test_rstr.py
+++ b/rpython/rtyper/test/test_rstr.py
@@ -972,6 +972,13 @@
s.count(s, -10)
py.test.raises(AnnotatorError, self.interpret, f, ())
+ def test_count_in_empty_string(self):
+ const = self.const
+ def fn():
+ return const('').count(const('ab'))
+ res = self.interpret(fn, [])
+ assert res == 0
+
def test_getitem_exc(self):
const = self.const
def f(x):
More information about the pypy-commit
mailing list