[pypy-commit] pypy cpyext-gc-support: Pass one test and a half

arigo noreply at buildbot.pypy.org
Fri Oct 16 13:08:58 EDT 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support
Changeset: r80286:937683219fcd
Date: 2015-10-16 19:09 +0200
http://bitbucket.org/pypy/pypy/changeset/937683219fcd/

Log:	Pass one test and a half

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -1602,6 +1602,10 @@
                 self._visit_old_objects_pointing_to_pinned, None)
             current_old_objects_pointing_to_pinned.delete()
         #
+        # visit the P list from rawrefcount, if enabled.
+        if self.rrc_enabled:
+            self.rrc_minor_collection_trace()
+        #
         while True:
             # If we are using card marking, do a partial trace of the arrays
             # that are flagged with GCFLAG_CARDS_SET.
@@ -1650,6 +1654,10 @@
         if self.young_rawmalloced_objects:
             self.free_young_rawmalloced_objects()
         #
+        # visit the P and O lists from rawrefcount, if enabled.
+        if self.rrc_enabled:
+            self.rrc_minor_collection_free()
+        #
         # All live nursery objects are out of the nursery or pinned inside
         # the nursery.  Create nursery barriers to protect the pinned objects,
         # fill the rest of the nursery with zeros and reset the current nursery
@@ -2734,10 +2742,16 @@
     # ----------
     # RawRefCount
 
-    OB_REFCNT    = 0
-    OB_PYPY_LINK = 1
+    rrc_enabled = False
 
-    rrc_enabled = False
+    _ADDRARRAY = lltype.Array(llmemory.Address, hints={'nolength': True})
+    PYOBJ_HDR = lltype.Struct('GCHdr_PyObject',
+                              ('ob_refcnt', lltype.Signed),
+                              ('ob_pypy_link', lltype.Signed))
+    PYOBJ_HDR_PTR = lltype.Ptr(PYOBJ_HDR)
+
+    def _pyobj(self, pyobjaddr):
+        return llmemory.cast_adr_to_ptr(pyobjaddr, self.PYOBJ_HDR_PTR)
 
     def rawrefcount_init(self):
         # see pypy/doc/discussion/rawrefcount.rst
@@ -2747,17 +2761,20 @@
             self.rrc_o_list_young = self.AddressStack()
             self.rrc_o_list_old   = self.AddressStack()
             self.rrc_dict         = self.AddressDict()
+            p = lltype.malloc(self._ADDRARRAY, 1, flavor='raw',
+                              track_allocation=False)
+            self.rrc_singleaddr = llmemory.cast_ptr_to_adr(p)
             self.rrc_enabled = True
 
     def rawrefcount_create_link_pypy(self, gcobj, pyobject):
         ll_assert(self.rrc_enabled, "rawrefcount.init not called")
         obj = llmemory.cast_ptr_to_adr(gcobj)
         if self.is_young_object(obj):
-            self.rrc_p_list_young.append(obj)
+            self.rrc_p_list_young.append(pyobject)
         else:
-            self.rrc_p_list_old.append(obj)
+            self.rrc_p_list_old.append(pyobject)
         objint = llmemory.cast_adr_to_int(obj, mode="symbolic")
-        pyobject.signed[self.OB_PYPY_LINK] = objint
+        self._pyobj(pyobject).ob_pypy_link = objint
         self.rrc_dict.setitem(obj, pyobject)
 
     def rawrefcount_from_obj(self, gcobj):
@@ -2765,5 +2782,67 @@
         return self.rrc_dict.get(obj)
 
     def rawrefcount_to_obj(self, pyobject):
-        obj = llmemory.cast_int_to_adr(pyobject.signed[self.OB_PYPY_LINK])
+        obj = llmemory.cast_int_to_adr(self._pyobj(pyobject).ob_pypy_link)
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
+
+
+    def rrc_minor_collection_trace(self):
+        self.rrc_p_list_young.foreach(self._rrc_minor_trace,
+                                      self.rrc_singleaddr)
+
+    def _rrc_minor_trace(self, pyobject, singleaddr):
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
+        #
+        rc = self._pyobj(pyobject).ob_refcnt
+        if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_DIRECT:
+            pass     # the corresponding object may die
+        else:
+            # force the corresponding object to be alive
+            intobj = self._pyobj(pyobject).ob_pypy_link
+            singleaddr.address[0] = llmemory.cast_int_to_adr(intobj)
+            self._trace_drag_out(singleaddr, llmemory.NULL)
+
+    def rrc_minor_collection_free(self):
+        lst = self.rrc_p_list_young
+        while lst.non_empty():
+            self._rrc_minor_free(lst.pop(), self.rrc_p_list_old)
+
+    def _rrc_minor_free(self, pyobject, add_into_list):
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
+        #
+        intobj = self._pyobj(pyobject).ob_pypy_link
+        obj = llmemory.cast_int_to_adr(intobj)
+        if self.is_in_nursery(obj):
+            if self.is_forwarded(obj):
+                # Common case: survives and moves
+                obj = self.get_forwarding_address(obj)
+                intobj = llmemory.cast_adr_to_int(obj, mode="symbolic")
+                self._pyobj(pyobject).ob_pypy_link = intobj
+                self.rrc_dict.setitem(obj, pyobject)
+                surviving = True
+            else:
+                surviving = False
+        elif (bool(self.young_rawmalloced_objects) and
+              self.young_rawmalloced_objects.contains(pointing_to)):
+            # young weakref to a young raw-malloced object
+            if self.header(pointing_to).tid & GCFLAG_VISITED_RMY:
+                surviving = True    # survives, but does not move
+            else:
+                surviving = False
+        #
+        if surviving:
+            add_into_list.append(obj)
+        else:
+            rc = self._pyobj(pyobject).ob_refcnt
+            if rc == self.REFCNT_FROM_PYPY_DIRECT:
+                llmemory.raw_free(pyobject)
+            else:
+                if rc > self.REFCNT_FROM_PYPY_DIRECT:
+                    rc -= self.REFCNT_FROM_PYPY_DIRECT
+                else:
+                    rc -= self.REFCNT_FROM_PYPY
+                    if rc == 0:
+                        xxx  # _Py_Dealloc(pyobject)
+                self._pyobj(pyobject).ob_refcnt = rc
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
@@ -4,11 +4,8 @@
 from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
 from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
 
-PYOBJ_HDR = lltype.Array(lltype.Signed, hints={'nolength': True})
-PYOBJ_HDR_PTR = lltype.Ptr(PYOBJ_HDR)
-
-OB_REFCNT = IncrementalMiniMarkGC.OB_REFCNT
-OB_PYPY_LINK = IncrementalMiniMarkGC.OB_PYPY_LINK
+PYOBJ_HDR = IncrementalMiniMarkGC.PYOBJ_HDR
+PYOBJ_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_HDR_PTR
 
 S = lltype.GcForwardReference()
 S.become(lltype.GcStruct('S',
@@ -29,9 +26,9 @@
         p1 = self.malloc(S)
         p1.x = intval
         p1ref = lltype.cast_opaque_ptr(llmemory.GCREF, p1)
-        r1 = lltype.malloc(PYOBJ_HDR, 3, flavor='raw')
-        r1[OB_REFCNT] = rc
-        r1[OB_PYPY_LINK] = 0
+        r1 = lltype.malloc(PYOBJ_HDR, flavor='raw')
+        r1.ob_refcnt = rc
+        r1.ob_pypy_link = 0
         r1addr = llmemory.cast_ptr_to_adr(r1)
         self.gc.rawrefcount_init()
         if is_pyobj:
@@ -39,8 +36,8 @@
             self.gc.rawrefcount_create_link_pyobj(p1ref, r1addr)
         else:
             self.gc.rawrefcount_create_link_pypy(p1ref, r1addr)
-        assert r1[OB_REFCNT] == rc
-        assert r1[OB_PYPY_LINK] != 0
+        assert r1.ob_refcnt == rc
+        assert r1.ob_pypy_link != 0
         return p1, p1ref, r1, r1addr
 
     def test_rawrefcount_objects_basic(self):
@@ -48,13 +45,13 @@
         p2 = self.malloc(S)
         p2.x = 84
         p2ref = lltype.cast_opaque_ptr(llmemory.GCREF, p2)
-        r2 = lltype.malloc(PYOBJ_HDR, 3, flavor='raw')
-        r2[0] = 1
-        r2[1] = 0
+        r2 = lltype.malloc(PYOBJ_HDR, flavor='raw')
+        r2.ob_refcnt = 1
+        r2.ob_pypy_link = 0
         r2addr = llmemory.cast_ptr_to_adr(r2)
         # p2 and r2 are not linked
-        assert r1[1] != 0
-        assert r2[1] == 0
+        assert r1.ob_pypy_link != 0
+        assert r2.ob_pypy_link == 0
         assert self.gc.rawrefcount_from_obj(p1ref) == r1addr
         assert self.gc.rawrefcount_from_obj(p2ref) == llmemory.NULL
         assert self.gc.rawrefcount_to_obj(r1addr) == p1ref
@@ -66,11 +63,11 @@
     def test_rawrefcount_objects_collection_survives_from_raw(self):
         for do_collect in [self.gc.minor_collection, self.gc.collect] * 2:
             p1, p1ref, r1, r1addr = self._rawrefcount_pair(42, is_direct=True)
-            assert r1.c_ob_refcnt == REFCNT_FROM_PYPY_DIRECT
+            assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT
             r1.ob_refcnt += 1
             do_collect()
-            assert r1.ob_refcnt == REFCNT_FROM_PYPY_OBJECT + 1
-            assert r1.ob_pypy_link != llmemory.NULL
+            assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT + 1
+            assert r1.ob_pypy_link != 0
             p1ref = self.gc.rawrefcount_to_obj(r1addr)
             assert lltype.cast_opaque_ptr(lltype.Ptr(S), p1ref).x == 42
             assert self.gc.rawrefcount_from_obj(p1ref) == r1addr


More information about the pypy-commit mailing list