[pypy-svn] r47642 - in pypy/dist/pypy/rpython/memory: . gc gctransform

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Oct 20 15:17:20 CEST 2007


Author: cfbolz
Date: Sat Oct 20 15:17:18 2007
New Revision: 47642

Modified:
   pypy/dist/pypy/rpython/memory/gc/generation.py
   pypy/dist/pypy/rpython/memory/gc/semispace.py
   pypy/dist/pypy/rpython/memory/gctransform/framework.py
   pypy/dist/pypy/rpython/memory/gctypelayout.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
Log:
(cfbolz, arigo review)
In minor collections of the GenerationGC, avoid scanning all static roots.
It is enough to scan the static roots not living inside a GcStruct (there
are only 3 of them in PyPy!) and remember which prebuilt GcStructs have
got a pointer to a young object.


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	Sat Oct 20 15:17:18 2007
@@ -1,5 +1,6 @@
 import sys
-from pypy.rpython.memory.gc.semispace import SemiSpaceGC
+from pypy.rpython.memory.gc.semispace import SemiSpaceGC, GCFLAGSHIFT, \
+    GCFLAG_IMMORTAL
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
 from pypy.rlib.objectmodel import free_non_gc_object, debug_assert
@@ -7,6 +8,7 @@
 nonnull_endmarker = llmemory.raw_malloc(llmemory.sizeof(lltype.Char))
 llmemory.raw_memclear(nonnull_endmarker, llmemory.sizeof(lltype.Char))
 
+GCFLAG_REMEMBERED = 2 << GCFLAGSHIFT
 
 class GenerationGC(SemiSpaceGC):
     """A basic generational GC: it's a SemiSpaceGC with an additional
@@ -35,6 +37,7 @@
         self.old_objects_pointing_to_young = nonnull_endmarker
         # ^^^ the head of a linked list inside the old objects space
         self.young_objects_with_weakrefs = self.AddressLinkedList()
+        self.static_to_young_pointer = self.AddressLinkedList()
 
     def reset_nursery(self):
         self.nursery      = llmemory.NULL
@@ -90,6 +93,7 @@
 
     def semispace_collect(self, size_changing=False):
         self.reset_forwarding() # we are doing a full collection anyway
+        self.reset_static()
         self.weakrefs_grow_older()
         self.reset_nursery()
         SemiSpaceGC.semispace_collect(self, size_changing)
@@ -102,6 +106,12 @@
             hdr.forw = llmemory.NULL
         self.old_objects_pointing_to_young = nonnull_endmarker
 
+    def reset_static(self):
+        while self.static_to_young_pointer.non_empty():
+            obj = self.static_to_young_pointer.pop()
+            hdr = self.header(obj)
+            hdr.tid &= ~GCFLAG_REMEMBERED
+
     def weakrefs_grow_older(self):
         while self.young_objects_with_weakrefs.non_empty():
             obj = self.young_objects_with_weakrefs.pop()
@@ -117,6 +127,7 @@
             # a nursery-only collection
             scan = self.free
             self.collect_oldrefs_to_nursery()
+            self.collect_static_to_nursery()
             self.collect_roots_in_nursery()
             self.scan_objects_just_copied_out_of_nursery(scan)
             if self.young_objects_with_weakrefs.non_empty():
@@ -149,8 +160,15 @@
             hdr.forw = llmemory.NULL
         self.old_objects_pointing_to_young = nonnull_endmarker
 
+    def collect_static_to_nursery(self):
+        while self.static_to_young_pointer.non_empty():
+            obj = self.static_to_young_pointer.pop()
+            hdr = self.header(obj)
+            hdr.tid &= ~GCFLAG_REMEMBERED
+            self.trace_and_drag_out_of_nursery(obj)
+
     def collect_roots_in_nursery(self):
-        roots = self.get_roots()
+        roots = self.get_roots(with_static=False)
         while 1:
             root = roots.pop()
             if root == NULL:
@@ -217,8 +235,17 @@
 
     def write_barrier(self, addr, addr_to, addr_struct):
         if not self.is_in_nursery(addr_struct) and self.is_in_nursery(addr):
-            oldhdr = self.header(addr_struct)
-            if oldhdr.forw == NULL:
-                oldhdr.forw = self.old_objects_pointing_to_young
-                self.old_objects_pointing_to_young = addr_struct
+            self.remember_young_pointer(addr_struct, addr)
         addr_to.address[0] = addr
+
+    def remember_young_pointer(self, addr_struct, addr):
+        oldhdr = self.header(addr_struct)
+        if oldhdr.forw == NULL:
+            oldhdr.forw = self.old_objects_pointing_to_young
+            self.old_objects_pointing_to_young = addr_struct
+        elif (oldhdr.tid & (GCFLAG_IMMORTAL | GCFLAG_REMEMBERED) ==
+                 GCFLAG_IMMORTAL):
+            self.static_to_young_pointer.append(addr_struct)
+            oldhdr.tid |= GCFLAG_REMEMBERED
+    remember_young_pointer.dont_inline = True
+

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	Sat Oct 20 15:17:18 2007
@@ -9,9 +9,12 @@
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.memory.gc.base import MovingGCBase
 
-
 import sys, os
 
+TYPEID_MASK = 0xffff
+GCFLAGSHIFT = 16
+GCFLAG_IMMORTAL = 1 << GCFLAGSHIFT
+
 memoryError = MemoryError()
 
 class SemiSpaceGC(MovingGCBase):
@@ -288,7 +291,7 @@
         # immortal objects always have forward to themselves
         hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
         hdr.forw = addr + self.gcheaderbuilder.size_gc_header
-        hdr.tid = typeid
+        hdr.tid = typeid | GCFLAG_IMMORTAL
 
     def deal_with_objects_with_finalizers(self):
         # walk over list of objects with finalizers

Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py	Sat Oct 20 15:17:18 2007
@@ -112,8 +112,9 @@
         # to make the annotator happy.  The fields are patched in finish()
         # to point to a real array (not 'static_roots', another one).
         a_random_address = llmemory.cast_ptr_to_adr(gcdata.type_info_table)
-        gcdata.static_root_start = a_random_address   # patched in finish()
-        gcdata.static_root_end = a_random_address     # patched in finish()
+        gcdata.static_root_start = a_random_address      # patched in finish()
+        gcdata.static_root_nongcstart = a_random_address # patched in finish()
+        gcdata.static_root_end = a_random_address        # patched in finish()
         self.gcdata = gcdata
         self.malloc_fnptr_cache = {}
 
@@ -154,6 +155,9 @@
             'static_root_start',
             annmodel.SomeAddress())
         data_classdef.generalize_attr(
+            'static_root_nongcstart',
+            annmodel.SomeAddress())
+        data_classdef.generalize_attr(
             'static_root_end',
             annmodel.SomeAddress())
 
@@ -339,9 +343,12 @@
                 return top.address[0]
             pop_root = staticmethod(pop_root)
 
-            def __init__(self):
+            def __init__(self, with_static=True):
                 self.stack_current = gcdata.root_stack_top
-                self.static_current = gcdata.static_root_start
+                if with_static:
+                    self.static_current = gcdata.static_root_start
+                else:
+                    self.static_current = gcdata.static_root_nongcstart
 
             def pop(self):
                 while self.static_current != gcdata.static_root_end:
@@ -400,7 +407,9 @@
         ll_instance.inst_type_info_table = table
         #self.gcdata.type_info_table = table
 
-        addresses_of_static_ptrs = self.layoutbuilder.addresses_of_static_ptrs
+        addresses_of_static_ptrs = (
+            self.layoutbuilder.addresses_of_static_ptrs +
+            self.layoutbuilder.addresses_of_static_ptrs_in_nongc)
         log.info("found %s static roots" % (len(addresses_of_static_ptrs), ))
         ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
                                                len(addresses_of_static_ptrs),
@@ -408,6 +417,7 @@
         for i in range(len(addresses_of_static_ptrs)):
             ll_static_roots_inside[i] = addresses_of_static_ptrs[i]
         ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address))
+        ll_instance.inst_static_root_nongcstart = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(self.layoutbuilder.addresses_of_static_ptrs)
         ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside)
 
         newgcdependencies = []

Modified: pypy/dist/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctypelayout.py	Sat Oct 20 15:17:18 2007
@@ -10,12 +10,13 @@
         self.type_info_list = [dummy]   # don't use typeid 0, helps debugging
         self.id_of_type = {}      # {LLTYPE: type_id}
         self.seen_roots = {}
-        # the following is a list of addresses of gc pointers living inside
-        # the prebuilt structures (independently on whether the prebuilt
-        # structures are themselves GcStruct or plain Struct).  It should
-        # list all the locations that could possibly point to a GC heap
-        # object.
+        # the following are lists of addresses of gc pointers living inside the
+        # prebuilt structures.  It should list all the locations that could
+        # possibly point to a GC heap object.
+        # this lists contains pointers in GcStructs and GcArrays
         self.addresses_of_static_ptrs = []
+        # this lists contains pointers in raw Structs and Arrays
+        self.addresses_of_static_ptrs_in_nongc = []
         self.finalizer_funcptrs = {}
 
     def get_type_id(self, TYPE):
@@ -27,6 +28,7 @@
             # Record the new type_id description as a small dict for now.
             # It will be turned into a Struct("type_info") in finish()
             type_id = len(self.type_info_list)
+            assert type_id & 0xffff == type_id # make sure it fits into 2 bytes
             info = {}
             self.type_info_list.append(info)
             self.id_of_type[TYPE] = type_id
@@ -151,8 +153,12 @@
         # fields are potential roots: unless the structure is immutable,
         # they could be changed later to point to GC heap objects.
         adr = llmemory.cast_ptr_to_adr(value._as_ptr())
+        if TYPE._gckind == "gc":
+            appendto = self.addresses_of_static_ptrs
+        else:
+            appendto = self.addresses_of_static_ptrs_in_nongc
         for a in mutable_gc_pointers_inside(value, adr):
-            self.addresses_of_static_ptrs.append(a)
+            appendto.append(a)
 
 # ____________________________________________________________
 #

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Sat Oct 20 15:17:18 2007
@@ -26,11 +26,16 @@
             layoutbuilder.consider_constant(TYPE, obj, self.gc)
 
         self.constantroots = layoutbuilder.addresses_of_static_ptrs
+        self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc
 
-    def get_roots_from_llinterp(self):
+    def get_roots_from_llinterp(self, with_static=True):
         sizeofaddr = llmemory.sizeof(llmemory.Address)
         ll = [llmemory.NULL]     # end marker
-        for addrofaddr in self.constantroots:
+        if with_static:
+            for addrofaddr in self.constantroots:
+                if addrofaddr.address[0]:
+                    ll.append(addrofaddr)
+        for addrofaddr in self.constantrootsnongc:
             if addrofaddr.address[0]:
                 ll.append(addrofaddr)
         for addrofaddr in self.llinterp.find_roots():



More information about the Pypy-commit mailing list