Author: Matti Picus <matti.pi...@gmail.com> Branch: PyTuple_Type-subclass Changeset: r85339:1f707f869b48 Date: 2016-06-22 22:43 +0300 http://bitbucket.org/pypy/pypy/changeset/1f707f869b48/
Log: change PyTupleObject.ob_item from PyObject** to PyObject*[], implies tp_itemsize != 0 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/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 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, 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,22 @@ 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') + decref(space, py_tup.c_ob_item[i]) 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): """ @@ -101,7 +98,9 @@ p = py_tup.c_ob_item items_w = [None] * l for i in range(l): - w_item = from_ref(space, p[i]) + w_item = None + if p[i]: + w_item = from_ref(space, p[i]) if w_item is None: fatalerror_notb( "Fatal error in cpyext, CPython compatibility layer: " @@ -120,18 +119,17 @@ """ py_tup = rffi.cast(PyTupleObject, py_obj) p = py_tup.c_ob_item - if p: - for i in range(py_tup.c_ob_size): + for i in range(py_tup.c_ob_size): + if p[i] and p[i].c_ob_refcnt > 0: decref(space, p[i]) - lltype.free(p, flavor="raw") - from pypy.module.cpyext.object import PyObject_dealloc - PyObject_dealloc(space, py_obj) + while py_obj.c_ob_refcnt > 0: + decref(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): @@ -187,25 +185,23 @@ 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] + newref.c_ob_item[i] = oldref.c_ob_item[i] 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 @@ -659,6 +659,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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit