[pypy-commit] pypy cpyext-gc-cycle: Fixed issues with rrc tuples

stevie_92 pypy.commits at gmail.com
Sat Oct 5 04:50:52 EDT 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r97728:6e21fe036218
Date: 2019-10-05 10:50 +0200
http://bitbucket.org/pypy/pypy/changeset/6e21fe036218/

Log:	Fixed issues with rrc tuples Implemented cpyext statistics

diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -8,6 +8,7 @@
 from rpython.rlib import rawrefcount
 from rpython.rlib.debug import debug_print
 import sys
+import time
 
 
 # Keep track of exceptions raised in cpyext for a particular execution
@@ -159,6 +160,10 @@
                 space.actionflag.register_periodic_action(action,
                     use_bytecode_counter=True)
             else:
+                module = space.builtin_modules['gc']
+                attribute = space.newtext('cpyext_durations')
+                space.setattr(module, attribute, space.newlist([]))
+
                 pyobj_dealloc_action = PyObjDeallocAction(space)
                 self.dealloc_trigger = lambda: pyobj_dealloc_action.fire()
 
@@ -310,12 +315,14 @@
         return True
 
 
-def _rawrefcount_perform(space):
+def _rawrefcount_perform(space): # TODO: measure time spent, make incremental??
     from pypy.interpreter.baseobjspace import W_Root
     from pypy.module.cpyext.pyobject import (PyObject, incref, decref,
                                              finalize, from_ref, cts)
     from pypy.module.cpyext.api import generic_cpy_call
 
+    start = time.time()
+
     while True:
         py_obj = rawrefcount.next_dead(PyObject)
         if not py_obj:
@@ -337,11 +344,11 @@
         pto = pyobj.c_ob_type
         if pto.c_tp_clear:
             incref(space, py_obj)
-            if pto and pto.c_tp_name:
-                tp_name = pto.c_tp_name
-                name = rffi.charp2str(cts.cast('char*', tp_name))
-                debug_print("tp_clear", pyobj, ": type", pto,
-                            ": name", name)
+            #if pto and pto.c_tp_name:
+            #    tp_name = pto.c_tp_name
+            #    name = rffi.charp2str(cts.cast('char*', tp_name))
+            #    debug_print("tp_clear", pyobj, ": type", pto,
+            #                ": name", name)
             generic_cpy_call(space, pto.c_tp_clear, pyobj)
             decref(space, py_obj)
         head = rawrefcount.cyclic_garbage_head(PyObject)
@@ -365,6 +372,11 @@
                   w_list)
     rawrefcount.end_garbage()
 
+    duration = time.time() - start
+    module = space.builtin_modules['gc']
+    durations = space.getattr(module, space.newtext('cpyext_durations'))
+    durations.append(space.newfloat(duration))
+
 class PyObjDeallocAction(executioncontext.AsyncAction):
     """An action that invokes _Py_Dealloc() on the dying PyObjects.
     """
diff --git a/rpython/memory/gc/rrc/incmark.py b/rpython/memory/gc/rrc/incmark.py
--- a/rpython/memory/gc/rrc/incmark.py
+++ b/rpython/memory/gc/rrc/incmark.py
@@ -258,7 +258,8 @@
                 addr = self.snapshot_refs[obj.refs_index + j]
                 obj_ref = llmemory.cast_adr_to_ptr(addr,
                                                    self.PYOBJ_SNAPSHOT_OBJ_PTR)
-                obj_ref.refcnt -= 1
+                if obj_ref != lltype.nullptr(self.PYOBJ_SNAPSHOT_OBJ):
+                    obj_ref.refcnt -= 1
 
         # now all rawrefcounted roots or live border objects have a
         # refcount > 0
@@ -299,7 +300,8 @@
                 addr = self.snapshot_refs[snapobj.refs_index + j]
                 obj_ref = llmemory.cast_adr_to_ptr(addr,
                                                    self.PYOBJ_SNAPSHOT_OBJ_PTR)
-                obj_ref.refcnt += 1
+                if obj_ref != lltype.nullptr(self.PYOBJ_SNAPSHOT_OBJ):
+                    obj_ref.refcnt += 1
             # mark recursively, if it is a pypyobj
             if snapobj.pypy_link <> 0:
                 intobj = snapobj.pypy_link
@@ -320,6 +322,10 @@
             total_refcnt += self._take_snapshot_count_gc(pygchdr)
             total_objs += 1
             pygchdr = pygchdr.c_gc_next
+        pygchdr = self.tuple_list.c_gc_next
+        while pygchdr <> self.tuple_list:
+            total_refcnt += self._take_snapshot_count_gc(pygchdr)
+            pygchdr = pygchdr.c_gc_next
         pygchdr = self.pyobj_isolate_old_list.c_gc_next
         while pygchdr <> self.pyobj_isolate_old_list:
             total_refcnt += self._take_snapshot_count_gc(pygchdr)
@@ -364,7 +370,10 @@
             pygchdr = self.pyobj_as_gc(pyobj)
             if (pygchdr <> lltype.nullptr(self.PYOBJ_GC_HDR) and
                 pygchdr.c_gc_refs != self.RAWREFCOUNT_REFS_UNTRACKED):
-                obj = self.snapshot_objs[pygchdr.c_gc_refs - 1]
+                if pygchdr.c_gc_refs > 0:
+                    obj = self.snapshot_objs[pygchdr.c_gc_refs - 1]
+                else:
+                    obj = lltype.nullptr(self.PYOBJ_SNAPSHOT_OBJ)
             else:
                 obj = self.snapshot_objs[pyobj.c_ob_pypy_link - 1]
             self.snapshot_refs[i] = llmemory.cast_ptr_to_adr(obj)
diff --git a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot b/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
--- a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
+++ b/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
@@ -1,5 +1,5 @@
 digraph G {
-    "a" [type=C, alive=n, tuple=y];
+    "a" [type=C, alive=n, tuple=1];
     "b" [type=C, alive=n];
     "a" -> "b";
     "b" -> "a";
diff --git a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot b/rpython/memory/gc/test/dot/free_cpython_tuple_2.dot
copy from rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
copy to rpython/memory/gc/test/dot/free_cpython_tuple_2.dot
--- a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
+++ b/rpython/memory/gc/test/dot/free_cpython_tuple_2.dot
@@ -1,6 +1,5 @@
 digraph G {
-    "a" [type=C, alive=n, tuple=y];
-    "b" [type=C, alive=n];
+    "a" [type=C, alive=y, ext_refcnt=1];
+    "b" [type=C, alive=y, tuple=0];
     "a" -> "b";
-    "b" -> "a";
 }
diff --git a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot b/rpython/memory/gc/test/dot/free_cpython_tuple_3.dot
copy from rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
copy to rpython/memory/gc/test/dot/free_cpython_tuple_3.dot
--- a/rpython/memory/gc/test/dot/free_cpython_tuple_1.dot
+++ b/rpython/memory/gc/test/dot/free_cpython_tuple_3.dot
@@ -1,6 +1,5 @@
 digraph G {
-    "a" [type=C, alive=n, tuple=y];
-    "b" [type=C, alive=n];
+    "a" [type=C, alive=y, ext_refcnt=1];
+    "b" [type=C, alive=y, tuple=2];
     "a" -> "b";
-    "b" -> "a";
 }
diff --git a/rpython/memory/gc/test/test_rawrefcount.py b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -43,6 +43,7 @@
         self.pyobj_resurrect = {}
         self.pyobj_delete = {}
         self.is_pygc = []
+        self.tupletypes = []
 
         def rawrefcount_tp_traverse(obj, callback, args):
             refs = self.pyobj_refs[self.pyobjs.index(obj)]
@@ -73,13 +74,19 @@
                 return RAWREFCOUNT_FINALIZER_NONE
 
         def rawrefcount_tuple_maybe_untrack(obj):
-            #if foo:
-            #    gchdr = rawrefcount_pyobj_as_gc(obj)
-            #    next = gchdr.c_gc_next
-            #    next.c_gc_prev = gchdr.c_gc_prev
-            #    gchdr.c_gc_prev.c_gc_next = next
-            #    return 0
-            return 1 # TODO: add tests for 0 ("plain" tuple) and 2 (uninitialized)
+            index = self.pyobjs.index(obj)
+            if self.tupletypes[index] == '0':
+                gchdr = self.gcobjs[index]
+                next = gchdr.c_gc_next
+                next.c_gc_prev = gchdr.c_gc_prev
+                gchdr.c_gc_prev.c_gc_next = next
+                return 0
+            elif self.tupletypes[index] == '1':
+                return 1
+            elif self.tupletypes[index] == '2':
+                return 2
+            else:
+                assert False
 
         self.pyobj_list = lltype.malloc(PYOBJ_GC_HDR_PTR.TO, flavor='raw',
                                         immortal=True)
@@ -146,7 +153,7 @@
         return p1, p1ref, check_alive
 
     def _rawrefcount_pyobj(self, create_immortal=False, is_gc=True,
-                           tracked=True, tuple=tuple):
+                           tracked=True, tuple=False, tuple_type=None):
         r1 = lltype.malloc(PYOBJ_HDR, flavor='raw',
                            immortal=create_immortal)
         r1.c_ob_refcnt = 0
@@ -157,6 +164,7 @@
             self._rawrefcount_add_gc(tracked, tuple)
         else:
             self.gcobjs.append(lltype.nullptr(PYOBJ_GC_HDR))
+        self.tupletypes.append(tuple_type)
 
         self.pyobjs.append(r1)
         self.is_pygc.append(is_gc)
@@ -171,7 +179,7 @@
     def _rawrefcount_pair(self, intval, is_light=False, is_pyobj=False,
                           create_old=False, create_immortal=False,
                           rooted=False, force_external=False, is_gc=True,
-                          tracked=True, tuple=tuple):
+                          tracked=True, tuple=False, tuple_type=None):
         if is_light:
             rc = REFCNT_FROM_PYPY_LIGHT
         else:
@@ -207,6 +215,7 @@
             self._rawrefcount_add_gc(tracked, tuple)
         else:
             self.gcobjs.append(lltype.nullptr(PYOBJ_GC_HDR))
+        self.tupletypes.append(tuple_type)
 
         self.pyobjs.append(r1)
         self.is_pygc.append(is_gc)
@@ -558,7 +567,8 @@
             resurrect = attr['resurrect'] if 'resurrect' in attr else None
             delete = attr['delete'] if 'delete' in attr else None
             garbage = True if 'garbage' in attr else False
-            tuple = attr['tuple'] == "y" if 'tuple' in attr else False
+            tuple = True if 'tuple' in attr else False
+            tuple_type = attr['tuple'] if 'tuple' in attr else None
             gc = attr['gc'] == "y" if 'gc' in attr else True
             added = attr['added'] if 'added' in attr else None
             info = NodeInfo(type, alive, ext_refcnt, finalizer, resurrect,
@@ -569,7 +579,7 @@
                     add_pyobj_after_snap.append(nodes[name])
                 else:
                     r, raddr, check_alive = self._rawrefcount_pyobj(
-                        tracked=tracked, tuple=tuple)
+                        tracked=tracked, tuple=tuple, tuple_type=tuple_type)
                     r.c_ob_refcnt += ext_refcnt
                     nodes[name] = CPythonNode(r, raddr, check_alive, info)
             elif type == "P":
@@ -600,7 +610,7 @@
                         self._rawrefcount_pair(42 + i, rooted=rooted,
                                                create_old=True,
                                                tracked=tracked, tuple=tuple,
-                                               is_gc=gc)
+                                               tuple_type=tuple_type, is_gc=gc)
                     r.c_ob_refcnt += ext_refcnt
                     nodes[name] = BorderNode(p, pref, r, raddr, check_alive,
                                              info)


More information about the pypy-commit mailing list