Author: Armin Rigo <[email protected]>
Branch: gc-minimark-pinning
Changeset: r55059:77b5c76b9bdd
Date: 2012-05-12 18:26 +0200
http://bitbucket.org/pypy/pypy/changeset/77b5c76b9bdd/

Log:    - Separate the concerns of 'nursery_top' and a new 'nursery_limit'.
        Fixes is_in_nursery() for example, which could return False.

        - Comments and details.

        - Fix test_gc.py.

diff --git a/pypy/rpython/memory/gc/base.py b/pypy/rpython/memory/gc/base.py
--- a/pypy/rpython/memory/gc/base.py
+++ b/pypy/rpython/memory/gc/base.py
@@ -18,7 +18,7 @@
     needs_write_barrier = False
     malloc_zero_filled = False
     prebuilt_gc_objects_are_static_roots = True
-    can_always_pin_objects = False
+    can_usually_pin_objects = False
     object_minimal_size = 0
     gcflag_extra = 0   # or a real GC flag that is always 0 when not collecting
 
diff --git a/pypy/rpython/memory/gc/minimark.py 
b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -131,7 +131,7 @@
     needs_write_barrier = True
     prebuilt_gc_objects_are_static_roots = False
     malloc_zero_filled = True    # xxx experiment with False
-    can_always_pin_objects = True
+    can_usually_pin_objects = True
     gcflag_extra = GCFLAG_FINALIZATION_ORDERING
 
     # All objects start with a HDR, i.e. with a field 'tid' which contains
@@ -248,9 +248,10 @@
         # it gives a lower bound on the allowed size of the nursery.
         self.nonlarge_max = large_object - 1
         #
-        self.nursery      = NULL
-        self.nursery_free = NULL
-        self.nursery_top  = NULL
+        self.nursery      = NULL     # start of the nursery
+        self.nursery_free = NULL     # first free location, current ptr
+        self.nursery_limit= NULL     # current limit up to which allocate
+        self.nursery_top  = NULL     # end of the nursery
         self.debug_tiny_nursery = -1
         self.debug_rotating_nurseries = None
         #
@@ -311,7 +312,7 @@
         # GCFLAG_HAS_SHADOW to their future location at the next
         # minor collection.
         self.nursery_objects_shadows = self.AddressDict()
-        # all pinned objects that were in the nursery *before* last
+        # all surviving pinned objects that were in the nursery *before* last
         # minor collect. This is a sorted deque that should be consulted when
         # considering next nursery ceiling
         self.nursery_barriers = self.AddressDeque()
@@ -404,6 +405,7 @@
         self.nursery_free = self.nursery
         # the end of the nursery:
         self.nursery_top = self.nursery + self.nursery_size
+        self.nursery_limit = self.nursery_top
         # initialize the threshold
         self.min_heap_size = max(self.min_heap_size, self.nursery_size *
                                               self.major_collection_threshold)
@@ -468,6 +470,7 @@
             llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
             self.nursery = newnurs
             self.nursery_top = self.nursery + self.nursery_size
+            self.nursery_limit = self.nursery_top
             debug_print("switching from nursery", oldnurs,
                         "to nursery", self.nursery,
                         "size", self.nursery_size)
@@ -509,7 +512,7 @@
             # there, do a collect first.
             result = self.nursery_free
             self.nursery_free = result + totalsize
-            if self.nursery_free > self.nursery_top:
+            if self.nursery_free > self.nursery_limit:
                 result = self.maybe_collect_and_reserve(totalsize)
             #
             # Build the object.
@@ -568,7 +571,7 @@
             # there, do a collect first.
             result = self.nursery_free
             self.nursery_free = result + totalsize
-            if self.nursery_free > self.nursery_top:
+            if self.nursery_free > self.nursery_limit:
                 result = self.maybe_collect_and_reserve(totalsize)
             #
             # Build the object.
@@ -588,10 +591,11 @@
             self.major_collection()
 
     def maybe_collect_and_reserve(self, totalsize):
-        """To call when nursery_free overflows nursery_top.
-        Do a minor collection, and possibly also a major collection,
-        and finally reserve 'totalsize' bytes at the start of the
-        now-empty nursery.
+        """To call when nursery_free overflows nursery_limit.
+        Walks to the next block of contiguous memory between pinned
+        objects.  If there isn't any, do a minor collection, and
+        possibly also a major collection.  Returns when it succeeded
+        in reserving 'totalsize' bytes in the nursery.
         """
         count = 0
         #
@@ -601,9 +605,9 @@
                 # blocks from pinned objects, move to the next one
                 size_gc_header = self.gcheaderbuilder.size_gc_header
                 pinned_obj_size = size_gc_header + self.get_size(
-                    self.nursery_top + size_gc_header)
-                self.nursery_free = self.nursery_top + pinned_obj_size
-                self.nursery_top = self.nursery_barriers.popleft()
+                    self.nursery_limit + size_gc_header)
+                self.nursery_free = self.nursery_limit + pinned_obj_size
+                self.nursery_limit = self.nursery_barriers.popleft()
                 #
             else:
                 # do a minor collection
@@ -629,7 +633,7 @@
             # may fail again, and then we loop; but it's the uncommon case.
             result = self.nursery_free
             self.nursery_free = result + totalsize
-            if self.nursery_free <= self.nursery_top:
+            if self.nursery_free <= self.nursery_limit:
                 break
         #
         if self.debug_tiny_nursery >= 0:   # for debugging
@@ -789,7 +793,9 @@
         if self.next_major_collection_threshold < 0:
             # cannot trigger a full collection now, but we can ensure
             # that one will occur very soon
-            self.nursery_free = self.nursery_top
+            while self.nursery_barriers.non_empty():
+                self.nursery_barriers.popleft()
+            self.nursery_free = self.nursery_limit = self.nursery_top
 
     def can_optimize_clean_setarrayitems(self):
         if self.card_page_indices > 0:
@@ -1369,7 +1375,7 @@
         self.debug_rotate_nursery()
         self.nursery_free = self.nursery
         self.nursery_barriers.append(self.nursery + self.nursery_size)
-        self.nursery_top = self.nursery_barriers.popleft()
+        self.nursery_limit = self.nursery_barriers.popleft()
         #
         debug_print("minor collect, total memory used:",
                     self.get_total_memory_used())
diff --git a/pypy/rpython/memory/support.py b/pypy/rpython/memory/support.py
--- a/pypy/rpython/memory/support.py
+++ b/pypy/rpython/memory/support.py
@@ -196,6 +196,9 @@
                 got = next
 
         def sort(self):
+            """Sorts the items in the AddressStack.  They must not be more
+            than one chunk of them.  This results in a **reverse** order,
+            so that the first pop()ped items are the smallest ones."""
             ll_assert(self.chunk.next == null_chunk, "too big for sorting")
             sort_chunk(self.chunk, self.used_in_last_chunk)
 
diff --git a/pypy/rpython/memory/test/test_gc.py 
b/pypy/rpython/memory/test/test_gc.py
--- a/pypy/rpython/memory/test/test_gc.py
+++ b/pypy/rpython/memory/test/test_gc.py
@@ -722,14 +722,15 @@
             s = str(i)
             if not rgc.can_move(s):
                 return 13
-            sum = int(rgc.pin(s))
-            rgc.unpin(s)
-            return sum
+            res = int(rgc.pin(s))
+            if res:
+                rgc.unpin(s)
+            return res
 
         res = self.interpret(f, [10])
         if not self.GCClass.moving_gc:
             assert res == 13
-        elif self.GCClass.can_always_pin_objects:
+        elif self.GCClass.can_usually_pin_objects:
             assert res == 1
         else:
             assert res == 0 or res == 13
@@ -909,7 +910,7 @@
             e = lltype.malloc(TP)
             e.x = 3
             prev = llmemory.cast_ptr_to_adr(e)
-            rgc.pin(e)
+            assert rgc.pin(e)
             for k in range(i):
                 lltype.malloc(TP)
             res = int(llmemory.cast_ptr_to_adr(e) == prev)
@@ -937,8 +938,8 @@
             lltype.malloc(TP)
             e2 = lltype.malloc(TP)
             e2.x = 5
-            rgc.pin(e2)
-            rgc.pin(e)
+            assert rgc.pin(e2)
+            assert rgc.pin(e)
             prev = llmemory.cast_ptr_to_adr(e)
             prev2 = llmemory.cast_ptr_to_adr(e2)
             for k in range(i):
@@ -969,7 +970,7 @@
             c = lltype.malloc(TP)
             c.y = s
             c.x = 3
-            rgc.pin(c)
+            assert rgc.pin(c)
             for k in range(i):
                 lltype.malloc(TP)
             rgc.unpin(c)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to