[pypy-svn] r49701 - pypy/dist/pypy/rpython/memory/gc

arigo at codespeak.net arigo at codespeak.net
Thu Dec 13 13:07:27 CET 2007


Author: arigo
Date: Thu Dec 13 13:07:27 2007
New Revision: 49701

Modified:
   pypy/dist/pypy/rpython/memory/gc/base.py
   pypy/dist/pypy/rpython/memory/gc/generation.py
   pypy/dist/pypy/rpython/memory/gc/marksweep.py
   pypy/dist/pypy/rpython/memory/gc/semispace.py
Log:
Remove some code duplication by moving the tracing logic in the base class.


Modified: pypy/dist/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/base.py	Thu Dec 13 13:07:27 2007
@@ -106,6 +106,34 @@
     def x_become(self, target_addr, source_addr):
         raise RuntimeError("no support for x_become in the GC")
 
+    def trace(self, obj, callback, arg):
+        """Enumerate the locations inside the given obj that can contain
+        GC pointers.  For each such location, callback(pointer, arg) is
+        called, where 'pointer' is an address inside the object.
+        Typically, 'callback' is a bound method and 'arg' can be None.
+        """
+        typeid = self.get_type_id(obj)
+        offsets = self.offsets_to_gc_pointers(typeid)
+        i = 0
+        while i < len(offsets):
+            callback(obj + offsets[i], arg)
+            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]
+            offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
+            itemlength = self.varsize_item_sizes(typeid)
+            i = 0
+            while i < length:
+                item = obj + offset + itemlength * i
+                j = 0
+                while j < len(offsets):
+                    callback(item + offsets[j], arg)
+                    j += 1
+                i += 1
+    trace._annspecialcase_ = 'specialize:arg(2)'
+
 
 class MovingGCBase(GCBase):
     moving_gc = True

Modified: pypy/dist/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/generation.py	Thu Dec 13 13:07:27 2007
@@ -258,30 +258,11 @@
         young objects it references out of the nursery.
         """
         self.header(obj).tid |= GCFLAG_NO_YOUNG_PTRS
-        typeid = self.get_type_id(obj)
-        offsets = self.offsets_to_gc_pointers(typeid)
-        i = 0
-        while i < len(offsets):
-            pointer = obj + offsets[i]
-            if self.is_in_nursery(pointer.address[0]):
-                pointer.address[0] = self.copy(pointer.address[0])
-            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]
-            offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
-            itemlength = self.varsize_item_sizes(typeid)
-            i = 0
-            while i < length:
-                item = obj + offset + itemlength * i
-                j = 0
-                while j < len(offsets):
-                    pointer = item + offsets[j]
-                    if self.is_in_nursery(pointer.address[0]):
-                        pointer.address[0] = self.copy(pointer.address[0])
-                    j += 1
-                i += 1
+        self.trace(obj, self._trace_drag_out, None)
+
+    def _trace_drag_out(self, pointer, ignored):
+        if self.is_in_nursery(pointer.address[0]):
+            pointer.address[0] = self.copy(pointer.address[0])
 
     def invalidate_young_weakrefs(self):
         # walk over the list of objects that contain weakrefs and are in the

Modified: pypy/dist/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/marksweep.py	Thu Dec 13 13:07:27 2007
@@ -458,33 +458,18 @@
     STAT_BYTES_MALLOCED = 1
     STATISTICS_NUMBERS  = 2
 
-    def add_reachable_to_stack(self, obj, objects):
+    def get_type_id(self, obj):
         size_gc_header = self.gcheaderbuilder.size_gc_header
         gc_info = obj - size_gc_header
         hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
-        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])
-            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):
-                    pointer = item + offsets[j]
-                    objects.append(pointer.address[0])
-                    j += 1
-                i += 1
+        return hdr.typeid >> 1
+
+    def add_reachable_to_stack(self, obj, objects):
+        self.trace(obj, self._add_reachable, objects)
+
+    def _add_reachable(pointer, objects):
+        objects.append(pointer.address[0])
+    _add_reachable = staticmethod(_add_reachable)
 
     def statistics(self, index):
         # no memory allocation here!
@@ -675,48 +660,18 @@
         # 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):
+    def add_reachable_to_stack2(self, obj, objects):
         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]
-            # -------------------------------------------------
-            # begin difference from collect
-            if pointer.address[0] == target_addr:
-                pointer.address[0] = source_addr
-            # end difference from collect
-            # -------------------------------------------------
-            objects.append(pointer.address[0])
-            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):
-                    pointer = item + offsets[j]
-                    # -------------------------------------------------
-                    # begin difference from collect
-                    if pointer.address[0] == target_addr:
-                        pointer.address[0] = source_addr
-                    ## end difference from collect
-                    # -------------------------------------------------
-                    objects.append(pointer.address[0])
-                    j += 1
-                i += 1
+        self.trace(obj, self._add_reachable_and_rename, objects)
 
+    def _add_reachable_and_rename(self, pointer, objects):
+        if pointer.address[0] == self.x_become_target_addr:
+            pointer.address[0] = self.x_become_source_addr
+        objects.append(pointer.address[0])
 
     def x_become(self, target_addr, source_addr):
         # 1. mark from the roots, and also the objects that objects-with-del
@@ -754,6 +709,9 @@
         curr_heap_size = 0
         freed_size = 0
 
+        self.x_become_target_addr = target_addr
+        self.x_become_source_addr = source_addr
+
         # 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
@@ -763,7 +721,7 @@
             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)
+            self.add_reachable_to_stack2(obj, objects)
             addr = llmemory.cast_ptr_to_adr(hdr)
             size = self.fixed_size(typeid)
             if self.is_varsize(typeid):
@@ -777,7 +735,7 @@
         # stack until the stack is empty
         while objects.non_empty():  #mark
             curr = objects.pop()
-            self.add_reachable_to_stack2(curr, objects, target_addr, source_addr)
+            self.add_reachable_to_stack2(curr, objects)
             gc_info = curr - size_gc_header
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             if hdr.typeid & 1:

Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/semispace.py	Thu Dec 13 13:07:27 2007
@@ -256,30 +256,11 @@
             return newobj
 
     def trace_and_copy(self, obj):
-        typeid = self.get_type_id(obj)
-        offsets = self.offsets_to_gc_pointers(typeid)
-        i = 0
-        while i < len(offsets):
-            pointer = obj + offsets[i]
-            if pointer.address[0] != NULL:
-                pointer.address[0] = self.copy(pointer.address[0])
-            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]
-            offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
-            itemlength = self.varsize_item_sizes(typeid)
-            i = 0
-            while i < length:
-                item = obj + offset + itemlength * i
-                j = 0
-                while j < len(offsets):
-                    pointer = item + offsets[j]
-                    if pointer.address[0] != NULL:
-                        pointer.address[0] = self.copy(pointer.address[0])
-                    j += 1
-                i += 1
+        self.trace(obj, self._trace_copy, None)
+
+    def _trace_copy(self, pointer, ignored):
+        if pointer.address[0] != NULL:
+            pointer.address[0] = self.copy(pointer.address[0])
 
     def is_forwarded(self, obj):
         return self.header(obj).forw != NULL



More information about the Pypy-commit mailing list