[pypy-svn] r32863 - in pypy/dist/pypy/rpython/memory/gctransform2: . test

mwh at codespeak.net mwh at codespeak.net
Wed Oct 4 13:21:11 CEST 2006


Author: mwh
Date: Wed Oct  4 13:21:10 2006
New Revision: 32863

Modified:
   pypy/dist/pypy/rpython/memory/gctransform2/refcounting.py
   pypy/dist/pypy/rpython/memory/gctransform2/support.py
   pypy/dist/pypy/rpython/memory/gctransform2/test/test_refcounting.py
   pypy/dist/pypy/rpython/memory/gctransform2/test/test_transform.py
   pypy/dist/pypy/rpython/memory/gctransform2/transform.py
Log:
add boehm to the gctransform2 package.
fix tests.


Modified: pypy/dist/pypy/rpython/memory/gctransform2/refcounting.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform2/refcounting.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform2/refcounting.py	Wed Oct  4 13:21:10 2006
@@ -1,6 +1,7 @@
 import py
 from pypy.rpython.memory.gctransform2.transform import GCTransformer
-from pypy.rpython.memory.gctransform2.support import find_gc_ptrs_in_type
+from pypy.rpython.memory.gctransform2.support import find_gc_ptrs_in_type, \
+     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.translator.backendopt.support import var_needsgc
@@ -9,63 +10,8 @@
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 #from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.rarithmetic import ovfcheck
-from pypy.rpython.extregistry import ExtRegistryEntry
-from pypy.annotation import model as annmodel
 from pypy.rpython.rbuiltin import gen_cast
-import os, sys
-
-
-class LLTransformerOp(object):
-    """Objects that can be called in ll functions.
-    Their calls are replaced by a simple operation of the GC transformer,
-    e.g. ll_pop_alive.
-    """
-    def __init__(self, transformer_method):
-        self.transformer_method = transformer_method
-
-class LLTransformerOpEntry(ExtRegistryEntry):
-    "Annotation and specialization of LLTransformerOp() instances."
-    _type_ = LLTransformerOp
-
-    def compute_result_annotation(self, s_arg):
-        return annmodel.s_None
-
-    def specialize_call(self, hop):
-        op = self.instance   # the LLTransformerOp instance
-        op.transformer_method(hop.args_v[0], hop.llops)
-        hop.exception_cannot_occur()
-        return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
-
-def ll_call_destructor(destrptr, destr_v):
-    try:
-        destrptr(destr_v)
-    except:
-        try:
-            os.write(2, "a destructor raised an exception, ignoring it\n")
-        except:
-            pass
-
-def _static_deallocator_body_for_type(v, TYPE, depth=1):
-    if isinstance(TYPE, lltype.Array):
-        inner = list(_static_deallocator_body_for_type('v_%i'%depth, TYPE.OF, depth+1))
-        if inner:
-            yield '    '*depth + 'i_%d = 0'%(depth,)
-            yield '    '*depth + 'l_%d = len(%s)'%(depth, v)
-            yield '    '*depth + 'while i_%d < l_%d:'%(depth, depth)
-            yield '    '*depth + '    v_%d = %s[i_%d]'%(depth, v, depth)
-            for line in inner:
-                yield line
-            yield '    '*depth + '    i_%d += 1'%(depth,)
-    elif isinstance(TYPE, lltype.Struct):
-        for name in TYPE._names:
-            inner = list(_static_deallocator_body_for_type(
-                v + '_' + name, TYPE._flds[name], depth))
-            if inner:
-                yield '    '*depth + v + '_' + name + ' = ' + v + '.' + name
-                for line in inner:
-                    yield line
-    elif isinstance(TYPE, lltype.Ptr) and TYPE._needsgc():
-        yield '    '*depth + 'pop_alive(%s)'%v
+import sys
 
 counts = {}
 
@@ -88,14 +34,6 @@
 
 ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
 
-def get_rtti(TYPE):
-    if isinstance(TYPE, lltype.RttiStruct):
-        try:
-            return lltype.getRuntimeTypeInfo(TYPE)
-        except ValueError:
-            pass
-    return None
-
 class RefcountingGCTransformer(GCTransformer):
 
     HDR = lltype.Struct("header", ("refcount", lltype.Signed))

Modified: pypy/dist/pypy/rpython/memory/gctransform2/support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform2/support.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform2/support.py	Wed Oct  4 13:21:10 2006
@@ -1,4 +1,7 @@
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.annotation import model as annmodel
+import os
 
 def var_ispyobj(var):
     if hasattr(var, 'concretetype'):
@@ -29,3 +32,77 @@
         raise Exception("don't know what is in %r" % (TYPE,))
     else:
         return []
+
+def type_contains_pyobjs(TYPE):
+    if isinstance(TYPE, lltype.Array):
+        return type_contains_pyobjs(TYPE.OF)
+    elif isinstance(TYPE, lltype.Struct):
+        result = []
+        for name in TYPE._names:
+            if type_contains_pyobjs(TYPE._flds[name]):
+                return True
+        return False
+    elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'cpy':
+        return True
+    else:
+        return False
+
+def get_rtti(TYPE):
+    if isinstance(TYPE, lltype.RttiStruct):
+        try:
+            return lltype.getRuntimeTypeInfo(TYPE)
+        except ValueError:
+            pass
+    return None
+
+def _static_deallocator_body_for_type(v, TYPE, depth=1):
+    if isinstance(TYPE, lltype.Array):
+        inner = list(_static_deallocator_body_for_type('v_%i'%depth, TYPE.OF, depth+1))
+        if inner:
+            yield '    '*depth + 'i_%d = 0'%(depth,)
+            yield '    '*depth + 'l_%d = len(%s)'%(depth, v)
+            yield '    '*depth + 'while i_%d < l_%d:'%(depth, depth)
+            yield '    '*depth + '    v_%d = %s[i_%d]'%(depth, v, depth)
+            for line in inner:
+                yield line
+            yield '    '*depth + '    i_%d += 1'%(depth,)
+    elif isinstance(TYPE, lltype.Struct):
+        for name in TYPE._names:
+            inner = list(_static_deallocator_body_for_type(
+                v + '_' + name, TYPE._flds[name], depth))
+            if inner:
+                yield '    '*depth + v + '_' + name + ' = ' + v + '.' + name
+                for line in inner:
+                    yield line
+    elif isinstance(TYPE, lltype.Ptr) and TYPE._needsgc():
+        yield '    '*depth + 'pop_alive(%s)'%v
+
+class LLTransformerOp(object):
+    """Objects that can be called in ll functions.
+    Their calls are replaced by a simple operation of the GC transformer,
+    e.g. ll_pop_alive.
+    """
+    def __init__(self, transformer_method):
+        self.transformer_method = transformer_method
+
+class LLTransformerOpEntry(ExtRegistryEntry):
+    "Annotation and specialization of LLTransformerOp() instances."
+    _type_ = LLTransformerOp
+
+    def compute_result_annotation(self, s_arg):
+        return annmodel.s_None
+
+    def specialize_call(self, hop):
+        op = self.instance   # the LLTransformerOp instance
+        op.transformer_method(hop.args_v[0], hop.llops)
+        hop.exception_cannot_occur()
+        return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
+
+def ll_call_destructor(destrptr, destr_v):
+    try:
+        destrptr(destr_v)
+    except:
+        try:
+            os.write(2, "a destructor raised an exception, ignoring it\n")
+        except:
+            pass

Modified: pypy/dist/pypy/rpython/memory/gctransform2/test/test_refcounting.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform2/test/test_refcounting.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform2/test/test_refcounting.py	Wed Oct  4 13:21:10 2006
@@ -1,7 +1,8 @@
-from pypy.rpython.memory.gctransform2.test.test_transform import rtype
+from pypy.rpython.memory.gctransform2.test.test_transform import rtype, rtype_and_transform, getops
 from pypy.rpython.memory.gctransform2.refcounting import RefcountingGCTransformer
-from pypy.translator.c.database import LowLevelDatabase
+from pypy.rpython.lltypesystem import lltype
 from pypy.translator.c.gc import RefcountingGcPolicy
+from pypy.translator.translator import TranslationContext, graphof
 from pypy import conftest
 
 class RefcountingGcPolicy2(RefcountingGcPolicy):
@@ -119,3 +120,176 @@
     res = llinterp.eval_graph(graph, [0])
     assert res == 3
 
+def make_deallocator(TYPE,
+                     attr="static_deallocation_funcptr_for_type",
+                     cls=RefcountingGCTransformer):
+    if TYPE._is_varsize():
+        def f():
+            return lltype.malloc(TYPE, 1)
+    else:
+        def f():
+            return lltype.malloc(TYPE)
+    t = TranslationContext()
+    t.buildannotator().build_types(f, [])
+    t.buildrtyper().specialize()
+    transformer = cls(t)
+    fptr = getattr(transformer, attr)(TYPE)
+    transformer.transform_graph(graphof(t, f))
+    transformer.finish()
+    if conftest.option.view:
+        t.view()
+    if fptr:
+        return fptr._obj.graph, t
+    else:
+        return None, t
+
+def test_deallocator_simple():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    dgraph, t = make_deallocator(S)
+    ops = []
+    for block in dgraph.iterblocks():
+        ops.extend([op for op in block.operations if op.opname != 'same_as']) # XXX
+    assert len(ops) == 1
+    op = ops[0]
+    assert op.opname == 'gc_free'
+
+def test_deallocator_less_simple():
+    TPtr = lltype.Ptr(lltype.GcStruct("T", ('a', lltype.Signed)))
+    S = lltype.GcStruct(
+        "S",
+        ('x', lltype.Signed),
+        ('y', TPtr),
+        ('z', TPtr),
+        )
+    dgraph, t = make_deallocator(S)
+    ops = getops(dgraph)
+    assert len(ops['direct_call']) == 2
+    assert len(ops['getfield']) == 2
+    assert len(ops['gc_free']) == 1
+
+def test_deallocator_array():
+    TPtr = lltype.Ptr(lltype.GcStruct("T", ('a', lltype.Signed)))
+    GcA = lltype.GcArray(('x', TPtr), ('y', TPtr))
+    A = lltype.Array(('x', TPtr), ('y', TPtr))
+    APtr = lltype.Ptr(GcA)
+    S = lltype.GcStruct('S', ('t', TPtr), ('x', lltype.Signed), ('aptr', APtr),
+                             ('rest', A))
+    dgraph, t = make_deallocator(S)
+    ops = getops(dgraph)
+    assert len(ops['direct_call']) == 4
+    assert len(ops['getfield']) == 4
+    assert len(ops['getarraysubstruct']) == 1
+    assert len(ops['gc_free']) == 1
+
+def test_deallocator_with_destructor():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    def f(s):
+        s.x = 1
+    def type_info_S(p):
+        return lltype.getRuntimeTypeInfo(S)
+    qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)],
+                                            lltype.Ptr(lltype.RuntimeTypeInfo)),
+                            "type_info_S", 
+                            _callable=type_info_S)
+    dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)],
+                                            lltype.Void), 
+                            "destructor_funcptr", 
+                            _callable=f)
+    pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp)
+    graph, t = make_deallocator(S)
+
+def test_caching_dynamic_deallocator():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed))
+    T = lltype.GcStruct("T", ('x', lltype.Signed))
+    def f_S(s):
+        s.x = 1
+    def f_S1(s1):
+        s1.s.x = 1
+        s1.y = 2
+    def f_T(s):
+        s.x = 1
+    def type_info_S(p):
+        return lltype.getRuntimeTypeInfo(S)
+    def type_info_T(p):
+        return lltype.getRuntimeTypeInfo(T)
+    qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)],
+                                            lltype.Ptr(lltype.RuntimeTypeInfo)),
+                            "type_info_S", 
+                            _callable=type_info_S)
+    dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)],
+                                            lltype.Void), 
+                            "destructor_funcptr", 
+                            _callable=f_S)
+    pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp)
+    dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)],
+                                            lltype.Void), 
+                            "destructor_funcptr", 
+                            _callable=f_S1)
+    pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp)
+    qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)],
+                                            lltype.Ptr(lltype.RuntimeTypeInfo)),
+                            "type_info_S", 
+                            _callable=type_info_T)
+    dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)],
+                                            lltype.Void), 
+                            "destructor_funcptr", 
+                            _callable=f_T)
+    pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp)
+    def f():
+        pass
+    t = TranslationContext()
+    t.buildannotator().build_types(f, [])
+    t.buildrtyper().specialize()
+    transformer = RefcountingGCTransformer(t)
+    p_S = transformer.dynamic_deallocation_funcptr_for_type(S)
+    p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1)
+    p_T = transformer.dynamic_deallocation_funcptr_for_type(T)
+    assert p_S is not p_T
+    assert p_S is p_S1
+
+def test_dynamic_deallocator():
+    class A(object):
+        pass
+    class B(A):
+        pass
+    def f(x):
+        a = A()
+        a.x = 1
+        b = B()
+        b.x = 2
+        b.y = 3
+        if x:
+            c = a
+        else:
+            c = b
+        return c.x
+    t, transformer = rtype_and_transform(
+        f, [int], RefcountingGCTransformer, check=False)
+    fgraph = graphof(t, f)
+    s_instance = t.annotator.bookkeeper.valueoftype(A)
+    TYPE = t.rtyper.getrepr(s_instance).lowleveltype.TO
+    p = transformer.dynamic_deallocation_funcptr_for_type(TYPE)
+    t.rtyper.specialize_more_blocks() 
+
+def test_recursive_structure():
+    F = lltype.GcForwardReference()
+    S = lltype.GcStruct('abc', ('x', lltype.Ptr(F)))
+    F.become(S)
+    def f():
+        s1 = lltype.malloc(S)
+        s2 = lltype.malloc(S)
+        s1.x = s2
+    t, transformer = rtype_and_transform(
+        f, [], RefcountingGCTransformer, check=False)
+
+def test_dont_decref_nongc_pointers():
+    S = lltype.GcStruct('S',
+                        ('x', lltype.Ptr(lltype.Struct('T', ('x', lltype.Signed)))),
+                        ('y', lltype.Ptr(lltype.GcStruct('Y', ('x', lltype.Signed))))
+                        )
+    def f():
+        pass
+    graph, t = make_deallocator(S)
+    ops = getops(graph)
+    assert len(ops['direct_call']) == 1

Modified: pypy/dist/pypy/rpython/memory/gctransform2/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform2/test/test_transform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform2/test/test_transform.py	Wed Oct  4 13:21:10 2006
@@ -11,11 +11,11 @@
 
 class _TestGCTransformer(GCTransformer):
 
-    def push_alive_nopyobj(self, var):
-        self.llops.genop("gc_push_alive", [var])
+    def push_alive_nopyobj(self, var, llops):
+        llops.genop("gc_push_alive", [var])
 
-    def pop_alive_nopyobj(self, var):
-        self.llops.genop("gc_pop_alive", [var])
+    def pop_alive_nopyobj(self, var, llops):
+        llops.genop("gc_pop_alive", [var])
 
 
 def checkblock(block, is_borrowed):

Modified: pypy/dist/pypy/rpython/memory/gctransform2/transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform2/transform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform2/transform.py	Wed Oct  4 13:21:10 2006
@@ -209,7 +209,7 @@
                     self.push_alive(var, llops)
             if llops:
                 if link.prevblock.exitswitch is None:
-                    link.prevblock.operations.extend(self.llops)
+                    link.prevblock.operations.extend(llops)
                 else:
                     insert_empty_block(self.translator.annotator, link, llops)
 



More information about the Pypy-commit mailing list