[pypy-svn] r50345 - in pypy/branch/applevel-ctypes/pypy/rpython/memory: . gc gctransform gctransform/test test

fijal at codespeak.net fijal at codespeak.net
Sat Jan 5 11:15:23 CET 2008


Author: fijal
Date: Sat Jan  5 11:15:22 2008
New Revision: 50345

Modified:
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py
   pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Merge the gc from dist, as translation is now broken on this branch.


Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py	Sat Jan  5 11:15:22 2008
@@ -6,6 +6,7 @@
     moving_gc = False
     needs_write_barrier = False
     needs_zero_gc_pointers = True
+    prebuilt_gc_objects_are_static_roots = True
 
     def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
                             is_gcarrayofgcptr,
@@ -160,6 +161,12 @@
         # more non-prebuild GC objects; this is fine because the
         # internal GC ptr in the prebuilt list or dict is found by
         # gctypelayout and listed in addresses_of_static_ptrs.
+
+        # XXX I'm not sure any more about the warning above.  The fields
+        # of 'self' are found by gctypelayout and added to
+        # addresses_of_static_ptrs_in_nongc, so in principle they could
+        # be mutated and still be found by collect().
+
         self.wr_to_objects_with_id = []
         self.object_id_dict = {}
         self.object_id_dict_ends_at = 0

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py	Sat Jan  5 11:15:22 2008
@@ -11,7 +11,11 @@
 # in the nursery.  It is initially set on all prebuilt and old objects,
 # and gets cleared by the write_barrier() when we write in them a
 # pointer to a young object.
-GCFLAG_NO_YOUNG_PTRS = 2 << GCFLAGSHIFT
+GCFLAG_NO_YOUNG_PTRS = 1 << (GCFLAGSHIFT+1)
+
+# The following flag is set for static roots which are not on the list
+# of static roots yet, but will appear with write barrier
+GCFLAG_NO_HEAP_PTRS = 1 << (GCFLAGSHIFT+2)
 
 DEBUG_PRINT = False
 
@@ -22,7 +26,9 @@
     list, chained to each other via their 'forw' header field.
     """
     inline_simple_malloc = True
+    inline_simple_malloc_varsize = True
     needs_write_barrier = True
+    prebuilt_gc_objects_are_static_roots = False
 
     def __init__(self, AddressLinkedList,
                  nursery_size=128,
@@ -135,7 +141,8 @@
     def init_gc_object(self, addr, typeid, flags=GCFLAG_NO_YOUNG_PTRS):
         SemiSpaceGC.init_gc_object(self, addr, typeid, flags)
 
-    def init_gc_object_immortal(self, addr, typeid, flags=GCFLAG_NO_YOUNG_PTRS):
+    def init_gc_object_immortal(self, addr, typeid,
+                                flags=GCFLAG_NO_YOUNG_PTRS|GCFLAG_NO_HEAP_PTRS):
         SemiSpaceGC.init_gc_object_immortal(self, addr, typeid, flags)
 
     def semispace_collect(self, size_changing=False):
@@ -288,12 +295,22 @@
         if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
             self.remember_young_pointer(addr_struct, newvalue)
 
+    def append_to_static_roots(self, pointer, arg):
+        self.get_roots.append_static_root(pointer)
+
+    def move_to_static_roots(self, addr_struct):
+        objhdr = self.header(addr_struct)
+        objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
+        self.trace(addr_struct, self.append_to_static_roots, None)
+
     def remember_young_pointer(self, addr_struct, addr):
         ll_assert(not self.is_in_nursery(addr_struct),
                      "nursery object with GCFLAG_NO_YOUNG_PTRS")
+        oldhdr = self.header(addr_struct)
         if self.is_in_nursery(addr):
-            oldhdr = self.header(addr_struct)
             oldhdr.forw = self.old_objects_pointing_to_young
             self.old_objects_pointing_to_young = addr_struct
             oldhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
-    remember_young_pointer.dont_inline = True
+        if oldhdr.tid & GCFLAG_NO_HEAP_PTRS:
+            self.move_to_static_roots(addr_struct)
+    remember_young_pointer._dont_inline_ = True

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py	Sat Jan  5 11:15:22 2008
@@ -102,7 +102,7 @@
         #llop.debug_print(lltype.Void, 'malloc typeid', typeid,
         #                 '->', llmemory.cast_adr_to_int(result))
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
-    malloc_fixedsize.dont_inline = True
+    malloc_fixedsize._dont_inline_ = True
 
     def malloc_fixedsize_clear(self, typeid, size, can_collect,
                                has_finalizer=False, contains_weakptr=False):
@@ -136,7 +136,7 @@
         #llop.debug_print(lltype.Void, 'malloc typeid', typeid,
         #                 '->', llmemory.cast_adr_to_int(result))
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
-    malloc_fixedsize_clear.dont_inline = True
+    malloc_fixedsize_clear._dont_inline_ = True
 
     def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
                        can_collect, has_finalizer=False):
@@ -171,7 +171,7 @@
         #                 'typeid', typeid,
         #                 '->', llmemory.cast_adr_to_int(result))
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
-    malloc_varsize.dont_inline = True
+    malloc_varsize._dont_inline_ = True
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
                              offset_to_length, can_collect,
@@ -208,7 +208,7 @@
         #                 'typeid', typeid,
         #                 '->', llmemory.cast_adr_to_int(result))
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
-    malloc_varsize_clear.dont_inline = True
+    malloc_varsize_clear._dont_inline_ = True
 
     def collect(self):
         # 1. mark from the roots, and also the objects that objects-with-del
@@ -483,8 +483,9 @@
         hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
         hdr.typeid = typeid << 1
 
-    def init_gc_object_immortal(self, addr, typeid):
+    def init_gc_object_immortal(self, addr, typeid, flags=0):
         # prebuilt gc structures always have the mark bit set
+        # ignore flags
         hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
         hdr.typeid = (typeid << 1) | 1
 

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py	Sat Jan  5 11:15:22 2008
@@ -21,6 +21,7 @@
 class SemiSpaceGC(MovingGCBase):
     _alloc_flavor_ = "raw"
     inline_simple_malloc = True
+    inline_simple_malloc_varsize = True
     needs_zero_gc_pointers = False
 
     HDR = lltype.Struct('header', ('forw', llmemory.Address),
@@ -107,7 +108,7 @@
         if not self.try_obtain_free_space(needed):
             raise memoryError
         return self.free
-    obtain_free_space.dont_inline = True
+    obtain_free_space._dont_inline_ = True
 
     def try_obtain_free_space(self, needed):
         # XXX for bonus points do big objects differently

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py	Sat Jan  5 11:15:22 2008
@@ -108,7 +108,7 @@
                    "    v = cast_adr_to_ptr(addr, PTR_TYPE)\n"
                    "%s\n")%(static_body,)
             exec src in d
-            fptr = self.annotate_helper(d['ll_finalizer'], [llmemory.Address], lltype.Void)
+            fptr = self.annotate_finalizer(d['ll_finalizer'], [llmemory.Address], lltype.Void)
         elif destrptr:
             EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
             def ll_finalizer(addr):
@@ -116,7 +116,7 @@
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
                 ll_call_destructor(destrptr, v)
                 llop.gc_restore_exception(lltype.Void, exc_instance)
-            fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void)
+            fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void)
         else:
             fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
 

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py	Sat Jan  5 11:15:22 2008
@@ -17,6 +17,7 @@
 from pypy.rpython.memory.gctypelayout import convert_weakref_to, WEAKREFPTR
 from pypy.rpython.memory.gctransform.log import log
 from pypy.tool.sourcetools import func_with_new_name
+from pypy.rpython.lltypesystem.lloperation import llop
 import sys
 
 
@@ -87,8 +88,8 @@
         mallocvars = {target.inputargs[index]: True}
         mallocnum += 1
         find_in_block(target, mallocvars)
-    if result:
-        print "found %s initializing stores in %s" % (len(result), graph.name)
+    #if result:
+    #    print "found %s initializing stores in %s" % (len(result), graph.name)
     return result
 
 class FrameworkGCTransformer(GCTransformer):
@@ -113,16 +114,19 @@
         self.get_type_id = self.layoutbuilder.get_type_id
 
         # set up dummy a table, to be overwritten with the real one in finish()
-        type_info_table = lltype.malloc(gctypelayout.GCData.TYPE_INFO_TABLE, 0,
-                                        immortal=True)
+        type_info_table = lltype._ptr(
+            lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE),
+            "delayed!type_info_table", solid=True)
         gcdata = gctypelayout.GCData(type_info_table)
 
         # initialize the following two fields with a random non-NULL address,
         # to make the annotator happy.  The fields are patched in finish()
-        # to point to a real array (not 'type_info_table', another one).
-        a_random_address = llmemory.cast_ptr_to_adr(type_info_table)
+        # to point to a real array.
+        foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1),
+                            immortal=True, zero=True)
+        a_random_address = llmemory.cast_ptr_to_adr(foo)
         gcdata.static_root_start = a_random_address      # patched in finish()
-        gcdata.static_root_nongcstart = a_random_address # patched in finish()
+        gcdata.static_root_nongcend = a_random_address   # patched in finish()
         gcdata.static_root_end = a_random_address        # patched in finish()
         self.gcdata = gcdata
         self.malloc_fnptr_cache = {}
@@ -143,16 +147,13 @@
         bk = self.translator.annotator.bookkeeper
 
         # the point of this little dance is to not annotate
-        # self.gcdata.type_info_table as a constant.
+        # self.gcdata.static_root_xyz as constants. XXX is it still needed??
         data_classdef = bk.getuniqueclassdef(gctypelayout.GCData)
         data_classdef.generalize_attr(
-            'type_info_table',
-            annmodel.SomePtr(lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE)))
-        data_classdef.generalize_attr(
             'static_root_start',
             annmodel.SomeAddress())
         data_classdef.generalize_attr(
-            'static_root_nongcstart',
+            'static_root_nongcend',
             annmodel.SomeAddress())
         data_classdef.generalize_attr(
             'static_root_end',
@@ -256,6 +257,28 @@
         else:
             self.malloc_fast_ptr = None
 
+        # in some GCs we can also inline the common case of
+        # malloc_varsize(typeid, length, (3 constant sizes), True, False)
+        if getattr(GCClass, 'inline_simple_malloc_varsize', False):
+            # make a copy of this function so that it gets annotated
+            # independently and the constants are folded inside
+            malloc_varsize_clear_fast = func_with_new_name(
+                GCClass.malloc_varsize_clear.im_func,
+                "malloc_varsize_clear_fast")
+            s_False = annmodel.SomeBool(); s_False.const = False
+            s_True  = annmodel.SomeBool(); s_True .const = True
+            self.malloc_varsize_clear_fast_ptr = getfn(
+                malloc_varsize_clear_fast,
+                [s_gc, annmodel.SomeInteger(nonneg=True),
+                 annmodel.SomeInteger(nonneg=True),
+                 annmodel.SomeInteger(nonneg=True),
+                 annmodel.SomeInteger(nonneg=True),
+                 annmodel.SomeInteger(nonneg=True),
+                 s_True, s_False], s_gcref,
+                inline = True)
+        else:
+            self.malloc_varsize_clear_fast_ptr = None
+
         if GCClass.moving_gc:
             self.id_ptr = getfn(GCClass.id.im_func,
                                 [s_gc, s_gcref], annmodel.SomeInteger(),
@@ -349,6 +372,11 @@
                 gcdata.root_stack_top = top + n*sizeofaddr
                 return top
             incr_stack = staticmethod(incr_stack)
+
+            def append_static_root(adr):
+                gcdata.static_root_end.address[0] = adr
+                gcdata.static_root_end += sizeofaddr
+            append_static_root = staticmethod(append_static_root)
             
             def decr_stack(n):
                 top = gcdata.root_stack_top - n*sizeofaddr
@@ -371,16 +399,16 @@
             def __init__(self, with_static=True):
                 self.stack_current = gcdata.root_stack_top
                 if with_static:
-                    self.static_current = gcdata.static_root_start
+                    self.static_current = gcdata.static_root_end
                 else:
-                    self.static_current = gcdata.static_root_nongcstart
+                    self.static_current = gcdata.static_root_nongcend
 
             def pop(self):
-                while self.static_current != gcdata.static_root_end:
-                    result = self.static_current
-                    self.static_current += sizeofaddr
-                    if result.address[0].address[0] != llmemory.NULL:
-                        return result.address[0]
+                while self.static_current != gcdata.static_root_start:
+                    self.static_current -= sizeofaddr
+                    result = self.static_current.address[0]
+                    if result.address[0] != llmemory.NULL:
+                        return result
                 while self.stack_current != gcdata.root_stack_base:
                     self.stack_current -= sizeofaddr
                     if self.stack_current.address[0] != llmemory.NULL:
@@ -418,9 +446,10 @@
 
         # replace the type_info_table pointer in gcdata -- at this point,
         # the database is in principle complete, so it has already seen
-        # the old (empty) array.  We need to force it to consider the new
-        # array now.  It's a bit hackish as the old empty array will also
-        # be generated in the C source, but that's a rather minor problem.
+        # the delayed pointer.  We need to force it to consider the new
+        # array now.
+
+        self.gcdata.type_info_table._become(table)
 
         # XXX because we call inputconst already in replace_malloc, we can't
         # modify the instance, we have to modify the 'rtyped instance'
@@ -430,24 +459,24 @@
             self.gcdata)
         r_gcdata = self.translator.rtyper.getrepr(s_gcdata)
         ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value
-        ll_instance.inst_type_info_table = table
-        #self.gcdata.type_info_table = table
 
         addresses_of_static_ptrs = (
-            self.layoutbuilder.addresses_of_static_ptrs +
-            self.layoutbuilder.addresses_of_static_ptrs_in_nongc)
+            self.layoutbuilder.addresses_of_static_ptrs_in_nongc +
+            self.layoutbuilder.addresses_of_static_ptrs)
         log.info("found %s static roots" % (len(addresses_of_static_ptrs), ))
+        additional_ptrs = self.layoutbuilder.additional_roots_sources
+        log.info("additional %d potential static roots" % additional_ptrs)
         ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
-                                               len(addresses_of_static_ptrs),
+                                               len(addresses_of_static_ptrs) +
+                                               additional_ptrs,
                                                immortal=True)
         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)
+        ll_instance.inst_static_root_nongcend = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(self.layoutbuilder.addresses_of_static_ptrs_in_nongc)
+        ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(addresses_of_static_ptrs)
 
         newgcdependencies = []
-        newgcdependencies.append(table)
         newgcdependencies.append(ll_static_roots_inside)
         self.write_typeid_list()
         return newgcdependencies
@@ -514,11 +543,11 @@
             v_length = op.args[-1]
             c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
             c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
-            malloc_ptr = self.malloc_varsize_clear_ptr
-##             if op.opname.startswith('zero'):
-##                 malloc_ptr = self.malloc_varsize_clear_ptr
-##             else:
-##                 malloc_ptr = self.malloc_varsize_clear_ptr
+            if (self.malloc_varsize_clear_fast_ptr is not None and
+                c_can_collect.value and not c_has_finalizer.value):
+                malloc_ptr = self.malloc_varsize_clear_fast_ptr
+            else:
+                malloc_ptr = self.malloc_varsize_clear_ptr
             args = [self.c_const_gc, c_type_id, v_length, c_size,
                     c_varitemsize, c_ofstolength, c_can_collect,
                     c_has_finalizer]
@@ -772,9 +801,9 @@
             def ll_finalizer(addr):
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
                 ll_call_destructor(destrptr, v)
-            fptr = self.transformer.annotate_helper(ll_finalizer,
-                                                    [llmemory.Address],
-                                                    lltype.Void)
+            fptr = self.transformer.annotate_finalizer(ll_finalizer,
+                                                       [llmemory.Address],
+                                                       lltype.Void)
         else:
             fptr = lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO)
         return fptr

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py	Sat Jan  5 11:15:22 2008
@@ -115,8 +115,8 @@
         self.dynamic_deallocator_funcptrs = {}
         self.queryptr2dynamic_deallocator_funcptr = {}
 
-    def finish_helpers(self):
-        GCTransformer.finish_helpers(self)
+    def finish_helpers(self, **kwds):
+        GCTransformer.finish_helpers(self, **kwds)
         from pypy.translator.backendopt.malloc import remove_mallocs
         seen = {}
         graphs = []
@@ -247,7 +247,7 @@
              'HDRPTR':lltype.Ptr(self.HDR)}
         exec src in d
         this = d['ll_deallocator']
-        fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void)
+        fptr = self.annotate_finalizer(this, [llmemory.Address], lltype.Void)
         self.static_deallocator_funcptrs[TYPE] = fptr
         for p in find_gc_ptrs_in_type(TYPE):
             self.static_deallocation_funcptr_for_type(p.TO)

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py	Sat Jan  5 11:15:22 2008
@@ -127,7 +127,7 @@
     transformer = cls(t)
     fptr = getattr(transformer, attr)(TYPE)
     transformer.transform_graph(graphof(t, f))
-    transformer.finish()
+    transformer.finish(backendopt=False)
     if conftest.option.view:
         t.view()
     if fptr:

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py	Sat Jan  5 11:15:22 2008
@@ -111,6 +111,7 @@
             self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
         self.graphs_to_inline = {}
         self.graph_dependencies = {}
+        self.ll_finalizers_ptrs = []
         if self.MinimalGCTransformer:
             self.minimalgctransformer = self.MinimalGCTransformer(self)
         else:
@@ -279,24 +280,37 @@
         self.need_minimal_transform(graph)
         if inline:
             self.graphs_to_inline[graph] = True
-        return self.mixlevelannotator.graph2delayed(graph)
+        FUNCTYPE = lltype.FuncType(ll_args, ll_result)
+        return self.mixlevelannotator.graph2delayed(graph, FUNCTYPE=FUNCTYPE)
 
     def inittime_helper(self, ll_helper, ll_args, ll_result, inline=True):
         ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=inline)
         return Constant(ptr, lltype.typeOf(ptr))
 
-    def finish_helpers(self):
+    def annotate_finalizer(self, ll_finalizer, ll_args, ll_result):
+        fptr = self.annotate_helper(ll_finalizer, ll_args, ll_result)
+        self.ll_finalizers_ptrs.append(fptr)
+        return fptr
+
+    def finish_helpers(self, backendopt=True):
         if self.translator is not None:
             self.mixlevelannotator.finish_annotate()
         self.finished_helpers = True
         if self.translator is not None:
             self.mixlevelannotator.finish_rtype()
+            if backendopt:
+                self.mixlevelannotator.backend_optimize()
+        # Make sure that the database also sees all finalizers now.
+        # XXX we need to think more about the interaction with stackless...
+        # It is likely that the finalizers need special support there
+        newgcdependencies = self.ll_finalizers_ptrs
+        return newgcdependencies
 
     def finish_tables(self):
         pass
 
-    def finish(self):
-        self.finish_helpers()
+    def finish(self, backendopt=True):
+        self.finish_helpers(backendopt=backendopt)
         self.finish_tables()
 
     def transform_generic_set(self, hop):
@@ -415,7 +429,7 @@
         except OverflowError:
             raise MemoryError()
         return tot_size
-    _ll_compute_size._inline_ = True
+    _ll_compute_size._always_inline_ = True
 
     def _ll_malloc_varsize_no_length(length, size, itemsize):
         tot_size = _ll_compute_size(length, size, itemsize)

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py	Sat Jan  5 11:15:22 2008
@@ -159,21 +159,14 @@
             ARRAY = TYPE._flds[TYPE._arrayfld]
             ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
             info.ofstolength = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
-            if ARRAY.OF != lltype.Void:
-                info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
-            else:
-                info.fixedsize = ofs1 + llmemory.sizeof(lltype.Signed)
+            info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
             # XXX we probably don't need isrpystring any more
             if ARRAY._hints.get('isrpystring'):
                 info.fixedsize = llmemory.sizeof(TYPE, 1)
         else:
             ARRAY = TYPE
             info.ofstolength = llmemory.ArrayLengthOffset(ARRAY)
-            if ARRAY.OF != lltype.Void:
-                info.ofstovar = llmemory.itemoffsetof(TYPE, 0)
-            else:
-                info.fixedsize = (llmemory.ArrayLengthOffset(ARRAY) +
-                                  llmemory.sizeof(lltype.Signed))
+            info.ofstovar = llmemory.itemoffsetof(TYPE, 0)
         assert isinstance(ARRAY, lltype.Array)
         if ARRAY.OF != lltype.Void:
             offsets = offsets_to_gc_pointers(ARRAY.OF)
@@ -203,6 +196,10 @@
         self.addresses_of_static_ptrs = []
         # this lists contains pointers in raw Structs and Arrays
         self.addresses_of_static_ptrs_in_nongc = []
+        # if not gc.prebuilt_gc_objects_are_static_roots, then
+        # additional_roots_sources counts the number of locations
+        # within prebuilt GC objects that are of type Ptr(Gc)
+        self.additional_roots_sources = 0
         self.finalizer_funcptrs = {}
         self.offsettable_cache = {}
         self.next_typeid_cache = {}
@@ -272,7 +269,8 @@
         return fptr
 
     def make_finalizer_funcptr_for_type(self, TYPE):
-        return None   # must be overridden for proper finalizer support
+        # must be overridden for proper finalizer support
+        return lltype.nullptr(GCData.ADDRESS_VOID_FUNC)
 
     def initialize_gc_query_function(self, gc):
         return GCData(self.type_info_list).set_query_functions(gc)
@@ -296,10 +294,15 @@
         # 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
+            if not gc.prebuilt_gc_objects_are_static_roots:
+                for a in gc_pointers_inside(value, adr):
+                    self.additional_roots_sources += 1
+                return
+            else:
+                appendto = self.addresses_of_static_ptrs
         else:
             appendto = self.addresses_of_static_ptrs_in_nongc
-        for a in mutable_gc_pointers_inside(value, adr):
+        for a in gc_pointers_inside(value, adr, mutable_only=True):
             appendto.append(a)
 
 # ____________________________________________________________
@@ -338,28 +341,30 @@
         return llmemory.offsetof(WEAKREF, "weakptr")
     return -1
 
-def mutable_gc_pointers_inside(v, adr):
+def gc_pointers_inside(v, adr, mutable_only=False):
     t = lltype.typeOf(v)
     if isinstance(t, lltype.Struct):
-        if t._hints.get('immutable'):
+        if mutable_only and t._hints.get('immutable'):
             return
         for n, t2 in t._flds.iteritems():
             if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc':
                 yield adr + llmemory.offsetof(t, n)
             elif isinstance(t2, (lltype.Array, lltype.Struct)):
-                for a in mutable_gc_pointers_inside(getattr(v, n),
-                                                adr + llmemory.offsetof(t, n)):
+                for a in gc_pointers_inside(getattr(v, n),
+                                            adr + llmemory.offsetof(t, n),
+                                            mutable_only):
                     yield a
     elif isinstance(t, lltype.Array):
-        if t._hints.get('immutable'):
+        if mutable_only and t._hints.get('immutable'):
             return
         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)
         elif isinstance(t.OF, lltype.Struct):
             for i in range(len(v.items)):
-                for a in mutable_gc_pointers_inside(v.items[i],
-                                            adr + llmemory.itemoffsetof(t, i)):
+                for a in gc_pointers_inside(v.items[i],
+                                            adr + llmemory.itemoffsetof(t, i),
+                                            mutable_only):
                     yield a
 
 def zero_gc_pointers(p):

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py	Sat Jan  5 11:15:22 2008
@@ -11,10 +11,13 @@
     def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}):
         self.AddressLinkedList = get_address_linked_list(10)
         self.gc = gc_class(self.AddressLinkedList, **GC_PARAMS)
-        self.gc.get_roots = self.get_roots_from_llinterp
+        def my_get_roots(with_static=True):
+            return self.get_roots_from_llinterp(with_static)
+        self.gc.get_roots = my_get_roots
         self.llinterp = llinterp
         self.prepare_graphs(flowgraphs)
         self.gc.setup()
+        my_get_roots.append_static_root = self.constantroots.append
 
     def prepare_graphs(self, flowgraphs):
         layoutbuilder = DirectRunLayoutBuilder(self.llinterp)
@@ -26,7 +29,7 @@
             TYPE = lltype.typeOf(obj)
             layoutbuilder.consider_constant(TYPE, obj, self.gc)
 
-        self.constantroots = layoutbuilder.addresses_of_static_ptrs
+        self.constantroots = list(layoutbuilder.addresses_of_static_ptrs)
         self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc
 
     def get_roots_from_llinterp(self, with_static=True):

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py	Sat Jan  5 11:15:22 2008
@@ -47,14 +47,14 @@
             new.length = 0
             self.chunk = new
             return new
-        enlarge.dont_inline = True
+        enlarge._dont_inline_ = True
 
         def shrink(self):
             old = self.chunk
             self.chunk = old.previous
             unused_chunks.put(old)
             return self.chunk
-        shrink.dont_inline = True
+        shrink._dont_inline_ = True
 
         def append(self, addr):
             if addr == llmemory.NULL:

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py	Sat Jan  5 11:15:22 2008
@@ -1,4 +1,4 @@
-from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder
+from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder, GCData
 from pypy.rpython.memory.gctypelayout import offsets_to_gc_pointers
 from pypy.rpython.lltypesystem import lltype
 
@@ -36,6 +36,7 @@
     for T1, T2 in [(GC_A, GC_S), (GC_A2, GC_S2), (GC_S3, GC_S2)]:
         tid1 = layoutbuilder.get_type_id(T1)
         tid2 = layoutbuilder.get_type_id(T2)
-        lst1 = layoutbuilder.q_varsize_offsets_to_gcpointers_in_var_part(tid1)
-        lst2 = layoutbuilder.q_offsets_to_gc_pointers(tid2)
+        gcdata = GCData(layoutbuilder.type_info_list)
+        lst1 = gcdata.q_varsize_offsets_to_gcpointers_in_var_part(tid1)
+        lst2 = gcdata.q_offsets_to_gc_pointers(tid2)
         assert len(lst1) == len(lst2)

Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py	Sat Jan  5 11:15:22 2008
@@ -37,7 +37,8 @@
     gcpolicy = None
     stacklessgc = False
 
-    def runner(self, f, nbargs=0, statistics=False, **extraconfigopts):
+    def runner(self, f, nbargs=0, statistics=False, transformer=False,
+               **extraconfigopts):
         if nbargs == 2:
             def entrypoint(args):
                 x = args[0]
@@ -84,6 +85,8 @@
             def statistics(index):
                 return llinterp.eval_graph(statisticsgraph, [ll_gc, index])
             return run, statistics
+        elif transformer:
+            return run, db.gctransformer
         else:
             return run
         
@@ -862,6 +865,42 @@
         run = self.runner(f, nbargs=0)
         run([])
 
+    def test_immutable_to_old_promotion(self):
+        T_CHILD = lltype.Ptr(lltype.GcStruct('Child', ('field', lltype.Signed)))
+        T_PARENT = lltype.Ptr(lltype.GcStruct('Parent', ('sub', T_CHILD)))
+        child = lltype.malloc(T_CHILD.TO)
+        child2 = lltype.malloc(T_CHILD.TO)
+        parent = lltype.malloc(T_PARENT.TO)
+        parent2 = lltype.malloc(T_PARENT.TO)
+        parent.sub = child
+        child.field = 3
+        parent2.sub = child2
+        child2.field = 8
+
+        T_ALL = lltype.Ptr(lltype.GcArray(T_PARENT))
+        all = lltype.malloc(T_ALL.TO, 2)
+        all[0] = parent
+        all[1] = parent2
+
+        def f(x, y):
+            res = all[x]
+            #all[x] = lltype.nullptr(T_PARENT.TO)
+            return res.sub.field
+
+        run, transformer = self.runner(f, nbargs=2, transformer=True)
+        run([1, 4])
+        assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0
+        assert transformer.layoutbuilder.additional_roots_sources >= 4
+        # NB. Remember that additional_roots_sources does not count
+        # the number of prebuilt GC objects, but the number of locations
+        # within prebuilt GC objects that are of type Ptr(Gc).
+        # At the moment we get additional_roots_sources == 6:
+        #  * all[0]
+        #  * all[1]
+        #  * parent.sub
+        #  * parent2.sub
+        #  * the GcArray pointer from gc.wr_to_objects_with_id
+        #  * the GcArray pointer from gc.object_id_dict.
 
 class TestGenerationalNoFullCollectGC(GCTest):
     # test that nursery is doing its job and that no full collection



More information about the Pypy-commit mailing list