[pypy-svn] r47026 - in pypy/dist/pypy: rpython rpython/lltypesystem/test rpython/memory/gctransform translator/c translator/c/src
arigo at codespeak.net
arigo at codespeak.net
Sat Sep 29 19:31:18 CEST 2007
Author: arigo
Date: Sat Sep 29 19:31:17 2007
New Revision: 47026
Modified:
pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
pypy/dist/pypy/rpython/memory/gctransform/refcounting.py
pypy/dist/pypy/rpython/rcpy.py
pypy/dist/pypy/translator/c/funcgen.py
pypy/dist/pypy/translator/c/src/mem.h
Log:
Support Python subclasses of types created by the extension compiler.
Don't think I'm actively developping the extension compiler - I was
fixing the failures in test_rcpyclass and I was forced to do the
right thing :-)
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rcpyclass.py Sat Sep 29 19:31:17 2007
@@ -14,7 +14,7 @@
return self.x * 2
-mytest = CPyTypeInterface('mytest', {})
+mytest = CPyTypeInterface('mytest', {}, subclassable=True)
def test_cpy_export():
def f():
@@ -22,7 +22,8 @@
return cpy_export(mytest, w)
fn = compile(f, [])
- res = fn(expected_extra_mallocs=1)
+ res = fn() # the W_MyTest is allocated with the CPython logic,
+ # so it doesn't count in expected_extra_mallocs
assert type(res).__name__ == 'mytest'
@@ -76,17 +77,17 @@
return cpy_export(mytest, w), total
fn = compile(f, [object])
- obj, total = fn(None, expected_extra_mallocs=2) # 1 W_MyTest (with 1 tuple)
+ obj, total = fn(None, expected_extra_mallocs=1) # 1 tuple in w.stuff
assert total == 1
- obj, total = fn(obj, expected_extra_mallocs=4) # 2 W_MyTests alive
- assert total == 3
- obj, total = fn(obj, expected_extra_mallocs=4) # 2 W_MyTests alive
+ obj, total = fn(obj, expected_extra_mallocs=2) # 2 tuples: old obj.stuff
+ assert total == 3 # + new obj.stuff
+ obj, total = fn(obj, expected_extra_mallocs=2)
assert total == 6
- obj, total = fn(obj, expected_extra_mallocs=4) # etc
+ obj, total = fn(obj, expected_extra_mallocs=2) # idem
assert total == 10
- obj, total = fn(obj, expected_extra_mallocs=4)
+ obj, total = fn(obj, expected_extra_mallocs=2)
assert total == 15
- obj, total = fn(obj, expected_extra_mallocs=4)
+ obj, total = fn(obj, expected_extra_mallocs=2)
assert total == 21
@@ -100,32 +101,32 @@
return cpy_export(mytest, w), w.x
fn = compile(f, [object])
- obj, x = fn(None, expected_extra_mallocs=1) # 1 W_MyTest
+ obj, x = fn(None)
assert x == 22
obj2 = type(obj)()
del obj
- obj, x = fn(obj2, expected_extra_mallocs=1) # 1 W_MyTest (obj2)
+ obj, x = fn(obj2)
assert obj is obj2
assert x == 601 # 600 is the class default of W_MyTest.x
def test_subclass_from_cpython():
- import py; py.test.skip("not implemented (see comments in rcpy.py)")
-
def f(input):
current = total = 10
if input:
w = cpy_import(W_MyTest, input)
- current, total = w.stuff
+ current = w.current # or 0 if left uninitialized, as by U()
+ total = w.total # or 0 if left uninitialized, as by U()
w = W_MyTest(21)
current += 1
total += current
- w.stuff = current, total
+ w.current = current
+ w.total = total
return cpy_export(mytest, w), total
fn = compile(f, [object])
- obj, total = fn(None, expected_extra_mallocs=2) # 1 W_MyTest (with 1 tuple)
+ obj, total = fn(None)
assert total == 21
T = type(obj)
class U(T):
@@ -136,11 +137,11 @@
del obj
objlist = [U() for i in range(100)]
- obj, total = fn(obj2, expected_extra_mallocs=204) # 102 W_MyTests alive
+ obj, total = fn(obj2)
assert total == 1
del objlist
- obj, total = fn(obj, expected_extra_mallocs=6) # 3 W_MyTests alive
+ obj, total = fn(obj)
assert total == 3
@@ -151,7 +152,7 @@
return cpy_export(mytest2, w)
fn = compile(f, [])
- obj = fn(expected_extra_mallocs=1)
+ obj = fn()
assert obj.hi == 123
assert type(obj).hi == 123
@@ -164,7 +165,7 @@
return cpy_export(mytest2, w)
fn = compile(f, [])
- obj = fn(expected_extra_mallocs=1)
+ obj = fn()
assert obj.hi == 123
assert type(obj).hi == 123
assert obj.there == "foo"
Modified: pypy/dist/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/refcounting.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/refcounting.py Sat Sep 29 19:31:17 2007
@@ -69,6 +69,8 @@
gcheader.refcount = refcount
def ll_no_pointer_dealloc(adr):
llop.gc_free(lltype.Void, adr)
+ def ll_no_pointer_cpydealloc(adr):
+ llop.cpy_free(lltype.Void, adr)
mh = mallocHelpers()
mh.allocate = lladdress.raw_malloc
@@ -102,6 +104,8 @@
ll_decref_simple, [llmemory.Address], lltype.Void)
self.no_pointer_dealloc_ptr = self.inittime_helper(
ll_no_pointer_dealloc, [llmemory.Address], lltype.Void)
+ self.no_pointer_cpydealloc_ptr = self.inittime_helper(
+ ll_no_pointer_cpydealloc, [llmemory.Address], lltype.Void)
self.malloc_fixedsize_ptr = self.inittime_helper(
ll_malloc_fixedsize, [lltype.Signed], llmemory.Address)
self.malloc_varsize_no_length_ptr = self.inittime_helper(
@@ -195,7 +199,10 @@
if destrptr is None and not find_gc_ptrs_in_type(TYPE):
#print repr(TYPE)[:80], 'is dealloc easy'
- p = self.no_pointer_dealloc_ptr.value
+ if TYPE._gckind == 'cpy':
+ p = self.no_pointer_cpydealloc_ptr.value
+ else:
+ p = self.no_pointer_dealloc_ptr.value
self.static_deallocator_funcptrs[TYPE] = p
return p
@@ -215,19 +222,19 @@
gcheader.refcount = refcount
if refcount == 0:
%s
- llop.gc_free(lltype.Void, addr)
+ llop.%s_free(lltype.Void, addr)
except:
pass
llop.gc_restore_exception(lltype.Void, exc_instance)
pop_alive(exc_instance)
# XXX layering of exceptiontransform versus gcpolicy
-""" % (body, )
+""" % (body, TYPE._gckind)
else:
call_del = None
body = '\n'.join(_static_deallocator_body_for_type('v', TYPE))
src = ('def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' +
- body + '\n llop.gc_free(lltype.Void, addr)\n')
+ body + '\n llop.%s_free(lltype.Void, addr)\n' % (TYPE._gckind,))
d = {'pop_alive': LLTransformerOp(self.pop_alive),
'llop': llop,
'lltype': lltype,
Modified: pypy/dist/pypy/rpython/rcpy.py
==============================================================================
--- pypy/dist/pypy/rpython/rcpy.py (original)
+++ pypy/dist/pypy/rpython/rcpy.py Sat Sep 29 19:31:17 2007
@@ -264,7 +264,7 @@
p[len(name)] = '\x00'
pytypeobj.c_tp_name = lltype.direct_arrayitems(p)
pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO)
- if cpytype.subclassable and False: # XXX deallocation of subclass object segfaults!
+ if cpytype.subclassable:
pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE)''')
else:
@@ -302,13 +302,6 @@
cache[r_inst.classdef] = result
return result
-# To make this a Py_TPFLAGS_BASETYPE, we need to have a tp_new that does
-# something different for subclasses: it needs to allocate a bit more
-# for CPython's GC (see PyObject_GC_Malloc); it needs to Py_INCREF the
-# type if it's a heap type; and it needs to PyObject_GC_Track() the object.
-# Also, tp_dealloc needs to untrack the object.
-
-
# ____________________________________________________________
# Emulation support, to have user-defined classes and instances
# work nicely on top of CPython running the CPyObjSpace
Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py (original)
+++ pypy/dist/pypy/translator/c/funcgen.py Sat Sep 29 19:31:17 2007
@@ -538,7 +538,7 @@
return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype)
def OP_CPY_FREE(self, op):
- return "OP_CPY_FREE(%s)" % (self.expr(op.args[1]),)
+ return "OP_CPY_FREE(%s);" % (self.expr(op.args[0]),)
def OP_DIRECT_FIELDPTR(self, op):
return self.OP_GETFIELD(op, ampersand='&')
Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h (original)
+++ pypy/dist/pypy/translator/c/src/mem.h Sat Sep 29 19:31:17 2007
@@ -115,10 +115,11 @@
#define OP_CPY_MALLOC(cpytype, r, restype) { \
/* XXX add tp_itemsize later */ \
- r = ((PyTypeObject *)cpytype)->tp_alloc((PyTypeObject *)cpytype, 0); \
+ r = (restype)((PyTypeObject *)cpytype)->tp_alloc( \
+ (PyTypeObject *)cpytype, 0); \
if (!r) RPyConvertExceptionFromCPython(); \
}
-#define OP_CPY_FREE(x) XXX "this shouldn't be used any more"
+#define OP_CPY_FREE(x) ((PyObject *)x)->ob_type->tp_free((PyObject *)x)
/************************************************************/
/* weakref support */
More information about the Pypy-commit
mailing list