[pypy-commit] pypy gc-del: Fixes

arigo noreply at buildbot.pypy.org
Mon Mar 25 18:55:47 CET 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r62744:5bf139dc8885
Date: 2013-03-25 18:11 +0100
http://bitbucket.org/pypy/pypy/changeset/5bf139dc8885/

Log:	Fixes

diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -37,7 +37,7 @@
         # and in its overriden versions! for the benefit of test_transformed_gc
         self.running_finalizers = False
         self.run_finalizers_queue = self.AddressDeque()
-        self.registered_finalizers = self.AddressDict()
+        self.run_finalizers_funcs = self.AddressDeque()
 
     def post_setup(self):
         # More stuff that needs to be initialized when the GC is already
@@ -333,15 +333,9 @@
 
     def register_finalizer(self, gcobj, llfn):
         llobj = llmemory.cast_ptr_to_adr(gcobj)
-        llfn1 = self.registered_finalizers.get(llobj)
-        if llfn1 == llmemory.NULL:
-            self.registered_finalizers.setitem(llobj, llfn)
-        else:
-            ll_assert(llfn1 == llfn,
-                      "registering multiple different finalizers")
-        self._register_finalizer_set_flag(llobj)
+        self._register_finalizer(llobj, llfn)
 
-    def _register_finalizer_set_flag(self, obj):
+    def _register_finalizer(self, obj, llfn):
         raise NotImplementedError   # must be overridden
 
     def execute_finalizers(self):
@@ -350,15 +344,12 @@
         self.running_finalizers = True
         try:
             while self.run_finalizers_queue.non_empty():
+                func = self.run_finalizers_funcs.peekleft()
                 obj = self.run_finalizers_queue.peekleft()
-                finalizer = self.registered_finalizers.get(obj)
-                ll_assert(finalizer != llmemory.NULL, "lost finalizer")
-                if not self.call_finalizer(finalizer, obj):
+                if not self.call_finalizer(func, obj):
                     break
-                obj1 = self.run_finalizers_queue.popleft()
-                ll_assert(obj1 == obj, "wrong finalized object")
-                self.registered_finalizers.setitem(obj, NULL)
-                # XXX MISSING: must clean up the dict regularly!
+                self.run_finalizers_funcs.popleft()
+                self.run_finalizers_queue.popleft()
         finally:
             self.running_finalizers = False
 
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -302,9 +302,8 @@
         self.old_objects_with_destructors = self.AddressStack()
         #
         # Two lists of all objects with finalizers, and a temporary
-        self.young_objects_with_finalizers = self.AddressStack()
-        self.old_objects_with_finalizers = self.AddressStack()
-        self.pending_objects_with_finalizers = self.AddressStack()
+        self.young_objects_with_finalizers = self.AddressStack()   # (obj,fn)
+        self.old_objects_with_finalizers = self.AddressStack()     # (obj,fn)
         #
         # Two lists of the objects with weakrefs.  No weakref can be an
         # old object weakly pointing to a young object: indeed, weakrefs
@@ -967,12 +966,16 @@
                           "the card marker bits are not cleared")
                 i -= 1
 
-    def _register_finalizer_set_flag(self, obj):
+    def _register_finalizer(self, obj, llfn):
+        if self.header(obj).tid & GCFLAG_HAS_FINALIZER:
+            return    # already have one
         self.header(obj).tid |= GCFLAG_HAS_FINALIZER
         if self.is_young_object(obj):
-            self.young_objects_with_finalizers.append(obj)
+            lst = self.young_objects_with_finalizers
         else:
-            self.old_objects_with_finalizers.append(obj)
+            lst = self.old_objects_with_finalizers
+        lst.append(obj)
+        lst.append(llfn)
 
     # ----------
     # Write barrier
@@ -1892,59 +1895,58 @@
         we also need to copy them out of the nursery.  The tricky part
         here is to enqueue them in topological order, if possible.
         """
-        finalizers_scheduled = self.AddressStack()
         pending = self.old_objects_pointing_to_young
+        ll_assert(not pending.non_empty(),
+                  "deal_with_young_objects_with_finalizers: "
+                  "old_objects_pointing_to_young should be empty")
+        finalizer_funcs = self.AddressDict()
         #
         while self.young_objects_with_finalizers.non_empty():
+            func = self.young_objects_with_finalizers.pop()
             obj = self.young_objects_with_finalizers.pop()
-            ll_assert(not pending.non_empty(),
-                      "deal_with_young_objects_with_finalizers: "
-                      "old_objects_pointing_to_young should be empty")
-            #
-            # Un-register the finalizer, because 'obj' will likely move
-            _finalizer = self.registered_finalizers.get(obj)
-            ll_assert(_finalizer != llmemory.NULL, "lost _finalizer")
-            self.registered_finalizers.setitem(obj, NULL)
             #
             # The following lines move 'obj' out of the nursery and add it to
-            # 'self.old_objects_pointing_to_young', unless the object was
-            # already seen previously, in which case they have no effect.
+            # 'self.old_objects_pointing_to_young'.
             root = self.temp_root
             root.address[0] = obj
             self._trace_drag_out1(root)
             objcopy = root.address[0]
             #
-            # Re-regsiter the finalizer
-            self.registered_finalizers.setitem(objcopy, _finalizer)
-            #
-            # Follow all refs
-            while pending.non_empty():
-                assert not self.old_objects_with_cards_set.non_empty(), "XXX"
+            # Remember the finalizer in the dict
+            finalizer_funcs.setitem(objcopy, func)
+        #
+        # Now follow all the refs
+        finalizers_scheduled = self.AddressStack()
+        while pending.non_empty():
+            assert not self.old_objects_with_cards_set.non_empty(), "XXX"
+            obj = pending.pop()
+            if obj:
+                #
+                if self.header(obj).tid & GCFLAG_HAS_FINALIZER:
+                    self.header(obj).tid &= ~GCFLAG_HAS_FINALIZER
+                    pending.append(obj)
+                    pending.append(NULL)   # marker
+                #
+                ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS
+                          == 0, "bad flags [deal_young_finalizer]")
+                self.header(obj).tid |= GCFLAG_TRACK_YOUNG_PTRS
+                self.trace_and_drag_out_of_nursery(obj)
+                #
+            else:
+                # seen a NULL marker
                 obj = pending.pop()
-                if obj:
-                    #
-                    if self.header(obj).tid & GCFLAG_HAS_FINALIZER:
-                        self.header(obj).tid &= ~GCFLAG_HAS_FINALIZER
-                        pending.append(obj)
-                        pending.append(NULL)   # marker
-                    #
-                    ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS
-                              == 0, "bad flags [deal_young_finalizer]")
-                    self.header(obj).tid |= GCFLAG_TRACK_YOUNG_PTRS
-                    self.trace_and_drag_out_of_nursery(obj)
-                    #
-                else:
-                    # seen a NULL marker
-                    obj = pending.pop()
-                    finalizers_scheduled.append(obj)
-            # End of loop
+                finalizers_scheduled.append(obj)
         #
         # Copy the objects scheduled into 'run_finalizers_queue', in
         # reverse order.
         while finalizers_scheduled.non_empty():
             obj = finalizers_scheduled.pop()
+            func = finalizer_funcs.get(obj)
+            ll_assert(func != llmemory.NULL, "lost finalizer [1]")
             self.run_finalizers_queue.append(obj)
+            self.run_finalizers_funcs.append(func)
         finalizers_scheduled.delete()
+        finalizer_funcs.delete()
 
 
     def deal_with_old_objects_with_finalizers(self):


More information about the pypy-commit mailing list