[pypy-commit] pypy cpyext-obj-stealing: rework refcounting to pass tests, use fresh object in test_list_macros
mattip
pypy.commits at gmail.com
Sat Apr 29 16:19:39 EDT 2017
Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-obj-stealing
Changeset: r91153:d8750637a6f7
Date: 2017-04-29 23:18 +0300
http://bitbucket.org/pypy/pypy/changeset/d8750637a6f7/
Log: rework refcounting to pass tests, use fresh object in
test_list_macros
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -3,7 +3,8 @@
from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, Py_ssize_t,
build_type_checkers)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
-from pypy.module.cpyext.pyobject import decref, PyObject, make_ref, w_obj_has_pyobj
+from pypy.module.cpyext.pyobject import (decref, incref, PyObject, make_ref,
+ w_obj_has_pyobj)
from pypy.objspace.std.listobject import W_ListObject
from pypy.interpreter.error import oefmt
@@ -19,10 +20,11 @@
PySequence_SetItem() or expose the object to Python code before
setting all items to a real object with PyList_SetItem().
"""
- return space.newlist([None] * len)
+ w_list = space.newlist([None] * len)
+ w_list.convert_to_cpy_strategy(space)
+ return w_list
- at cpython_api([rffi.VOIDP, Py_ssize_t, PyObject], PyObject, error=CANNOT_FAIL,
- result_borrowed=True)
+ at cpython_api([rffi.VOIDP, Py_ssize_t, PyObject], lltype.Void, error=CANNOT_FAIL)
def PyList_SET_ITEM(space, w_list, index, w_item):
"""Form of PyList_SetItem() without error checking. This is normally
only used to fill in new lists where there is no previous content.
@@ -31,10 +33,15 @@
discard a reference to any item that it being replaced; any reference in
list at position i will be leaked.
"""
+ from pypy.module.cpyext.sequence import CPyListStrategy
+ cpy_strategy = space.fromcache(CPyListStrategy)
assert isinstance(w_list, W_ListObject)
+ assert w_list.strategy is cpy_strategy, "list strategy not CPyListStrategy"
assert 0 <= index < w_list.length()
+ w_old = w_list.getitem(index)
+ incref(space, w_old) # since setitem calls decref, maintain cpython semantics here
w_list.setitem(index, w_item)
- return w_item
+ decref(space, w_item)
@cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
@@ -45,20 +52,15 @@
This function "steals" a reference to item and discards a reference to
an item already in the list at the affected position.
"""
- from pypy.module.cpyext.sequence import CPyListStrategy
- cpy_strategy = space.fromcache(CPyListStrategy)
if not isinstance(w_list, W_ListObject):
decref(space, w_item)
PyErr_BadInternalCall(space)
if index < 0 or index >= w_list.length():
decref(space, w_item)
raise oefmt(space.w_IndexError, "list assignment index out of range")
- if w_list.strategy is not cpy_strategy:
- w_list.ensure_object_strategy() # make sure we can use borrowed obj
- w_old = w_list.getitem(index)
- if w_obj_has_pyobj(w_old):
- decref(space, w_old)
+ w_list.convert_to_cpy_strategy(space)
w_list.setitem(index, w_item)
+ decref(space, w_item)
return 0
@cpython_api([PyObject, Py_ssize_t], PyObject, result_borrowed=True)
@@ -67,14 +69,11 @@
position must be positive, indexing from the end of the list is not
supported. If pos is out of bounds, return NULL and set an
IndexError exception."""
- from pypy.module.cpyext.sequence import CPyListStrategy
- cpy_strategy = space.fromcache(CPyListStrategy)
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
if index < 0 or index >= w_list.length():
raise oefmt(space.w_IndexError, "list index out of range")
- if w_list.strategy is not cpy_strategy:
- w_list.ensure_object_strategy() # make sure we can return a borrowed obj
+ w_list.convert_to_cpy_strategy(space)
w_res = w_list.getitem(index)
return w_res # borrowed ref
@@ -83,8 +82,9 @@
def PyList_Append(space, w_list, w_item):
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- make_ref(space, w_item)
+ #pyobj = make_ref(space, w_item)
w_list.append(w_item)
+ w_list.convert_to_cpy_strategy(space) # calls incref when switching strategy
return 0
@cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
diff --git a/pypy/module/cpyext/test/test_listobject.py b/pypy/module/cpyext/test/test_listobject.py
--- a/pypy/module/cpyext/test/test_listobject.py
+++ b/pypy/module/cpyext/test/test_listobject.py
@@ -152,16 +152,13 @@
def test_list_macros(self):
"""The PyList_* macros cast, and calls expecting that build."""
module = self.import_extension('foo', [
- ("test_macro_invocations", "METH_NOARGS",
+ ("test_macro_invocations", "METH_O",
"""
PyObject* o = PyList_New(2);
PyListObject* l = (PyListObject*)o;
-
- Py_INCREF(o);
- PyList_SET_ITEM(o, 0, o);
- Py_INCREF(o);
- PyList_SET_ITEM(l, 1, o);
+ PyList_SET_ITEM(o, 0, args);
+ PyList_SET_ITEM(l, 1, args);
if(PyList_GET_ITEM(o, 0) != PyList_GET_ITEM(l, 1))
{
@@ -179,8 +176,9 @@
"""
)
])
- x = module.test_macro_invocations()
- assert x[0] is x[1] is x
+ s = 'abcdef'
+ x = module.test_macro_invocations(s)
+ assert x[0] is x[1] is s
def test_get_item_macro(self):
module = self.import_extension('foo', [
More information about the pypy-commit
mailing list