[pypy-svn] r31376 - in pypy/dist/pypy: objspace/cpy objspace/cpy/test rpython
pedronis at codespeak.net
pedronis at codespeak.net
Thu Aug 17 18:11:16 CEST 2006
Author: pedronis
Date: Thu Aug 17 18:11:14 2006
New Revision: 31376
Modified:
pypy/dist/pypy/objspace/cpy/objspace.py
pypy/dist/pypy/objspace/cpy/test/test_typedef.py
pypy/dist/pypy/objspace/cpy/typedef.py
pypy/dist/pypy/rpython/rcpy.py
Log:
(arre, pedronis)
support in the ext-compiler __new__ using allocate_instance. Subclassing doesn't work properly because
deallocation is wrongly done resulting in a segfault for now.
Modified: pypy/dist/pypy/objspace/cpy/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/objspace.py (original)
+++ pypy/dist/pypy/objspace/cpy/objspace.py Thu Aug 17 18:11:14 2006
@@ -8,7 +8,7 @@
from pypy.interpreter.function import Function
from pypy.interpreter.typedef import GetSetProperty
from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong
-from pypy.rpython.objectmodel import we_are_translated
+from pypy.rpython.objectmodel import we_are_translated, instantiate
class CPyObjSpace(baseobjspace.ObjSpace):
@@ -115,6 +115,16 @@
else:
return None
+ def allocate_instance(self, cls, w_subtype):
+ if we_are_translated():
+ from pypy.objspace.cpy.typedef import cpython_allocate
+ obj = cpython_allocate(cls, w_subtype)
+ else:
+ assert self.is_w(self.gettypefor(cls), w_subtype)
+ obj = object.__new__(cls)
+ return self.wrap(obj)
+
+
# __________ operations with a direct CPython equivalent __________
getattr = staticmethod(PyObject_GetAttr)
Modified: pypy/dist/pypy/objspace/cpy/test/test_typedef.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/test/test_typedef.py (original)
+++ pypy/dist/pypy/objspace/cpy/test/test_typedef.py Thu Aug 17 18:11:14 2006
@@ -292,6 +292,67 @@
assert type(res).__name__ == 'MyType'
assert res.x == 42
+def test_with_new_with_allocate_instance():
+ def mytype_new(space, w_subtype, x):
+ w_obj = space.allocate_instance(W_MyType, w_subtype)
+ W_MyType.__init__(space.interp_w(W_MyType, w_obj), space, x)
+ return w_obj
+ mytype_new.unwrap_spec = [ObjSpace, W_Root, int]
+
+ W_MyType.typedef = TypeDef("MyType",
+ __new__ = interp2app(mytype_new),
+ x = interp_attrproperty("x", W_MyType))
+ space = CPyObjSpace()
+
+ def build():
+ w_type = space.gettypefor(W_MyType)
+ return space.call_function(w_type, space.wrap(42))
+
+ w_obj = build()
+ w_name = space.getattr(space.type(w_obj), space.wrap('__name__'))
+ assert space.unwrap(w_name) == 'MyType'
+ assert space.int_w(space.getattr(w_obj, space.wrap('x'))) == 42
+
+ fn = compile(build, [],
+ annotatorpolicy = CPyAnnotatorPolicy(space))
+ res = fn(expected_extra_mallocs=1)
+ assert type(res).__name__ == 'MyType'
+ assert res.x == 42
+
+def test_with_new_with_allocate_instance_subclass():
+ py.test.skip("dealloction for now segfaults")
+ def mytype_new(space, w_subtype, x):
+ w_obj = space.allocate_instance(W_MyType, w_subtype)
+ W_MyType.__init__(space.interp_w(W_MyType, w_obj), space, x)
+ return w_obj
+ mytype_new.unwrap_spec = [ObjSpace, W_Root, int]
+
+ W_MyType.typedef = TypeDef("MyType",
+ __new__ = interp2app(mytype_new),
+ x = interp_attrproperty("x", W_MyType))
+ space = CPyObjSpace()
+
+ def build():
+ w_type = space.gettypefor(W_MyType)
+ return space.call_function(w_type, space.wrap(42))
+
+ fn = compile(build, [],
+ annotatorpolicy = CPyAnnotatorPolicy(space))
+ res = fn(expected_extra_mallocs=1)
+ assert type(res).__name__ == 'MyType'
+ assert res.x == 42
+
+ class MyType2(type(res)):
+ pass
+
+ res2 = MyType2(42)
+ assert type(res2) is MyType2
+ assert res2.x == 42
+
+ del res2
+ import gc
+ gc.collect()
+
def test_prebuilt_type():
def mytype_new(space, w_subtype, x):
return space.wrap(W_MyType(space, x))
Modified: pypy/dist/pypy/objspace/cpy/typedef.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/typedef.py (original)
+++ pypy/dist/pypy/objspace/cpy/typedef.py Thu Aug 17 18:11:14 2006
@@ -10,7 +10,7 @@
from pypy.interpreter.typedef import GetSetProperty
from pypy.rpython.objectmodel import we_are_translated
from pypy.rpython.rcpy import CPyTypeInterface, cpy_export, cpy_import
-from pypy.rpython.rcpy import cpy_typeobject, rpython_object
+from pypy.rpython.rcpy import cpy_typeobject, rpython_object, cpy_allocate
from pypy.rpython.rcpy import init_rpython_data, get_rpython_data
from pypy.rpython.lltypesystem import lltype
@@ -76,6 +76,11 @@
cpython2rpython._annspecialcase_ = 'specialize:arg(1)'
cpython2rpython.allow_someobjects = True
+def cpython_allocate(cls, w_subtype):
+ return cpy_allocate(cls, w_subtype.value)
+cpython_allocate._annspecialcase_ = 'specialize:arg(0)'
+cpython_allocate.allow_someobjects = True
+
# ____________________________________________________________
class TypeDefCache(SpaceCache):
@@ -97,7 +102,7 @@
# typedef.name, name))
w_value = space.wrap(value)
objects[name] = lltype.pyobjectptr(w_value.value)
- typeintf = CPyTypeInterface(typedef.name, objects)
+ typeintf = CPyTypeInterface(typedef.name, objects, typedef.acceptable_as_base_class)
return typeintf
def wraptypeintf(cache, cls, typeintf):
Modified: pypy/dist/pypy/rpython/rcpy.py
==============================================================================
--- pypy/dist/pypy/rpython/rcpy.py (original)
+++ pypy/dist/pypy/rpython/rcpy.py Thu Aug 17 18:11:14 2006
@@ -8,7 +8,7 @@
class CPyTypeInterface(object):
- def __init__(self, name, objects={}):
+ def __init__(self, name, objects={}, subclassable=False):
# the exported name of the type
self.name = name
@@ -16,6 +16,7 @@
# a dict {name: pyobjectptr()} for general class attributes
# (not for special methods!)
self.objects = objects.copy()
+ self.subclassable = subclassable
def _freeze_(self):
return True
@@ -41,6 +42,9 @@
def cpy_typeobject(cpytype, cls):
raise NotImplementedError("only works in translated versions")
+def cpy_allocate(cls, cpytype):
+ raise NotImplementedError("only works in translated versions")
+
# ____________________________________________________________
# Implementation
@@ -115,6 +119,26 @@
cpytype = build_pytypeobject(r_inst)
return hop.inputconst(PyObjPtr, cpytype)
+class Entry(ExtRegistryEntry):
+ _about_ = cpy_allocate
+
+ def compute_result_annotation(self, s_cls, s_cpytype):
+ from pypy.annotation.model import SomeObject, SomeInstance
+ assert s_cls.is_constant()
+ [classdesc] = s_cls.descriptions
+ classdef = classdesc.getuniqueclassdef()
+ return SomeInstance(classdef)
+
+ def specialize_call(self, hop):
+ from pypy.rpython.rclass import getinstancerepr
+ s_cls = hop.args_s[0]
+ assert s_cls.is_constant()
+ [classdesc] = s_cls.descriptions
+ classdef = classdesc.getuniqueclassdef()
+ r_inst = getinstancerepr(hop.rtyper, classdef)
+ vinst = r_inst.new_instance(hop.llops, v_cpytype = hop.args_v[1])
+ return vinst
+
def attach_cpy_flavor(classdef, cpytype):
for parentdef in classdef.getmro():
@@ -218,6 +242,7 @@
from pypy.rpython.rtyper import LowLevelOpList
typetype = lltype.pyobjectptr(type)
+ # XXX default tp_new should go away
# make the graph of tp_new manually
v1 = Variable('tp'); v1.concretetype = lltype.Ptr(PY_TYPE_OBJECT)
v2 = Variable('args'); v2.concretetype = PyObjPtr
@@ -242,8 +267,12 @@
p[len(name)] = '\x00'
pytypeobj.c_tp_name = lltype.direct_arrayitems(p)
pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO)
- pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT |
- Py_TPFLAGS_CHECKTYPES)''')
+ if cpytype.subclassablei and False: # XXX deallocation of subclass object segfaults!
+ pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE)''')
+ else:
+ pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_CHECKTYPES)''')
pytypeobj.c_tp_new = rtyper.type_system.getcallable(tp_new_graph)
pytypeobj.c_tp_dealloc = rtyper.annotate_helper_fn(ll_tp_dealloc,
[PyObjPtr])
More information about the Pypy-commit
mailing list