[pypy-commit] pypy py3k: hg merge default
rlamy
pypy.commits at gmail.com
Mon Jun 27 13:37:49 EDT 2016
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3k
Changeset: r85411:111ead0c2445
Date: 2016-06-27 18:37 +0100
http://bitbucket.org/pypy/pypy/changeset/111ead0c2445/
Log: hg merge default
diff --git a/pypy/doc/config/commandline.txt b/pypy/doc/config/commandline.txt
--- a/pypy/doc/config/commandline.txt
+++ b/pypy/doc/config/commandline.txt
@@ -9,7 +9,7 @@
PyPy Python interpreter options
-------------------------------
-The following options can be used after ``translate.py
+The following options can be used after ``rpython
targetpypystandalone`` or as options to ``py.py``.
.. GENERATE: objspace
@@ -22,7 +22,7 @@
General translation options
---------------------------
-The following are options of ``translate.py``. They must be
+The following are options of ``bin/rpython``. They must be
given before the ``targetxxx`` on the command line.
* `--opt -O:`__ set the optimization level `[0, 1, size, mem, 2, 3]`
diff --git a/pypy/doc/config/index.rst b/pypy/doc/config/index.rst
--- a/pypy/doc/config/index.rst
+++ b/pypy/doc/config/index.rst
@@ -15,12 +15,12 @@
./py.py <`objspace options`_>
-and the ``translate.py`` translation entry
+and the ``rpython/bin/rpython`` translation entry
point which takes arguments of this form:
.. parsed-literal::
- ./translate.py <`translation options`_> <target>
+ ./rpython/bin/rpython <`translation options`_> <target>
For the common case of ``<target>`` being ``targetpypystandalone.py``,
you can then pass the `object space options`_ after
@@ -28,7 +28,7 @@
.. parsed-literal::
- ./translate.py <`translation options`_> targetpypystandalone.py <`objspace options`_>
+ ./rpython/bin/rpython <`translation options`_> targetpypystandalone.py <`objspace options`_>
There is an `overview`_ of all command line arguments that can be
passed in either position.
diff --git a/pypy/doc/config/opt.rst b/pypy/doc/config/opt.rst
--- a/pypy/doc/config/opt.rst
+++ b/pypy/doc/config/opt.rst
@@ -4,8 +4,8 @@
This meta-option selects a default set of optimization
settings to use during a translation. Usage::
- translate.py --opt=#
- translate.py -O#
+ bin/rpython --opt=#
+ bin/rpython -O#
where ``#`` is the desired optimization level. The valid choices are:
diff --git a/pypy/doc/config/translation.dont_write_c_files.txt b/pypy/doc/config/translation.dont_write_c_files.txt
--- a/pypy/doc/config/translation.dont_write_c_files.txt
+++ b/pypy/doc/config/translation.dont_write_c_files.txt
@@ -1,4 +1,4 @@
write the generated C files to ``/dev/null`` instead of to the disk. Useful if
-you want to use translate.py as a benchmark and don't want to access the disk.
+you want to use translation as a benchmark and don't want to access the disk.
.. _`translation documentation`: ../translation.html
diff --git a/pypy/doc/config/translation.fork_before.txt b/pypy/doc/config/translation.fork_before.txt
--- a/pypy/doc/config/translation.fork_before.txt
+++ b/pypy/doc/config/translation.fork_before.txt
@@ -1,4 +1,4 @@
This is an option mostly useful when working on the PyPy toolchain. If you use
-it, translate.py will fork before the specified phase. If the translation
+it, translation will fork before the specified phase. If the translation
crashes after that fork, you can fix the bug in the toolchain, and continue
translation at the fork-point.
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -122,7 +122,7 @@
$ hg up reflex-support # optional
# This example shows python, but using pypy-c is faster and uses less memory
- $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
+ $ python rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
This will build a ``pypy-c`` that includes the cppyy module, and through that,
Reflex support.
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
@@ -42,3 +42,14 @@
Allow rw access to the char* returned from PyString_AS_STRING, also refactor
PyStringObject to look like cpython's and allow subclassing PyString_Type and
PyUnicode_Type
+
+.. branch: save_socket_errno
+
+Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
+the errno of the failing system call, but instead some random previous
+errno.
+
+.. branch: PyTuple_Type-subclass
+
+Refactor PyTupleObject to look like cpython's and allow subclassing
+PyTuple_Type
diff --git a/pypy/module/cpyext/bytearrayobject.py b/pypy/module/cpyext/bytearrayobject.py
--- a/pypy/module/cpyext/bytearrayobject.py
+++ b/pypy/module/cpyext/bytearrayobject.py
@@ -26,54 +26,10 @@
PyByteArrayObjectStruct = lltype.ForwardReference()
PyByteArrayObject = lltype.Ptr(PyByteArrayObjectStruct)
PyByteArrayObjectFields = PyVarObjectFields
-# (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
cpython_struct("PyByteArrayObject", PyByteArrayObjectFields, PyByteArrayObjectStruct)
- at bootstrap_function
-def init_bytearrayobject(space):
- "Type description of PyByteArrayObject"
- #make_typedescr(space.w_bytearray.layout.typedef,
- # basestruct=PyByteArrayObject.TO,
- # attach=bytearray_attach,
- # dealloc=bytearray_dealloc,
- # realize=bytearray_realize)
-
PyByteArray_Check, PyByteArray_CheckExact = build_type_checkers("ByteArray", "w_bytearray")
-# XXX dead code to be removed
-#def bytearray_attach(space, py_obj, w_obj):
-# """
-# Fills a newly allocated PyByteArrayObject with the given bytearray object
-# """
-# py_ba = rffi.cast(PyByteArrayObject, py_obj)
-# py_ba.c_ob_size = len(space.str_w(w_obj))
-# py_ba.c_ob_bytes = lltype.nullptr(rffi.CCHARP.TO)
-# py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
-
-#def bytearray_realize(space, py_obj):
-# """
-# Creates the bytearray in the interpreter.
-# """
-# py_ba = rffi.cast(PyByteArrayObject, py_obj)
-# if not py_ba.c_ob_bytes:
-# py_ba.c_buffer = lltype.malloc(rffi.CCHARP.TO, py_ba.c_ob_size + 1,
-# flavor='raw', zero=True)
-# s = rffi.charpsize2str(py_ba.c_ob_bytes, py_ba.c_ob_size)
-# w_obj = space.wrap(s)
-# py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
-# track_reference(space, py_obj, w_obj)
-# return w_obj
-
-#@cpython_api([PyObject], lltype.Void, header=None)
-#def bytearray_dealloc(space, py_obj):
-# """Frees allocated PyByteArrayObject resources.
-# """
-# py_ba = rffi.cast(PyByteArrayObject, py_obj)
-# if py_ba.c_ob_bytes:
-# lltype.free(py_ba.c_ob_bytes, flavor="raw")
-# from pypy.module.cpyext.object import PyObject_dealloc
-# PyObject_dealloc(space, py_obj)
-
#_______________________________________________________________________
@cpython_api([PyObject], PyObject, result_is_ll=True)
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -120,8 +120,8 @@
def bytes_dealloc(space, py_obj):
"""Frees allocated PyBytesObject resources.
"""
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
#_______________________________________________________________________
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -46,8 +46,8 @@
Py_DecRef(space, py_code)
Py_DecRef(space, py_frame.c_f_globals)
Py_DecRef(space, py_frame.c_f_locals)
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
def frame_realize(space, py_obj):
"""
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -60,8 +60,8 @@
def function_dealloc(space, py_obj):
py_func = rffi.cast(PyFunctionObject, py_obj)
Py_DecRef(space, py_func.c_func_name)
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
def code_attach(space, py_obj, w_obj):
py_code = rffi.cast(PyCodeObject, py_obj)
@@ -80,8 +80,8 @@
py_code = rffi.cast(PyCodeObject, py_obj)
Py_DecRef(space, py_code.c_co_name)
Py_DecRef(space, py_code.c_co_filename)
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
@cpython_api([PyObject], PyObject, result_borrowed=True)
def PyFunction_GetCode(space, w_func):
diff --git a/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h b/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h
--- a/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h
+++ b/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h
@@ -5,7 +5,12 @@
npy_bool obval;
} PyBoolScalarObject;
-static int import_array(){return 0;};
-static int _import_array(){return 0;};
-static int _import_math(){return 0;};
+#if PY_VERSION_HEX >= 0x03000000
+#define NUMPY_IMPORT_ARRAY_RETVAL NULL
+#else
+#define NUMPY_IMPORT_ARRAY_RETVAL
+#endif
+#define import_array() {return NUMPY_IMPORT_ARRAY_RETVAL;}
+
+
diff --git a/pypy/module/cpyext/include/tupleobject.h b/pypy/module/cpyext/include/tupleobject.h
--- a/pypy/module/cpyext/include/tupleobject.h
+++ b/pypy/module/cpyext/include/tupleobject.h
@@ -8,9 +8,12 @@
#endif
typedef struct {
- PyObject_HEAD
- Py_ssize_t ob_size;
- PyObject **ob_item; /* XXX optimize to ob_item[] */
+ PyObject_VAR_HEAD
+ PyObject *ob_item[1];
+ /* ob_item contains space for 'ob_size' elements.
+ * Items must normally not be NULL, except during construction when
+ * the tuple is not yet visible outside the function that builds it.
+ */
} PyTupleObject;
/* defined in varargswrapper.c */
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -55,8 +55,8 @@
py_func = rffi.cast(PyCFunctionObject, py_obj)
Py_DecRef(space, py_func.c_m_self)
Py_DecRef(space, py_func.c_m_module)
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
class W_PyCFunctionObject(W_Root):
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -58,6 +58,9 @@
@cpython_api([PyObject], lltype.Void)
def PyObject_dealloc(space, obj):
+ return _dealloc(space, obj)
+
+def _dealloc(space, obj):
# This frees an object after its refcount dropped to zero, so we
# assert that it is really zero here.
assert obj.c_ob_refcnt == 0
diff --git a/pypy/module/cpyext/pytraceback.py b/pypy/module/cpyext/pytraceback.py
--- a/pypy/module/cpyext/pytraceback.py
+++ b/pypy/module/cpyext/pytraceback.py
@@ -46,5 +46,5 @@
py_traceback = rffi.cast(PyTracebackObject, py_obj)
Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_frame))
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/sliceobject.py b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -44,8 +44,8 @@
Py_DecRef(space, py_slice.c_start)
Py_DecRef(space, py_slice.c_stop)
Py_DecRef(space, py_slice.c_step)
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
PySlice_Check, PySlice_CheckExact = build_type_checkers("Slice")
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
@@ -4,6 +4,15 @@
#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
+ #define PyThing_FromStringAndSize PyUnicode_FromStringAndSize
+ #define PyThing_FromString PyUnicode_FromString
+ #define PyThing_Check PyUnicode_Check
+ #define _PyThing_AsString _PyUnicode_AsString
+#else
+ #define PyThing_FromStringAndSize PyString_FromStringAndSize
+ #define PyThing_FromString PyString_FromString
+ #define PyThing_Check PyString_Check
+ #define _PyThing_AsString PyString_AsString
#endif
typedef struct {
@@ -93,7 +102,7 @@
static PyObject *
foo_get_name(PyObject *self, void *closure)
{
- return PyUnicode_FromStringAndSize("Foo Example", 11);
+ return PyThing_FromStringAndSize("Foo Example", 11);
}
static PyObject *
@@ -119,7 +128,7 @@
{
PyObject *format;
- format = PyUnicode_FromString("<Foo>");
+ format = PyThing_FromString("<Foo>");
if (format == NULL) return NULL;
return format;
}
@@ -135,11 +144,11 @@
foo_setattro(fooobject *self, PyObject *name, PyObject *value)
{
char *name_str;
- if (!PyUnicode_Check(name)) {
+ if (!PyThing_Check(name)) {
PyErr_SetObject(PyExc_AttributeError, name);
return -1;
}
- name_str = _PyUnicode_AsString(name);
+ name_str = _PyThing_AsString(name);
if (strcmp(name_str, "set_foo") == 0)
{
long v = PyInt_AsLong(value);
@@ -625,21 +634,39 @@
(destructor)custom_dealloc, /*tp_dealloc*/
};
+static PyTypeObject TupleLike = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "foo.TupleLike", /*tp_name*/
+ sizeof(PyObject), /*tp_size*/
+};
+
+
static PyObject *size_of_instances(PyObject *self, PyObject *t)
{
return PyInt_FromLong(((PyTypeObject *)t)->tp_basicsize);
}
+
+static PyObject * is_TupleLike(PyObject *self, PyObject * t)
+{
+ int tf = t->ob_type == &TupleLike;
+ if (t->ob_type->tp_itemsize == 0)
+ return PyInt_FromLong(-1);
+ return PyInt_FromLong(tf);
+}
+
/* List of functions exported by this module */
static PyMethodDef foo_functions[] = {
{"new", (PyCFunction)foo_new, METH_NOARGS, NULL},
{"newCustom", (PyCFunction)newCustom, METH_NOARGS, NULL},
{"size_of_instances", (PyCFunction)size_of_instances, METH_O, NULL},
+ {"is_TupleLike", (PyCFunction)is_TupleLike, METH_O, NULL},
{NULL, NULL} /* Sentinel */
};
-
+#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"foo",
@@ -651,6 +678,7 @@
NULL,
NULL,
};
+#define INITERROR return NULL
/* Initialize this module. */
#ifdef __GNUC__
@@ -661,8 +689,30 @@
PyMODINIT_FUNC
PyInit_foo(void)
+
+#else
+
+#define INITERROR return
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+initfoo(void)
+#endif
{
- PyObject *m, *d;
+ PyObject *d;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+#else
+ PyObject *module = Py_InitModule("foo", foo_functions);
+#endif
+ if (module == NULL)
+ INITERROR;
footype.tp_new = PyType_GenericNew;
@@ -671,53 +721,59 @@
MetaType.tp_base = &PyType_Type;
if (PyType_Ready(&footype) < 0)
- return NULL;
+ INITERROR;
if (PyType_Ready(&UnicodeSubtype) < 0)
- return NULL;
+ INITERROR;
if (PyType_Ready(&UnicodeSubtype2) < 0)
- return NULL;
+ INITERROR;
if (PyType_Ready(&MetaType) < 0)
- return NULL;
+ INITERROR;
if (PyType_Ready(&InitErrType) < 0)
- return NULL;
+ INITERROR;
if (PyType_Ready(&SimplePropertyType) < 0)
- return NULL;
+ INITERROR;
SimplePropertyType.tp_new = PyType_GenericNew;
InitErrType.tp_new = PyType_GenericNew;
CustomType.ob_type = &MetaType;
if (PyType_Ready(&CustomType) < 0)
- return NULL;
+ INITERROR;
UnicodeSubtype3.tp_flags = Py_TPFLAGS_DEFAULT;
UnicodeSubtype3.tp_base = &UnicodeSubtype;
UnicodeSubtype3.tp_bases = Py_BuildValue("(OO)", &UnicodeSubtype,
&CustomType);
if (PyType_Ready(&UnicodeSubtype3) < 0)
- return NULL;
+ INITERROR;
- m = PyModule_Create(&moduledef);
- if (m == NULL)
- return NULL;
- d = PyModule_GetDict(m);
+ TupleLike.tp_base = &PyTuple_Type;
+ if (PyType_Ready(&TupleLike) < 0)
+ INITERROR;
+
+
+ d = PyModule_GetDict(module);
if (d == NULL)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "UnicodeSubtype", (PyObject *) &UnicodeSubtype) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "UnicodeSubtype2", (PyObject *) &UnicodeSubtype2) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "UnicodeSubtype3", (PyObject *) &UnicodeSubtype3) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
- return NULL;
+ INITERROR;
if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
- return NULL;
- return m;
+ INITERROR;
+ if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0)
+ INITERROR;
+#if PY_MAJOR_VERSION >=3
+ return module;
+#endif
}
diff --git a/pypy/module/cpyext/test/test_bytearrayobject.py b/pypy/module/cpyext/test/test_bytearrayobject.py
--- a/pypy/module/cpyext/test/test_bytearrayobject.py
+++ b/pypy/module/cpyext/test/test_bytearrayobject.py
@@ -17,24 +17,10 @@
"""
PyObject* s = PyByteArray_FromStringAndSize("Hello world", 12);
int result = 0;
- size_t expected_size;
if(PyByteArray_Size(s) == 12) {
result = 1;
}
- #ifdef PYPY_VERSION
- expected_size = sizeof(void*)*3;
- #elif defined Py_DEBUG
- expected_size = 64;
- #else
- expected_size = 48;
- #endif
- if(s->ob_type->tp_basicsize != expected_size)
- {
- printf("tp_basicsize==%ld\\n",
- (long)s->ob_type->tp_basicsize);
- result = 0;
- }
Py_DECREF(s);
return PyBool_FromLong(result);
"""),
diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -25,24 +25,8 @@
("test_Size", "METH_NOARGS",
"""
PyObject* s = PyBytes_FromString("Hello world");
- int result = 0;
- size_t expected_size;
+ int result = PyBytes_Size(s);
- if(PyBytes_Size(s) == 11) {
- result = 1;
- }
- #ifdef PYPY_VERSION
- expected_size = 48;
- #elif defined Py_DEBUG
- expected_size = 53;
- #else
- expected_size = 37;
- #endif
- if(s->ob_type->tp_basicsize != expected_size)
- {
- printf("tp_basicsize==%zd\\n", s->ob_type->tp_basicsize);
- result = 0;
- }
Py_DECREF(s);
return PyBool_FromLong(result);
"""),
diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -51,7 +51,7 @@
api._PyTuple_Resize(ar, 10)
assert api.PyTuple_Size(ar[0]) == 10
for i in range(3, 10):
- rffi.cast(PyTupleObject, py_tuple).c_ob_item[i] = make_ref(
+ rffi.cast(PyTupleObject, ar[0]).c_ob_item[i] = make_ref(
space, space.wrap(42 + i))
w_tuple = from_ref(space, ar[0])
assert space.int_w(space.len(w_tuple)) == 10
@@ -151,3 +151,8 @@
"""),
])
module.run()
+
+ def test_tuple_subclass(self):
+ module = self.import_module(name='foo')
+ a = module.TupleLike([1, 2, 3])
+ assert module.is_TupleLike(a) == 1
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
@@ -2,10 +2,10 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.debug import fatalerror_notb
from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
- build_type_checkers, PyObjectFields,
+ build_type_checkers, PyVarObjectFields,
cpython_struct, bootstrap_function)
from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
- make_ref, from_ref, decref,
+ make_ref, from_ref, decref, incref, pyobj_has_w_obj,
track_reference, make_typedescr, get_typedescr)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.objspace.std.tupleobject import W_TupleObject
@@ -29,8 +29,8 @@
PyTupleObjectStruct = lltype.ForwardReference()
PyTupleObject = lltype.Ptr(PyTupleObjectStruct)
ObjectItems = rffi.CArray(PyObject)
-PyTupleObjectFields = PyObjectFields + \
- (("ob_size", Py_ssize_t), ("ob_item", lltype.Ptr(ObjectItems)))
+PyTupleObjectFields = PyVarObjectFields + \
+ (("ob_item", ObjectItems),)
cpython_struct("PyTupleObject", PyTupleObjectFields, PyTupleObjectStruct)
@bootstrap_function
@@ -56,14 +56,12 @@
tuple_realize() is called. Refcount of the result is 1.
"""
typedescr = get_typedescr(space.w_tuple.layout.typedef)
- py_obj = typedescr.allocate(space, space.w_tuple)
+ py_obj = typedescr.allocate(space, space.w_tuple, length)
py_tup = rffi.cast(PyTupleObject, py_obj)
-
- py_tup.c_ob_item = lltype.malloc(ObjectItems, length,
- flavor='raw', zero=True,
- add_memory_pressure=True)
- py_tup.c_ob_size = length
- return py_tup
+ p = py_tup.c_ob_item
+ for i in range(py_tup.c_ob_size):
+ p[i] = lltype.nullptr(PyObject.TO)
+ return py_obj
def tuple_attach(space, py_obj, w_obj):
"""
@@ -71,23 +69,24 @@
buffer must not be modified.
"""
items_w = space.fixedview(w_obj)
- l = len(items_w)
- p = lltype.malloc(ObjectItems, l, flavor='raw',
- add_memory_pressure=True)
+ py_tup = rffi.cast(PyTupleObject, py_obj)
+ length = len(items_w)
+ if py_tup.c_ob_size < length:
+ raise oefmt(space.w_ValueError,
+ "tuple_attach called on object with ob_size %d but trying to store %d",
+ py_tup.c_ob_size, length)
i = 0
try:
- while i < l:
- p[i] = make_ref(space, items_w[i])
+ while i < length:
+ py_tup.c_ob_item[i] = make_ref(space, items_w[i])
i += 1
except:
while i > 0:
i -= 1
- decref(space, p[i])
- lltype.free(p, flavor='raw')
+ ob = py_tup.c_ob_item[i]
+ py_tup.c_ob_item[i] = lltype.nullptr(PyObject.TO)
+ decref(space, ob)
raise
- py_tup = rffi.cast(PyTupleObject, py_obj)
- py_tup.c_ob_size = l
- py_tup.c_ob_item = p
def tuple_realize(space, py_obj):
"""
@@ -108,7 +107,9 @@
"converting a PyTupleObject into a W_TupleObject, "
"but found NULLs as items")
items_w[i] = w_item
- w_obj = space.newtuple(items_w)
+ w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
+ w_obj = space.allocate_instance(W_TupleObject, w_type)
+ w_obj.__init__(items_w)
track_reference(space, py_obj, w_obj)
return w_obj
@@ -118,18 +119,16 @@
"""
py_tup = rffi.cast(PyTupleObject, py_obj)
p = py_tup.c_ob_item
- if p:
- for i in range(py_tup.c_ob_size):
- decref(space, p[i])
- lltype.free(p, flavor="raw")
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ for i in range(py_tup.c_ob_size):
+ decref(space, p[i])
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
#_______________________________________________________________________
@cpython_api([Py_ssize_t], PyObject, result_is_ll=True)
def PyTuple_New(space, size):
- return rffi.cast(PyObject, new_empty_tuple(space, size))
+ return new_empty_tuple(space, size)
@cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
def PyTuple_SetItem(space, ref, index, py_obj):
@@ -185,25 +184,25 @@
ref = p_ref[0]
if not tuple_check_ref(space, ref):
PyErr_BadInternalCall(space)
- ref = rffi.cast(PyTupleObject, ref)
- oldsize = ref.c_ob_size
- oldp = ref.c_ob_item
- newp = lltype.malloc(ObjectItems, newsize, zero=True, flavor='raw',
- add_memory_pressure=True)
+ oldref = rffi.cast(PyTupleObject, ref)
+ oldsize = oldref.c_ob_size
+ p_ref[0] = new_empty_tuple(space, newsize)
+ newref = rffi.cast(PyTupleObject, p_ref[0])
try:
if oldsize < newsize:
to_cp = oldsize
else:
to_cp = newsize
for i in range(to_cp):
- newp[i] = oldp[i]
+ ob = oldref.c_ob_item[i]
+ incref(space, ob)
+ newref.c_ob_item[i] = ob
except:
- lltype.free(newp, flavor='raw')
+ decref(space, p_ref[0])
+ p_ref[0] = lltype.nullptr(PyObject.TO)
raise
- ref.c_ob_item = newp
- ref.c_ob_size = newsize
- lltype.free(oldp, flavor='raw')
- # in this version, p_ref[0] never needs to be updated
+ finally:
+ decref(space, ref)
return 0
@cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -371,6 +371,8 @@
# (minimally, if tp_basicsize is zero we copy it from the base)
if not pto.c_tp_basicsize:
pto.c_tp_basicsize = base_pto.c_tp_basicsize
+ if pto.c_tp_itemsize < base_pto.c_tp_itemsize:
+ pto.c_tp_itemsize = base_pto.c_tp_itemsize
flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
base_object_pyo = make_ref(space, space.w_object)
base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
@@ -503,7 +505,7 @@
@cpython_api([PyObject], lltype.Void, header=None)
def type_dealloc(space, obj):
- from pypy.module.cpyext.object import PyObject_dealloc
+ from pypy.module.cpyext.object import _dealloc
obj_pto = rffi.cast(PyTypeObjectPtr, obj)
base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base)
Py_DecRef(space, obj_pto.c_tp_bases)
@@ -514,7 +516,7 @@
heaptype = rffi.cast(PyHeapTypeObject, obj)
Py_DecRef(space, heaptype.c_ht_name)
Py_DecRef(space, base_pyo)
- PyObject_dealloc(space, obj)
+ _dealloc(space, obj)
def type_alloc(space, w_metatype, itemsize=0):
@@ -565,6 +567,8 @@
subtype_dealloc.api_func.get_wrapper(space))
if space.is_w(w_type, space.w_str):
pto.c_tp_itemsize = 1
+ elif space.is_w(w_type, space.w_tuple):
+ pto.c_tp_itemsize = rffi.sizeof(PyObject)
# buffer protocol
if space.is_w(w_type, space.w_str):
setup_bytes_buffer_procs(space, pto)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -85,8 +85,8 @@
lltype.free(py_unicode.c_buffer, flavor="raw")
if py_unicode.c_utf8buffer:
lltype.free(py_unicode.c_utf8buffer, flavor="raw")
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ from pypy.module.cpyext.object import _dealloc
+ _dealloc(space, py_obj)
@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
def Py_UNICODE_ISSPACE(space, ch):
diff --git a/rpython/doc/getting-started.rst b/rpython/doc/getting-started.rst
--- a/rpython/doc/getting-started.rst
+++ b/rpython/doc/getting-started.rst
@@ -142,8 +142,8 @@
Translating Full Programs
~~~~~~~~~~~~~~~~~~~~~~~~~
-To translate full RPython programs, there is the script ``translate.py`` in
-:source:`rpython/translator/goal`. Examples for this are a slightly changed version of
+To translate full RPython programs, there is the script ``bin/rpython`` in
+:source:`rpython/bin/`. Examples for this are a slightly changed version of
Pystone::
python bin/rpython translator/goal/targetrpystonedalone
diff --git a/rpython/memory/gctransform/boehm.py b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -1,6 +1,7 @@
from rpython.memory.gctransform.transform import GCTransformer, mallocHelpers
from rpython.memory.gctransform.support import (get_rtti,
- _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor)
+ _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor,
+ ll_report_finalizer_error)
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.flowspace.model import Constant
from rpython.rtyper.lltypesystem.lloperation import llop
@@ -58,6 +59,9 @@
self.mixlevelannotator.finish() # for now
self.mixlevelannotator.backend_optimize()
+ self.finalizer_triggers = []
+ self.finalizer_queue_indexes = {} # {fq: index}
+
def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
# XXX same behavior for zero=True: in theory that's wrong
if TYPE._is_atomic():
@@ -115,6 +119,39 @@
self.finalizer_funcptrs[TYPE] = fptr
return fptr
+ def get_finalizer_queue_index(self, hop):
+ fq_tag = hop.spaceop.args[0].value
+ assert 'FinalizerQueue TAG' in fq_tag.expr
+ fq = fq_tag.default
+ try:
+ index = self.finalizer_queue_indexes[fq]
+ except KeyError:
+ index = len(self.finalizer_queue_indexes)
+ assert index == len(self.finalizer_triggers)
+ #
+ def ll_finalizer_trigger():
+ try:
+ fq.finalizer_trigger()
+ except Exception as e:
+ ll_report_finalizer_error(e)
+ ll_trigger = self.annotate_finalizer(ll_finalizer_trigger, [],
+ lltype.Void)
+ self.finalizer_triggers.append(ll_trigger)
+ self.finalizer_queue_indexes[fq] = index
+ return index
+
+ def gct_gc_fq_register(self, hop):
+ index = self.get_finalizer_queue_index(hop)
+ c_index = rmodel.inputconst(lltype.Signed, index)
+ v_ptr = hop.spaceop.args[1]
+ hop.genop("boehm_fq_register", [c_index, v_ptr])
+
+ def gct_gc_fq_next_dead(self, hop):
+ index = self.get_finalizer_queue_index(hop)
+ c_index = rmodel.inputconst(lltype.Signed, index)
+ hop.genop("boehm_fq_next_dead", [c_index],
+ resultvar = hop.spaceop.result)
+
def gct_weakref_create(self, hop):
v_instance, = hop.spaceop.args
v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -487,7 +487,9 @@
#hstrerror.argtypes = [c_int]
#hstrerror.restype = c_char_p
-socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type)
+socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type,
+ save_err=SAVE_ERR)
+
if WIN32:
socketclosename = 'closesocket'
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -589,3 +589,15 @@
return 0
fc = compile(f, [], thread=True)
assert fc() == 0
+
+def test_socket_saves_errno(tmpdir):
+ # ensure errno is set to a known value...
+ unconnected_sock = RSocket()
+ e = py.test.raises(CSocketError, unconnected_sock.recv, 1024)
+ # ...which is ENOTCONN
+ assert e.value.errno == errno.ENOTCONN
+
+ e = py.test.raises(CSocketError,
+ RSocket,
+ family=AF_INET, type=SOCK_STREAM, proto=SOL_UDP)
+ assert e.value.errno in (errno.EPROTOTYPE, errno.EPROTONOSUPPORT)
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -166,7 +166,19 @@
})
if '__int128_t' in rffi.TYPES:
- _ctypes_cache[rffi.__INT128_T] = ctypes.c_longlong # XXX: Not right at all. But for some reason, It started by while doing JIT compile after a merge with default. Can't extend ctypes, because thats a python standard, right?
+ class c_int128(ctypes.Array): # based on 2 ulongs
+ _type_ = ctypes.c_uint64
+ _length_ = 2
+ @property
+ def value(self):
+ if sys.byteorder == 'little':
+ res = self[0] | (self[1] << 64)
+ else:
+ res = self[1] | (self[0] << 64)
+ if res >= (1 << 127):
+ res -= 1 << 128
+ return res
+ _ctypes_cache[rffi.__INT128_T] = c_int128
# for unicode strings, do not use ctypes.c_wchar because ctypes
# automatically converts arrays into unicode strings.
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -825,3 +825,13 @@
assert charp2str(p2) == "helLD"
free_charp(p1)
free_charp(p2)
+
+def test_sign_when_casting_uint_to_larger_int():
+ from rpython.rtyper.lltypesystem import rffi
+ from rpython.rlib.rarithmetic import r_uint32, r_uint64
+ #
+ value = 0xAAAABBBB
+ assert cast(lltype.SignedLongLong, r_uint32(value)) == value
+ if hasattr(rffi, '__INT128_T'):
+ value = 0xAAAABBBBCCCCDDDD
+ assert cast(rffi.__INT128_T, r_uint64(value)) == value
diff --git a/rpython/translator/backendopt/finalizer.py b/rpython/translator/backendopt/finalizer.py
--- a/rpython/translator/backendopt/finalizer.py
+++ b/rpython/translator/backendopt/finalizer.py
@@ -36,8 +36,8 @@
raise FinalizerError(msg)
else:
result = self.analyze_direct_call(graph)
- if result is self.top_result():
- log.red('old-style non-light finalizer: %r' % (graph,))
+ #if result is self.top_result():
+ # log.red('old-style non-light finalizer: %r' % (graph,))
return result
def analyze_simple_operation(self, op, graphinfo):
diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py
--- a/rpython/translator/c/gc.py
+++ b/rpython/translator/c/gc.py
@@ -212,6 +212,24 @@
compile_extra=['-DPYPY_USING_BOEHM_GC'],
))
+ gct = self.db.gctransformer
+ gct.finalizer_triggers = tuple(gct.finalizer_triggers) # stop changing
+ sourcelines = ['']
+ for trig in gct.finalizer_triggers:
+ sourcelines.append('RPY_EXTERN void %s(void);' % (
+ self.db.get(trig),))
+ sourcelines.append('')
+ sourcelines.append('void (*boehm_fq_trigger[])(void) = {')
+ for trig in gct.finalizer_triggers:
+ sourcelines.append('\t%s,' % (self.db.get(trig),))
+ sourcelines.append('\tNULL')
+ sourcelines.append('};')
+ sourcelines.append('struct boehm_fq_s *boehm_fq_queues[%d];' % (
+ len(gct.finalizer_triggers),))
+ sourcelines.append('')
+ eci = eci.merge(ExternalCompilationInfo(
+ separate_module_sources=['\n'.join(sourcelines)]))
+
return eci
def gc_startup_code(self):
diff --git a/rpython/translator/c/src/int.h b/rpython/translator/c/src/int.h
--- a/rpython/translator/c/src/int.h
+++ b/rpython/translator/c/src/int.h
@@ -121,7 +121,7 @@
#define OP_LLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
r = (long long)(((unsigned long long)(x)) << (y))
#define OP_LLLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, 128); \
- r = (__int128)(((unsigned __int128)(x)) << (y))
+ r = (__int128_t)(((__uint128_t)(x)) << (y))
#define OP_UINT_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONG_BIT); \
r = (x) << (y)
@@ -157,7 +157,7 @@
#define OP_CAST_UINT_TO_INT(x,r) r = (Signed)(x)
#define OP_CAST_INT_TO_UINT(x,r) r = (Unsigned)(x)
#define OP_CAST_INT_TO_LONGLONG(x,r) r = (long long)(x)
-#define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128)(x)
+#define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128_t)(x)
#define OP_CAST_CHAR_TO_INT(x,r) r = (Signed)((unsigned char)(x))
#define OP_CAST_INT_TO_CHAR(x,r) r = (char)(x)
#define OP_CAST_PTR_TO_INT(x,r) r = (Signed)(x) /* XXX */
diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c
--- a/rpython/translator/c/src/mem.c
+++ b/rpython/translator/c/src/mem.c
@@ -73,9 +73,17 @@
#ifdef PYPY_USING_BOEHM_GC
+struct boehm_fq_s {
+ void *obj;
+ struct boehm_fq_s *next;
+};
+RPY_EXTERN void (*boehm_fq_trigger[])(void);
+
int boehm_gc_finalizer_lock = 0;
void boehm_gc_finalizer_notifier(void)
{
+ int i;
+
boehm_gc_finalizer_lock++;
while (GC_should_invoke_finalizers()) {
if (boehm_gc_finalizer_lock > 1) {
@@ -86,6 +94,11 @@
}
GC_invoke_finalizers();
}
+
+ i = 0;
+ while (boehm_fq_trigger[i])
+ boehm_fq_trigger[i++]();
+
boehm_gc_finalizer_lock--;
}
@@ -100,6 +113,28 @@
GC_finalize_on_demand = 1;
GC_set_warn_proc(mem_boehm_ignore);
}
+
+void boehm_fq_callback(void *obj, void *rawfqueue)
+{
+ struct boehm_fq_s **fqueue = rawfqueue;
+ struct boehm_fq_s *node = GC_malloc(sizeof(void *) * 2);
+ if (!node)
+ return; /* ouch, too bad */
+ node->obj = obj;
+ node->next = *fqueue;
+ *fqueue = node;
+}
+
+void *boehm_fq_next_dead(struct boehm_fq_s **fqueue)
+{
+ struct boehm_fq_s *node = *fqueue;
+ if (node != NULL) {
+ *fqueue = node->next;
+ return node->obj;
+ }
+ else
+ return NULL;
+}
#endif /* BOEHM GC */
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -104,13 +104,21 @@
RPY_EXTERN int boehm_gc_finalizer_lock;
RPY_EXTERN void boehm_gc_startup_code(void);
RPY_EXTERN void boehm_gc_finalizer_notifier(void);
+struct boehm_fq_s;
+RPY_EXTERN struct boehm_fq_s *boehm_fq_queues[];
+RPY_EXTERN void (*boehm_fq_trigger[])(void);
+RPY_EXTERN void boehm_fq_callback(void *, void *);
+RPY_EXTERN void *boehm_fq_next_dead(struct boehm_fq_s **);
#define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++
#define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \
boehm_gc_finalizer_notifier())
-#define OP_GC_FQ_REGISTER(tag, obj, r) /* ignored so far */
-#define OP_GC_FQ_NEXT_DEAD(tag, r) (r = NULL)
+#define OP_BOEHM_FQ_REGISTER(tagindex, obj, r) \
+ GC_REGISTER_FINALIZER(obj, boehm_fq_callback, \
+ boehm_fq_queues + tagindex, NULL, NULL)
+#define OP_BOEHM_FQ_NEXT_DEAD(tagindex, r) \
+ r = boehm_fq_next_dead(boehm_fq_queues + tagindex)
#endif /* PYPY_USING_BOEHM_GC */
diff --git a/rpython/translator/c/test/test_boehm.py b/rpython/translator/c/test/test_boehm.py
--- a/rpython/translator/c/test/test_boehm.py
+++ b/rpython/translator/c/test/test_boehm.py
@@ -393,20 +393,36 @@
assert res[3] == compute_hash(d)
assert res[4] == compute_hash(("Hi", None, (7.5, 2, d)))
- def test_finalizer_queue_is_at_least_ignored(self):
+ def test_finalizer_queue(self):
class A(object):
- pass
+ def __init__(self, i):
+ self.i = i
+ class Glob:
+ triggered = 0
+ glob = Glob()
class FQ(rgc.FinalizerQueue):
Class = A
+ triggered = 0
def finalizer_trigger(self):
- debug.debug_print("hello!") # not called so far
+ glob.triggered += 1
fq = FQ()
#
def fn():
- fq.register_finalizer(A())
+ for i in range(1000):
+ fq.register_finalizer(A(i))
rgc.collect()
rgc.collect()
- fq.next_dead()
+ if glob.triggered == 0:
+ print "not triggered!"
+ return 50
+ seen = {}
+ for i in range(1000):
+ a = fq.next_dead()
+ assert a.i not in seen
+ seen[a.i] = True
+ if len(seen) < 500:
+ print "seen only %d!" % len(seen)
+ return 51
return 42
f = self.getcompiled(fn)
More information about the pypy-commit
mailing list