[pypy-svn] r17111 - in pypy/dist/pypy/rpython/memory: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Wed Aug 31 03:59:55 CEST 2005


Author: cfbolz
Date: Wed Aug 31 03:59:46 2005
New Revision: 17111

Modified:
   pypy/dist/pypy/rpython/memory/convertlltype.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
   pypy/dist/pypy/rpython/memory/test/test_gc.py
Log:
fix the deferred refcounting GC and make in running on the llinterpreter +
tests


Modified: pypy/dist/pypy/rpython/memory/convertlltype.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/convertlltype.py	(original)
+++ pypy/dist/pypy/rpython/memory/convertlltype.py	Wed Aug 31 03:59:46 2005
@@ -58,7 +58,7 @@
             self.curraddress += size
             if self.gc is not None:
                 typeid = self.query_types.get_typeid(TYPE)
-                self.gc.init_gc_object(startaddr, typeid)
+                self.gc.init_gc_object_immortal(startaddr, typeid)
                 startaddr += self.gc.size_gc_header(typeid)
                 self.curraddress += self.gc.size_gc_header(typeid)
             ptr = init_object_on_address(startaddr, TYPE, arraylength)
@@ -98,7 +98,7 @@
             self.curraddress += size
             if self.gc is not None:
                 typeid = self.query_types.get_typeid(TYPE)
-                self.gc.init_gc_object(startaddr, typeid)
+                self.gc.init_gc_object_immortal(startaddr, typeid)
                 startaddr += self.gc.size_gc_header(typeid)
                 self.curraddress += self.gc.size_gc_header(typeid)
             ptr = init_object_on_address(startaddr, TYPE, inlinedarraylength)

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Wed Aug 31 03:59:46 2005
@@ -5,6 +5,8 @@
 from pypy.rpython import lltype
 from pypy.rpython.objectmodel import free_non_gc_object
 
+import sys
+
 int_size = lltypesimulation.sizeof(lltype.Signed)
 
 class GCError(Exception):
@@ -171,7 +173,7 @@
     def init_gc_object(self, addr, typeid):
         addr.signed[0] = 0
         addr.signed[1] = typeid
-
+    init_gc_object_immortal = init_gc_object
 
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"
@@ -305,17 +307,18 @@
     def init_gc_object(self, addr, typeid):
         addr.signed[0] = 0
         addr.signed[1] = typeid
-
+    init_gc_object_immortal = init_gc_object
 
 class DeferredRefcountingGC(GCBase):
     _alloc_flavor_ = "raw"
 
-    def __init__(self, max_refcount_zero=10, get_roots=None):
+    def __init__(self, max_refcount_zero=50, get_roots=None):
         self.zero_ref_counts = AddressLinkedList()
         self.length_zero_ref_counts = 0
         self.max_refcount_zero = max_refcount_zero
         self.set_query_functions(None, None, None, None, None, None, None)
         self.get_roots = get_roots
+        self.collecting = False
 
     def malloc(self, typeid, length=0):
         size = self.fixed_size(typeid)
@@ -323,53 +326,61 @@
             size += length * self.varsize_item_sizes(typeid)
         size_gc_header = self.size_gc_header()
         result = raw_malloc(size + size_gc_header)
-        print "mallocing %s, size %s at %s" % (typeid, size, result)
-        self.init_gc_object(result, typeid)
+##         print "mallocing %s, size %s at %s" % (typeid, size, result)
+        result.signed[0] = 0 # refcount
+        result.signed[1] = typeid
         return result + size_gc_header
 
     def collect(self):
+        if self.collecting:
+            return
+        else:
+            self.collecting = True
         roots = self.get_roots()
         curr = roots.first
         while 1:
             root = curr.address[1]
-            print "root", root, root.address[0]
+##             print "root", root, root.address[0]
+##             assert self.refcount(root.address[0]) >= 0, "refcount negative"
             self.incref(root.address[0])
             if curr.address[0] == NULL:
                 break
             curr = curr.address[0]
         dealloc_list = AddressLinkedList()
+        self.length_zero_ref_counts = 0
         while 1:
             candidate = self.zero_ref_counts.pop()
-            self.length_zero_ref_counts -= 1
             if candidate == NULL:
                 break
             refcount = self.refcount(candidate)
-            if (refcount == 0 and
-                (candidate - self.size_gc_header()).signed[1] != -1):
-                (candidate - self.size_gc_header()).signed[1] = -1
+            typeid = (candidate - self.size_gc_header()).signed[1]
+            if (refcount == 0 and typeid >= 0):
+                (candidate - self.size_gc_header()).signed[1] = -typeid - 1
                 dealloc_list.append(candidate)
         while 1:
             deallocate = dealloc_list.pop()
             if deallocate == NULL:
                 break
+            typeid = (deallocate - self.size_gc_header()).signed[1]
+            (deallocate - self.size_gc_header()).signed[1] = -typeid - 1
             self.deallocate(deallocate)
         free_non_gc_object(dealloc_list)
         while 1:
             root = roots.pop()
             if root == NULL:
                 break
-            print "root", root, root.address[0]
             self.decref(root.address[0])
+        self.collecting = False
 
     def write_barrier(self, addr, addr_to, addr_struct):
         self.decref(addr_to.address[0])
         addr_to.address[0] = addr
         self.incref(addr)
 
-    def deallocate(self, addr):
+    def deallocate(self, obj):
         gc_info = obj - self.size_gc_header()
         typeid = gc_info.signed[1]
-        print "deallocating", obj, typeid
+##         print "deallocating", obj, typeid
         offsets = self.offsets_to_gc_pointers(typeid)
         i = 0
         while i < len(offsets):
@@ -391,7 +402,7 @@
                     self.decref(pointer.address[0])
                     j += 1
                 i += 1
-        raw_free(addr)
+        raw_free(gc_info)
 
     def incref(self, addr):
         (addr - self.size_gc_header()).signed[0] += 1
@@ -400,21 +411,25 @@
         if addr == NULL:
             return
         refcount = (addr - self.size_gc_header()).signed[0]
+##         assert refcount > 0, "neg refcount"
         if refcount == 1:
             self.zero_ref_counts.append(addr)
             self.length_zero_ref_counts += 1
             if self.length_zero_ref_counts > self.max_refcount_zero:
                 self.collect()
         (addr - self.size_gc_header()).signed[0] = refcount - 1
-        assert refcount > 0
 
     def refcount(self, addr):
-        (addr - self.size_gc_header()).signed[0]
+        return (addr - self.size_gc_header()).signed[0]
 
     def init_gc_object(self, addr, typeid):
         addr.signed[0] = 0 # refcount
         addr.signed[1] = typeid
 
+    def init_gc_object_immortal(self, addr, typeid):
+        addr.signed[0] = sys.maxint // 2 # refcount
+        addr.signed[1] = typeid
+
     def size_gc_header(self, typeid=0):
         return int_size * 2
 

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Wed Aug 31 03:59:46 2005
@@ -190,7 +190,7 @@
         return self.llinterp.llt.functionptr(gc.gc_interface["write_barrier"],
                                              "write_barrier",
                                              _callable=self.gc.write_barrier)
-
+ 
 
     def update_changed_addresses(self):
         for i, root in enumerate(self.roots):
@@ -251,6 +251,8 @@
         fgcc = FlowGraphConstantConverter(a.translator.flowgraphs)
         fgcc.convert()
         self.malloc_graph = a.translator.flowgraphs[self.gc.malloc.im_func]
+        self.write_barrier_graph = a.translator.flowgraphs[
+            self.gc.write_barrier.im_func]
 
         # create a gc via invoking instantiate_gc
         self.gcptr = self.llinterp.eval_function(
@@ -260,7 +262,6 @@
         setattr(self.gcptr, "inst_get_roots",
                 lltypesimulation.functionptr(GETROOTS_FUNCTYPE, "get_roots",
                                              _callable=self.get_roots))
-
         #get funcptrs neccessary to build the result of get_roots
         self.instantiate_linked_list = getfunctionptr(
             a.translator, instantiate_linked_list)
@@ -270,7 +271,7 @@
             a.translator, AddressLinkedList.pop.im_func)
         self.gc.get_roots = None
         self.translator = a.translator
-#        a.translator.view()
+##         a.translator.view()
 
     def get_arg_malloc(self, TYPE, size=0):
         typeid = self.query_types.get_typeid(TYPE)
@@ -286,6 +287,26 @@
         self.update_changed_addresses()
         return result
 
+    def get_arg_write_barrier(self, obj, index_or_field, item):
+        #XXX: quick hack to get the correct addresses, fix later
+        layout = lltypelayout.get_layout(lltype.typeOf(obj).TO)
+        if isinstance(lltype.typeOf(obj).TO, lltype.Array):
+            assert isinstance(index_or_field, int)
+            offset = layout[0] + layout[1] * index_or_field
+            addr_to = obj._address + layout[0] + index_or_field * layout[1]
+            return self.gcptr, item._address, addr_to, obj._address
+        else:
+            offset = layout[index_or_field]
+            addr_to = obj._address + offset
+            return self.gcptr, item._address, addr_to, obj._address
+            
+    def get_funcptr_write_barrier(self):
+        return self.llinterp.llt.functionptr(gc.gc_interface["write_barrier"],
+                                             "write_barrier",
+                                             _callable=self.gc.write_barrier,
+                                             graph=self.write_barrier_graph)
+
+
     def get_roots(self):
         # call the llinterpreter to construct the result in a suitable way
         self.get_roots_from_llinterp()

Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py	Wed Aug 31 03:59:46 2005
@@ -30,6 +30,15 @@
     gclltype.prepare_graphs_and_create_gc = gclltype.create_no_gc
 
 class TestMarkSweepGC(object):
+    def setup_class(cls):
+        cls.prep_old = gclltype.prepare_graphs_and_create_gc
+        gclltype.use_gc = MarkSweepGC
+        cls.old = gclltype.use_gc
+
+    def teardown_class(cls):
+        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
+        gclltype.use_gc = cls.old
+
     def test_llinterp_lists(self):
         curr = simulator.current_size
         def malloc_a_lot():
@@ -108,11 +117,21 @@
         gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
         gclltype.use_gc = cls.old
 
-
-class DONOTTestDeferredRefcountingGC(TestMarkSweepGC):
+class TestDeferredRefcountingGC(TestMarkSweepGC):
     def setup_class(cls):
         gclltype.use_gc = DeferredRefcountingGC
         cls.old = gclltype.use_gc
     def teardown_class(cls):
         gclltype.use_gc = cls.old
 
+
+class TestDeferredRefcountingGCRunningOnLLinterp(TestMarkSweepGC):
+    def setup_class(cls):
+        cls.prep_old = gclltype.prepare_graphs_and_create_gc
+        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
+        gclltype.use_gc = DeferredRefcountingGC
+        cls.old = gclltype.use_gc
+
+    def teardown_class(cls):
+        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
+        gclltype.use_gc = cls.old



More information about the Pypy-commit mailing list