[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