[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