Author: Armin Rigo <[email protected]>
Branch:
Changeset: r92380:90a0d3659179
Date: 2017-09-14 00:32 +0200
http://bitbucket.org/pypy/pypy/changeset/90a0d3659179/
Log: Found out that gc.get_objects() returns some, but not all, objects
with finalizers, in some strange way. More precisely, it completely
misses objects with finalizers that have recently become
unreachable, but it no longer misses these objects after the next
major collection occurred.
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
@@ -336,6 +336,7 @@
callback2, attrname = _convert_callback_formats(callback) # :-/
setattr(self, attrname, arg)
self.root_walker.walk_roots(callback2, callback2, callback2)
+ self.enum_live_with_finalizers(callback, arg)
self.enum_pending_finalizers(callback, arg)
enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
@@ -348,6 +349,12 @@
i += 1
enum_pending_finalizers._annspecialcase_ = 'specialize:arg(1)'
+ def enum_live_with_finalizers(self, callback, arg):
+ # as far as possible, enumerates the live objects with finalizers,
+ # even if they have not been detected as unreachable yet (but may be)
+ pass
+ enum_live_with_finalizers._annspecialcase_ = 'specialize:arg(1)'
+
def _copy_pending_finalizers_deque(self, deque, copy_fn):
tmp = self.AddressDeque()
while deque.non_empty():
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
@@ -2515,6 +2515,11 @@
MovingGCBase.enumerate_all_roots(self, callback, arg)
enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
+ def enum_live_with_finalizers(self, callback, arg):
+ self.probably_young_objects_with_finalizers.foreach(callback, arg, 2)
+ self.old_objects_with_finalizers.foreach(callback, arg, 2)
+ enum_live_with_finalizers._annspecialcase_ = 'specialize:arg(1)'
+
def _collect_obj(self, obj, ignored):
# Ignore pinned objects, which are the ones still in the nursery here.
# Cache effects: don't read any flag out of 'obj' at this point.
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
@@ -1780,6 +1780,11 @@
MovingGCBase.enumerate_all_roots(self, callback, arg)
enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
+ def enum_live_with_finalizers(self, callback, arg):
+ self.probably_young_objects_with_finalizers.foreach(callback, arg, 2)
+ self.old_objects_with_finalizers.foreach(callback, arg, 2)
+ enum_live_with_finalizers._annspecialcase_ = 'specialize:arg(1)'
+
@staticmethod
def _collect_obj(obj, objects_to_trace):
objects_to_trace.append(obj)
diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -269,22 +269,23 @@
self.index_in_oldest = index + 1
return result
- def foreach(self, callback, arg):
+ def foreach(self, callback, arg, step=1):
"""Invoke 'callback(address, arg)' for all addresses in the deque.
Typically, 'callback' is a bound method and 'arg' can be None.
+ If step > 1, only calls it for addresses multiple of 'step'.
"""
chunk = self.oldest_chunk
index = self.index_in_oldest
while chunk is not self.newest_chunk:
while index < chunk_size:
callback(chunk.items[index], arg)
- index += 1
+ index += step
chunk = chunk.next
- index = 0
+ index -= chunk_size
limit = self.index_in_newest
while index < limit:
callback(chunk.items[index], arg)
- index += 1
+ index += step
foreach._annspecialcase_ = 'specialize:arg(1)'
def delete(self):
diff --git a/rpython/memory/test/test_support.py
b/rpython/memory/test/test_support.py
--- a/rpython/memory/test/test_support.py
+++ b/rpython/memory/test/test_support.py
@@ -160,6 +160,10 @@
ll.foreach(callback, 42)
assert seen == addrs
+ seen = []
+ ll.foreach(callback, 42, step=2)
+ assert seen == addrs[::2]
+
for a in addrs:
b = ll.popleft()
assert a == b
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit