[pypy-commit] pypy lightweight-finalizers: Make it work with generation & hybrid. Improve the test

fijal noreply at buildbot.pypy.org
Fri Sep 30 17:34:51 CEST 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: lightweight-finalizers
Changeset: r47718:f290c558b3be
Date: 2011-09-30 11:31 -0300
http://bitbucket.org/pypy/pypy/changeset/f290c558b3be/

Log:	Make it work with generation & hybrid. Improve the test

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
@@ -353,6 +353,12 @@
         finally:
             self.finalizer_lock_count -= 1
 
+    def _free_raw_mem_from(self, addr):
+        typeid = self.get_type_id(addr)
+        p = (addr + self.ofs_to_raw_mem_ptr(typeid)).ptr[0]
+        if p:
+            lltype.free(p, flavor='raw')
+
 
 class MovingGCBase(GCBase):
     moving_gc = True
diff --git a/pypy/rpython/memory/gc/generation.py b/pypy/rpython/memory/gc/generation.py
--- a/pypy/rpython/memory/gc/generation.py
+++ b/pypy/rpython/memory/gc/generation.py
@@ -87,6 +87,7 @@
 
         self.last_generation_root_objects = self.AddressStack()
         self.young_objects_with_id = self.AddressDict()
+        self.young_objects_with_raw_mem = self.AddressStack()
         SemiSpaceGC.setup(self)
         self.set_nursery_size(self.initial_nursery_size)
         # the GC is fully setup now.  The rest can make use of it.
@@ -188,6 +189,8 @@
         llarena.arena_reserve(result, totalsize)
         # GCFLAG_NO_YOUNG_PTRS is never set on young objs
         self.init_gc_object(result, typeid, flags=0)
+        if self.has_raw_mem_ptr(typeid):
+            self.young_objects_with_raw_mem.append(result + size_gc_header)
         self.nursery_free = result + totalsize
         if contains_weakptr:
             self.young_objects_with_weakrefs.append(result + size_gc_header)
@@ -265,6 +268,7 @@
     def semispace_collect(self, size_changing=False):
         self.reset_young_gcflags() # we are doing a full collection anyway
         self.weakrefs_grow_older()
+        self.raw_mem_grow_older()
         self.ids_grow_older()
         self.reset_nursery()
         SemiSpaceGC.semispace_collect(self, size_changing)
@@ -299,6 +303,11 @@
             obj = self.young_objects_with_weakrefs.pop()
             self.objects_with_weakrefs.append(obj)
 
+    def raw_mem_grow_older(self):
+        while self.young_objects_with_raw_mem.non_empty():
+            obj = self.young_objects_with_raw_mem.pop()
+            self.objects_with_raw_mem.append(obj)
+
     def collect_roots(self):
         """GenerationGC: collects all roots.
            HybridGC: collects all roots, excluding the generation 3 ones.
@@ -358,6 +367,8 @@
                 self.invalidate_young_weakrefs()
             if self.young_objects_with_id.length() > 0:
                 self.update_young_objects_with_id()
+            if self.young_objects_with_raw_mem.non_empty():
+                self.deal_with_young_objects_with_raw_mem()
             # mark the nursery as free and fill it with zeroes again
             llarena.arena_reset(self.nursery, self.nursery_size, 2)
             debug_print("survived (fraction of the size):",
@@ -560,6 +571,18 @@
         # minimal size, which is actually a good idea: a large, mostly-empty
         # table is bad for the next call to 'foreach'.
 
+    def deal_with_young_objects_with_raw_mem(self):
+        new_objs_with_raw_mem = self.AddressStack()
+        while self.young_objects_with_raw_mem.non_empty():
+            addr = self.young_objects_with_raw_mem.pop()
+            if self.surviving(addr):
+                new_objs_with_raw_mem.append(self.get_forwarding_address(addr))
+            else:
+                self._free_raw_mem_from(addr)
+
+        self.young_objects_with_raw_mem.delete()
+        self.young_objects_with_raw_mem = new_objs_with_raw_mem
+
     def ids_grow_older(self):
         self.young_objects_with_id.foreach(self._id_grow_older, None)
         self.young_objects_with_id.clear()
diff --git a/pypy/rpython/memory/gc/marksweep.py b/pypy/rpython/memory/gc/marksweep.py
--- a/pypy/rpython/memory/gc/marksweep.py
+++ b/pypy/rpython/memory/gc/marksweep.py
@@ -363,10 +363,7 @@
                     self.write_free_statistics(typeid, obj)
                     freed_size += estimate
                     if self.has_raw_mem_ptr(typeid):
-                        p = (addr + size_gc_header +
-                             self.ofs_to_raw_mem_ptr(typeid)).ptr[0]
-                        if p:
-                            lltype.free(p, flavor='raw')
+                        self._free_raw_mem_from(addr + size_gc_header)
                     raw_free(addr)
                 hdr = next
             ppnext.address[0] = llmemory.NULL
diff --git a/pypy/rpython/memory/gc/semispace.py b/pypy/rpython/memory/gc/semispace.py
--- a/pypy/rpython/memory/gc/semispace.py
+++ b/pypy/rpython/memory/gc/semispace.py
@@ -82,7 +82,7 @@
         self.free = self.tospace
         MovingGCBase.setup(self)
         self.objects_with_finalizers = self.AddressDeque()
-        self.objects_with_raw_mem = self.AddressDeque()
+        self.objects_with_raw_mem = self.AddressStack()
         self.objects_with_weakrefs = self.AddressStack()
 
     def _teardown(self):
@@ -529,17 +529,13 @@
         return scan
 
     def deal_with_objects_with_raw_mem(self):
-        new_with_raw_mem = self.AddressDeque()
+        new_with_raw_mem = self.AddressStack()
         while self.objects_with_raw_mem.non_empty():
-            addr = self.objects_with_raw_mem.popleft()
+            addr = self.objects_with_raw_mem.pop()
             if self.surviving(addr):
                 new_with_raw_mem.append(self.get_forwarding_address(addr))
             else:
-                typeid = self.get_type_id(addr)
-                p = (addr + self.ofs_to_raw_mem_ptr(typeid)).ptr[0]
-                if p:
-                    lltype.free(p, flavor='raw')
-        self.objects_with_raw_mem.delete()
+                self._free_raw_mem_from(addr)
         self.objects_with_raw_mem = new_with_raw_mem
 
 
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
@@ -142,15 +142,19 @@
                     self.p = lltype.malloc(T, flavor='raw')
 
         def f():
+            a = AClass(0)
             for i in range(3):
-                AClass(3)
+                a = AClass(3)
                 AClass(0)
             llop.gc__collect(lltype.Void)
+            assert a.p
+            del a
+            llop.gc__collect(lltype.Void)
             # assert did not crash with malloc mismatch, ie those things
             # has been freed
 
         self.interpret(f, [])
-        
+
     def test_finalizer(self):
         class B(object):
             pass


More information about the pypy-commit mailing list