[pypy-svn] r27564 - pypy/dist/pypy/rpython/memory

mwh at codespeak.net mwh at codespeak.net
Mon May 22 01:07:16 CEST 2006


Author: mwh
Date: Mon May 22 01:07:15 2006
New Revision: 27564

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
Log:
another version of x_become(), copying what collect() looks like now :)
still doesn't work.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Mon May 22 01:07:15 2006
@@ -531,18 +531,73 @@
         # reinstall the pool that was current at the beginning of x_clone()
         clonedata.pool = self.x_swap_pool(curpool)
 
+    def add_reachable_to_stack2(self, obj, objects, target_addr, source_addr):
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        gc_info = obj - size_gc_header
+        hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
+        if hdr.typeid & 1:
+            return
+        typeid = hdr.typeid >> 1
+        offsets = self.offsets_to_gc_pointers(typeid)
+        i = 0
+        while i < len(offsets):
+            pointer = obj + offsets[i]
+            objects.append(pointer.address[0])
+            # -------------------------------------------------
+            # begin difference from collect
+            llop.debug_debug(lltype.Void,
+                             pointer.address[0], target_addr,
+                             pointer.address[0] == target_addr,
+                             )
+            if pointer.address[0] == target_addr:
+                pointer.address[0] = source_addr
+            # end difference from collect
+            # -------------------------------------------------
+            i += 1
+        if self.is_varsize(typeid):
+            offset = self.varsize_offset_to_variable_part(
+                typeid)
+            length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
+            obj += offset
+            offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
+            itemlength = self.varsize_item_sizes(typeid)
+            i = 0
+            while i < length:
+                item = obj + itemlength * i
+                j = 0
+                while j < len(offsets):
+                    objects.append((item + offsets[j]).address[0])
+                    # -------------------------------------------------
+                    # begin difference from collect
+                    pointer = item + offsets[j]
+                    if pointer.address[0] == target_addr:
+                        pointer.address[0] = source_addr
+                    ## end difference from collect
+                    # -------------------------------------------------
+                    j += 1
+                i += 1
+
+
     def x_become(self, target_addr, source_addr):
-        # become is implemented very very much like collect currently...
-        import os, time
+        # 1. mark from the roots, and also the objects that objects-with-del
+        #    point to (using the list of malloced_objects_with_finalizer)
+        # 2. walk the list of objects-without-del and free the ones not marked
+        # 3. walk the list of objects-with-del and for the ones not marked:
+        #    call __del__, move the object to the list of object-without-del
+        import time
+        from pypy.rpython.lltypesystem.lloperation import llop
         if DEBUG_PRINT:
-            os.write(2, 'becoming...\n')
+            llop.debug_print(lltype.Void, 'collecting...')
         start_time = time.time()
         roots = self.get_roots()
         size_gc_header = self.gcheaderbuilder.size_gc_header
-        objects = self.AddressLinkedList()
+##        llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes,
+##                        size_gc_header)
+
+        # push the roots on the mark stack
+        objects = self.AddressLinkedList() # mark stack
         while 1:
             curr = roots.pop()
-##             print "root: ", curr
             if curr == NULL:
                 break
             # roots is a list of addresses to addresses:
@@ -562,48 +617,37 @@
         # from this point onwards, no more mallocs should be possible
         old_malloced = self.bytes_malloced
         self.bytes_malloced = 0
+        curr_heap_size = 0
+        freed_size = 0
+
+        # mark objects reachable by objects with a finalizer, but not those
+        # themselves. add their size to curr_heap_size, since they always
+        # survive the collection
+        hdr = self.malloced_objects_with_finalizer
+        while hdr:
+            next = hdr.next
+            typeid = hdr.typeid >> 1
+            gc_info = llmemory.cast_ptr_to_adr(hdr)
+            obj = gc_info + size_gc_header
+            self.add_reachable_to_stack2(obj, objects, target_addr, source_addr)
+            addr = llmemory.cast_ptr_to_adr(hdr)
+            size = self.fixed_size(typeid)
+            if self.is_varsize(typeid):
+                length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
+                size += self.varsize_item_sizes(typeid) * length
+            estimate = raw_malloc_usage(size_gc_header + size)
+            curr_heap_size += estimate
+            hdr = next
+
+        # mark thinks on the mark stack and put their descendants onto the
+        # stack until the stack is empty
         while objects.non_empty():  #mark
             curr = objects.pop()
-##             print "object: ", curr
+            self.add_reachable_to_stack2(curr, objects, target_addr, source_addr)
             gc_info = curr - size_gc_header
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             if hdr.typeid & 1:
                 continue
-            typeid = hdr.typeid >> 1
-            offsets = self.offsets_to_gc_pointers(typeid)
-            i = 0
-            while i < len(offsets):
-                pointer = curr + offsets[i]
-                objects.append(pointer.address[0])
-                # -------------------------------------------------
-                # begin difference from collect
-                if pointer.address[0] == target_addr:
-                    pointer.address[0] == source_addr
-                # end difference from collect
-                # -------------------------------------------------
-                i += 1
-            if self.is_varsize(typeid):
-                offset = self.varsize_offset_to_variable_part(
-                    typeid)
-                length = (curr + self.varsize_offset_to_length(typeid)).signed[0]
-                curr += offset
-                offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
-                itemlength = self.varsize_item_sizes(typeid)
-                i = 0
-                while i < length:
-                    item = curr + itemlength * i
-                    j = 0
-                    while j < len(offsets):
-                        objects.append((item + offsets[j]).address[0])
-                        # -------------------------------------------------
-                        # begin difference from collect
-                        pointer = item + offsets[j]
-                        if pointer.address[0] == target_addr:
-                            pointer.address[0] == source_addr
-                        ## end difference from collect
-                        # -------------------------------------------------
-                        j += 1
-                    i += 1
             hdr.typeid = hdr.typeid | 1
         objects.delete()
         # also mark self.curpool
@@ -612,15 +656,16 @@
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             hdr.typeid = hdr.typeid | 1
 
-        curr_heap_size = 0
-        freed_size = 0
+        # sweep: delete objects without del if they are not marked
+        # unmark objects without del that are marked
         firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw')
         firstpoolnode.linkedlist = self.malloced_objects
         firstpoolnode.nextnode = self.poolnodes
         prevpoolnode = lltype.nullptr(self.POOLNODE)
         poolnode = firstpoolnode
         while poolnode:   #sweep
-            ppnext = lltype.direct_fieldptr(poolnode, 'linkedlist')
+            ppnext = llmemory.cast_ptr_to_adr(poolnode)
+            ppnext += llmemory.offsetof(self.POOLNODE, 'linkedlist')
             hdr = poolnode.linkedlist
             while hdr:  #sweep
                 typeid = hdr.typeid >> 1
@@ -633,14 +678,15 @@
                 estimate = raw_malloc_usage(size_gc_header + size)
                 if hdr.typeid & 1:
                     hdr.typeid = hdr.typeid & (~1)
-                    ppnext[0] = hdr
-                    ppnext = lltype.direct_fieldptr(hdr, 'next')
+                    ppnext.address[0] = addr
+                    ppnext = llmemory.cast_ptr_to_adr(hdr)
+                    ppnext += llmemory.offsetof(self.HDR, 'next')
                     curr_heap_size += estimate
                 else:
                     freed_size += estimate
                     raw_free(addr)
                 hdr = next
-            ppnext[0] = lltype.nullptr(self.HDR)
+            ppnext.address[0] = llmemory.NULL
             next = poolnode.nextnode
             if not poolnode.linkedlist and prevpoolnode:
                 # completely empty node
@@ -657,21 +703,43 @@
             self.bytes_malloced_threshold = curr_heap_size
         end_time = time.time()
         self.total_collection_time += end_time - start_time
-        # 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)
-            os.write(2, "  heap usage at start of collection:  %s bytes\n" %
-                     (self.heap_usage + old_malloced))
-            os.write(2, "  freed:                              %s bytes\n" %
-                     freed_size)
-            os.write(2, "  new heap usage:                     %s bytes\n" %
-                     curr_heap_size)
-            os.write(2, "  total time spent collecting:        %s seconds\n" %
-                     self.total_collection_time)
+            llop.debug_print(lltype.Void,
+                             "  malloced since previous collection:",
+                             old_malloced, "bytes")
+            llop.debug_print(lltype.Void,
+                             "  heap usage at start of collection: ",
+                             self.heap_usage + old_malloced, "bytes")
+            llop.debug_print(lltype.Void,
+                             "  freed:                             ",
+                             freed_size, "bytes")
+            llop.debug_print(lltype.Void,
+                             "  new heap usage:                    ",
+                             curr_heap_size, "bytes")
+            llop.debug_print(lltype.Void,
+                             "  total time spent collecting:       ",
+                             self.total_collection_time, "seconds")
+##        llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes,
+##                        size_gc_header)
         assert self.heap_usage + old_malloced == curr_heap_size + freed_size
+
+        # call finalizers if needed
         self.heap_usage = curr_heap_size
+        hdr = self.malloced_objects_with_finalizer
+        self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR)
+        while hdr:
+            next = hdr.next
+            if hdr.typeid & 1:
+                hdr.next = self.malloced_objects_with_finalizer
+                self.malloced_objects_with_finalizer = hdr
+                hdr.typeid = hdr.typeid & (~1)
+            else:
+                obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header
+                finalizer = self.getfinalizer(hdr.typeid >> 1)
+                finalizer(obj)
+                hdr.next = self.malloced_objects
+                self.malloced_objects = hdr
+            hdr = next
 
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"



More information about the Pypy-commit mailing list