[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