[pypy-commit] pypy gc-del: Record surviving young objects with finalizers.
arigo
noreply at buildbot.pypy.org
Mon Mar 25 18:55:48 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r62745:53d11c6f0880
Date: 2013-03-25 18:29 +0100
http://bitbucket.org/pypy/pypy/changeset/53d11c6f0880/
Log: Record surviving young objects with finalizers.
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
@@ -1596,8 +1596,8 @@
# with a finalizer and all objects reachable from there (and also
# moves some objects from 'objects_with_finalizers' to
# 'run_finalizers').
- #if self.objects_with_finalizers.non_empty():
- # self.deal_with_objects_with_finalizers()
+ if self.old_objects_with_finalizers.non_empty():
+ self.deal_with_old_objects_with_finalizers()
#
self.objects_to_trace.delete()
#
@@ -1880,11 +1880,29 @@
if not self.is_forwarded(obj):
destructor = self.getdestructor(self.get_type_id(obj))
ll_assert(bool(destructor), "destructor missing")
- destructor(obj, llmemory.NULL)
+ destructor(obj, NULL)
else:
obj = self.get_forwarding_address(obj)
self.old_objects_with_destructors.append(obj)
+ def deal_with_old_objects_with_destructors(self):
+ """Same as deal_with_young_objects_with_destructors(), but for
+ old objects.
+ """
+ new_objects = self.AddressStack()
+ while self.old_objects_with_destructors.non_empty():
+ obj = self.old_objects_with_destructors.pop()
+ if self.header(obj).tid & GCFLAG_VISITED:
+ # surviving
+ new_objects.append(obj)
+ else:
+ # dying
+ destructor = self.getdestructor(self.get_type_id(obj))
+ ll_assert(bool(destructor), "no light finalizer found")
+ destructor(obj, NULL)
+ self.old_objects_with_destructors.delete()
+ self.old_objects_with_destructors = new_objects
+
# ----------
# Finalizers
@@ -1906,7 +1924,9 @@
obj = self.young_objects_with_finalizers.pop()
#
# The following lines move 'obj' out of the nursery and add it to
- # 'self.old_objects_pointing_to_young'.
+ # 'self.old_objects_pointing_to_young' --- unless the object
+ # survive, in which case it was already seen and the following
+ # lines have no effect.
root = self.temp_root
root.address[0] = obj
self._trace_drag_out1(root)
@@ -1942,36 +1962,27 @@
while finalizers_scheduled.non_empty():
obj = finalizers_scheduled.pop()
func = finalizer_funcs.get(obj)
- ll_assert(func != llmemory.NULL, "lost finalizer [1]")
+ ll_assert(func != NULL, "lost finalizer [1]")
self.run_finalizers_queue.append(obj)
self.run_finalizers_funcs.append(func)
+ finalizer_funcs.setitem(obj, NULL)
finalizers_scheduled.delete()
+ #
+ # The non-NULL entries remaining in 'finalizer_funcs' correspond
+ # to objects that survived, because they have not been traced by
+ # this function but already before.
+ finalizer_funcs.foreach(self._move_to_old_finalizer,
+ self.old_objects_with_finalizers)
finalizer_funcs.delete()
+ @staticmethod
+ def _move_to_old_finalizer(obj, finalizer, old_objects_with_finalizers):
+ if finalizer != NULL:
+ old_objects_with_finalizers.append(obj)
+ old_objects_with_finalizers.append(finalizer)
+
def deal_with_old_objects_with_finalizers(self):
- """ This is a much simpler version of dealing with finalizers
- and an optimization - we can reasonably assume that those finalizers
- don't do anything fancy and *just* call them. Among other things
- they won't resurrect objects
- """
- XXXX
- new_objects = self.AddressStack()
- while self.old_objects_with_light_finalizers.non_empty():
- obj = self.old_objects_with_light_finalizers.pop()
- if self.header(obj).tid & GCFLAG_VISITED:
- # surviving
- new_objects.append(obj)
- else:
- # dying
- finalizer = self.getlightfinalizer(self.get_type_id(obj))
- ll_assert(bool(finalizer), "no light finalizer found")
- finalizer(obj, llmemory.NULL)
- self.old_objects_with_light_finalizers.delete()
- self.old_objects_with_light_finalizers = new_objects
-
- def deal_with_objects_with_finalizers(self):
- XXXXXXXXX
# Walk over list of objects with finalizers.
# If it is not surviving, add it to the list of to-be-called
# finalizers and make it survive, to make the finalizer runnable.
More information about the pypy-commit
mailing list