Author: Armin Rigo <[email protected]>
Branch: gc-del-2
Changeset: r66070:62c37017e2a6
Date: 2013-08-11 12:32 +0200
http://bitbucket.org/pypy/pypy/changeset/62c37017e2a6/

Log:    Introduce and use filter() on AddressStack.

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
@@ -1602,17 +1602,11 @@
         self.free_rawmalloced_object_if_unvisited(obj)
 
     def remove_young_arrays_from_old_objects_pointing_to_young(self):
-        old = self.old_objects_pointing_to_young
-        new = self.AddressStack()
-        while old.non_empty():
-            obj = old.pop()
-            if not self.young_rawmalloced_objects.contains(obj):
-                new.append(obj)
-        # an extra copy, to avoid assignments to
-        # 'self.old_objects_pointing_to_young'
-        while new.non_empty():
-            old.append(new.pop())
-        new.delete()
+        self.old_objects_pointing_to_young.filter(self._filter_young_array,
+                                                  None)
+
+    def _filter_young_array(self, obj, ignored):
+        return not self.young_rawmalloced_objects.contains(obj)
 
     # ----------
     # Full collection
diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -143,6 +143,30 @@
                 count = chunk_size
         foreach._annspecialcase_ = 'specialize:arg(1)'
 
+        def filter(self, callback, arg):
+            """Invoke 'callback(address, arg)' for all addresses in the stack.
+            When it returns False, remove the item from the stack (by
+            replacing it with self.pop(), so the order is destroyed).
+            Typically, 'callback' is a bound method and 'arg' can be None.
+            """
+            chunk = self.chunk
+            count = self.used_in_last_chunk
+            while chunk:
+                nextchunk = chunk.next
+                while count > 0:
+                    count -= 1
+                    if not callback(chunk.items[count], arg):
+                        # a version of pop-and-put-back-at-chunk.items[count]
+                        used = self.used_in_last_chunk - 1
+                        ll_assert(used >= 0, "pop on empty AddressStack [2]")
+                        chunk.items[count] = self.chunk.items[used]
+                        self.used_in_last_chunk = used
+                        if used == 0 and self.chunk.next:
+                            self.shrink()
+                chunk = nextchunk
+                count = chunk_size
+        filter._annspecialcase_ = 'specialize:arg(1)'
+
         def stack2dict(self):
             result = AddressDict(self._length_estimate())
             self.foreach(_add_in_dict, result)
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
@@ -78,6 +78,32 @@
         ll.foreach(callback, 42)
         assert seen == addrs or seen[::-1] == addrs   # order not guaranteed
 
+    def test_filter(self):
+        import random
+        AddressStack = get_address_stack()
+        addrs = [raw_malloc(llmemory.sizeof(lltype.Signed))
+                 for i in range(1500)]
+        addrset = set(addrs)
+
+        for kept in [0.0, 0.5, 1.0]:
+            ll = AddressStack()
+            for i in range(1500):
+                ll.append(addrs[i])
+
+            keep = set([a for a in addrs if random.random() < kept])
+
+            def filter(addr, fortytwo):
+                assert fortytwo == 42
+                assert addr in addrset
+                return addr in keep
+
+            ll.filter(filter, 42)
+
+            seen = set()
+            while ll.non_empty():
+                seen.add(ll.pop())
+            assert seen == keep
+
     def test_remove(self):
         AddressStack = get_address_stack()
         addrs = [raw_malloc(llmemory.sizeof(lltype.Signed))
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to