[pypy-svn] r44967 - in pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython: . lltypesystem memory/gctransform memory/gctransform/test

mwh at codespeak.net mwh at codespeak.net
Thu Jul 12 15:43:45 CEST 2007


Author: mwh
Date: Thu Jul 12 15:43:43 2007
New Revision: 44967

Modified:
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/llinterp.py
   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/test/test_boehm.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_refcounting.py
   pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_transform.py
Log:
(pedronis, mwh)
make the boehm gc transformer do most of the things that are now done in the
backend.
add more tests for the boehm gc transformer, and support for a couple of new
operations to the llinterp.


Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/llinterp.py	Thu Jul 12 15:43:43 2007
@@ -758,6 +758,8 @@
         assert lltype.typeOf(size) == lltype.Signed
         return self.heap.raw_malloc(size)
 
+    op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
+
     def op_raw_malloc_usage(self, size):
         assert lltype.typeOf(size) == lltype.Signed
         return self.heap.raw_malloc_usage(size)

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 15:43:43 2007
@@ -339,6 +339,8 @@
 
     # __________ address operations __________
 
+    'boehm_malloc':         LLOp(),
+    'boehm_malloc_atomic':  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 15:43:43 2007
@@ -3,11 +3,51 @@
      get_rtti, _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython import rmodel
+from pypy.rlib.rarithmetic import ovfcheck
 
 class BoehmGCTransformer(GCTransformer):
     def __init__(self, translator, inline=False):
         super(BoehmGCTransformer, self).__init__(translator, inline=inline)
         self.finalizer_funcptrs = {}
+        memoryError = MemoryError()
+
+        def ll_malloc_fixedsize(size):
+            result = llop.boehm_malloc(llmemory.Address, size)
+            if not result:
+                raise memoryError
+            return result
+        def ll_malloc_fixedsize_atomic(size):
+            result = llop.boehm_malloc_atomic(llmemory.Address, size)
+            if not result:
+                raise memoryError
+            return result
+        # XXX, do we need/want an atomic version of this function?
+        def ll_malloc_varsize_no_length(length, size, itemsize):
+            try:
+                varsize = ovfcheck(itemsize * length)
+                tot_size = ovfcheck(size + varsize)
+            except OverflowError:
+                raise memoryError
+            result = llop.boehm_malloc(llmemory.Address, tot_size)
+            if not result:
+                raise memoryError
+            return result
+        def ll_malloc_varsize(length, size, itemsize, lengthoffset):
+            result = ll_malloc_varsize_no_length(length, size, itemsize)
+            (result + lengthoffset).signed[0] = length
+            return result
+
+        if self.translator:
+            self.malloc_fixedsize_ptr = self.inittime_helper(
+                ll_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+            self.malloc_fixedsize_atomic_ptr = self.inittime_helper(
+                ll_malloc_fixedsize_atomic, [lltype.Signed], llmemory.Address)
+            self.malloc_varsize_no_length_ptr = self.inittime_helper(
+                ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address)
+            self.malloc_varsize_ptr = self.inittime_helper(
+                ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address)
+            self.mixlevelannotator.finish()   # for now
 
     def push_alive_nopyobj(self, var, llops):
         pass
@@ -23,6 +63,53 @@
         """ for boehm it is enough to do nothing"""
         pass
 
+    def gct_malloc(self, hop):
+        TYPE = hop.spaceop.result.concretetype.TO
+        assert not TYPE._is_varsize()
+        c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE))
+        if TYPE._is_atomic():
+            funcptr = self.malloc_fixedsize_atomic_ptr
+        else:
+            funcptr = self.malloc_fixedsize_ptr
+        v_raw = hop.genop("direct_call", [funcptr, c_size],
+                          resulttype=llmemory.Address)
+        hop.cast_result(v_raw)
+
+    def gct_malloc_varsize(self, hop):
+        def intconst(c): return rmodel.inputconst(lltype.Signed, c)
+
+        op = hop.spaceop
+        TYPE = op.result.concretetype.TO
+        assert TYPE._is_varsize()
+
+        if isinstance(TYPE, lltype.Struct):
+            ARRAY = TYPE._flds[TYPE._arrayfld]
+        else:
+            ARRAY = TYPE
+        assert isinstance(ARRAY, lltype.Array)
+        if ARRAY._hints.get('isrpystring', False):
+            c_const_size = intconst(llmemory.sizeof(TYPE, 1))
+        else:
+            c_const_size = intconst(llmemory.sizeof(TYPE, 0))
+        c_item_size = intconst(llmemory.sizeof(ARRAY.OF))
+
+        if ARRAY._hints.get("nolength", False):
+            v_raw = hop.genop("direct_call",
+                               [self.malloc_varsize_no_length_ptr, op.args[-1],
+                                c_const_size, c_item_size],
+                               resulttype=llmemory.Address)
+        else:
+            if isinstance(TYPE, lltype.Struct):
+                offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \
+                                   llmemory.ArrayLengthOffset(ARRAY)
+            else:
+                offset_to_length = llmemory.ArrayLengthOffset(ARRAY)
+            v_raw = hop.genop("direct_call",
+                               [self.malloc_varsize_ptr, op.args[-1],
+                                c_const_size, c_item_size, intconst(offset_to_length)],
+                               resulttype=llmemory.Address)
+        hop.cast_result(v_raw)
+
     def finalizer_funcptr_for_type(self, TYPE):
         if TYPE in self.finalizer_funcptrs:
             return self.finalizer_funcptrs[TYPE]

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_boehm.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_boehm.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_boehm.py	Thu Jul 12 15:43:43 2007
@@ -3,9 +3,14 @@
 from pypy.rpython.memory.gctransform.test.test_refcounting import make_deallocator
 from pypy.rpython.lltypesystem import lltype
 from pypy.translator.translator import graphof
+from pypy.translator.c.gc import BoehmGcPolicy
+from pypy.rpython.memory.gctransform.test.test_transform import LLInterpedTranformerTests
 from pypy import conftest
 import py
 
+class TestLLInterpedBoehm(LLInterpedTranformerTests):
+    gcpolicy = BoehmGcPolicy
+
 def make_boehm_finalizer(TYPE):
     return make_deallocator(TYPE, attr="finalizer_funcptr_for_type",
                             cls=BoehmGCTransformer)

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_refcounting.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_refcounting.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_refcounting.py	Thu Jul 12 15:43:43 2007
@@ -1,117 +1,47 @@
 from pypy.rpython.memory.gctransform.test.test_transform import rtype, rtype_and_transform, getops
+from pypy.rpython.memory.gctransform.test.test_transform import LLInterpedTranformerTests
 from pypy.rpython.memory.gctransform.refcounting import RefcountingGCTransformer
 from pypy.rpython.lltypesystem import lltype
-from pypy.translator.c.gc import RefcountingGcPolicy
 from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.c.gc import RefcountingGcPolicy
 from pypy import conftest
 
-def llinterpreter_for_refcounted_graph(f, args_s):
-    from pypy.rpython.llinterp import LLInterpreter
-    from pypy.translator.c.genc import CStandaloneBuilder
-    from pypy.translator.c import gc
-
-    t = rtype(f, args_s)
-    cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=RefcountingGcPolicy)
-    db = cbuild.generate_graphs_for_llinterp()
-    graph = cbuild.getentrypointptr()._obj.graph
-    llinterp = LLInterpreter(t.rtyper)
-    if conftest.option.view:
-        t.view()
-    return llinterp, graph
-
-
-def test_llinterp_refcounted_graph():
-    from pypy.annotation.model import SomeInteger
+class TestLLInterpedRefcounting(LLInterpedTranformerTests):
+    gcpolicy = RefcountingGcPolicy
 
-    class C:
-        pass
-    c = C()
-    c.x = 1
-    def g(x):
-        if x:
-            return c
-        else:
-            d = C()
-            d.x = 2
-            return d
-    def f(x):
-        return g(x).x
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
-
-    res = llinterp.eval_graph(graph, [0])
-    assert res == f(0)
-    res = llinterp.eval_graph(graph, [1])
-    assert res == f(1)
-
-def test_llinterp_refcounted_graph_varsize():
-    from pypy.annotation.model import SomeInteger
-
-    def f(x):
-        r = []
-        for i in range(x):
-            if i % 2:
-                r.append(x)
-        return len(r)
-
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
-
-    res = llinterp.eval_graph(graph, [0])
-    assert res == f(0)
-    res = llinterp.eval_graph(graph, [10])
-    assert res == f(10)
-
-def test_llinterp_refcounted_graph_str():
-    from pypy.annotation.model import SomeString
-    from pypy.rpython.lltypesystem.rstr import string_repr
-
-    def f(x):
-        return len(x + 'a')
-
-
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeString()])
-
-    cc = string_repr.convert_const
-
-    res = llinterp.eval_graph(graph, [cc('a')])
-    assert res == f('a')
-    res = llinterp.eval_graph(graph, [cc('brrrrrr')])
-    assert res == f('brrrrrr')
-
-def test_llinterp_refcounted_graph_with_del():
-    from pypy.annotation.model import SomeInteger
-
-    class D:
-        pass
-
-    delcounter = D()
-    delcounter.dels = 0
-
-    class C:
-        def __del__(self):
-            delcounter.dels += 1
-    c = C()
-    c.x = 1
-    def h(x):
-        if x:
-            return c
-        else:
-            d = C()
-            d.x = 2
-            return d
-    def g(x):
-        return h(x).x
-    def f(x):
-        r = g(x)
-        return r + delcounter.dels
+    def test_llinterp_refcounted_graph_with_del(self):
+        from pypy.annotation.model import SomeInteger
 
-    llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()])
+        class D:
+            pass
 
-    res = llinterp.eval_graph(graph, [1])
-    assert res == 1
-    res = llinterp.eval_graph(graph, [0])
-    assert res == 3
+        delcounter = D()
+        delcounter.dels = 0
+
+        class C:
+            def __del__(self):
+                delcounter.dels += 1
+        c = C()
+        c.x = 1
+        def h(x):
+            if x:
+                return c
+            else:
+                d = C()
+                d.x = 2
+                return d
+        def g(x):
+            return h(x).x
+        def f(x):
+            r = g(x)
+            return r + delcounter.dels
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [1])
+        assert res == 1
+        res = llinterp.eval_graph(graph, [0])
+        assert res == 3
 
 def test_simple_barrier():
     S = lltype.GcStruct("S", ('x', lltype.Signed))

Modified: pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_transform.py
==============================================================================
--- pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_transform.py	(original)
+++ pypy/branch/emptying-the-malloc-zoo-2/pypy/rpython/memory/gctransform/test/test_transform.py	Thu Jul 12 15:43:43 2007
@@ -10,6 +10,83 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy import conftest
 
+class LLInterpedTranformerTests:
+
+    def llinterpreter_for_transformed_graph(self, f, args_s):
+        from pypy.rpython.llinterp import LLInterpreter
+        from pypy.translator.c.genc import CStandaloneBuilder
+        from pypy.translator.c import gc
+
+        t = rtype(f, args_s)
+        # XXX we shouldn't need an actual gcpolicy here.
+        cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=self.gcpolicy)
+        db = cbuild.generate_graphs_for_llinterp()
+        graph = cbuild.getentrypointptr()._obj.graph
+        llinterp = LLInterpreter(t.rtyper)
+        if conftest.option.view:
+            t.view()
+        return llinterp, graph
+
+
+    def test_simple(self):
+        from pypy.annotation.model import SomeInteger
+
+        class C:
+            pass
+        c = C()
+        c.x = 1
+        def g(x):
+            if x:
+                return c
+            else:
+                d = C()
+                d.x = 2
+                return d
+        def f(x):
+            return g(x).x
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [0])
+        assert res == f(0)
+        res = llinterp.eval_graph(graph, [1])
+        assert res == f(1)
+
+    def test_simple_varsize(self):
+        from pypy.annotation.model import SomeInteger
+
+        def f(x):
+            r = []
+            for i in range(x):
+                if i % 2:
+                    r.append(x)
+            return len(r)
+
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeInteger()])
+
+        res = llinterp.eval_graph(graph, [0])
+        assert res == f(0)
+        res = llinterp.eval_graph(graph, [10])
+        assert res == f(10)
+
+    def test_str(self):
+        from pypy.annotation.model import SomeString
+        from pypy.rpython.lltypesystem.rstr import string_repr
+
+        def f(x):
+            return len(x + 'a')
+
+
+        llinterp, graph = self.llinterpreter_for_transformed_graph(f, [SomeString()])
+
+        cc = string_repr.convert_const
+
+        res = llinterp.eval_graph(graph, [cc('a')])
+        assert res == f('a')
+        res = llinterp.eval_graph(graph, [cc('brrrrrr')])
+        assert res == f('brrrrrr')
+
 class _TestGCTransformer(GCTransformer):
 
     def push_alive_nopyobj(self, var, llops):



More information about the Pypy-commit mailing list