[pypy-svn] r20971 - in pypy/dist/pypy/translator/c: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri Dec 9 20:27:44 CET 2005
Author: cfbolz
Date: Fri Dec 9 20:27:43 2005
New Revision: 20971
Modified:
pypy/dist/pypy/translator/c/gc.py
pypy/dist/pypy/translator/c/test/test_backendoptimized.py
Log:
(johahn, cfbolz)
support __del__ in genc if using refcounting.
Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py (original)
+++ pypy/dist/pypy/translator/c/gc.py Fri Dec 9 20:27:43 2005
@@ -84,6 +84,7 @@
class RefcountingInfo:
deallocator = None
static_deallocator = None
+ destructor = None
class RefcountingGcPolicy(BasicGcPolicy):
@@ -184,6 +185,10 @@
gcinfo.rtti_query_funcptr = db.get(fnptr)
T = typeOf(fnptr).TO.ARGS[0]
gcinfo.rtti_query_funcptr_argtype = db.gettype(T)
+ if hasattr(rtti._obj, 'destructor_funcptr'):
+ destrptr = rtti._obj.destructor_funcptr
+ gcinfo.destructor = db.get(destrptr)
+ T = typeOf(destrptr).TO.ARGS[0]
else:
# is a deallocator really needed, or would it be empty?
if list(self.deallocator_lines(structdefnode, '')):
@@ -198,14 +203,32 @@
def struct_implementationcode(self, structdefnode):
if structdefnode.gcinfo:
gcinfo = structdefnode.gcinfo
- if gcinfo.static_deallocator:
+ has_dynamic_deallocator = gcinfo.deallocator and gcinfo.deallocator != gcinfo.static_deallocator
+ if gcinfo.static_deallocator and not has_dynamic_deallocator:
yield 'void %s(struct %s *p) {' % (gcinfo.static_deallocator,
structdefnode.name)
+ # insert decrefs to objects we have a reference to
for line in self.deallocator_lines(structdefnode, '(*p)'):
yield '\t' + line
yield '\tOP_FREE(p);'
yield '}'
- if gcinfo.deallocator and gcinfo.deallocator != gcinfo.static_deallocator:
+ elif has_dynamic_deallocator:
+ # write static deallocator
+ yield 'void %s(struct %s *p) {' % (gcinfo.static_deallocator,
+ structdefnode.name)
+ # insert call to __del__ if necessary
+ if gcinfo.destructor:
+ yield "\t%s((%s) p);" % (gcinfo.destructor,
+ cdecl(gcinfo.destructor_argtype, ''))
+ # insert decrefs to objects we have a reference to
+ yield '\tif (!--p->%s) {' % (structdefnode.gcheader,)
+ for line in self.deallocator_lines(structdefnode, '(*p)'):
+ yield '\t\t' + line
+ yield '\t\tOP_FREE(p);'
+ yield '\t}'
+ yield '}'
+
+ # write dynamic deallocator
yield 'void %s(struct %s *p) {' % (gcinfo.deallocator, structdefnode.name)
yield '\tvoid (*staticdealloc) (void *);'
# the refcount should be 0; temporarily bump it to 1
@@ -214,8 +237,7 @@
yield '\tstaticdealloc = %s((%s) p);' % (
gcinfo.rtti_query_funcptr,
cdecl(gcinfo.rtti_query_funcptr_argtype, ''))
- yield '\tif (!--p->%s)' % (structdefnode.gcheader,)
- yield '\t\tstaticdealloc(p);'
+ yield '\tstaticdealloc(p);'
yield '}'
Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_backendoptimized.py (original)
+++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Fri Dec 9 20:27:43 2005
@@ -7,6 +7,7 @@
def process(self, t):
_TestTypedTestCase.process(self, t)
+ self.t = t
backend_optimizations(t)
def test_remove_same_as(self):
@@ -18,3 +19,60 @@
fn = self.getcompiled(f)
assert f(True) == 123
assert f(False) == 456
+
+ def test__del__(self):
+ import os
+ class B(object):
+ pass
+ b = B()
+ b.nextid = 0
+ b.num_deleted = 0
+ class A(object):
+ def __init__(self):
+ self.id = b.nextid
+ b.nextid += 1
+
+ def __del__(self):
+ b.num_deleted += 1
+
+ def f(x=int):
+ a = A()
+ for i in range(x):
+ a = A()
+ return b.num_deleted
+
+ fn = self.getcompiled(f)
+ res = f(5)
+ assert res == 5
+ res = fn(5)
+ # translated function looses its last reference earlier
+ assert res == 6
+
+ def test_del_inheritance(self):
+ class State:
+ pass
+ s = State()
+ s.a_dels = 0
+ s.b_dels = 0
+ class A(object):
+ def __del__(self):
+ s.a_dels += 1
+ class B(A):
+ def __del__(self):
+ s.b_dels += 1
+ class C(A):
+ pass
+ def f():
+ A()
+ B()
+ C()
+ A()
+ B()
+ C()
+ return s.a_dels * 10 + s.b_dels
+ res = f()
+ assert res == 42
+ fn = self.getcompiled(f)
+ res = fn()
+ assert res == 42
+
More information about the Pypy-commit
mailing list