[pypy-commit] pypy gc-del: intermediate checkin, probably going to be partially reverted
arigo
noreply at buildbot.pypy.org
Tue Mar 26 00:25:00 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r62769:c5a0ce8bcab3
Date: 2013-03-26 00:24 +0100
http://bitbucket.org/pypy/pypy/changeset/c5a0ce8bcab3/
Log: intermediate checkin, probably going to be partially reverted
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
@@ -1243,6 +1243,7 @@
#
# Before everything else, remove from 'old_objects_pointing_to_young'
# the young arrays.
+ self.remember_young_rawmalloced_visited = None
if self.young_rawmalloced_objects:
self.remove_young_arrays_from_old_objects_pointing_to_young()
#
@@ -1492,7 +1493,7 @@
# We will fix such references to point to the copy of the young
# objects when we walk 'old_objects_pointing_to_young'.
self.old_objects_pointing_to_young.append(newobj)
- #debug_print("adding", newobj)
+ debug_print("adding", newobj)
_trace_drag_out._always_inline_ = True
def _visit_young_rawmalloced_object(self, obj):
@@ -1522,6 +1523,10 @@
added_somewhere = True
#
ll_assert(added_somewhere, "wrong flag combination on young array")
+ #
+ # If 'remember_young_rawmalloced_visited', record it there as well
+ if self.remember_young_rawmalloced_visited:
+ self.remember_young_rawmalloced_visited.append(obj)
def _malloc_out_of_nursery(self, totalsize):
@@ -1922,85 +1927,75 @@
objects with finalizers. As these survive for a bit longer,
we also need to copy them out of the nursery. The tricky part
here is to enqueue them in topological order, if possible.
+
+ This is done as three steps: first we find which objects are
+ not reachable at all from 'outside'; then we copy them outside
+ the nursery together with everything they point to; and finally
+ we use on them the generic _deal_with_objects_with_finalizers().
"""
ll_assert(not self.old_objects_pointing_to_young.non_empty(),
"deal_with_young_objects_with_finalizers: "
"old_objects_pointing_to_young should be empty")
+ ll_assert(not self.objects_to_trace.non_empty(),
+ "objects_to_trace non empty [deal_young_finalizer]")
finalizer_funcs = self.AddressDict()
- self.finalizers_scheduled = self.AddressStack()
#
while self.young_objects_with_finalizers.non_empty():
func = self.young_objects_with_finalizers.pop()
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' --- 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)
- objcopy = root.address[0]
- #debug_print("finalizer for", obj)
- #debug_print("object moving to", objcopy)
+ survives = False
#
- # Remember the finalizer in the dict
- finalizer_funcs.setitem(objcopy, func)
+ if self.is_in_nursery(obj):
+ if self.is_forwarded(obj):
+ obj = self.get_forwarding_address(obj)
+ survives = True
+ else:
+ #
+ # The following lines move 'obj' out of the nursery and
+ # add it to 'self.old_objects_pointing_to_young'.
+ root = self.temp_root
+ root.address[0] = obj
+ self._trace_drag_out1(root)
+ obj = root.address[0]
#
- # Now follow all the refs
- self._follow_references_from_young_object_with_finalizer()
+ elif (bool(self.young_rawmalloced_objects) and
+ self.young_rawmalloced_objects.contains(obj)):
+ if self.header(obj).tid & GCFLAG_VISITED:
+ survives = True
+ #
+ if survives:
+ self.old_objects_with_finalizers.append(obj)
+ self.old_objects_with_finalizers.append(func)
+ else:
+ # Remember the finalizer in the dict
+ finalizer_funcs.setitem(obj, func)
+ self.objects_to_trace.append(obj)
#
- # Copy the objects scheduled into 'run_finalizers_queue', in
- # reverse order.
- while self.finalizers_scheduled.non_empty():
- obj = self.finalizers_scheduled.pop()
- func = finalizer_funcs.get(obj)
- ll_assert(func != NULL, "lost finalizer [1]")
- self.run_finalizers_queue.append(obj)
- self.run_finalizers_funcs.append(func)
- finalizer_funcs.setitem(obj, NULL)
- self.finalizers_scheduled.delete()
+ # Follow all refs
+ self.remember_young_rawmalloced_visited = self.AddressStack()
+ self.collect_oldrefs_to_nursery()
#
- # 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()
+ # Reset GCFLAG_VISITED on young rawmalloced objects added just before
+ self.remember_young_rawmalloced_visited.foreach(
+ self._remove_gcflag_visited, None)
+ self.remember_young_rawmalloced_visited.delete()
+ self.remember_young_rawmalloced_visited = None
+ #
+ # At this point all objects reachable from 'finalizer_funcs'
+ # are disconnected from the rest of the world, and none has
+ # the GCFLAG_VISITED set. Use the generic method.
+ self._deal_with_objects_with_finalizers(finalizer_funcs)
- def _follow_references_from_young_object_with_finalizer(self):
- pending = self.old_objects_pointing_to_young
- while pending.non_empty():
- assert not self.old_objects_with_cards_set.non_empty(), "XXX"
- obj = pending.pop()
- #debug_print("popping", obj)
- if obj:
- #
- if self.header(obj).tid & GCFLAG_HAS_FINALIZER:
- self.header(obj).tid &= ~GCFLAG_HAS_FINALIZER
- #debug_print("this object has a 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()
- #debug_print("adding to scheduled", obj)
- self.finalizers_scheduled.append(obj)
- @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 _remove_gcflag_visited(self, obj, ignored):
+ # 'obj' has GCFLAG_VISITED; remove it.
+ ll_assert(self.header(obj).tid & GCFLAG_VISITED != 0,
+ "remove_gcflag_visited: not?")
+ self.header(obj).tid &= ~GCFLAG_VISITED
- def deal_with_old_objects_with_finalizers(self):
+ def _deal_with_objects_with_finalizers(self, finalizer_funcs):
# 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.
@@ -2008,28 +2003,7 @@
# CPython does. The details of this algorithm are in
# pypy/doc/discussion/finalizer-order.txt.
#
- ll_assert(not self.objects_to_trace.non_empty(),
- "objects_to_trace non empty [deal_old_finalizer]")
- #
- old_objs = self.old_objects_with_finalizers
- self.old_objects_with_finalizers = self.AddressStack()
- finalizer_funcs = self.AddressDict()
- #
- while old_objs.non_empty():
- func = old_objs.pop()
- obj = old_objs.pop()
- ll_assert(bool(self.header(obj).tid & GCFLAG_HAS_FINALIZER),
- "lost GCFLAG_HAS_FINALIZER")
- #
- if self.header(obj).tid & GCFLAG_VISITED:
- # surviving
- self.old_objects_with_finalizers.append(obj)
- self.old_objects_with_finalizers.append(func)
- #
- else:
- # dying
- self.objects_to_trace.append(obj)
- finalizer_funcs.setitem(obj, func)
+ xxxxxxxxxxx
#
# Now follow all the refs
finalizers_scheduled = self.AddressStack()
@@ -2063,6 +2037,33 @@
old_objs.delete()
+ def deal_with_old_objects_with_finalizers(self):
+ ll_assert(not self.objects_to_trace.non_empty(),
+ "objects_to_trace non empty [deal_old_finalizer]")
+ #
+ old_objs = self.old_objects_with_finalizers
+ self.old_objects_with_finalizers = self.AddressStack()
+ finalizer_funcs = self.AddressDict()
+ #
+ while old_objs.non_empty():
+ func = old_objs.pop()
+ obj = old_objs.pop()
+ ll_assert(bool(self.header(obj).tid & GCFLAG_HAS_FINALIZER),
+ "lost GCFLAG_HAS_FINALIZER")
+ #
+ if self.header(obj).tid & GCFLAG_VISITED:
+ # surviving
+ self.old_objects_with_finalizers.append(obj)
+ self.old_objects_with_finalizers.append(func)
+ #
+ else:
+ # dying
+ self.objects_to_trace.append(obj)
+ finalizer_funcs.setitem(obj, func)
+ #
+ self._deal_with_objects_with_finalizers(finalizer_funcs)
+
+
# ----------
# Weakrefs
diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py
--- a/rpython/memory/test/snippet.py
+++ b/rpython/memory/test/snippet.py
@@ -12,6 +12,7 @@
def definestr_finalizer_order(cls):
import random
x = random.randrange(0,10000)
+ x = 2696
print "R"*1000
print x
print '-'*60
@@ -19,7 +20,7 @@
from rpython.tool.algo import graphlib
cls.finalizer_order_examples = examples = []
- if cls.large_tests_ok:
+ if 1: # cls.large_tests_ok:
letters = 'abcdefghijklmnopqrstuvwxyz'
COUNT = 20
else:
@@ -76,7 +77,7 @@
vertices[c].refs.append(vertices[d])
def f(_):
- i = 0
+ i = 2
while i < len(examples):
debug_print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
input, components, strict = examples[i]
diff --git a/rpython/memory/test/test_gc.py b/rpython/memory/test/test_gc.py
--- a/rpython/memory/test/test_gc.py
+++ b/rpython/memory/test/test_gc.py
@@ -1060,8 +1060,8 @@
GC_PARAMS = {'card_page_indices': 4}
class TestMiniMarkGCLargeNursery(TestMiniMarkGC):
- GC_PARAMS = {'nursery_size': 1024*WORD}
- def setup_class(cls):
- py.test.skip("takes a lot of extra time to run")
- def teardown_class(cls):
- pass
+ GC_PARAMS = {'nursery_size': 16384*WORD}
+ #def setup_class(cls):
+ # py.test.skip("takes a lot of extra time to run")
+ #def teardown_class(cls):
+ # pass
More information about the pypy-commit
mailing list