[pypy-svn] r70950 - in pypy/branch/gc-huge-list/pypy/rpython/memory/gc: . test

arigo at codespeak.net arigo at codespeak.net
Thu Jan 28 14:35:30 CET 2010


Author: arigo
Date: Thu Jan 28 14:35:29 2010
New Revision: 70950

Modified:
   pypy/branch/gc-huge-list/pypy/rpython/memory/gc/generation.py
   pypy/branch/gc-huge-list/pypy/rpython/memory/gc/hybrid.py
   pypy/branch/gc-huge-list/pypy/rpython/memory/gc/test/test_direct.py
Log:
(arigo, fijal)
Finish and cleanup implementation of writebarrier_before_copy.
Implement assume_young_pointers


Modified: pypy/branch/gc-huge-list/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/gc-huge-list/pypy/rpython/memory/gc/generation.py	Thu Jan 28 14:35:29 2010
@@ -476,12 +476,15 @@
                 objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
                 self.last_generation_root_objects.append(addr_struct)
 
-    def assume_young_pointers(self, addr_struct):
-        # XXX fix for hybrid
+    def _assume_young_pointers(self, addr_struct):
         objhdr = self.header(addr_struct)
         if objhdr.tid & GCFLAG_NO_YOUNG_PTRS:
             self.old_objects_pointing_to_young.append(addr_struct)
             objhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
+
+    def assume_young_pointers(self, addr_struct):
+        self._assume_young_pointers(addr_struct)
+        objhdr = self.header(addr_struct)
         if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
             objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
             self.last_generation_root_objects.append(addr_struct)

Modified: pypy/branch/gc-huge-list/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/rpython/memory/gc/hybrid.py	(original)
+++ pypy/branch/gc-huge-list/pypy/rpython/memory/gc/hybrid.py	Thu Jan 28 14:35:29 2010
@@ -573,19 +573,23 @@
         if hdr.tid & GCFLAG_CARDMARKS:
             # Mark the correct card, don't clear GCFLAG_NO_YOUNG_PTRS flag.
             # Note that 'offset' does not include the size_gc_header.
-            size_gc_header = self.gcheaderbuilder.size_gc_header
             num = raw_malloc_usage(offset) / self.card_size
-            addr = (addr_struct - size_gc_header + llarena.negative_byte_index(num>>3))
-            flag = 1 << (num&7)
-            value = ord(addr.char[0])
-            if value & flag == 0:
-                addr.char[0] = chr(value | flag)
-                if hdr.tid & GCFLAG_CARDMARK_SET == 0:
-                    hdr.tid |= GCFLAG_CARDMARK_SET
-                    self.old_objects_pointing_to_young.append(addr_struct)
+            self.set_card_mark(addr_struct, num)
         else:
             GenerationGC.remember_pointer_to_nursery(self, addr_struct, offset)
 
+    def set_card_mark(self, addr_struct, num):
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        addr = (addr_struct - size_gc_header + llarena.negative_byte_index(num>>3))
+        flag = 1 << (num&7)
+        value = ord(addr.char[0])
+        if value & flag == 0:
+            addr.char[0] = chr(value | flag)
+            hdr = self.header(addr_struct)
+            if hdr.tid & GCFLAG_CARDMARK_SET == 0:
+                hdr.tid |= GCFLAG_CARDMARK_SET
+                self.old_objects_pointing_to_young.append(addr_struct)
+
     def reset_young_gcflags(self):
         oldlist = self.old_objects_pointing_to_young
         while oldlist.non_empty():
@@ -676,43 +680,40 @@
             i += 1
 
     def mark_cards(self, addr, start, length):
-        size_gc_header = self.gcheaderbuilder.size_gc_header
-        hdr = self.header(addr)
-        hdr.tid |= GCFLAG_CARDMARK_SET
         typeid = self.get_type_id(addr)
         itemsize = self.varsize_item_sizes(typeid)
         offset = self.varsize_offset_to_variable_part(typeid) + itemsize * start
         first_card = raw_malloc_usage(offset) / self.card_size
         offset += itemsize * length
-        last_card = raw_malloc_usage(offset) / self.card_size
-        i = first_card >> 3
-        while i <= last_card >> 3:
-            card_adr = addr - size_gc_header + llarena.negative_byte_index(i)
-            card_adr.char[0] = chr(0xff)
+        last_card = (raw_malloc_usage(offset) - 1) / self.card_size
+        i = first_card
+        while i <= last_card:
+            self.set_card_mark(addr, i)
             i += 1
 
+    def _assume_young_pointers(self, addr):
+        hdr = self.header(addr)
+        if hdr.tid & GCFLAG_CARDMARKS:
+            typeid = self.get_type_id(addr)
+            offset_to_length = self.varsize_offset_to_length(typeid)
+            self.mark_cards(addr, 0, (addr + offset_to_length).signed[0])
+        else:
+            GenerationGC._assume_young_pointers(self, addr)
+
     def _writebarrier_before_copy(self, source_addr, dest_addr, source_start,
                                   dest_start, length):
-        """ A hook for hybrid gc
-        """
         source_hdr = self.header(source_addr)
+        if (source_hdr.tid & (GCFLAG_NO_YOUNG_PTRS & GCFLAG_CARDMARK_SET) ==
+            GCFLAG_NO_YOUNG_PTRS):
+            return     # the source object has no young pointer at all
         dest_hdr = self.header(dest_addr)
-        if source_hdr.tid & GCFLAG_NO_YOUNG_PTRS == 0:
-            if dest_hdr.tid & GCFLAG_CARDMARKS:
-                # we copy from small -> larg list, set all cards up
-                self.mark_cards(dest_addr, dest_start, length)
-                return
-        if source_hdr.tid & GCFLAG_CARDMARK_SET:
-            if dest_hdr.tid & GCFLAG_CARDMARKS:
-                # large -> large, copy cardmarks.
-                # XXX for now just set all cards within range
-                # that's why we need source_start, possibly
-                self.mark_cards(dest_addr, dest_start, length)
-                return
-            # large -> small
-        # there might be an object in source that is in nursery
-        self.old_objects_pointing_to_young.append(dest_addr)
-        dest_hdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
+        if dest_hdr.tid & GCFLAG_CARDMARKS:
+            # we copy into a large object with card marks:
+            # mark all cards that have been overwritten
+            self.mark_cards(dest_addr, dest_start, length)
+        else:
+            self.old_objects_pointing_to_young.append(dest_addr)
+            dest_hdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
 
     def debug_check_object_no_nursery_pointer(self, obj):
         tid = self.header(obj).tid

Modified: pypy/branch/gc-huge-list/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/rpython/memory/gc/test/test_direct.py	(original)
+++ pypy/branch/gc-huge-list/pypy/rpython/memory/gc/test/test_direct.py	Thu Jan 28 14:35:29 2010
@@ -472,9 +472,10 @@
         assert gc.header(addr1).tid & GCFLAG_CARDMARK_SET
         assert gc.header(addr2).tid & GCFLAG_CARDMARK_SET == 0
         gc.writebarrier_before_copy(addr1, addr2, 0, 0, 48)
-        for i in range(3):
+        for i in range(2):
             addr = addr2 - size_gc_header + llarena.negative_byte_index(i)
             assert addr.char[0] == '\xff', i
+        assert (addr2 - size_gc_header + llarena.negative_byte_index(2)).char[0] == '\x01'
 
         objs = []
         def callback(obj, arg):
@@ -485,6 +486,20 @@
         obj2[0] = p
         gc.foreach_marked_card(addr2, callback, None)
         assert objs == [addrp]
+
+    def test_assume_young_pointers_cardmarking(self):
+        from pypy.rpython.lltypesystem import llarena
+
+        gc = self.gc
+        size_gc_header = gc.gcheaderbuilder.size_gc_header
+        typeid = self.get_type_id(VAR)
+        addr1 = llmemory.cast_ptr_to_adr(gc.malloc_varsize_slowpath(typeid, 48))
+        obj = llmemory.cast_adr_to_ptr(addr1, lltype.Ptr(VAR))
+        gc.assume_young_pointers(addr1)
+        for i in range(2):
+            addr = addr1 - size_gc_header + llarena.negative_byte_index(i)
+            assert addr.char[0] == '\xff', i
+        assert (addr1 - size_gc_header + llarena.negative_byte_index(2)).char[0] == '\x01'
         
 class TestMarkCompactGC(DirectGCTest):
     from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass



More information about the Pypy-commit mailing list