[pypy-commit] pypy cpyext-gc-support-2: Next fix (rawrefcount debugging code takes weakrefs to the W_Root objects)

arigo pypy.commits at gmail.com
Tue Feb 16 11:33:26 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support-2
Changeset: r82285:860e2a46b04c
Date: 2016-02-16 17:32 +0100
http://bitbucket.org/pypy/pypy/changeset/860e2a46b04c/

Log:	Next fix (rawrefcount debugging code takes weakrefs to the W_Root
	objects)

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -27,7 +27,7 @@
 class W_Root(object):
     """This is the abstract root class of all wrapped objects that live
     in a 'normal' object space like StdObjSpace."""
-    __slots__ = ()
+    __slots__ = ('__weakref__',)
     user_overridden_class = False
 
     def getdict(self, space):
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -911,7 +911,7 @@
 
     def prepare(self, py_obj, w_obj):
         from pypy.module.cpyext.pyobject import track_reference
-        py_obj.c_ob_refcnt = 1
+        py_obj.c_ob_refcnt = 1     # 1 for kept immortal
         track_reference(self.space, py_obj, w_obj)
         self.to_attach.append((py_obj, w_obj))
 
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
@@ -6,7 +6,7 @@
     Py_GE, CONST_STRING, FILEP, fwrite)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
-    track_reference, get_typedescr, _Py_NewReference, RefcountState)
+    get_typedescr, _Py_NewReference, RefcountState)
 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
 from pypy.objspace.std.typeobject import W_TypeObject
@@ -33,7 +33,7 @@
     assert isinstance(w_type, W_TypeObject)
     typedescr = get_typedescr(w_type.instancetypedef)
     py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
-    py_obj.c_ob_refcnt = 0
+    #py_obj.c_ob_refcnt = 0 --- will be set to 1 again by PyObject_Init{Var}
     if type.c_tp_itemsize == 0:
         w_obj = PyObject_Init(space, py_obj, type)
     else:
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -32,14 +32,15 @@
     def allocate(self, space, w_type, itemcount=0):
         # similar to PyType_GenericAlloc?
         # except that it's not related to any pypy object.
+        # this returns a PyObject with ob_refcnt == 1.
 
-        pytype = make_ref(space, w_type)
+        pytype = as_pyobj(space, w_type)
         pytype = rffi.cast(PyTypeObjectPtr, pytype)
         assert pytype
         # Don't increase refcount for non-heaptypes
         flags = rffi.cast(lltype.Signed, pytype.c_tp_flags)
-        if not flags & Py_TPFLAGS_HEAPTYPE:
-            Py_DecRef(space, w_type)
+        if flags & Py_TPFLAGS_HEAPTYPE:
+            Py_IncRef(space, w_type)
 
         if pytype:
             size = pytype.c_tp_basicsize
@@ -170,12 +171,22 @@
     typedescr = get_typedescr(w_obj.typedef)
     py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
     track_reference(space, py_obj, w_obj)
+    #
+    # py_obj.c_ob_refcnt should be exactly REFCNT_FROM_PYPY + 1 here,
+    # and we want only REFCNT_FROM_PYPY, i.e. only count as attached
+    # to the W_Root but not with any reference from the py_obj side.
+    assert py_obj.c_ob_refcnt > rawrefcount.REFCNT_FROM_PYPY
+    py_obj.c_ob_refcnt -= 1
+    #
     typedescr.attach(space, py_obj, w_obj)
     return py_obj
 
 def track_reference(space, py_obj, w_obj):
     """
     Ties together a PyObject and an interpreter object.
+    The PyObject's refcnt is increased by REFCNT_FROM_PYPY.
+    The reference in 'py_obj' is not stolen!  Remember to Py_DecRef()
+    it is you need to.
     """
     # XXX looks like a PyObject_GC_TRACK
     assert py_obj.c_ob_refcnt < rawrefcount.REFCNT_FROM_PYPY
@@ -226,7 +237,6 @@
         py_obj = rawrefcount.from_obj(PyObject, w_obj)
         if not py_obj:
             py_obj = create_ref(space, w_obj)
-            #track_reference(space, py_obj, w_obj) -- included with create_ref()
         return py_obj
     else:
         return lltype.nullptr(PyObject.TO)
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -69,9 +69,9 @@
 
 def new_empty_str(space, length):
     """
-    Allocatse a PyStringObject and its buffer, but without a corresponding
+    Allocate a PyStringObject and its buffer, but without a corresponding
     interpreter object.  The buffer may be mutated, until string_realize() is
-    called.
+    called.  Refcount of the result is 1.
     """
     typedescr = get_typedescr(space.w_str.instancetypedef)
     py_obj = typedescr.allocate(space, space.w_str)
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
@@ -52,7 +52,7 @@
     """
     Allocate a PyTupleObject and its array of PyObject *, but without a
     corresponding interpreter object.  The array may be mutated, until
-    tuple_realize() is called.
+    tuple_realize() is called.  Refcount of the result is 1.
     """
     typedescr = get_typedescr(space.w_tuple.instancetypedef)
     py_obj = typedescr.allocate(space, space.w_tuple)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -44,9 +44,9 @@
 
 def new_empty_unicode(space, length):
     """
-    Allocatse a PyUnicodeObject and its buffer, but without a corresponding
+    Allocate a PyUnicodeObject and its buffer, but without a corresponding
     interpreter object.  The buffer may be mutated, until unicode_realize() is
-    called.
+    called.  Refcount of the result is 1.
     """
     typedescr = get_typedescr(space.w_unicode.instancetypedef)
     py_obj = typedescr.allocate(space, space.w_unicode)


More information about the pypy-commit mailing list