Author: Matti Picus <[email protected]>
Branch: 
Changeset: r85403:9bf5c0afe0d0
Date: 2016-06-27 18:41 +0300
http://bitbucket.org/pypy/pypy/changeset/9bf5c0afe0d0/

Log:    merge PyTuple_Type-subclass which changes the model of PyTupleObject
        and allows subclassing it

diff --git a/pypy/module/cpyext/bufferobject.py 
b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -79,5 +79,5 @@
         Py_DecRef(space, py_buf.c_b_base)
     else:
         rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr))
-    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/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)
 
-@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 string_dealloc(space, py_obj):
     """Frees allocated PyStringObject 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/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
@@ -54,6 +54,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
@@ -1,6 +1,20 @@
 #include "Python.h"
 #include "structmember.h"
 
+#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
+    # defin 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 {
     PyObject_HEAD
     int    foo;        /* the context holder */
@@ -88,7 +102,7 @@
 static PyObject *
 foo_get_name(PyObject *self, void *closure)
 {
-    return PyString_FromStringAndSize("Foo Example", 11);
+    return PyThing_FromStringAndSize("Foo Example", 11);
 }
 
 static PyObject *
@@ -114,7 +128,7 @@
 {
     PyObject *format;
 
-    format = PyString_FromString("<Foo>");
+    format = PyThing_FromString("<Foo>");
     if (format == NULL) return NULL;
     return format;
 }
@@ -130,11 +144,11 @@
 foo_setattro(fooobject *self, PyObject *name, PyObject *value)
 {
     char *name_str;
-    if (!PyString_Check(name)) {
+    if (!PyThing_Check(name)) {
         PyErr_SetObject(PyExc_AttributeError, name);
         return -1;
     }
-    name_str = PyString_AsString(name);
+    name_str = _PyThing_AsString(name);
     if (strcmp(name_str, "set_foo") == 0)
     {
         long v = PyInt_AsLong(value);
@@ -620,20 +634,65 @@
     (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",
+    "Module Doc",
+    -1,
+    foo_functions, 
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+#define INITERROR return NULL
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+PyInit_foo(void)
+
+#else
+
+#define INITERROR return
 
 /* Initialize this module. */
 #ifdef __GNUC__
@@ -644,8 +703,16 @@
 
 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;
 
@@ -654,52 +721,59 @@
     MetaType.tp_base = &PyType_Type;
 
     if (PyType_Ready(&footype) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&UnicodeSubtype) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&UnicodeSubtype2) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&MetaType) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&InitErrType) < 0)
-        return;
+        INITERROR;
     if (PyType_Ready(&SimplePropertyType) < 0)
-        return;
+        INITERROR;
 
     SimplePropertyType.tp_new = PyType_GenericNew;
     InitErrType.tp_new = PyType_GenericNew;
 
     CustomType.ob_type = &MetaType;
     if (PyType_Ready(&CustomType) < 0)
-        return;
+        INITERROR;
 
     UnicodeSubtype3.tp_flags = Py_TPFLAGS_DEFAULT;
     UnicodeSubtype3.tp_base = &UnicodeSubtype;
     UnicodeSubtype3.tp_bases = Py_BuildValue("(OO)", &UnicodeSubtype,
                                                     &CustomType);
     if (PyType_Ready(&UnicodeSubtype3) < 0)
+        INITERROR;
+
+    TupleLike.tp_base = &PyTuple_Type;
+    if (PyType_Ready(&TupleLike) < 0)
         return;
 
-    m = Py_InitModule("foo", foo_functions);
-    if (m == NULL)
-        return;
-    d = PyModule_GetDict(m);
+
+    d = PyModule_GetDict(module);
     if (d == NULL)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype", (PyObject *) 
&UnicodeSubtype) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype2", (PyObject *) 
&UnicodeSubtype2) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "UnicodeSubtype3", (PyObject *) 
&UnicodeSubtype3) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) 
< 0)
-        return;
+        INITERROR;
     if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
-        return;
+        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_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)
@@ -597,7 +599,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)
@@ -608,7 +610,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):
@@ -659,6 +661,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
     setup_buffer_procs(space, w_type, 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
@@ -90,8 +90,9 @@
     Py_DecRef(space, py_unicode.c_defenc)
     if py_unicode.c_str:
         lltype.free(py_unicode.c_str, 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):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to