[pypy-commit] pypy fix-sre-problems: merge default
cfbolz
pypy.commits at gmail.com
Wed Mar 28 03:24:48 EDT 2018
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: fix-sre-problems
Changeset: r94152:f034b1d5a9e9
Date: 2018-03-28 09:24 +0200
http://bitbucket.org/pypy/pypy/changeset/f034b1d5a9e9/
Log: merge default
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
@@ -59,6 +59,16 @@
Refactor in rpython signatures
+.. branch: cpyext-tls-operror2
+
+Store error state thread-locally in executioncontext, fixes issue #2764
+
+.. branch: cpyext-fast-typecheck
+
+Optimize `Py*_Check` for `Bool`, `Float`, `Set`. Also refactor and simplify
+`W_PyCWrapperObject` which is used to call slots from the C-API, greatly
+improving microbenchmarks in https://github.com/antocuni/cpyext-benchmarks
+
.. branch: fix-sre-problems:
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -5,7 +5,8 @@
from pypy.objspace.std.listobject import (
ListStrategy, UNROLL_CUTOFF, W_ListObject, ObjectListStrategy)
from pypy.module.cpyext.api import (
- cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t, PyObject, PyObjectP)
+ cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t, PyObject, PyObjectP,
+ generic_cpy_call)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.pyobject import as_pyobj, incref
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -145,21 +146,26 @@
# XXX we should call Py*_GET_ITEM() instead of Py*_GetItem()
# from here, but we cannot because we are also called from
# PySequence_GetItem()
+ py_obj = as_pyobj(space, w_obj)
if isinstance(w_obj, tupleobject.W_TupleObject):
from pypy.module.cpyext.tupleobject import PyTuple_GetItem
- py_obj = as_pyobj(space, w_obj)
py_res = PyTuple_GetItem(space, py_obj, i)
incref(space, py_res)
keepalive_until_here(w_obj)
return py_res
if isinstance(w_obj, W_ListObject):
from pypy.module.cpyext.listobject import PyList_GetItem
- py_obj = as_pyobj(space, w_obj)
py_res = PyList_GetItem(space, py_obj, i)
incref(space, py_res)
keepalive_until_here(w_obj)
return py_res
- return make_ref(space, space.getitem(w_obj, space.newint(i)))
+
+ as_sequence = py_obj.c_ob_type.c_tp_as_sequence
+ if not as_sequence or not as_sequence.c_sq_item:
+ raise oefmt(space.w_TypeError,
+ "'%T' object does not support indexing", w_obj)
+ ret = generic_cpy_call(space, as_sequence.c_sq_item, w_obj, i)
+ return make_ref(space, ret)
@cpython_api([PyObject, Py_ssize_t], PyObject, result_is_ll=True)
def PySequence_GetItem(space, w_obj, i):
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2202,6 +2202,16 @@
Py_RETURN_NONE;
};
+static PyObject *
+getitem(PyObject* self, PyObject * args) {
+ PyObject * obj;
+ int i;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &i)) {
+ return NULL;
+ }
+ return PySequence_ITEM(obj, i);
+}
+
PyDoc_STRVAR(module_doc,
"This module defines an object type which can efficiently represent\n\
an array of basic values: characters, integers, floating point\n\
@@ -2491,6 +2501,7 @@
{"get_releasebuffer_cnt", (PyCFunction)get_releasebuffer_cnt, METH_NOARGS, NULL},
{"create_and_release_buffer", (PyCFunction)create_and_release_buffer, METH_O, NULL},
{"same_dealloc", (PyCFunction)same_dealloc, METH_VARARGS, NULL},
+ {"getitem", (PyCFunction)getitem, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} /* Sentinel */
};
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -76,7 +76,9 @@
else:
expected = '\x01\0\0\0' '\x02\0\0\0' '\x03\0\0\0' '\x04\0\0\0'
assert str(buf) == expected
- assert str(buffer('') + arr) == expected
+ assert str(buffer('a') + arr) == "a" + expected
+ # python2 special cases empty-buffer + obj
+ assert str(buffer('') + arr) == "array('i', [1, 2, 3, 4])"
def test_releasebuffer(self):
module = self.import_module(name='array')
@@ -172,3 +174,15 @@
fd = BytesIO()
# only test that it works
fd.write(a)
+
+ def test_getitem_via_PySequence_GetItem(self):
+ module = self.import_module(name='array')
+ a = module.array('i', range(10))
+ # call via tp_as_mapping.mp_subscript
+ assert 5 == a[-5]
+ # PySequence_ITEM used to call space.getitem() which
+ # prefers tp_as_mapping.mp_subscript over tp_as_sequence.sq_item
+ # Now fixed so this test raises (array_item does not add len(a),
+ # array_subscr does)
+ raises(IndexError, module.getitem, a, -5)
+
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -1,3 +1,4 @@
+import pytest
from pypy.interpreter import gateway
from rpython.rtyper.lltypesystem import rffi
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
@@ -6,6 +7,7 @@
from pypy.module.cpyext.pyobject import make_ref, from_ref, decref, as_pyobj
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
+
class AppTestTypeObject(AppTestCpythonExtensionBase):
def setup_class(cls):
@@ -136,8 +138,10 @@
module = self.import_module(name='foo')
descr = module.fooType.copy
assert type(descr).__name__ == 'method_descriptor'
- assert str(descr) == "<method 'copy' of 'foo.foo' objects>"
- assert repr(descr) == "<method 'copy' of 'foo.foo' objects>"
+ assert str(descr) in ("<method 'copy' of 'foo.foo' objects>",
+ "<method 'copy' of 'foo' objects>")
+ assert repr(descr) in ("<method 'copy' of 'foo.foo' objects>",
+ "<method 'copy' of 'foo' objects>")
raises(TypeError, descr, None)
def test_cython_fake_classmethod(self):
@@ -250,7 +254,7 @@
import re
assert re.sre_compile._sre is module
s = u"Foo " * 1000 + u"Bar"
- prog = re.compile(ur"Foo.*Bar")
+ prog = re.compile(u"Foo.*Bar")
assert prog.match(s)
m = re.search(u"xyz", u"xyzxyz")
assert m
@@ -319,7 +323,7 @@
def test_tp_dict(self):
foo = self.import_module("foo")
module = self.import_extension('test', [
- ("read_tp_dict", "METH_O",
+ ("read_tp_dict", "METH_O",
'''
PyObject *method;
if (!args->ob_type->tp_dict)
@@ -420,7 +424,7 @@
return NULL;
Py_DECREF(a1);
PyType_Modified(type);
- value = PyObject_GetAttrString((PyObject*)type, "a");
+ value = PyObject_GetAttrString((PyObject *)type, "a");
Py_DECREF(value);
if (PyDict_SetItemString(type->tp_dict, "a",
@@ -428,7 +432,7 @@
return NULL;
Py_DECREF(a2);
PyType_Modified(type);
- value = PyObject_GetAttrString((PyObject*)type, "a");
+ value = PyObject_GetAttrString((PyObject *)type, "a");
return value;
'''
)
@@ -529,7 +533,7 @@
py_type = rffi.cast(PyTypeObjectPtr, ref)
w_dict = from_ref(space, py_type.c_tp_dict)
- w_name = space.wrap('a')
+ w_name = space.newtext('a')
space.setitem(w_dict, w_name, space.wrap(1))
assert space.int_w(space.getattr(w_class, w_name)) == 1
space.delitem(w_dict, w_name)
@@ -611,16 +615,21 @@
module = self.import_extension('foo', [
("test_tp_getattro", "METH_VARARGS",
'''
+ #if PY_MAJOR_VERSION > 2
+ #define PyString_FromString PyUnicode_FromString
+ #define PyIntObject PyLongObject
+ #define PyInt_AsLong PyLong_AsLong
+ #endif
PyObject *name, *obj = PyTuple_GET_ITEM(args, 0);
- PyIntObject *attr, *value = (PyIntObject*) PyTuple_GET_ITEM(args, 1);
+ PyObject *attr, *value = PyTuple_GET_ITEM(args, 1);
if (!obj->ob_type->tp_getattro)
{
PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
return NULL;
}
name = PyString_FromString("attr1");
- attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name);
- if (attr->ob_ival != value->ob_ival)
+ attr = obj->ob_type->tp_getattro(obj, name);
+ if (PyInt_AsLong(attr) != PyInt_AsLong(value))
{
PyErr_SetString(PyExc_ValueError,
"tp_getattro returned wrong value");
@@ -629,7 +638,7 @@
Py_DECREF(name);
Py_DECREF(attr);
name = PyString_FromString("attr2");
- attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name);
+ attr = obj->ob_type->tp_getattro(obj, name);
if (attr == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
{
PyErr_Clear();
@@ -652,6 +661,9 @@
module = self.import_extension('foo', [
("get_foo", "METH_O",
'''
+ #if PY_MAJOR_VERSION > 2
+ #define PyString_FromString PyUnicode_FromString
+ #endif
char* name = "foo";
PyTypeObject *tp = Py_TYPE(args);
PyObject *res;
@@ -836,6 +848,10 @@
'''
)], prologue='''
static int
+ #if PY_MAJOR_VERSION > 2
+ #define PyString_FromString PyBytes_FromString
+ #define PyInt_Check PyLong_Check
+ #endif
mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
{
if (PyInt_Check(key)) {
@@ -898,6 +914,10 @@
return obj;
'''
)], prologue='''
+ #if PY_MAJOR_VERSION > 2
+ #define PyInt_Check PyLong_Check
+ #define PyInt_AsLong PyLong_AsLong
+ #endif
static int
sq_ass_slice(PyObject *self, Py_ssize_t a, Py_ssize_t b, PyObject *o)
{
@@ -935,6 +955,10 @@
return obj;
'''
)], prologue='''
+ #if PY_MAJOR_VERSION > 2
+ #define PyInt_Check PyLong_Check
+ #define PyInt_AsLong PyLong_AsLong
+ #endif
static int
sq_ass_item(PyObject *self, Py_ssize_t i, PyObject *o)
{
@@ -983,6 +1007,9 @@
),
("tp_iternext", "METH_VARARGS",
'''
+ #if PY_MAJOR_VERSION > 2
+ #define PyString_FromString PyBytes_FromString
+ #endif
PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 0);
PyObject *obj = PyTuple_GET_ITEM(args, 1);
PyObject *result;
@@ -1002,7 +1029,7 @@
it = module.tp_iter(list, l)
assert type(it) is type(iter([]))
assert module.tp_iternext(type(it), it) == 1
- assert module.tp_iternext(type(it), it) == "stop!"
+ assert module.tp_iternext(type(it), it) == b"stop!"
#
class LL(list):
def __iter__(self):
@@ -1132,7 +1159,11 @@
PyObject_HEAD
long ival;
} IntLikeObject;
-
+ #if PY_MAJOR_VERSION > 2
+ #define PyInt_Check PyLong_Check
+ #define PyInt_AsLong PyLong_AsLong
+ #define PyInt_FromLong PyLong_FromLong
+ #endif
static PyObject *
intlike_nb_add(PyObject *self, PyObject *other)
{
@@ -1476,7 +1507,6 @@
)])
# used to segfault after some iterations
for i in range(11):
- print i
class A(object):
pass
class B:
@@ -1488,10 +1518,10 @@
def test_getattr_getattro(self):
module = self.import_module(name='foo')
- assert module.gettype2.dcba == 'getattro:dcba'
+ assert module.gettype2.dcba == b'getattro:dcba'
assert (type(module.gettype2).__getattribute__(module.gettype2, 'dcBA')
- == 'getattro:dcBA')
- assert module.gettype1.abcd == 'getattr:abcd'
+ == b'getattro:dcBA')
+ assert module.gettype1.abcd == b'getattr:abcd'
# GetType1 objects have a __getattribute__ method, but this
# doesn't call tp_getattr at all, also on CPython
raises(AttributeError, type(module.gettype1).__getattribute__,
@@ -1533,6 +1563,9 @@
return PyInt_FromLong(42);
'''
)], prologue='''
+ #if PY_MAJOR_VERSION > 2
+ #define PyInt_FromLong PyLong_FromLong
+ #endif
static PyTypeObject Foo_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"foo.foo",
@@ -1635,8 +1668,10 @@
(int, Py_TPFLAGS_INT_SUBCLASS),
(list, Py_TPFLAGS_LIST_SUBCLASS),
(tuple, Py_TPFLAGS_TUPLE_SUBCLASS),
+ (bytes, Py_TPFLAGS_STRING_SUBCLASS),
(str, Py_TPFLAGS_STRING_SUBCLASS),
(unicode, Py_TPFLAGS_UNICODE_SUBCLASS),
+ (dict, Py_TPFLAGS_DICT_SUBCLASS),
(Exception, Py_TPFLAGS_BASE_EXC_SUBCLASS),
(type, Py_TPFLAGS_TYPE_SUBCLASS),
):
@@ -1664,7 +1699,7 @@
return PyLong_FromLong(0);
'''),])
# copied from object.h
- Py_TPPYPYFLAGS_FLOAT_SUBCLASS = (1L<<0)
+ Py_TPPYPYFLAGS_FLOAT_SUBCLASS = (1<<0)
class MyFloat(float):
pass
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
--- a/pypy/module/cpyext/userslot.py
+++ b/pypy/module/cpyext/userslot.py
@@ -49,6 +49,11 @@
w_stararg=w_args, w_starstararg=w_kwds)
return space.call_args(w_impl, args)
+ at slot_function([PyObject, PyObject, PyObject], PyObject)
+def slot_tp_call(space, w_self, w_args, w_kwds):
+ args = Arguments(space, [], w_stararg=w_args, w_starstararg=w_kwds)
+ return space.call_args(w_self, args)
+
# unary functions
@slot_function([PyObject], PyObject)
diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -94,7 +94,7 @@
try:
posix.fstat(fd)
except OSError as e:
- raise IOError(e.errno, e.message)
+ raise OSError(e.errno, e.message)
return _fdopen(fd, mode, buffering)
else:
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -303,7 +303,7 @@
try:
fid = posix.fdopen(fd)
fid.read(10)
- except IOError as e:
+ except OSError as e:
assert e.errno == errno.EBADF
else:
assert False, "using result of fdopen(fd) on closed file must raise"
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -375,27 +375,58 @@
log = self.run(main, [300])
loop, = log.loops_by_filename(self.filepath)
assert loop.match("""
- i161 = int_lt(i160, i43)
+ i106 = getfield_gc_i(p20, descr=...)
+ i161 = int_lt(i106, i43)
guard_true(i161, descr=...)
- i162 = int_add(i160, 1)
- setfield_gc(p22, i162, descr=<FieldS pypy.module.__builtin__.functional.W_XRangeIterator.inst_current .>)
+ i162 = int_add(i106, 1)
+ p110 = getfield_gc_r(p16, descr=...)
+ setfield_gc(p20, i162, descr=...)
+ guard_value(p110, ConstPtr(ptr111), descr=...)
guard_not_invalidated(descr=...)
p163 = force_token()
p164 = force_token()
- p167 = call_r(ConstClass(_ll_0_alloc_with_del___), descr=<Callr . EF=5>)
+ p118 = getfield_gc_r(p16, descr=...)
+ p120 = getarrayitem_gc_r(p118, 0, descr=...)
+ guard_value(p120, ConstPtr(ptr121), descr=...)
+ p122 = getfield_gc_r(p120, descr=...)
+ guard_value(p122, ConstPtr(ptr123), descr=...)
+ p125 = getfield_gc_r(p16, descr=...)
+ guard_nonnull_class(p125, ..., descr=...)
+ p127 = getfield_gc_r(p125, descr=...)
+ guard_value(p127, ConstPtr(ptr128), descr=...)
+ p129 = getfield_gc_r(p127, descr=...)
+ guard_value(p129, ConstPtr(ptr130), descr=...)
+ p132 = call_r(ConstClass(_ll_0_alloc_with_del___), descr=...)
guard_no_exception(descr=...)
- i112 = int_signext(i160, 2)
- setfield_gc(p167, ConstPtr(ptr85), descr=<FieldP pypy.module._cffi_backend.cdataobj.W_CData.inst_ctype .+>)
- setfield_gc(p167, -1, descr=<FieldS pypy.module._cffi_backend.cdataobj.W_CDataNewOwning.inst_allocated_length .+>)
- i114 = int_ne(i160, i112)
- guard_false(i114, descr=...)
- --TICK--
- i123 = arraylen_gc(p67, descr=<ArrayP .>)
- i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize_zero_mpressure__Signed), 6, descr=<Calli . i EF=5 OS=110>)
- check_memory_error(i119)
- raw_store(i119, 0, i160, descr=<ArrayS 2>)
- raw_store(i119, 2, i160, descr=<ArrayS 2>)
- raw_store(i119, 4, i160, descr=<ArrayS 2>)
- setfield_gc(p167, i119, descr=<FieldU pypy.module._cffi_backend.cdataobj.W_CData.inst__ptr .+>)
+ p133 = force_token()
+ p134 = new_with_vtable(descr=...)
+ setfield_gc(p134, ..., descr=...)
+ setfield_gc(p134, ConstPtr(null), descr=...)
+ setfield_gc(p48, p134, descr=...)
+ setfield_gc(p132, ..., descr=...)
+ i138 = call_i(ConstClass(_ll_1_raw_malloc_varsize_zero__Signed), 6, descr=...)
+ check_memory_error(i138)
+ setfield_gc(p132, i138, descr=...)
+ setfield_gc(p132, ConstPtr(ptr139), descr=...)
+ setfield_gc(p132, -1, descr=...)
+ setfield_gc(p0, p133, descr=...)
+ call_may_force_n(ConstClass(_ll_2_gc_add_memory_pressure__Signed_pypy_module__cffi_backend_cdataobj_W_CDataNewStdPtr), 6, p132, descr=...)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
+ i144 = int_add(i138, 0)
+ i146 = int_signext(i106, 2)
+ i147 = int_ne(i106, i146)
+ guard_false(i147, descr=...)
+ setarrayitem_raw(i144, 0, i106, descr=...)
+ i150 = int_add(i138, 2)
+ setarrayitem_raw(i150, 0, i106, descr=...)
+ i153 = int_add(i138, 4)
+ setarrayitem_raw(i153, 0, i106, descr=...)
+ p156 = getfield_gc_r(p48, descr=...)
+ i158 = getfield_raw_i(..., descr=...)
+ setfield_gc(p48, p49, descr=...)
+ setfield_gc(p134, ConstPtr(null), descr=...)
+ i160 = int_lt(i158, 0)
+ guard_false(i160, descr=...)
jump(..., descr=...)
""")
diff --git a/pypy/objspace/std/bufferobject.py b/pypy/objspace/std/bufferobject.py
--- a/pypy/objspace/std/bufferobject.py
+++ b/pypy/objspace/std/bufferobject.py
@@ -89,9 +89,14 @@
def descr_str(self, space):
return space.newbytes(self.buf.as_str())
- @unwrap_spec(other='bufferstr')
- def descr_add(self, space, other):
- return space.newbytes(self.buf.as_str() + other)
+ def descr_add(self, space, w_other):
+ try:
+ other = w_other.readbuf_w(space)
+ except BufferInterfaceNotFound:
+ raise oefmt(space.w_TypeError, "bad argument type for built-in operation")
+ if self.buf.getlength() < 1:
+ return w_other
+ return space.newbytes(self.buf.as_str() + other.as_str())
def _make_descr__cmp(name):
def descr__cmp(self, space, w_other):
diff --git a/pypy/objspace/std/test/test_bufferobject.py b/pypy/objspace/std/test/test_bufferobject.py
--- a/pypy/objspace/std/test/test_bufferobject.py
+++ b/pypy/objspace/std/test/test_bufferobject.py
@@ -29,9 +29,11 @@
def test_array_buffer(self):
import array
- b = buffer(array.array("B", [1, 2, 3]))
+ arr = array.array("B", [1, 2, 3])
+ b = buffer(arr)
assert len(b) == 3
assert b[0:3] == "\x01\x02\x03"
+ assert buffer('') + arr is arr
def test_nonzero(self):
assert buffer('\x00')
@@ -51,6 +53,7 @@
assert buffer('abc') + 'def' == 'abcdef'
import array
assert buffer('abc') + array.array('c', 'def') == 'abcdef'
+ raises(TypeError, buffer('abc').__add__, 3)
def test_cmp(self):
assert buffer('ab') != 'ab'
@@ -199,6 +202,9 @@
raises(TypeError, "buf[MyInt(0):MyInt(5)]")
def test_pypy_raw_address_base(self):
+ import sys
+ if '__pypy__' not in sys.builtin_module_names:
+ skip('PyPy only')
a = buffer("foobar")._pypy_raw_address()
assert a != 0
b = buffer(u"foobar")._pypy_raw_address()
More information about the pypy-commit
mailing list