Author: Matti Picus <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit