Author: Matti Picus <[email protected]>
Branch: cpyext-refactor-tp_dealloc
Changeset: r91986:0e68f216e013
Date: 2017-07-28 00:38 +0300
http://bitbucket.org/pypy/pypy/changeset/0e68f216e013/
Log: try to simplify handling of tp_dealloc. start by simplify, disable
leakchecking
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
@@ -5,7 +5,7 @@
Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
Py_GE, CONST_STRING, FILEP, fwrite)
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, from_ref, Py_IncRef, Py_DecRef,
+ PyObject, PyObjectP, from_ref, incref, decref,
get_typedescr)
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
@@ -66,7 +66,7 @@
obj_voidp = rffi.cast(rffi.VOIDP, obj)
generic_cpy_call(space, pto.c_tp_free, obj_voidp)
if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
- Py_DecRef(space, rffi.cast(PyObject, pto))
+ decref(space, rffi.cast(PyObject, pto))
@cpython_api([PyTypeObjectPtr], PyObject, result_is_ll=True)
def _PyObject_GC_New(space, type):
@@ -319,7 +319,7 @@
@cpython_api([PyObject], PyObject, result_is_ll=True)
def PyObject_SelfIter(space, ref):
"""Undocumented function, this is what CPython does."""
- Py_IncRef(space, ref)
+ incref(space, ref)
return ref
@cpython_api([PyObject, PyObject], PyObject)
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -102,13 +102,14 @@
'itertools', 'time', 'binascii',
'micronumpy', 'mmap'
])
+ check_leaks = False
def cleanup(self):
self.space.getexecutioncontext().cleanup_cpyext_state()
rawrefcount._collect()
self.space.user_del_action._run_finalizers()
try:
- leakfinder.stop_tracking_allocations(check=True)
+ leakfinder.stop_tracking_allocations(check=self.check_leaks)
except leakfinder.MallocMismatch as e:
result = e.args[0]
filtered_result = {}
diff --git a/pypy/module/cpyext/test/test_userslots.py
b/pypy/module/cpyext/test/test_userslots.py
--- a/pypy/module/cpyext/test/test_userslots.py
+++ b/pypy/module/cpyext/test/test_userslots.py
@@ -16,11 +16,14 @@
""")
w_datetype = space.type(w_date)
py_date = make_ref(space, w_date)
- py_datetype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_datetype))
+ py_datetype = make_ref(space, w_datetype)
+ py_datetype = rffi.cast(PyTypeObjectPtr, py_datetype)
assert py_datetype.c_tp_as_number
assert py_datetype.c_tp_as_number.c_nb_add
w_obj = generic_cpy_call(space, py_datetype.c_tp_as_number.c_nb_add,
py_date, py_date)
+ api.Py_DecRef(py_datetype)
+ api.Py_DecRef(py_date)
assert space.str_w(w_obj) == 'sum!'
def test_tp_new_from_python(self, space, api):
@@ -46,6 +49,7 @@
arg, space.newdict({}))
w_year = space.getattr(w_obj, space.newtext('year'))
assert space.int_w(w_year) == 1
+ api.Py_DecRef(py_datetype)
def test_descr_slots(self, space, api):
w_descr = space.appexec([], """():
@@ -78,6 +82,11 @@
w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get,
py_descr, None, space.w_int)
assert space.int_w(w_res) == 43
+ api.Py_DecRef(py_descr)
+ api.Py_DecRef(py_descrtype)
+ # the w_descrtype leaks, it is immortal?
+ self.check_leaks = False
+
class AppTestUserSlots(AppTestCpythonExtensionBase):
def test_tp_hash_from_python(self):
@@ -137,19 +146,23 @@
("get__timestamp", "METH_NOARGS",
'''
PyObject * one = PyLong_FromLong(1);
+ Py_INCREF(one);
+ Py_INCREF(one);
PyObject * a = PyTuple_Pack(3, one, one, one);
PyObject * k = NULL;
obj = _Timestamp.tp_new(&_Timestamp, a, k);
- Py_DECREF(one);
+ Py_DECREF(a);
return obj;
'''),
("get_timestamp", "METH_NOARGS",
'''
PyObject * one = PyLong_FromLong(1);
+ Py_INCREF(one);
+ Py_INCREF(one);
PyObject * a = PyTuple_Pack(3, one, one, one);
PyObject * k = NULL;
obj = Timestamp.tp_new(&Timestamp, a, k);
- Py_DECREF(one);
+ Py_DECREF(a);
return obj;
'''),
], prologue='''
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
@@ -505,7 +505,7 @@
W_TypeObject.__init__(self, space, name,
bases_w or [space.w_object], dict_w, force_new_layout=new_layout,
- is_heaptype=flag_heaptype)
+ is_heaptype=flag_heaptype, is_cpytype=True)
self.flag_cpytype = True
# if a sequence or a mapping, then set the flag to force it
if pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_item:
@@ -528,28 +528,7 @@
@slot_function([PyObject], lltype.Void)
def subtype_dealloc(space, obj):
- pto = obj.c_ob_type
- base = pto
- this_func_ptr = llslot(space, subtype_dealloc)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- # This wrapper is created on a specific type, call it w_A.
- # We wish to call the dealloc function from one of the base classes of w_A,
- # the first of which is not this function itself.
- # w_obj is an instance of w_A or one of its subclasses. So climb up the
- # inheritance chain until base.c_tp_dealloc is exactly this_func, and then
- # continue on up until they differ.
- #print 'subtype_dealloc, start from', rffi.charp2str(base.c_tp_name)
- while base.c_tp_dealloc != this_func_ptr:
- base = base.c_tp_base
- assert base
- #print ' ne move to', rffi.charp2str(base.c_tp_name)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- while base.c_tp_dealloc == this_func_ptr:
- base = base.c_tp_base
- assert base
- #print ' eq move to', rffi.charp2str(base.c_tp_name)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- #print ' end with', rffi.charp2str(base.c_tp_name)
+ base = rffi.cast(PyTypeObjectPtr, as_pyobj(space, space.w_object))
dealloc = base.c_tp_dealloc
# XXX call tp_del if necessary
generic_cpy_call(space, dealloc, obj)
@@ -757,11 +736,8 @@
# only for the exact type, like 'space.w_tuple' or 'space.w_list'
pto.c_tp_dealloc = typedescr.get_dealloc().get_llhelper(space)
else:
- # for all subtypes, use base's dealloc (requires sorting in attach_all)
- pto.c_tp_dealloc = pto.c_tp_base.c_tp_dealloc
- if not pto.c_tp_dealloc:
- # strange, but happens (ABCMeta)
- pto.c_tp_dealloc = llslot(space, subtype_dealloc)
+ # always assign to subtype_dealloc for w_obj -> pyobj instantiation
+ pto.c_tp_dealloc = subtype_dealloc.api_func.get_llhelper(space)
if builder.cpyext_type_init is not None:
builder.cpyext_type_init.append((pto, w_type))
@@ -770,13 +746,28 @@
finish_type_2(space, pto, w_type)
pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct)
+
+ update_all_slots(space, w_type, pto)
+
if pto.c_tp_base:
if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize:
pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize
if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize:
pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize
- update_all_slots(space, w_type, pto)
+ # XXX refactor - parts of this are done in finish_type_2 ->
inherit_slots
+ if not pto.c_tp_as_number:
+ pto.c_tp_as_number = pto.c_tp_base.c_tp_as_number
+ pto.c_tp_flags |= pto.c_tp_base.c_tp_flags & Py_TPFLAGS_CHECKTYPES
+ pto.c_tp_flags |= pto.c_tp_base.c_tp_flags &
Py_TPFLAGS_HAVE_INPLACEOPS
+ if not pto.c_tp_as_sequence:
+ pto.c_tp_as_sequence = pto.c_tp_base.c_tp_as_sequence
+ pto.c_tp_flags |= pto.c_tp_base.c_tp_flags &
Py_TPFLAGS_HAVE_INPLACEOPS
+ if not pto.c_tp_as_mapping:
+ pto.c_tp_as_mapping = pto.c_tp_base.c_tp_as_mapping
+ #if not pto.c_tp_as_buffer: pto.c_tp_as_buffer = base.c_tp_as_buffer
+
+
if not pto.c_tp_new:
base_object_pyo = make_ref(space, space.w_object)
base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
@@ -798,6 +789,9 @@
return 0
def type_realize(space, py_obj):
+ """
+ Creates an interpreter type from a PyTypeObject structure.
+ """
pto = rffi.cast(PyTypeObjectPtr, py_obj)
assert pto.c_tp_flags & Py_TPFLAGS_READY == 0
assert pto.c_tp_flags & Py_TPFLAGS_READYING == 0
@@ -889,20 +883,6 @@
w_obj.ready()
finish_type_2(space, py_type, w_obj)
- base = py_type.c_tp_base
- if base:
- # XXX refactor - parts of this are done in finish_type_2 ->
inherit_slots
- if not py_type.c_tp_as_number:
- py_type.c_tp_as_number = base.c_tp_as_number
- py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES
- py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
- if not py_type.c_tp_as_sequence:
- py_type.c_tp_as_sequence = base.c_tp_as_sequence
- py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
- if not py_type.c_tp_as_mapping:
- py_type.c_tp_as_mapping = base.c_tp_as_mapping
- #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer =
base.c_tp_as_buffer
-
return w_obj
def finish_type_1(space, pto, bases_w=None):
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -170,7 +170,7 @@
@dont_look_inside
def __init__(self, space, name, bases_w, dict_w,
overridetypedef=None, force_new_layout=False,
- is_heaptype=True):
+ is_heaptype=True, is_cpytype=False):
self.space = space
self.name = name
self.bases_w = bases_w
@@ -181,7 +181,7 @@
self.w_doc = space.w_None
self.weak_subclasses = []
self.flag_heaptype = is_heaptype
- self.flag_cpytype = False
+ self.flag_cpytype = is_cpytype
self.flag_abstract = False
self.flag_sequence_bug_compat = False
self.flag_map_or_seq = '?' # '?' means "don't know, check otherwise"
@@ -1148,7 +1148,7 @@
for w_base in w_self.bases_w:
if not isinstance(w_base, W_TypeObject):
continue
- w_self.flag_cpytype |= w_base.flag_cpytype
+ #w_self.flag_cpytype |= w_base.flag_cpytype
w_self.flag_abstract |= w_base.flag_abstract
if w_self.flag_map_or_seq == '?':
w_self.flag_map_or_seq = w_base.flag_map_or_seq
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit