[pypy-commit] pypy gc-minimark-pinning: pass more of a test and write insert for support. crap ugly

fijal noreply at buildbot.pypy.org
Thu Apr 12 23:32:10 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: gc-minimark-pinning
Changeset: r54317:aa6c3180899c
Date: 2012-04-12 23:31 +0200
http://bitbucket.org/pypy/pypy/changeset/aa6c3180899c/

Log:	pass more of a test and write insert for support. crap ugly

diff --git a/pypy/rpython/lltypesystem/llarena.py b/pypy/rpython/lltypesystem/llarena.py
--- a/pypy/rpython/lltypesystem/llarena.py
+++ b/pypy/rpython/lltypesystem/llarena.py
@@ -394,7 +394,7 @@
     arena_addr = getfakearenaaddress(arena_addr)
     assert arena_addr.offset == 0
     assert size == arena_addr.arena.nbytes
-    arena_addr.arena.set_protect(inaccessible)
+    arena_addr.arena.set_protect(inaccessible)    
 
 # ____________________________________________________________
 #
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
@@ -247,6 +247,8 @@
         self.nursery_top  = NULL
         self.debug_tiny_nursery = -1
         self.debug_rotating_nurseries = None
+        self.surviving_pinned_objects = NULL
+        self.nursery_barriers = NULL
         #
         # The ArenaCollection() handles the nonmovable objects allocation.
         if ArenaCollectionClass is None:
@@ -306,7 +308,7 @@
         # minor collection.
         self.nursery_objects_shadows = self.AddressDict()
         # all pinned objects that were in the nursery *before* last
-        # minor collect. This is a sorted stack that should be consulted when
+        # minor collect. This is a sorted deque that should be consulted when
         # considering next nursery ceiling
         self.nursery_barriers = self.AddressDeque()
     
@@ -1257,6 +1259,8 @@
         #
         # Before everything else, remove from 'old_objects_pointing_to_young'
         # the young arrays.
+        self.nursery_barriers.delete()
+        self.surviving_pinned_objects = self.AddressStack()
         if self.young_rawmalloced_objects:
             self.remove_young_arrays_from_old_objects_pointing_to_young()
         #
@@ -1308,22 +1312,24 @@
         # All live nursery objects are out, and the rest dies.  Fill
         # the whole nursery with zero and reset the current nursery pointer.
         # self.nursery_barriers are *not* freed
-        # XXX sort the nursery_barriers
-        new_barriers = self.AddressDeque()
+        nursery_barriers = self.AddressDeque()
         prev = self.nursery
         size_gc_header = self.gcheaderbuilder.size_gc_header
-        while self.nursery_barriers.non_empty():
-            next = self.nursery_barriers.popleft()
-            llarena.arena_reset(prev, next - prev, 2)
+        while self.surviving_pinned_objects.non_empty():
+            next = self.surviving_pinned_objects.pop()
+            assert next >= prev
+            size = llarena.getfakearenaaddress(next) - prev
+            llarena.arena_reset(prev, size, 2)
             # clean the visited flag
             obj = next + size_gc_header
             self.header(obj).tid &= ~GCFLAG_VISITED
-            prev = prev + (next - prev) + (size_gc_header +
+            prev = prev + size + (size_gc_header +
                            self.get_size(obj))
-            new_barriers.append(next)
+            nursery_barriers.append(next)
         llarena.arena_reset(prev, self.nursery_top - prev, 2)
-        self.nursery_barriers.delete()
-        self.nursery_barriers = new_barriers
+        self.surviving_pinned_objects.delete()
+        self.surviving_pinned_objects = NULL
+        self.nursery_barriers = nursery_barriers
         self.debug_rotate_nursery()
         self.nursery_free = self.nursery
         self.nursery_barriers.append(self.nursery + self.nursery_size)
@@ -1478,7 +1484,8 @@
             hdr.tid |= GCFLAG_VISITED
             ll_assert(not self.header(obj).tid & GCFLAG_HAS_SHADOW, "support shadow with pinning")
             ll_assert(not self.header(obj).tid & GCFLAG_HAS_CARDS, "support cards with pinning")
-            self.nursery_barriers.append(obj - size_gc_header)
+            self.surviving_pinned_objects.insert(
+                llarena.getfakearenaaddress(obj - size_gc_header))
             return
         elif self.header(obj).tid & GCFLAG_HAS_SHADOW == 0:
             #
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
@@ -173,6 +173,47 @@
                 chunk.items[count] = got
                 got = next
 
+        def insert(self, addr):
+            """ Insert addr in the already sorted stack to make sure
+            the smallest one is on top
+            """
+            if self.used_in_last_chunk == 0:
+                self.append(addr)
+                return
+            got = self.pop()
+            read = self.used_in_last_chunk - 1
+            if read == -1 and got <= addr:
+                self.append(addr)
+                self.append(got)
+                return
+            read_chunk = self.chunk
+            self.append(got)
+            if got > addr:
+                self.append(addr)
+                return
+            write = self.used_in_last_chunk
+            if self.used_in_last_chunk == chunk_size:
+                self.enlarge()
+                write = 0
+            self.used_in_last_chunk += 1
+            write_chunk = self.chunk
+            while got < addr and not read_chunk is null_chunk:
+                write_chunk.items[write] = got
+                write -= 1
+                if write < 0:
+                    write_chunk = write_chunk.next
+                    write = chunk_size - 1
+                got = read_chunk.items[read]
+                read -= 1
+                if read < 0:
+                    read_chunk = read_chunk.next
+                    read = chunk_size - 1
+            if got < addr:
+                write_chunk.items[write] = got
+                write_chunk.items[0] = addr
+            else:
+                write_chunk.items[write] = addr
+
     cache[chunk_size] = AddressStack
     return AddressStack
 
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
@@ -966,5 +966,35 @@
         res = self.interpret(f, [10])
         assert res == 2
 
+    def test_pinning_collect_2(self):
+        from pypy.rpython.lltypesystem import llmemory
+
+        TP = lltype.GcStruct('x', ('x', lltype.Signed), ('y', lltype.Signed))
+        
+        def f(i):
+            e = lltype.malloc(TP)
+            e.x = 3
+            lltype.malloc(TP)
+            e2 = lltype.malloc(TP)
+            e2.x = 5
+            rgc.pin(e2)
+            rgc.pin(e)
+            prev = llmemory.cast_ptr_to_adr(e)
+            prev2 = llmemory.cast_ptr_to_adr(e2)
+            for k in range(i):
+                lltype.malloc(TP)
+            res = int(llmemory.cast_ptr_to_adr(e) == prev)
+            res += int(llmemory.cast_ptr_to_adr(e2) == prev2)
+            rgc.unpin(e)
+            for k in range(i):
+                lltype.malloc(TP)
+            rgc.unpin(e2)
+            assert e.x == 3 # noone overwrote it
+            assert e2.x == 5 # noone overwrote it
+            return res
+
+        res = self.interpret(f, [10])
+        assert res == 2
+
 class TestMiniMarkGCCardMarking(TestMiniMarkGC):
     GC_PARAMS = {'card_page_indices': 4}
diff --git a/pypy/rpython/memory/test/test_support.py b/pypy/rpython/memory/test/test_support.py
--- a/pypy/rpython/memory/test/test_support.py
+++ b/pypy/rpython/memory/test/test_support.py
@@ -3,7 +3,7 @@
 from pypy.rpython.memory.support import get_address_deque
 
 from pypy.rpython.test.test_llinterp import interpret
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena
 from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free, NULL
 
 class TestAddressStack(object):
@@ -94,6 +94,26 @@
             assert a == addrs[i]
         assert not ll.non_empty()
 
+    def test_insert(self):
+        AddressStack = get_address_stack(chunk_size=5)
+        ll = AddressStack()
+        lla = llarena.arena_malloc(10, 2)
+        addrs = [lla + i for i in range(10)]
+        ll.insert(addrs[2])
+        ll.insert(addrs[1])
+        ll.insert(addrs[5])
+        ll.insert(addrs[4])
+        ll.insert(addrs[6])
+        ll.insert(addrs[9])
+        ll.insert(addrs[0])
+        ll.insert(addrs[8])
+        ll.insert(addrs[7])
+        ll.insert(addrs[3])
+        expected = range(10)
+        for i in expected:
+            a = ll.pop()
+            assert a == addrs[i]
+
 
 class TestAddressDeque:
     def test_big_access(self):


More information about the pypy-commit mailing list