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

Reply via email to