[pypy-svn] r72761 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test

xoraxax at codespeak.net xoraxax at codespeak.net
Wed Mar 24 22:15:24 CET 2010


Author: xoraxax
Date: Wed Mar 24 22:15:22 2010
New Revision: 72761

Modified:
   pypy/branch/cpython-extension/pypy/module/cpyext/TODO
   pypy/branch/cpython-extension/pypy/module/cpyext/api.py
   pypy/branch/cpython-extension/pypy/module/cpyext/dictobject.py
   pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py
   pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
   pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
Log:
Support non-external functions. These are the ones that would be declared static in the CPython code (yes, not really part of the API but I need them to fill the slots).

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/TODO
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/TODO	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/TODO	Wed Mar 24 22:15:22 2010
@@ -1,7 +1,6 @@
  - Generate header files programmatically.
  - Implement C API.
  - Complete the PyTypeObject initialization code.
- - Free pto.c_tp_name correctly
  - properly support "borrowed" references: the PyObject must be stored
    somewhere
  - lltype.free in PyObject_Del() sometimes raise an exception (but all

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py	Wed Mar 24 22:15:22 2010
@@ -38,6 +38,7 @@
 constant_names = """
 Py_TPFLAGS_READY Py_TPFLAGS_READYING
 METH_COEXIST METH_STATIC METH_CLASS METH_NOARGS
+Py_TPFLAGS_HEAPTYPE
 """.split()
 for name in constant_names:
     setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
@@ -64,7 +65,7 @@
         self.argnames = argnames[1:]
         assert len(self.argnames) == len(self.argtypes)
 
-def cpython_api(argtypes, restype, borrowed=False, error=_NOT_SPECIFIED):
+def cpython_api(argtypes, restype, borrowed=False, error=_NOT_SPECIFIED, external=True):
     if error is _NOT_SPECIFIED:
         if restype is PyObject:
             error = lltype.nullptr(PyObject.TO)
@@ -108,7 +109,9 @@
 
         func.api_func = api_function
         unwrapper.api_func = api_function
-        FUNCTIONS[func.func_name] = api_function
+        unwrapper.func = func
+        if external:
+            FUNCTIONS[func.func_name] = api_function
         INTERPLEVEL_API[func.func_name] = unwrapper
         return unwrapper
     return decorate
@@ -190,7 +193,7 @@
             if space.is_w(w_type, w_obj):
                 pto = py_obj
             else:
-                pto = make_ref(space, w_type, borrowed=True)
+                pto = make_ref(space, w_type)
         elif isinstance(w_obj, W_PyCObject):
             w_type = space.type(w_obj)
             assert isinstance(w_type, W_PyCTypeObject)
@@ -200,7 +203,7 @@
             py_obj = lltype.malloc(T, None, flavor="raw")
         else:
             py_obj = lltype.malloc(PyObject.TO, None, flavor="raw")
-            pto = make_ref(space, space.type(w_obj), borrowed=True)
+            pto = make_ref(space, space.type(w_obj))
         py_obj.c_obj_type = rffi.cast(PyObject, pto)
         py_obj.c_obj_refcnt = 1
         ctypes_obj = ll2ctypes.lltype2ctypes(py_obj)
@@ -304,6 +307,8 @@
     renamed_symbols = []
     if rename:
         for name in export_symbols:
+            if name.startswith("PyPy"):
+                continue
             if "#" in name:
                 deref = "*"
             else:

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/dictobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/dictobject.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/dictobject.py	Wed Mar 24 22:15:22 2010
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import cpython_api, PyObject, CANNOT_FAIL
+from pypy.module.cpyext.api import cpython_api, PyObject, CANNOT_FAIL, \
+    general_check
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 
 @cpython_api([], PyObject)
@@ -9,8 +10,7 @@
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyDict_Check(space, w_obj):
     w_type = space.w_dict
-    w_obj_type = space.type(w_obj)
-    return space.is_w(w_obj_type, w_type) or space.is_true(space.issubtype(w_obj_type, w_type))
+    return general_check(space, w_obj, w_type)
 
 
 @cpython_api([PyObject, rffi.CCHARP, PyObject], rffi.INT_real, error=-1)
@@ -22,4 +22,4 @@
         space.setitem(w_dict, space.wrap(key), w_obj)
         return 0
     else:
-        PyErr_BadInternalCall()
+        PyErr_BadInternalCall(space)

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py	Wed Mar 24 22:15:22 2010
@@ -80,4 +80,4 @@
         assert isinstance(w_mod, Module)
         return w_mod.getdict()
     else:
-        PyErr_BadInternalCall()
+        PyErr_BadInternalCall(space)

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py	Wed Mar 24 22:15:22 2010
@@ -139,6 +139,7 @@
                                self.space.wrap('foo'))
             self.space.delitem(self.space.sys.get('modules'),
                                self.space.wrap('foo'))
+            Py_DECREF(self.space, w_mod)
         except OperationError:
             pass
         self.space.fromcache(State).print_refcounts()
@@ -372,6 +373,8 @@
             Py_InitModule("foo", methods);
         """
         body = """
+        PyObject* PyPy_Crash1(void);
+        long PyPy_Crash2(void);
         static PyObject* foo_crash1(PyObject* self, PyObject *args)
         {
             return PyPy_Crash1();

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py	Wed Mar 24 22:15:22 2010
@@ -12,7 +12,7 @@
 from pypy.module.cpyext.api import cpython_api, cpython_api_c, cpython_struct
 from pypy.module.cpyext.api import PyObject, PyVarObjectFields, Py_ssize_t
 from pypy.module.cpyext.api import Py_TPFLAGS_READYING, Py_TPFLAGS_READY
-from pypy.module.cpyext.api import make_wrapper
+from pypy.module.cpyext.api import make_wrapper, Py_TPFLAGS_HEAPTYPE
 from pypy.interpreter.module import Module
 from pypy.module.cpyext.modsupport import PyMethodDef, convert_method_defs
 from pypy.module.cpyext.state import State
@@ -215,22 +215,57 @@
         w_type = space.type(self)
         assert isinstance(w_type, W_PyCTypeObject)
         pto = w_type.pto
+        print "Called W_PyCObject.__del__"
         generic_cpy_call(space, pto.c_tp_dealloc, self)
 
 
+ at cpython_api([PyObject], lltype.Void, external=False)
+def subtype_dealloc(space, obj):
+    pto = rffi.cast(PyTypeObjectPtr, obj.c_obj_type)
+    assert pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
+    base = pto
+    #basedealloc = pto.c_tp_dealloc
+    # XXX lookup basedealloc which is not subtype_dealloc
+    # XXX call tp_del if necessary
+    # XXX call basedealloc instead of a fixed type_dealloc
+    type_dealloc(space, obj)
+    Py_DECREF(space, pto)
+
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def type_dealloc(space, obj):
+    print "type_dealloc of", obj
+    obj_pto = rffi.cast(PyTypeObjectPtr, obj)
+    type_pto = rffi.cast(PyTypeObjectPtr, obj.c_obj_type)
+    # type_dealloc code follows:
+    # XXX XDECREF tp_base, tp_dict, tp_bases, tp_mro, tp_cache,
+    #             tp_subclasses
+    # free tp_doc
+    lltype.free(obj_pto.c_tp_name, flavor="raw")
+    generic_cpy_call(space, type_pto.c_tp_free, obj)
+
+
 
 def allocate_type_obj(space, w_type):
+    """ Allocates a pto from a w_type which must be a PyPy type. """
     from pypy.module.cpyext.object import PyObject_dealloc, PyObject_Del
+    assert not isinstance(w_type, W_PyCTypeObject)
     pto = lltype.malloc(PyTypeObject, None, flavor="raw")
-    callable = PyObject_dealloc
-    pto.c_tp_dealloc = llhelper(callable.api_func.functype,
-            make_wrapper(space, callable))
+    if space.is_w(w_type, space.w_type):
+        callable = subtype_dealloc
+        pto.c_tp_dealloc = llhelper(callable.api_func.functype,
+                make_wrapper(space, callable))
+    else:
+        callable = PyObject_dealloc
+        pto.c_tp_dealloc = llhelper(callable.api_func.functype,
+                make_wrapper(space, callable))
+    print "Chose dealloc strategy %r for %r" % (callable.func, w_type)
     callable = PyObject_Del
+    pto.c_tp_flags = Py_TPFLAGS_HEAPTYPE
     pto.c_tp_free = llhelper(callable.api_func.functype,
             make_wrapper(space, callable))
-    # XXX free c_tp_name again!
     pto.c_tp_name = rffi.str2charp(w_type.getname(space, "?"))
-    pto.c_tp_basicsize = -1 # hopefully this makes malloc bail
+    pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out
     #  XXX fill slots in pto
     return pto
 



More information about the Pypy-commit mailing list