[pypy-commit] pypy cpyext-avoid-roundtrip: implement _PyObject_New, _PyObject_NewVar and _PyObject_GC_New in C
antocuni
pypy.commits at gmail.com
Sun Oct 8 18:13:15 EDT 2017
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: cpyext-avoid-roundtrip
Changeset: r92666:e5413301904e
Date: 2017-10-09 00:12 +0200
http://bitbucket.org/pypy/pypy/changeset/e5413301904e/
Log: implement _PyObject_New, _PyObject_NewVar and _PyObject_GC_New in C
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -627,6 +627,7 @@
'_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', '_Py_PackageContext',
'_PyTraceMalloc_Track', '_PyTraceMalloc_Untrack', 'PyMem_Malloc',
'Py_IncRef', 'Py_DecRef', 'PyObject_Free', 'PyObject_GC_Del', 'PyType_GenericAlloc',
+ '_PyObject_New', '_PyObject_NewVar', '_PyObject_GC_New',
]
TYPES = {}
FORWARD_DECLS = []
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -342,6 +342,10 @@
#define PyObject_Del PyObject_Free
#define PyObject_DEL PyObject_Free
+PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
+PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
+PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *);
+
/* PyPy internal ----------------------------------- */
PyAPI_FUNC(int) PyPyType_Register(PyTypeObject *);
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -36,24 +36,16 @@
def _PyPy_Free(ptr):
lltype.free(ptr, flavor='raw')
- at cpython_api([PyTypeObjectPtr], PyObject, result_is_ll=True)
-def _PyObject_New(space, type):
- return _PyObject_NewVar(space, type, 0)
+ at c_only([Py_ssize_t], rffi.VOIDP)
+def _PyPy_Malloc(size):
+ # XXX: the malloc inside BaseCpyTypedescr.allocate and
+ # typeobject.type_alloc specify zero=True, so this is why we use it also
+ # here. However, CPython does a simple non-initialized malloc, so we
+ # should investigate whether we can remove zero=True as well
+ return lltype.malloc(rffi.VOIDP.TO, size,
+ flavor='raw', zero=True,
+ add_memory_pressure=True)
-# CCC port to C
- at cpython_api([PyTypeObjectPtr, Py_ssize_t], PyObject, result_is_ll=True)
-def _PyObject_NewVar(space, type, itemcount):
- w_type = from_ref(space, rffi.cast(PyObject, type))
- assert isinstance(w_type, W_TypeObject)
- typedescr = get_typedescr(w_type.layout.typedef)
- py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
- #py_obj.c_ob_refcnt = 0 --- will be set to 1 again by PyObject_Init{Var}
- if type.c_tp_itemsize == 0:
- w_obj = PyObject_Init(space, py_obj, type)
- else:
- py_objvar = rffi.cast(PyVarObject, py_obj)
- w_obj = PyObject_InitVar(space, py_objvar, type, itemcount)
- return py_obj
def _dealloc(space, obj):
# This frees an object after its refcount dropped to zero, so we
@@ -65,10 +57,6 @@
if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
Py_DecRef(space, rffi.cast(PyObject, pto))
- at cpython_api([PyTypeObjectPtr], PyObject, result_is_ll=True)
-def _PyObject_GC_New(space, type):
- return _PyObject_New(space, type)
-
@cpython_api([PyObject], PyObjectP, error=CANNOT_FAIL)
def _PyObject_GetDictPtr(space, op):
return lltype.nullptr(PyObjectP.TO)
@@ -173,6 +161,7 @@
space.delitem(w_obj, w_key)
return 0
+# CCC port to C
@cpython_api([PyObject, PyTypeObjectPtr], PyObject, result_is_ll=True)
def PyObject_Init(space, obj, type):
"""Initialize a newly-allocated object op with its type and initial
@@ -187,6 +176,7 @@
obj.c_ob_refcnt = 1
return obj
+# CCC port to C
@cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject, result_is_ll=True)
def PyObject_InitVar(space, py_obj, type, size):
"""This does everything PyObject_Init() does, and also initializes the
diff --git a/pypy/module/cpyext/src/object.c b/pypy/module/cpyext/src/object.c
--- a/pypy/module/cpyext/src/object.c
+++ b/pypy/module/cpyext/src/object.c
@@ -2,6 +2,9 @@
#include "Python.h"
+extern void _PyPy_Free(void *ptr);
+extern void *_PyPy_Malloc(Py_ssize_t size);
+
void
Py_IncRef(PyObject *o)
{
@@ -36,8 +39,6 @@
Py_DECREF(pto);
}
-extern void _PyPy_Free(void *ptr);
-
void
PyObject_Free(void *obj)
{
@@ -53,5 +54,77 @@
PyObject *
PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
{
- return _PyObject_NewVar(type, nitems);
+ return (PyObject*)_PyObject_NewVar(type, nitems);
}
+
+PyObject *
+_PyObject_New(PyTypeObject *type)
+{
+ return (PyObject*)_PyObject_NewVar(type, 0);
+}
+
+PyObject * _PyObject_GC_New(PyTypeObject *type)
+{
+ return _PyObject_New(type);
+}
+
+
+static PyObject *
+_type_alloc(PyTypeObject *metatype)
+{
+ PyHeapTypeObject *heaptype = (PyHeapTypeObject*)_PyPy_Malloc(sizeof(PyTypeObject));
+ PyTypeObject *pto = &heaptype->ht_type;
+
+ pto->ob_refcnt = 1;
+ pto->ob_pypy_link = 0;
+ pto->ob_type = metatype;
+ pto->tp_flags |= Py_TPFLAGS_HEAPTYPE;
+ pto->tp_as_number = &heaptype->as_number;
+ pto->tp_as_sequence = &heaptype->as_sequence;
+ pto->tp_as_mapping = &heaptype->as_mapping;
+ pto->tp_as_buffer = &heaptype->as_buffer;
+ pto->tp_basicsize = -1; /* hopefully this makes malloc bail out */
+ pto->tp_itemsize = 0;
+ return (PyObject*)heaptype;
+}
+
+static PyObject *
+_generic_alloc(PyTypeObject *type, Py_ssize_t nitems)
+{
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+ Py_INCREF(type);
+
+ Py_ssize_t size = type->tp_basicsize;
+ if (type->tp_itemsize)
+ size += nitems * type->tp_itemsize;
+
+ PyObject *pyobj = (PyObject*)_PyPy_Malloc(size);
+
+ if (type->tp_itemsize)
+ ((PyVarObject*)pyobj)->ob_size = nitems;
+
+ pyobj->ob_refcnt = 1;
+ /* pyobj->ob_pypy_link should get assigned very quickly */
+ pyobj->ob_type = type;
+ return pyobj;
+}
+
+PyVarObject *
+_PyObject_NewVar(PyTypeObject *type, Py_ssize_t nitems)
+{
+ /* Note that this logic is slightly different than the one used by
+ CPython. The plan is to try to follow as closely as possible the
+ current cpyext logic here, and fix it when the migration to C is
+ completed
+ */
+ PyObject *py_obj;
+ if (type == &PyType_Type)
+ py_obj = _type_alloc(type);
+ else
+ py_obj = _generic_alloc(type, nitems);
+
+ if (type->tp_itemsize == 0)
+ return PyObject_Init(py_obj, type);
+ else
+ return PyObject_InitVar((PyVarObject*)py_obj, type, nitems);
+}
More information about the pypy-commit
mailing list