[pypy-svn] r44977 - in pypy/branch/emptying-the-malloc-zoo-2/pypy: rpython/lltypesystem rpython/memory/gctransform translator/c translator/c/src translator/c/test

mwh at codespeak.net mwh at codespeak.net
Thu Jul 12 17:33:47 CEST 2007


Author: mwh
Date: Thu Jul 12 17:33:45 2007
New Revision: 44977

Modified:
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/boehm.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/refcounting.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/funcgen.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/gc.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/src/mem.h
   pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/support.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/test/test_boehm.py
Log:
(mwh, pedronis)
make the boehm gc transformer do way more and the boehm gcpolicy in genc do way
less


Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/lltypesystem/lloperation.py	Thu Jul 12 17:33:45 2007
@@ -341,6 +341,7 @@
 
     'boehm_malloc':         LLOp(),
     'boehm_malloc_atomic':  LLOp(),
+    'boehm_register_finalizer': LLOp(),
     'raw_malloc':           LLOp(),
     'raw_malloc_usage':     LLOp(sideeffects=False),
     'raw_free':             LLOp(),

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/boehm.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/boehm.py	Thu Jul 12 17:33:45 2007
@@ -5,22 +5,29 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython import rmodel
 from pypy.rlib.rarithmetic import ovfcheck
+from pypy.objspace.flow.model import Constant
 
 class BoehmGCTransformer(GCTransformer):
+    FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
+
     def __init__(self, translator, inline=False):
         super(BoehmGCTransformer, self).__init__(translator, inline=inline)
         self.finalizer_funcptrs = {}
         memoryError = MemoryError()
 
-        def ll_malloc_fixedsize(size):
+        def ll_malloc_fixedsize(size, finalizer):
             result = llop.boehm_malloc(llmemory.Address, size)
             if not result:
                 raise memoryError
+            if finalizer: # XXX runtime check here is bad?
+                llop.boehm_register_finalizer(lltype.Void, result, finalizer)
             return result
-        def ll_malloc_fixedsize_atomic(size):
+        def ll_malloc_fixedsize_atomic(size, finalizer):
             result = llop.boehm_malloc_atomic(llmemory.Address, size)
             if not result:
                 raise memoryError
+            if finalizer: # XXX runtime check here is bad?
+                llop.boehm_register_finalizer(lltype.Void, result, finalizer)
             return result
         # XXX, do we need/want an atomic version of this function?
         def ll_malloc_varsize_no_length(length, size, itemsize):
@@ -40,9 +47,9 @@
 
         if self.translator:
             self.malloc_fixedsize_ptr = self.inittime_helper(
-                ll_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+                ll_malloc_fixedsize, [lltype.Signed, self.FINALIZER_PTR], llmemory.Address)
             self.malloc_fixedsize_atomic_ptr = self.inittime_helper(
-                ll_malloc_fixedsize_atomic, [lltype.Signed], llmemory.Address)
+                ll_malloc_fixedsize_atomic, [lltype.Signed, self.FINALIZER_PTR], llmemory.Address)
             self.malloc_varsize_no_length_ptr = self.inittime_helper(
                 ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False)
             self.malloc_varsize_ptr = self.inittime_helper(
@@ -71,10 +78,15 @@
             funcptr = self.malloc_fixedsize_atomic_ptr
         else:
             funcptr = self.malloc_fixedsize_ptr
-        v_raw = hop.genop("direct_call", [funcptr, c_size],
+        c_finalizer_ptr = Constant(self.finalizer_funcptr_for_type(TYPE), self.FINALIZER_PTR)
+        v_raw = hop.genop("direct_call",
+                          [funcptr, c_size, c_finalizer_ptr],
                           resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    # XXX In theory this is wrong:
+    gct_zero_malloc = gct_malloc
+
     def gct_malloc_varsize(self, hop):
         def intconst(c): return rmodel.inputconst(lltype.Signed, c)
 
@@ -82,6 +94,8 @@
         TYPE = op.result.concretetype.TO
         assert TYPE._is_varsize()
 
+        assert not self.finalizer_funcptr_for_type(TYPE)
+
         if isinstance(TYPE, lltype.Struct):
             ARRAY = TYPE._flds[TYPE._arrayfld]
         else:
@@ -110,6 +124,8 @@
                                resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    gct_zero_malloc_varsize = gct_malloc_varsize
+
     def finalizer_funcptr_for_type(self, TYPE):
         if TYPE in self.finalizer_funcptrs:
             return self.finalizer_funcptrs[TYPE]
@@ -144,7 +160,7 @@
                 llop.gc_restore_exception(lltype.Void, exc_instance)
             fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void)
         else:
-            fptr = None
+            fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
 
         self.finalizer_funcptrs[TYPE] = fptr
         return fptr

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/refcounting.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/refcounting.py	Thu Jul 12 17:33:45 2007
@@ -155,6 +155,8 @@
                           resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    gct_zero_malloc = gct_malloc
+
     def gct_malloc_varsize(self, hop):
         def intconst(c): return rmodel.inputconst(lltype.Signed, c)
 
@@ -190,6 +192,8 @@
                                resulttype=llmemory.Address)
         hop.cast_result(v_raw)
 
+    gct_zero_malloc_varsize = gct_malloc_varsize
+
     def gct_gc_deallocate(self, hop):
         TYPE = hop.spaceop.args[0].value
         v_addr = hop.spaceop.args[1]

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/funcgen.py	Thu Jul 12 17:33:45 2007
@@ -510,62 +510,17 @@
                                      self.expr(op.args[0]),
                                      self.expr(op.args[1]))
 
-    def OP_ZERO_MALLOC(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        eresult = self.expr(op.result)
-        esize = 'sizeof(%s)' % cdecl(typename, '')
-
-        return self.gcpolicy.zero_malloc(TYPE, esize, eresult)
-
-    def OP_MALLOC(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        eresult = self.expr(op.result)
-        esize = 'sizeof(%s)' % cdecl(typename, '')
-
-        return self.gcpolicy.malloc(TYPE, esize, eresult)
-
-    OP_ZERO_MALLOC = OP_MALLOC
-    
-    def OP_MALLOC_VARSIZE(self, op):
-        TYPE = self.lltypemap(op.result).TO
-        typename = self.db.gettype(TYPE)
-        lenfld = 'length'
-        nodedef = self.db.gettypedefnode(TYPE)
-        if isinstance(TYPE, Struct):
-            arfld = TYPE._arrayfld
-            lenfld = "%s.length" % nodedef.c_struct_field_name(arfld)
-            VARPART = TYPE._flds[TYPE._arrayfld]
-        else:
-            VARPART = TYPE
-        assert isinstance(VARPART, Array)
-        itemtypename = self.db.gettype(VARPART.OF)
-        elength = self.expr(op.args[1])
-        eresult = self.expr(op.result)
-        if VARPART.OF is Void:    # strange
-            esize = 'sizeof(%s)' % (cdecl(typename, ''),)
-            result = '{\n'
-        else:
-            itemtype = cdecl(itemtypename, '')
-            result = 'IF_VARSIZE_OVERFLOW(%s, %s, %s)\nelse {\n' % (
-                elength,
-                itemtype,
-                eresult)
-            esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % (
-                cdecl(typename, ''),
-                itemtype,
-                elength,
-                itemtype)
-        result += self.gcpolicy.zero_malloc(TYPE, esize, eresult)
-
-        # ctypes Arrays have no length field
-        if not VARPART._hints.get('nolength', False):
-            result += '\nif(%s) %s->%s = %s;' % (eresult, eresult, lenfld, elength)
-        result += '\n}'
-        return result
-    
-    OP_ZERO_MALLOC_VARSIZE = OP_MALLOC_VARSIZE
+    def OP_BOEHM_MALLOC(self, op):
+        return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 0, 0);' % (self.expr(op.args[0]),
+                                                               self.expr(op.result))
+
+    def OP_BOEHM_MALLOC_ATOMIC(self, op):
+        return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
+                                                               self.expr(op.result))
+
+    def OP_BOEHM_REGISTER_FINALIZER(self, op):
+        return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
+               % (self.expr(op.args[0]), self.expr(op.args[1]))
 
     def OP_RAW_MALLOC(self, op):
         eresult = self.expr(op.result)
@@ -573,6 +528,7 @@
         return "OP_RAW_MALLOC(%s, %s, void *);" % (esize, eresult)
 
     def OP_FLAVORED_MALLOC(self, op):
+        # XXX this function should DIE!
         TYPE = self.lltypemap(op.result).TO
         typename = self.db.gettype(TYPE)
         eresult = self.expr(op.result)
@@ -590,6 +546,7 @@
             raise NotImplementedError
 
     def OP_FLAVORED_MALLOC_VARSIZE(self, op):
+        # XXX this function should DIE!, at least twice over
         # XXX I know this working in just one case, probably makes
         # sense to assert it here, rest is just copied
         flavor = op.args[0].value

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/gc.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/gc.py	Thu Jul 12 17:33:45 2007
@@ -117,14 +117,6 @@
 
     # zero malloc impl
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        assert TYPE._gckind == 'gc'   # we don't really support this
-        typename = self.db.gettype(TYPE)
-        erestype = cdecl(typename, '*')
-        return 'OP_ZERO_MALLOC(%s, %s, %s);' % (esize, eresult, erestype)
-
-    malloc = zero_malloc
-
     def OP_GC_CALL_RTTI_DESTRUCTOR(self, funcgen, op):
         args = [funcgen.expr(v) for v in op.args]
         line = '%s(%s);' % (args[0], ', '.join(args[1:]))
@@ -180,18 +172,11 @@
 class BoehmGcPolicy(BasicGcPolicy):
     transformerclass = boehm.BoehmGCTransformer
 
-    def setup_gcinfo(self, defnode):
-        transformer = defnode.db.gctransformer
-        fptr = transformer.finalizer_funcptr_for_type(defnode.LLTYPE)
-        if fptr:
-            defnode.gcinfo = BoehmInfo()
-            defnode.gcinfo.finalizer = defnode.db.get(fptr)
-
     def array_setup(self, arraydefnode):
-        self.setup_gcinfo(arraydefnode)
+        pass
 
     def struct_setup(self, structdefnode, rtti):
-        self.setup_gcinfo(structdefnode)
+        pass
 
     def rtti_type(self):
         return BoehmGcRuntimeTypeInfo_OpaqueNode.typename
@@ -199,25 +184,6 @@
     def rtti_node_factory(self):
         return BoehmGcRuntimeTypeInfo_OpaqueNode
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        gcinfo = self.db.gettypedefnode(TYPE).gcinfo
-        assert TYPE._gckind == 'gc'   # _is_atomic() depends on this!
-        is_atomic = TYPE._is_atomic()
-        is_varsize = TYPE._is_varsize()
-        typename = self.db.gettype(TYPE)
-        erestype = cdecl(typename, '*')
-        result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %s, %d, %d);' % (esize,
-                                                            eresult,
-                                                            erestype,
-                                                            is_atomic,
-                                                            is_varsize)
-        if gcinfo and gcinfo.finalizer:
-            result += ('\nGC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);'
-                       % (eresult, gcinfo.finalizer))
-        return result
-
-    malloc = zero_malloc
-
     def gc_libraries(self):
         if sys.platform == 'win32':
             return ['gc_pypy']
@@ -301,7 +267,6 @@
         yield "#include <gc/gc_typed.h>"
 
     def struct_setup(self, structdefnode, rtti):
-        self.setup_gcinfo(structdefnode)
         T = structdefnode.STRUCT
         if T._is_atomic():
             malloc_exact = False
@@ -336,37 +301,11 @@
                 self.get_descr_name(defnode), T)
             yield "}"
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        defnode = self.db.gettypedefnode(TYPE)
-        gcinfo = defnode.gcinfo
-        if gcinfo:
-            if not gcinfo.malloc_exact:
-                assert TYPE._gckind == 'gc'   # _is_atomic() depends on this!
-                is_atomic = TYPE._is_atomic()
-                is_varsize = TYPE._is_varsize()
-                typename = self.db.gettype(TYPE)
-                erestype = cdecl(typename, '*')
-                result = 'OP_BOEHM_ZERO_MALLOC(%s, %s, %s, %d, %d);' % (
-                    esize, eresult, erestype, is_atomic, is_varsize)
-            else:
-                result = '%s = GC_MALLOC_EXPLICITLY_TYPED(%s, %s);' % (
-                    eresult, esize, self.get_descr_name(defnode))
-            if gcinfo.finalizer:
-                result += ('\nGC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);'
-                       % (eresult, gcinfo.finalizer))
-        else:
-            return super(MoreExactBoehmGcPolicy, self).zero_malloc(
-                TYPE, esize, eresult)
-        return result
-
-    malloc = zero_malloc
 
 # to get an idea how it looks like with no refcount/gc at all
 
 class NoneGcPolicy(BoehmGcPolicy):
 
-    zero_malloc = RefcountingGcPolicy.zero_malloc.im_func
-    malloc = RefcountingGcPolicy.malloc.im_func
     gc_libraries = RefcountingGcPolicy.gc_libraries.im_func
     gc_startup_code = RefcountingGcPolicy.gc_startup_code.im_func
 
@@ -421,11 +360,6 @@
         o = top_container(defnode.obj)
         return defnode.db.gctransformer.gc_field_values_for(o)
 
-    def zero_malloc(self, TYPE, esize, eresult):
-        assert False, "a malloc operation in a framework build??"
-
-    malloc = zero_malloc
-
 class StacklessFrameworkGcPolicy(FrameworkGcPolicy):
     transformerclass = stacklessframework.StacklessFrameworkGCTransformer
     requires_stackless = True

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/src/mem.h	Thu Jul 12 17:33:45 2007
@@ -116,7 +116,6 @@
 
 #define OP_BOEHM_ZERO_MALLOC(size, r, restype, is_atomic, is_varsize)   {             \
 	r = (restype) BOEHM_MALLOC_ ## is_atomic ## _ ## is_varsize (size);    \
-	if (r == NULL) {FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");}  \
         else {                                                               \
             if (is_atomic)  /* the non-atomic versions return cleared memory */  \
                 memset((void*) r, 0, size);                                   \

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/support.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/support.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/support.py	Thu Jul 12 17:33:45 2007
@@ -52,6 +52,10 @@
     else:
         return s[:2].lower()
 
+def is_pointer_to_forward_ref(T):
+    if not isinstance(T, lltype.Ptr):
+        return False
+    return isinstance(T.TO, lltype.ForwardReference)
 
 def llvalue_from_constant(c):
     try:
@@ -64,7 +68,12 @@
         if T == lltype.Void:
             return None
         else:
-            assert lltype.typeOf(c.value) == T
+            ACTUAL_TYPE = lltype.typeOf(c.value)
+            # If the type is still uncomputed, we can't make this
+            # check.  Something else will blow up instead, probably
+            # very confusingly.
+            if not is_pointer_to_forward_ref(ACTUAL_TYPE):
+                assert ACTUAL_TYPE == T
             return c.value
 
 

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/translator/c/test/test_boehm.py	Thu Jul 12 17:33:45 2007
@@ -1,6 +1,6 @@
 import py
 from pypy.translator.translator import TranslationContext
-from pypy.rpython.lltypesystem.lltype import Void
+from pypy.rpython.lltypesystem import lltype
 from pypy.translator.tool.cbuild import check_boehm_presence
 from pypy.translator.c.genc import CExtModuleBuilder
 from pypy import conftest
@@ -62,7 +62,6 @@
 
     def test__del__(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         class State:
             pass
         s = State()
@@ -98,7 +97,6 @@
 
     def test_weakgcaddress_is_weak(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         from pypy.rlib.objectmodel import cast_object_to_weakgcaddress
         class State:
             pass
@@ -130,7 +128,6 @@
 
     def test_del_raises(self):
         from pypy.rpython.lltypesystem.lloperation import llop
-        from pypy.rpython.lltypesystem import lltype
         import os
         class A(object):
             def __del__(self):
@@ -160,7 +157,6 @@
         assert res > 0
 
     def test_memory_error_varsize(self):
-        from pypy.rpython.lltypesystem import lltype
         N = int(2**31-1)
         A = lltype.GcArray(lltype.Char)
         def alloc(n):
@@ -183,7 +179,7 @@
         def prob_with_pyobj(b):
             return 3, b
         def collect():
-            llop.gc__collect(Void)
+            llop.gc__collect(lltype.Void)
         f = self.getcompiled(prob_with_pyobj, [object])
         c = self.getcompiled(collect, [])
         from sys import getrefcount as g
@@ -202,6 +198,23 @@
         after = g(obj)
         assert abs(before - after) < 5
 
+    def test_zero_malloc(self):
+        T = lltype.GcStruct("C", ('x', lltype.Signed))
+        def fixed_size():
+            t = lltype.malloc(T, zero=True)
+            return t.x
+        c_fixed_size = self.getcompiled(fixed_size, [])
+        res = c_fixed_size()
+        assert res == 0
+        A = lltype.GcArray(lltype.Signed)
+        def var_size():
+            a = lltype.malloc(A, 1, zero=True)
+            return a[0]
+        c_var_size = self.getcompiled(var_size, [])
+        res = c_var_size()
+        assert res == 0
+
+
 
 class TestUsingExactBoehm(TestUsingBoehm):
     gcpolicy = "exact_boehm"



More information about the Pypy-commit mailing list