[pypy-svn] r51722 - in pypy/branch/unified-rtti/pypy: rpython rpython/lltypesystem rpython/memory rpython/memory/gctransform translator/c translator/c/src

arigo at codespeak.net arigo at codespeak.net
Thu Feb 21 14:58:44 CET 2008


Author: arigo
Date: Thu Feb 21 14:58:42 2008
New Revision: 51722

Modified:
   pypy/branch/unified-rtti/pypy/rpython/llinterp.py
   pypy/branch/unified-rtti/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/unified-rtti/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py
   pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py
   pypy/branch/unified-rtti/pypy/translator/c/gc.py
   pypy/branch/unified-rtti/pypy/translator/c/src/mem.h
Log:
Progress in porting the refcounting transformer to the new model.
Deleted a number of lines in refcounting.py, so I guess it's good.


Modified: pypy/branch/unified-rtti/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/unified-rtti/pypy/rpython/llinterp.py	Thu Feb 21 14:58:42 2008
@@ -753,20 +753,12 @@
     def op_gc__collect(self):
         self.heap.collect()
 
-    def op_gc_free(self, addr):
-        # what can you do?
-        pass
-        #raise NotImplementedError("gc_free")
-
     def op_gc_fetch_exception(self):
         raise NotImplementedError("gc_fetch_exception")
 
     def op_gc_restore_exception(self, exc):
         raise NotImplementedError("gc_restore_exception")
 
-    def op_gc_deallocate(self, TYPE, addr):
-        raise NotImplementedError("gc_deallocate")
-
     def op_gc_push_alive_pyobj(self, pyobj):
         raise NotImplementedError("gc_push_alive_pyobj")
 

Modified: pypy/branch/unified-rtti/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/unified-rtti/pypy/rpython/lltypesystem/llmemory.py	Thu Feb 21 14:58:42 2008
@@ -263,6 +263,15 @@
 
 
 class GCHeaderOffset(AddressOffset):
+    """Hack: this 'offset' is really 0, but it is used symbolically to
+    go from a GcStruct instance to its header (by subtraction, as if the
+    header was before the GcStruct).  The GCHeaderOffset internally
+    holds a reference to a GCHeaderBuilder, which maps between GcStructs
+    and their headers.  The point of this is to *not* have a global
+    mapping from GcStructs to their headers -- indeed, the same prebuilt
+    GcStruct instance could be reused by several translations, each with
+    their own different GCs.
+    """
     def __init__(self, gcheaderbuilder):
         self.gcheaderbuilder = gcheaderbuilder
 
@@ -306,6 +315,30 @@
         assert isinstance(rest[0], GCHeaderOffset)
         return rest[1]._raw_malloc(rest[2:], zero=zero)
 
+class GCTypeInfoOffset(AddressOffset):
+    """Hack: this 'offset' is really 0, but it is used symbolically to
+    go from a Ptr(RuntimeTypeInfo) to the real GC-specific structure
+    that contains the information.  The GCTypeInfoOffset internally
+    holds a reference to a GCHeaderBuilder, which maps between
+    RuntimeTypeInfos and their GC-specific equivalents.  The point of
+    this is to *not* have a global mapping -- indeed, the same
+    RuntimeTypeInfo could be seen in several translations, each with
+    their own different GCs.
+    """
+    def __init__(self, gcheaderbuilder):
+        self.gcheaderbuilder = gcheaderbuilder
+
+    def __repr__(self):
+        return '< GCTypeInfoOffset >'
+
+    def __neg__(self):
+        raise NotImplementedError("XXX for now, cannot cast from a GC-specific"
+                                  " type info to Ptr(RuntimeTypeInfo)")
+
+    def ref(self, rttiptr):
+        typeinfoptr = self.gcheaderbuilder.typeinfo_from_rtti(rttiptr)
+        return typeinfoptr
+
 # ____________________________________________________________
 
 def sizeof(TYPE, n=None):

Modified: pypy/branch/unified-rtti/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/unified-rtti/pypy/rpython/lltypesystem/lloperation.py	Thu Feb 21 14:58:42 2008
@@ -387,11 +387,9 @@
     # __________ GC operations __________
 
     'gc__collect':          LLOp(canunwindgc=True),
-    'gc_free':              LLOp(),
     'gc_fetch_exception':   LLOp(),
     'gc_restore_exception': LLOp(),
     'gc_runtime_type_info': LLOp(canfold=True),
-    'gc_deallocate':        LLOp(),
     'gc_push_alive_pyobj':  LLOp(),
     'gc_pop_alive_pyobj':   LLOp(),
     'gc_reload_possibly_moved': LLOp(),

Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py	(original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py	Thu Feb 21 14:58:42 2008
@@ -8,11 +8,14 @@
 
 class GCHeaderBuilder(object):
 
-    def __init__(self, HDR):
+    def __init__(self, HDR, TYPEINFO):
         """NOT_RPYTHON"""
         self.HDR = HDR
+        self.TYPEINFO = TYPEINFO
         self.obj2header = weakref.WeakKeyDictionary()
+        self.rtti2typeinfo = weakref.WeakKeyDictionary()
         self.size_gc_header = llmemory.GCHeaderOffset(self)
+        self.size_gc_typeinfo = llmemory.GCTypeInfoOffset(self)
 
     def header_of_object(self, gcptr):
         # XXX hackhackhack
@@ -43,5 +46,16 @@
         self.attach_header(gcptr, headerptr)
         return headerptr
 
+    def typeinfo_from_rtti(self, rttiptr):
+        rttiptr = lltype.cast_pointer(lltype.Ptr(lltype.RuntimeTypeInfo),
+                                      rttiptr)
+        return self.rtti2typeinfo[rttiptr._obj]
+
+    def cast_rtti_to_typeinfo(self, rttiptr):
+        # this is RPython
+        addr = llmemory.cast_ptr_to_adr(rttiptr)
+        addr += self.size_gc_typeinfo
+        return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.TYPEINFO))
+
     def _freeze_(self):
         return True     # for reads of size_gc_header

Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py	(original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py	Thu Feb 21 14:58:42 2008
@@ -40,11 +40,16 @@
     HDR = lltype.Struct("header", ("refcount", lltype.Signed),
                                   ("typeptr", RTTIPTR))
 
+    TYPEINFO = lltype.Struct("typeinfo",
+                             ("dealloc", lltype.Ptr(ADDRESS_VOID_FUNC)))
+
     def __init__(self, translator):
         super(RefcountingGCTransformer, self).__init__(translator, inline=True)
-        self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
+        gchdrbuilder = GCHeaderBuilder(self.HDR, self.TYPEINFO)
+        self.gcheaderbuilder = gchdrbuilder
         gc_header_offset = self.gcheaderbuilder.size_gc_header
         self.deallocator_graphs_needing_transforming = []
+        self.rtticache = {}
 
         # create incref, etc  graph
 
@@ -61,9 +66,11 @@
                 refcount = gcheader.refcount - 1
                 gcheader.refcount = refcount
                 if refcount == 0:
-                    gcheader.typeptr.xxx(adr)
+                    rtti = gcheader.typeptr
+                    typeinfo = gchdrbuilder.cast_rtti_to_typeinfo(rtti)
+                    typeinfo.dealloc(adr)
         def ll_no_pointer_dealloc(adr):
-            llop.gc_free(lltype.Void, adr)
+            llmemory.raw_free(adr)
 
         mh = mallocHelpers()
         mh.allocate = llmemory.raw_malloc
@@ -73,7 +80,14 @@
             llmemory.raw_memclear(result, size)
             result += gc_header_offset
             return result
-        def ll_malloc_varsize_no_length(length, size, itemsize):
+        def ll_malloc_fixedsize_rtti(size, rtti):
+            size = gc_header_offset + size
+            result = mh._ll_malloc_fixedsize(size)
+            llmemory.raw_memclear(result, size)
+            llmemory.cast_adr_to_ptr(result, HDRPTR).typeptr = rtti
+            result += gc_header_offset
+            return result
+        def ll_malloc_varsize_no_length_rtti(length, size, itemsize, rtti):
             try:
                 fixsize = gc_header_offset + size
                 varsize = ovfcheck(itemsize * length)
@@ -82,34 +96,35 @@
                 raise MemoryError()
             result = mh._ll_malloc_fixedsize(tot_size)
             llmemory.raw_memclear(result, tot_size)
+            llmemory.cast_adr_to_ptr(result, HDRPTR).typeptr = rtti
             result += gc_header_offset
             return result
-        mh.ll_malloc_varsize_no_length = ll_malloc_varsize_no_length
-        ll_malloc_varsize = mh.ll_malloc_varsize
+        def ll_malloc_varsize_rtti(length, size, itemsize, lengthoffset, rtti):
+            result = ll_malloc_varsize_no_length_rtti(length, size,
+                                                      itemsize, rtti)
+            (result + lengthoffset).signed[0] = length
+            return result
 
         if self.translator:
             self.increfptr = self.inittime_helper(
                 ll_incref, [llmemory.Address], lltype.Void)
-            self.decref_ptr = self.inittime_helper(
-                ll_decref, [llmemory.Address, lltype.Ptr(ADDRESS_VOID_FUNC)],
-                lltype.Void)
-            self.decref_simple_ptr = self.inittime_helper(
-                ll_decref_simple, [llmemory.Address], lltype.Void)
+            self.decrefptr = self.inittime_helper(
+                ll_decref, [llmemory.Address], lltype.Void)
             self.no_pointer_dealloc_ptr = self.inittime_helper(
                 ll_no_pointer_dealloc, [llmemory.Address], lltype.Void)
             self.malloc_fixedsize_ptr = self.inittime_helper(
-                ll_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+                ll_malloc_fixedsize_rtti, [lltype.Signed, RTTIPTR],
+                llmemory.Address)
             self.malloc_varsize_no_length_ptr = self.inittime_helper(
-                ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address)
+                ll_malloc_varsize_no_length_rtti, [lltype.Signed]*3+[RTTIPTR],
+                llmemory.Address)
             self.malloc_varsize_ptr = self.inittime_helper(
-                ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address)
+                ll_malloc_varsize_rtti, [lltype.Signed]*4+[RTTIPTR],
+                llmemory.Address)
             self.mixlevelannotator.finish()
             self.mixlevelannotator.backend_optimize()
         # cache graphs:
-        self.decref_funcptrs = {}
         self.static_deallocator_funcptrs = {}
-        self.dynamic_deallocator_funcptrs = {}
-        self.queryptr2dynamic_deallocator_funcptr = {}
 
     def finish_helpers(self, **kwds):
         GCTransformer.finish_helpers(self, **kwds)
@@ -132,45 +147,34 @@
         llops.genop("direct_call", [self.increfptr, v_adr])
 
     def pop_alive_nopyobj(self, var, llops):
-        PTRTYPE = var.concretetype
         v_adr = gen_cast(llops, llmemory.Address, var)
-
-        dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO)
-        if dealloc_fptr is self.no_pointer_dealloc_ptr.value:
-            # simple case
-            llops.genop("direct_call", [self.decref_simple_ptr, v_adr])
-        else:
-            cdealloc_fptr = rmodel.inputconst(
-                lltype.typeOf(dealloc_fptr), dealloc_fptr)
-            llops.genop("direct_call", [self.decref_ptr, v_adr, cdealloc_fptr])
+        llops.genop("direct_call", [self.decrefptr, v_adr])
 
     def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
-        v_raw = hop.genop("direct_call", [self.malloc_fixedsize_ptr, c_size],
+        rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+        c_rtti = rmodel.inputconst(RTTIPTR, rtti)
+        v_raw = hop.genop("direct_call",
+                          [self.malloc_fixedsize_ptr, c_size, c_rtti],
                           resulttype=llmemory.Address)
         return v_raw
 
     def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
                                                                    c_offset_to_length):
+        rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+        c_rtti = rmodel.inputconst(RTTIPTR, rtti)
         if c_offset_to_length is None:
             v_raw = hop.genop("direct_call",
                                [self.malloc_varsize_no_length_ptr, v_length,
-                                c_const_size, c_item_size],
+                                c_const_size, c_item_size, c_rtti],
                                resulttype=llmemory.Address)
         else:
             v_raw = hop.genop("direct_call",
                                [self.malloc_varsize_ptr, v_length,
-                                c_const_size, c_item_size, c_offset_to_length],
+                                c_const_size, c_item_size, c_offset_to_length,
+                                c_rtti],
                                resulttype=llmemory.Address)
         return v_raw
 
-    def gct_gc_deallocate(self, hop):
-        TYPE = hop.spaceop.args[0].value
-        v_addr = hop.spaceop.args[1]
-        dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(TYPE)
-        cdealloc_fptr = rmodel.inputconst(
-            lltype.typeOf(dealloc_fptr), dealloc_fptr)
-        hop.genop("direct_call", [cdealloc_fptr, v_addr])
-
     def consider_constant(self, TYPE, value):
         if value is not lltype.top_container(value):
                 return
@@ -181,18 +185,25 @@
                 hdr.refcount = sys.maxint // 2
 
     def static_deallocation_funcptr_for_type(self, TYPE):
+        """The 'static deallocator' for a type is the function that can
+        free a pointer that we know points exactly to a TYPE structure
+        (and not to a larger structure that starts with TYPE).  This
+        function is the one that ends up in the 'dealloc' field of
+        TYPEINFO.
+        """
         if TYPE in self.static_deallocator_funcptrs:
             return self.static_deallocator_funcptrs[TYPE]
         #print_call_chain(self)
 
         if TYPE._gckind == 'cpy':
             return # you don't really have an RPython deallocator for PyObjects
-        rtti = get_rtti(TYPE) 
-        if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
-            destrptr = rtti._obj.destructor_funcptr
+        assert TYPE._gckind == 'gc'
+
+        rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+        destrptr = rtti.destructor_funcptr
+        if destrptr is not None:
             DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
         else:
-            destrptr = None
             DESTR_ARG = None
 
         if destrptr is None and not find_gc_ptrs_in_type(TYPE):
@@ -206,36 +217,37 @@
 def ll_deallocator(addr):
     exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE)
     try:
-        v = cast_adr_to_ptr(addr, PTR_TYPE)
-        gcheader = cast_adr_to_ptr(addr - gc_header_offset, HDRPTR)
+        v = llmemory.cast_adr_to_ptr(addr, PTR_TYPE)
+        gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, HDRPTR)
         # refcount is at zero, temporarily bump it to 1:
         gcheader.refcount = 1
-        destr_v = cast_pointer(DESTR_ARG, v)
+        destr_v = lltype.cast_pointer(DESTR_ARG, v)
         ll_call_destructor(destrptr, destr_v)
         refcount = gcheader.refcount - 1
         gcheader.refcount = refcount
         if refcount == 0:
 %s
-            llop.%s_free(lltype.Void, addr)
+            llmemory.raw_free(addr)
     except:
         pass
     llop.gc_restore_exception(lltype.Void, exc_instance)
     pop_alive(exc_instance)
     # XXX layering of exceptiontransform versus gcpolicy
 
-""" % (body, TYPE._gckind)
+""" % (body,)
         else:
             call_del = None
             body = '\n'.join(_static_deallocator_body_for_type('v', TYPE))
-            src = ('def ll_deallocator(addr):\n    v = cast_adr_to_ptr(addr, PTR_TYPE)\n' +
-                   body + '\n    llop.%s_free(lltype.Void, addr)\n' % (TYPE._gckind,))
+            src = ('def ll_deallocator(addr):\n' +
+                   '    v = llmemory.cast_adr_to_ptr(addr, PTR_TYPE)\n' +
+                   body + '\n' +
+                   '    llmemory.raw_free(addr)\n')
         d = {'pop_alive': LLTransformerOp(self.pop_alive),
              'llop': llop,
              'lltype': lltype,
              'destrptr': destrptr,
              'gc_header_offset': self.gcheaderbuilder.size_gc_header,
-             'cast_adr_to_ptr': llmemory.cast_adr_to_ptr,
-             'cast_pointer': lltype.cast_pointer,
+             'llmemory': llmemory,
              'PTR_TYPE': lltype.Ptr(TYPE),
              'DESTR_ARG': DESTR_ARG,
              'EXC_INSTANCE_TYPE': self.translator.rtyper.exceptiondata.lltype_of_exception_value,
@@ -248,38 +260,3 @@
         for p in find_gc_ptrs_in_type(TYPE):
             self.static_deallocation_funcptr_for_type(p.TO)
         return fptr
-
-    def dynamic_deallocation_funcptr_for_type(self, TYPE):
-        assert TYPE._gckind != 'cpy'
-        if TYPE in self.dynamic_deallocator_funcptrs:
-            return self.dynamic_deallocator_funcptrs[TYPE]
-        #print_call_chain(self)
-
-        rtti = lltype.getRuntimeTypeInfo(TYPE)
-        if rtti is None:
-            p = self.static_deallocation_funcptr_for_type(TYPE)
-            self.dynamic_deallocator_funcptrs[TYPE] = p
-            return p
-
-        queryptr = rtti._obj.query_funcptr
-        if queryptr._obj in self.queryptr2dynamic_deallocator_funcptr:
-            return self.queryptr2dynamic_deallocator_funcptr[queryptr._obj]
-
-        RTTI_PTR = lltype.Ptr(lltype.RuntimeTypeInfo)
-        QUERY_ARG_TYPE = lltype.typeOf(queryptr).TO.ARGS[0]
-        gc_header_offset = self.gcheaderbuilder.size_gc_header
-        HDRPTR = lltype.Ptr(self.HDR)
-        def ll_dealloc(addr):
-            # bump refcount to 1
-            gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, HDRPTR)
-            gcheader.refcount = 1
-            v = llmemory.cast_adr_to_ptr(addr, QUERY_ARG_TYPE)
-            rtti = queryptr(v)
-            gcheader.refcount = 0
-            llop.gc_call_rtti_destructor(lltype.Void, rtti, addr)
-        fptr = self.annotate_helper(ll_dealloc, [llmemory.Address], lltype.Void)
-        self.dynamic_deallocator_funcptrs[TYPE] = fptr
-        self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] = fptr
-        return fptr
-
-

Modified: pypy/branch/unified-rtti/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/translator/c/gc.py	(original)
+++ pypy/branch/unified-rtti/pypy/translator/c/gc.py	Thu Feb 21 14:58:42 2008
@@ -124,10 +124,6 @@
         args = [funcgen.expr(v) for v in op.args]
         line = '%s(%s);' % (args[0], ', '.join(args[1:]))
         return line     
-    
-    def OP_GC_FREE(self, funcgen, op):
-        args = [funcgen.expr(v) for v in op.args]
-        return 'OP_FREE(%s);' % (args[0], )    
 
     def OP_GC__COLLECT(self, funcgen, op):
         return ''

Modified: pypy/branch/unified-rtti/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/unified-rtti/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/unified-rtti/pypy/translator/c/src/mem.h	Thu Feb 21 14:58:42 2008
@@ -69,8 +69,6 @@
 
 /************************************************************/
 
-#define OP_FREE(p)	OP_RAW_FREE(p, do_not_use)
-
 /*------------------------------------------------------------*/
 #ifndef COUNT_OP_MALLOCS
 /*------------------------------------------------------------*/



More information about the Pypy-commit mailing list