[pypy-svn] r58875 - in pypy/dist/pypy/translator/backendopt: . test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 10 10:31:08 CEST 2008


Author: arigo
Date: Fri Oct 10 10:31:07 2008
New Revision: 58875

Modified:
   pypy/dist/pypy/translator/backendopt/mallocv.py
   pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
Log:
(fijal, arigo)
* Don't malloc-remove structures with a destructor.
* Improve the tests, counting remaining mallocs and remaining calls.


Modified: pypy/dist/pypy/translator/backendopt/mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/mallocv.py	(original)
+++ pypy/dist/pypy/translator/backendopt/mallocv.py	Fri Oct 10 10:31:07 2008
@@ -11,11 +11,24 @@
 class MallocTypeDesc(object):
 
     def __init__(self, MALLOCTYPE):
+        if not isinstance(MALLOCTYPE, lltype.GcStruct):
+            raise CannotRemoveThisType
         self.MALLOCTYPE = MALLOCTYPE
         self.names_and_types = []
         self.name2index = {}
         self.initialize_type(MALLOCTYPE)
         #self.immutable_struct = MALLOCTYPE._hints.get('immutable')
+        self.check_no_destructor()
+
+    def check_no_destructor(self):
+        STRUCT = self.MALLOCTYPE
+        try:
+            rttiptr = lltype.getRuntimeTypeInfo(STRUCT)
+        except ValueError:
+            return    # ok
+        destr_ptr = getattr(rttiptr._obj, 'destructor_funcptr', None)
+        if destr_ptr:
+            raise CannotRemoveThisType
 
     def initialize_type(self, TYPE):
         fieldnames = TYPE._names
@@ -180,6 +193,9 @@
 class ForcedInline(Exception):
     pass
 
+class CannotRemoveThisType(Exception):
+    pass
+
 
 class MallocVirtualizer(object):
 
@@ -200,7 +216,13 @@
         for block in graph.iterblocks():
             for op in block.operations:
                 if op.opname == 'malloc':
-                    result.append((block, op))
+                    MALLOCTYPE = op.result.concretetype.TO
+                    try:
+                        self.getmalloctypedesc(MALLOCTYPE)
+                    except CannotRemoveThisType:
+                        pass
+                    else:
+                        result.append((block, op))
         return result
 
     def remove_mallocs_once(self):

Modified: pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_mallocv.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_mallocv.py	Fri Oct 10 10:31:07 2008
@@ -20,21 +20,22 @@
         if self.type_system == 'ootype':
             py.test.skip(msg)
 
-    def check_malloc_removed(cls, graph):
-        #remover = cls.MallocRemover()
-        checkgraph(graph)
-        count = 0
+    def check_malloc_removed(cls, graph, expected_mallocs, expected_calls):
+        count_mallocs = 0
+        count_calls = 0
         for node in flatten(graph):
             if isinstance(node, Block):
                 for op in node.operations:
-                    if op.opname == 'malloc': #cls.MallocRemover.MALLOC_OP:
-                        S = op.args[0].value
-                        #if not remover.union_wrapper(S):   # union wrappers are fine
-                        count += 1
-        assert count == 0   # number of mallocs left
+                    if op.opname == 'malloc':
+                        count_mallocs += 1
+                    if op.opname == 'direct_call':
+                        count_calls += 1
+        assert count_mallocs == expected_mallocs
+        assert count_calls == expected_calls
     check_malloc_removed = classmethod(check_malloc_removed)
 
-    def check(self, fn, signature, args, expected_result, must_be_removed=True):
+    def check(self, fn, signature, args, expected_result,
+              expected_mallocs=0, expected_calls=0):
         t = TranslationContext()
         t.buildannotator().build_types(fn, signature)
         t.buildrtyper(type_system=self.type_system).specialize()
@@ -56,8 +57,7 @@
                 assert res == expected_result
             if not progress:
                 break
-        if must_be_removed:
-            self.check_malloc_removed(graph)
+        self.check_malloc_removed(graph, expected_mallocs, expected_calls)
         return graph
 
     def test_fn1(self):
@@ -93,7 +93,8 @@
             return a * b
         def f(x):
             return g((x+1, x-1))
-        graph = self.check(f, [int], [10], 99)
+        graph = self.check(f, [int], [10], 99,
+                           expected_calls=1)     # not inlined
 
     def test_direct_call_mutable_simple(self):
         A = lltype.GcStruct('A', ('x', lltype.Signed))
@@ -104,9 +105,8 @@
             a.x = x
             g(a)
             return a.x
-        graph = self.check(f, [int], [41], 42)
-        insns = summary(graph)
-        assert insns.get('direct_call', 0) == 0     # no more call, inlined
+        graph = self.check(f, [int], [41], 42,
+                           expected_calls=0)     # no more call, inlined
 
     def test_direct_call_mutable_retval(self):
         A = lltype.GcStruct('A', ('x', lltype.Signed))
@@ -118,9 +118,8 @@
             a.x = x
             y = g(a)
             return a.x + y
-        graph = self.check(f, [int], [41], 4242)
-        insns = summary(graph)
-        assert insns.get('direct_call', 0) == 0     # no more call, inlined
+        graph = self.check(f, [int], [41], 4242,
+                           expected_calls=0)     # no more call, inlined
 
     def test_direct_call_mutable_ret_virtual(self):
         A = lltype.GcStruct('A', ('x', lltype.Signed))
@@ -132,9 +131,8 @@
             a.x = x
             b = g(a)
             return a.x + b.x
-        graph = self.check(f, [int], [41], 84)
-        insns = summary(graph)
-        assert insns.get('direct_call', 0) == 0     # no more call, inlined
+        graph = self.check(f, [int], [41], 84,
+                           expected_calls=0)     # no more call, inlined
 
     def test_direct_call_mutable_lastref(self):
         A = lltype.GcStruct('A', ('x', lltype.Signed))
@@ -146,9 +144,8 @@
             a.x = x
             y = g(a)
             return x - y
-        graph = self.check(f, [int], [5], -45)
-        insns = summary(graph)
-        assert insns.get('direct_call', 0) == 1     # not inlined
+        graph = self.check(f, [int], [5], -45,
+                           expected_calls=1)     # not inlined
 
     def test_direct_call_ret_virtual(self):
         A = lltype.GcStruct('A', ('x', lltype.Signed))
@@ -162,9 +159,8 @@
             a.x = 2
             a = g(a)
             return prebuilt_a.x * a.x
-        graph = self.check(f, [int], [19], 42)
-        insns = summary(graph)
-        assert insns.get('direct_call', 0) == 0     # inlined
+        graph = self.check(f, [int], [19], 42,
+                           expected_calls=0)     # inlined
 
     def test_fn2(self):
         class T:
@@ -224,6 +220,13 @@
             return a1.x
         self.check(fn6, [int], [1], 12)
 
+    def test_with__del__(self):
+        class A(object):
+            def __del__(self):
+                pass
+        def fn7():
+            A()
+        self.check(fn7, [], [], None, expected_mallocs=1)  # don't remove
 
 
 class TestLLTypeMallocRemoval(BaseMallocRemovalTest):



More information about the Pypy-commit mailing list