[pypy-svn] r71437 - pypy/branch/gc-prebuilt-dying/pypy/rpython/memory

arigo at codespeak.net arigo at codespeak.net
Tue Feb 23 18:50:21 CET 2010


Author: arigo
Date: Tue Feb 23 18:50:19 2010
New Revision: 71437

Modified:
   pypy/branch/gc-prebuilt-dying/pypy/rpython/memory/gctypelayout.py
Log:
Intermediate check-in.  Mess.  It's not going to work unless I find
a new idea.


Modified: pypy/branch/gc-prebuilt-dying/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/gc-prebuilt-dying/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/branch/gc-prebuilt-dying/pypy/rpython/memory/gctypelayout.py	Tue Feb 23 18:50:19 2010
@@ -182,17 +182,23 @@
         self.lltype2vtable = lltype2vtable
         self.make_type_info_group()
         self.id_of_type = {}      # {LLTYPE: type_id}
-        self.seen_roots = {}
-        # 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 = []
-        # for debugging, the following list collects all the prebuilt
-        # GcStructs and GcArrays
-        self.all_prebuilt_gc = []
+        # This is a list of the GC objects that must be kept alive in all
+        # cases.  It lists all prebuilt GcStructs and GcArrays that are
+        # directly referenced from the code, and those that are referenced
+        # from an immutable GC pointer in some raw Struct or Array.  It
+        # does not list prebuilt GC objects that are only referenced from
+        # other prebuilt GC objects.  This is the basic 'root set'.
+        self.root_prebuilt_gc = []
+        # This is a list of all the locations in raw Structs and Arrays
+        # of type GC pointer that could possibly be modified.  They are
+        # locations that might point to either a prebuilt or a heap GC
+        # object.
+        self.addresses_of_gc_ptrs_in_nongc = []
+        #
+        self.seen_roots = {}         # set of objects in root_prebuilt_gc
+        self.seen_gcs = {}           # set of all gc objects seen so far
+        self.seen_nongcs = {}        # set of all non-gc objects seen so far
+        #
         self.finalizer_funcptrs = {}
         self.offsettable_cache = {}
 
@@ -306,35 +312,72 @@
     def initialize_gc_query_function(self, gc):
         return GCData(self.type_info_group).set_query_functions(gc)
 
-    def consider_constant(self, TYPE, value, gc):
-        if value is not lltype.top_container(value):
-            return
-        if id(value) in self.seen_roots:
-            return
-        self.seen_roots[id(value)] = True
-
-        if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
+    def consider_constant_gcobj(self, TYPE, value, gc, add_root):
+        """This is supposed to be called for every Struct, Array, GcStruct
+        or GcArray.
+        GcArray.  'add_root' is a flag that tells if the gc object must
+        be recorded in self.root_prebuilt_gc or not.
+        """
+        assert value._parentstructure() is None
+        assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray))
+        if id(value) not in self.seen_gcs:
+            self.seen_gcs[id(value)] = value
+            # initialize the gc header of the object
             typeid = self.get_type_id(TYPE)
             hdr = gc.gcheaderbuilder.new_header(value)
             adr = llmemory.cast_ptr_to_adr(hdr)
             gc.init_gc_object_immortal(adr, typeid)
-            self.all_prebuilt_gc.append(value)
+        #
+        if add_root:
+            # if the GC object is referenced from "outside"
+            self.add_root(value)
+
+    def consider_constant_nongcobj(self, TYPE, value):
+        """This is supposed to be called once for every raw Struct
+        or Array.
+
+        elif TYPE._kind != "gc":
+            # we have a raw structure or array
+            if id(value) not in self.seen_nongcs:
+                self.seen_nongcs[id(value)] = value
+                adr = llmemory.cast_ptr_to_adr(value._as_ptr())
+                for a, immutable in enum_gc_pointers_inside(value, adr):
+                    if immutable:
+                        # an immutable GC ref: find out what it points to
+                        ptr = a.ptr
+                        if ptr:
+                            ......
+                        ...
+            
+        #
+        # do the rest only once, even if we are called multiple times
+        if id(value) in self.seen_constants:
+            return
+        self.seen_constants[id(value)] = value
+        #
+        if is_gc_object:
+        else:
+            # for non-gc objects: find their mutable gc references
+            ........
+        for a in mutable_gc_pointers_inside(value, adr):
+            
+            ...
 
-        # The following collects the addresses of all the fields that have
-        # a GC Pointer type, inside the current prebuilt object.  All such
-        # 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":
-            if gc.prebuilt_gc_objects_are_static_roots or gc.DEBUG:
+            if gc.prebuilt_gc_objects_are_static_roots:
                 appendto = self.addresses_of_static_ptrs
             else:
                 return
         else:
             appendto = self.addresses_of_static_ptrs_in_nongc
-        for a in gc_pointers_inside(value, adr, mutable_only=True):
             appendto.append(a)
 
+    def add_root(self, value):
+        if id(value) not in self.seen_roots:
+            self.seen_roots[id(value)] = True
+            self.root_prebuilt_gc.append(value)
+
 # ____________________________________________________________
 #
 # Helpers to discover GC pointers inside structures
@@ -366,35 +409,34 @@
         offsets.append(0)
     return offsets
 
-def gc_pointers_inside(v, adr, mutable_only=False):
+def enum_gc_pointers_inside(v, adr):
+    """Enumerate the GC pointers from the constant struct or array 'v'.
+    For each of them, yields (addr-of-field, mutable-flag).
+    """
     t = lltype.typeOf(v)
     if isinstance(t, lltype.Struct):
-        skip = ()
-        if mutable_only:
-            if t._hints.get('immutable'):
-                return
-            if 'immutable_fields' in t._hints:
-                skip = t._hints['immutable_fields'].fields
+        fully_immutable = t._hints.get('immutable', False)
+        if 'immutable_fields' in t._hints:
+            immutable_fields = t._hints['immutable_fields'].fields
+        else:
+            immutable_fields = ()
         for n, t2 in t._flds.iteritems():
             if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc':
-                if n not in skip:
-                    yield adr + llmemory.offsetof(t, n)
+                yield (adr + llmemory.offsetof(t, n),
+                       fully_immutable or n in immutable_fields)
             elif isinstance(t2, (lltype.Array, lltype.Struct)):
-                for a in gc_pointers_inside(getattr(v, n),
-                                            adr + llmemory.offsetof(t, n),
-                                            mutable_only):
+                for a in enum_gc_pointers_inside(getattr(v, n),
+                                            adr + llmemory.offsetof(t, n)):
                     yield a
     elif isinstance(t, lltype.Array):
-        if mutable_only and t._hints.get('immutable'):
-            return
+        fully_immutable = t._hints.get('immutable', False)
         if isinstance(t.OF, lltype.Ptr) and t.OF.TO._gckind == 'gc':
             for i in range(len(v.items)):
-                yield adr + llmemory.itemoffsetof(t, i)
+                yield (adr + llmemory.itemoffsetof(t, i), fully_immutable)
         elif isinstance(t.OF, lltype.Struct):
             for i in range(len(v.items)):
-                for a in gc_pointers_inside(v.items[i],
-                                            adr + llmemory.itemoffsetof(t, i),
-                                            mutable_only):
+                for a in enum_gc_pointers_inside(v.items[i],
+                                            adr + llmemory.itemoffsetof(t, i)):
                     yield a
 
 def zero_gc_pointers(p):



More information about the Pypy-commit mailing list