[pypy-svn] r77085 - in pypy/branch/gen2-gc/pypy/rpython/memory/gc: . test

arigo at codespeak.net arigo at codespeak.net
Wed Sep 15 13:56:02 CEST 2010


Author: arigo
Date: Wed Sep 15 13:56:01 2010
New Revision: 77085

Modified:
   pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimarkpage.py
   pypy/branch/gen2-gc/pypy/rpython/memory/gc/test/test_minimarkpage.py
Log:
Another test, and implementation.


Modified: pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimarkpage.py
==============================================================================
--- pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimarkpage.py	(original)
+++ pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimarkpage.py	Wed Sep 15 13:56:01 2010
@@ -187,42 +187,63 @@
         size_class = self.small_request_threshold / WORD
         while size_class >= 1:
             #
-            # Walk the pages in 'page_for_size[size_class]' and free objects.
+            # Walk the pages in 'page_for_size[size_class]' and
+            # 'full_page_for_size[size_class]' and free some objects.
             # Pages completely freed are added to 'self.free_pages', and
             # become available for reuse by any size class.  Pages not
-            # completely freed are re-chained in 'newlist'.
-            self.mass_free_in_partial_list(size_class, ok_to_free_func)
+            # completely freed are re-chained either in
+            # 'full_page_for_size[]' or 'page_for_size[]'.
+            self.mass_free_in_page(size_class, ok_to_free_func)
             #
             size_class -= 1
 
 
-    def mass_free_in_partial_list(self, size_class, ok_to_free_func):
-        page = self.page_for_size[size_class]
+    def mass_free_in_page(self, size_class, ok_to_free_func):
         nblocks = self.nblocks_for_size[size_class]
         block_size = size_class * WORD
-        remaining_pages = PAGE_NULL
+        remaining_partial_pages = PAGE_NULL
+        remaining_full_pages = PAGE_NULL
         #
-        while page != PAGE_NULL:
-            #
-            # Collect the page.
-            surviving = self.walk_page(page, block_size,
-                                       nblocks, ok_to_free_func)
-            nextpage = page.nextpage
+        step = 0
+        while step < 2:
+            if step == 0:
+                page = self.full_page_for_size[size_class]
+            else:
+                page = self.page_for_size[size_class]
             #
-            if surviving > 0:
+            while page != PAGE_NULL:
                 #
-                # Found at least 1 object surviving.  Re-insert the page
-                # in the chained list.
-                page.nextpage = remaining_pages
-                remaining_pages = page
+                # Collect the page.
+                surviving = self.walk_page(page, block_size,
+                                           nblocks, ok_to_free_func)
+                nextpage = page.nextpage
                 #
-            else:
-                # No object survives; free the page.
-                self.free_page(page)
+                if surviving == nblocks:
+                    #
+                    # The page is still full.  Re-insert it in the
+                    # 'remaining_full_pages' chained list.
+                    ll_assert(step == 0,
+                              "A non-full page became full while freeing")
+                    page.nextpage = remaining_full_pages
+                    remaining_full_pages = page
+                    #
+                elif surviving > 0:
+                    #
+                    # There is at least 1 object surviving.  Re-insert
+                    # the page in the 'remaining_partial_pages' chained list.
+                    page.nextpage = remaining_partial_pages
+                    remaining_partial_pages = page
+                    #
+                else:
+                    # No object survives; free the page.
+                    self.free_page(page)
 
-            page = nextpage
+                page = nextpage
+            #
+            step += 1
         #
-        self.page_for_size[size_class] = remaining_pages
+        self.page_for_size[size_class] = remaining_partial_pages
+        self.full_page_for_size[size_class] = remaining_full_pages
 
 
     def free_page(self, page):

Modified: pypy/branch/gen2-gc/pypy/rpython/memory/gc/test/test_minimarkpage.py
==============================================================================
--- pypy/branch/gen2-gc/pypy/rpython/memory/gc/test/test_minimarkpage.py	(original)
+++ pypy/branch/gen2-gc/pypy/rpython/memory/gc/test/test_minimarkpage.py	Wed Sep 15 13:56:01 2010
@@ -69,10 +69,11 @@
         page = llmemory.cast_adr_to_ptr(pageaddr, PAGE_PTR)
         page.nfree = 0
         page.nuninitialized = nblocks - nusedblocks
-        page.freeblock = pageaddr + hdrsize + nusedblocks * size_block
         if nusedblocks < nblocks:
+            page.freeblock = pageaddr + hdrsize + nusedblocks * size_block
             chainedlists = ac.page_for_size
         else:
+            page.freeblock = NULL
             chainedlists = ac.full_page_for_size
         page.nextpage = chainedlists[size_class]
         chainedlists[size_class] = page
@@ -226,3 +227,20 @@
     assert pageaddr == ac.free_pages
     assert pageaddr.address[0] == NULL
     assert ac.page_for_size[2] == PAGE_NULL
+
+def test_mass_free_full_remains_full():
+    pagesize = hdrsize + 7*WORD
+    ac = arena_collection_for_test(pagesize, "#", fill_with_objects=2)
+    ok_to_free = OkToFree(ac, False)
+    ac.mass_free(ok_to_free)
+    assert ok_to_free.seen == [hdrsize + 0*WORD,
+                               hdrsize + 2*WORD,
+                               hdrsize + 4*WORD]
+    page = getpage(ac, 0)
+    assert page == ac.full_page_for_size[2]
+    assert page.nextpage == PAGE_NULL
+    assert page.nuninitialized == 0
+    assert page.nfree == 0
+    assert page.freeblock == NULL
+    assert ac.free_pages == NULL
+    assert ac.page_for_size[2] == PAGE_NULL



More information about the Pypy-commit mailing list