[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