[pypy-svn] r27492 - in pypy/dist/pypy/rpython: lltypesystem memory memory/test

arigo at codespeak.net arigo at codespeak.net
Sat May 20 10:47:15 CEST 2006


Author: arigo
Date: Sat May 20 10:47:12 2006
New Revision: 27492

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Renamed 'malloced_lists' to 'pools'.  These pools are now GcOpaque
objects themselves, so that they are collectable.  Work in progress.
(Collecting a pool only means collecting the small overhead data, not
all the objects inside the pool, which stay alive as usual as long as
they are referenced.)



Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sat May 20 10:47:12 2006
@@ -319,7 +319,7 @@
     'gc_reload_possibly_moved': LLOp(),
     # experimental operations in support of thread cloning, only
     # implemented by the Mark&Sweep GC
-    'gc_x_swap_list':       LLOp(),
+    'gc_x_swap_pool':       LLOp(canraise=(MemoryError,)),
     'gc_x_clone':           LLOp(canraise=(MemoryError,)),
 
     # __________ stackless operation(s) __________

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sat May 20 10:47:12 2006
@@ -12,8 +12,12 @@
 int_size = lltypesimulation.sizeof(lltype.Signed)
 gc_header_two_ints = 2*int_size
 
+X_POOL = lltype.GcOpaqueType('gc.pool')
+X_POOL_PTR = lltype.Ptr(X_POOL)
 X_CLONE = lltype.GcStruct('CloneData', ('gcobjectptr', llmemory.GCREF),
-                                       ('malloced_list', llmemory.Address))
+                                       ('pool',        X_POOL_PTR))
+X_CLONE_PTR = lltype.Ptr(X_CLONE)
+
 
 class GCError(Exception):
     pass
@@ -114,6 +118,9 @@
     HDR.become(lltype.Struct('header', ('typeid', lltype.Signed),
                                        ('next', HDRPTR)))
 
+    POOL = lltype.GcStruct('gc_pool')
+    POOLPTR = lltype.Ptr(POOL)
+
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
         self.heap_usage = 0          # at the end of the latest collection
         self.bytes_malloced = 0      # since the latest collection
@@ -122,6 +129,7 @@
         self.AddressLinkedList = AddressLinkedList
         #self.set_query_functions(None, None, None, None, None, None, None)
         self.malloced_objects = lltype.nullptr(self.HDR)
+        self.curpool = lltype.nullptr(self.POOL)
         self.get_roots = get_roots
         self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
 
@@ -255,8 +263,8 @@
             self.bytes_malloced_threshold = curr_heap_size
         end_time = time.time()
         self.total_collection_time += end_time - start_time
-        # warning, the following debug print allocates memory to manipulate
-        # the strings!  so it must be at the end
+        # warning, the following debug prints allocate memory to manipulate
+        # the strings!  so they must be at the end
         if DEBUG_PRINT:
             os.write(2, "  malloced since previous collection: %s bytes\n" %
                      old_malloced)
@@ -285,24 +293,54 @@
     init_gc_object_immortal = init_gc_object
 
     # experimental support for thread cloning
-    def x_swap_list(self, malloced_list):
-        # Swap the current malloced_objects linked list with another one.
-        # All malloc'ed objects are put into the current malloced_objects
-        # list; this is a way to separate objects depending on when they
-        # were allocated.
-        current = llmemory.cast_ptr_to_adr(self.malloced_objects)
-        self.malloced_objects = llmemory.cast_adr_to_ptr(malloced_list,
-                                                         self.HDRPTR)
-        return current
+    def x_swap_pool(self, newpool):
+        # Set newpool as the current pool (create one if newpool == NULL).
+        # All malloc'ed objects are put into the current pool;this is a
+        # way to separate objects depending on when they were allocated.
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        # invariant: each POOL GcStruct is at the _front_ of a linked list
+        # of malloced objects.
+        oldpool = self.curpool
+        if not oldpool:
+            # make a fresh pool object, which is automatically inserted at the
+            # front of the current list
+            oldpool = lltype.malloc(self.POOL)
+        else:
+            # manually insert oldpool at the front of the current list
+            addr = llmemory.cast_ptr_to_adr(oldpool)
+            addr -= size_gc_header
+            hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+            hdr.next = self.malloced_objects
+
+        newpool = lltype.cast_opaque_ptr(self.POOLPTR, newpool)
+        if newpool:
+            # newpool is at the front of the new linked list to install
+            addr = llmemory.cast_ptr_to_adr(newpool)
+            addr -= size_gc_header
+            hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+            self.malloced_objects = hdr.next
+        else:
+            # start a fresh new linked list
+            self.malloced_objects = lltype.nullptr(self.HDR)
+        # note that newpool will not be freed by a collect as long as
+        # it sits in self.malloced_objects_box, because it is not itself
+        # part of any linked list
+        self.curpool = newpool
+        return lltype.cast_opaque_ptr(X_POOL_PTR, oldpool)
 
     def x_clone(self, clonedata):
         # Recursively clone the gcobject and everything it points to,
         # directly or indirectly -- but stops at objects that are not
-        # in the malloced_list.  The gcobjectptr and the malloced_list
-        # fields of clonedata are adjusted to refer to the result.
+        # in the specified pool.  A new pool is built to contain the
+        # copies, and the 'gcobjectptr' and 'pool' fields of clonedata
+        # are adjusted to refer to the result.
         size_gc_header = self.gcheaderbuilder.size_gc_header
         oldobjects = self.AddressLinkedList()
-        hdr = llmemory.cast_adr_to_ptr(clonedata.malloced_list, self.HDRPTR)
+        oldpool = lltype.cast_opaque_ptr(self.POOLPTR, clonedata.pool)
+        addr = llmemory.cast_ptr_to_adr(oldpool)
+        addr -= size_gc_header
+        hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+        hdr = hdr.next
         while hdr:
             next = hdr.next
             hdr.typeid |= 1    # mark all objects from malloced_list
@@ -348,8 +386,6 @@
             newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
             gcptr_addr.address[0] = newobj_addr
 
-        clonedata.malloced_list = llmemory.cast_ptr_to_adr(newobjectlist)
-
         # re-create the original linked list
         next = lltype.nullptr(self.HDR)
         while oldobjects.non_empty():
@@ -359,6 +395,12 @@
             next = hdr
         oldobjects.delete()
 
+        # make the new pool object to collect newobjectlist
+        curpool = self.x_swap_pool(lltype.nullptr(X_POOL))
+        assert not self.malloced_objects
+        self.malloced_objects = newobjectlist
+        clonedata.pool = self.x_swap_pool(curpool)
+
 
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat May 20 10:47:12 2006
@@ -844,9 +844,11 @@
         
         annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
 
-        def getfn(ll_function, args_s, s_result, inline=False):
+        def getfn(ll_function, args_s, s_result, inline=False,
+                  minimal_transform=True):
             graph = annhelper.getgraph(ll_function, args_s, s_result)
-            self.need_minimal_transform(graph)
+            if minimal_transform:
+                self.need_minimal_transform(graph)
             if inline:
                 self.graphs_to_inline[graph] = True
             return annhelper.graph2const(graph)
@@ -888,13 +890,18 @@
                                     [s_gc], annmodel.SomeTuple(statics_s))
 
         # experimental gc_x_* operations
-        self.x_swap_list_ptr = getfn(GCClass.x_swap_list.im_func,
-                                     [s_gc, annmodel.SomeAddress()],
-                                     annmodel.SomeAddress())
+        s_x_pool  = annmodel.SomePtr(gc.X_POOL_PTR)
+        s_x_clone = annmodel.SomePtr(gc.X_CLONE_PTR)
+        # the x_*() methods use some regular mallocs that must be
+        # transformed in the normal way
+        self.x_swap_pool_ptr = getfn(GCClass.x_swap_pool.im_func,
+                                     [s_gc, s_x_pool],
+                                     s_x_pool,
+                                     minimal_transform = False)
         self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
-                                 [s_gc,
-                                  annmodel.SomePtr(lltype.Ptr(gc.X_CLONE))],
-                                 annmodel.s_None)
+                                 [s_gc, s_x_clone],
+                                 annmodel.s_None,
+                                 minimal_transform = False)
 
         annhelper.finish()   # at this point, annotate all mix-level helpers
         annhelper.backend_optimize()
@@ -1162,10 +1169,10 @@
                                         block.operations.index(op))
         return ops
 
-    def replace_gc_x_swap_list(self, op, livevars, block):
+    def replace_gc_x_swap_pool(self, op, livevars, block):
         [v_malloced] = op.args
         newop = SpaceOperation("direct_call",
-                               [self.x_swap_list_ptr, self.c_const_gc,
+                               [self.x_swap_pool_ptr, self.c_const_gc,
                                                       v_malloced],
                                op.result)
         return [newop]

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Sat May 20 10:47:12 2006
@@ -161,7 +161,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory.support import INT_SIZE
-from pypy.rpython.memory.gc import X_CLONE
+from pypy.rpython.memory.gc import X_CLONE, X_POOL, X_POOL_PTR
 from pypy import conftest
 
 
@@ -304,18 +304,18 @@
             return a
         def func():
             a1 = make(111)
-            # start recording mallocs in a new list
-            oldlist = llop.gc_x_swap_list(llmemory.Address, llmemory.NULL)
+            # start recording mallocs in a new pool
+            oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL))
             # the following a2 goes into the new list
             a2 = make(222)
-            # now put the old list back and get the new list
-            newlist = llop.gc_x_swap_list(llmemory.Address, oldlist)
+            # now put the old pool back and get the new pool
+            newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool)
             a3 = make(333)
             # clone a2
             a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2)
             clonedata = lltype.malloc(X_CLONE)
             clonedata.gcobjectptr = a2ref
-            clonedata.malloced_list = newlist
+            clonedata.pool = newpool
             llop.gc_x_clone(lltype.Void, clonedata)
             a2copyref = clonedata.gcobjectptr
             a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref)



More information about the Pypy-commit mailing list