[WIP] bpo-40601: Add functions to get builtin types by vstinner · Pull Request #24146 · python/cpython · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Include/dictobject.h
38 changes: 24 additions & 14 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,25 @@ struct _ceval_state {
#endif
};

#define _PY_NSMALLPOSINTS 257
#define _PY_NSMALLNEGINTS 5

// _PyLong_GetZero() and _PyLong_GetOne() must always be available
#if _PY_NSMALLPOSINTS < 2
# error "_PY_NSMALLPOSINTS must be greater than 1"
#endif

struct _Py_long_state {
PyTypeObject *type; // borrowed reference
/* Small integers are preallocated in this array so that they
can be shared.
The integers that are preallocated are those in the range
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
*/
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];

};

/* fs_codec.encoding is initialized to NULL.
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
struct _Py_unicode_fs_codec {
Expand All @@ -70,6 +89,8 @@ struct _Py_unicode_ids {
};

struct _Py_unicode_state {
// Borrowed reference
PyTypeObject *type;
// The empty Unicode object is a singleton to improve performance.
PyObject *empty_string;
/* Single character Unicode strings in the Latin-1 range are being
Expand Down Expand Up @@ -125,6 +146,7 @@ struct _Py_tuple_state {
#endif

struct _Py_list_state {
PyTypeObject *type; // borrowed reference
PyListObject *free_list[PyList_MAXFREELIST];
int numfree;
};
Expand All @@ -134,6 +156,7 @@ struct _Py_list_state {
#endif

struct _Py_dict_state {
PyTypeObject *type; // borrowed reference
/* Dictionary reuse scheme to save calls to malloc and free */
PyDictObject *free_list[PyDict_MAXFREELIST];
int numfree;
Expand Down Expand Up @@ -214,14 +237,6 @@ struct type_cache {

/* interpreter state */

#define _PY_NSMALLPOSINTS 257
#define _PY_NSMALLNEGINTS 5

// _PyLong_GetZero() and _PyLong_GetOne() must always be available
#if _PY_NSMALLPOSINTS < 2
# error "_PY_NSMALLPOSINTS must be greater than 1"
#endif

// The PyInterpreterState typedef is in Include/pystate.h.
struct _is {

Expand Down Expand Up @@ -294,12 +309,7 @@ struct _is {

PyObject *audit_hooks;

/* Small integers are preallocated in this array so that they
can be shared.
The integers that are preallocated are those in the range
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
*/
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
struct _Py_long_state long_state;
struct _Py_bytes_state bytes;
struct _Py_unicode_state unicode;
struct _Py_float_state float_state;
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static inline PyObject* __PyLong_GetSmallInt_internal(int value)
#endif
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
size_t index = _PY_NSMALLNEGINTS + value;
PyObject *obj = (PyObject*)tstate->interp->small_ints[index];
PyObject *obj = (PyObject*)tstate->interp->long_state.small_ints[index];
// _PyLong_GetZero() and _PyLong_GetOne() must not be called
// before _PyLong_Init() nor after _PyLong_Fini()
assert(obj != NULL);
Expand Down
3 changes: 2 additions & 1 deletion Include/listobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ PyAPI_DATA(PyTypeObject) PyListRevIter_Type;

#define PyList_Check(op) \
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)
#define PyList_CheckExact(op) Py_IS_TYPE(op, &PyList_Type)
PyAPI_FUNC(int) _PyList_CheckExact(PyObject *op);
#define PyList_CheckExact(op) _PyList_CheckExact(_PyObject_CAST(op))

PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size);
PyAPI_FUNC(Py_ssize_t) PyList_Size(PyObject *);
Expand Down
6 changes: 5 additions & 1 deletion Include/longobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ extern "C" {
typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */

PyAPI_DATA(PyTypeObject) PyLong_Type;
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyTypeObject*) _Py_GetLongType(void);
#endif

#define PyLong_Check(op) \
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS)
#define PyLong_CheckExact(op) Py_IS_TYPE(op, &PyLong_Type)
PyAPI_FUNC(int) _PyLong_CheckExact(PyObject *op);
#define PyLong_CheckExact(op) _PyLong_CheckExact(_PyObject_CAST(op))

PyAPI_FUNC(PyObject *) PyLong_FromLong(long);
PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned long);
Expand Down
6 changes: 5 additions & 1 deletion Include/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,14 @@ extern "C" {

PyAPI_DATA(PyTypeObject) PyUnicode_Type;
PyAPI_DATA(PyTypeObject) PyUnicodeIter_Type;
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyTypeObject*) _Py_GetUnicodeType(void);
#endif

#define PyUnicode_Check(op) \
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS)
#define PyUnicode_CheckExact(op) Py_IS_TYPE(op, &PyUnicode_Type)
PyAPI_FUNC(int) _PyUnicode_CheckExact(PyObject *op);
#define PyUnicode_CheckExact(op) _PyUnicode_CheckExact(_PyObject_CAST(op))

/* --- Constants ---------------------------------------------------------- */

Expand Down
25 changes: 16 additions & 9 deletions Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,13 @@ static PyTypeObject dequereviter_type = {

/* defaultdict type *********************************************************/

static PyTypeObject*
get_dict_type(void)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
return interp->dict_state.type;
}

typedef struct {
PyDictObject dict;
PyObject *default_factory;
Expand Down Expand Up @@ -2086,7 +2093,7 @@ defdict_dealloc(defdictobject *dd)
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(dd);
Py_CLEAR(dd->default_factory);
PyDict_Type.tp_dealloc((PyObject *)dd);
get_dict_type()->tp_dealloc((PyObject *)dd);
}

static PyObject *
Expand All @@ -2095,7 +2102,7 @@ defdict_repr(defdictobject *dd)
PyObject *baserepr;
PyObject *defrepr;
PyObject *result;
baserepr = PyDict_Type.tp_repr((PyObject *)dd);
baserepr = get_dict_type()->tp_repr((PyObject *)dd);
if (baserepr == NULL)
return NULL;
if (dd->default_factory == NULL)
Expand Down Expand Up @@ -2162,14 +2169,14 @@ static int
defdict_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(((defdictobject *)self)->default_factory);
return PyDict_Type.tp_traverse(self, visit, arg);
return get_dict_type()->tp_traverse(self, visit, arg);
}

static int
defdict_tp_clear(defdictobject *dd)
{
Py_CLEAR(dd->default_factory);
return PyDict_Type.tp_clear((PyObject *)dd);
return get_dict_type()->tp_clear((PyObject *)dd);
}

static int
Expand Down Expand Up @@ -2198,7 +2205,7 @@ defdict_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1;
Py_XINCREF(newdefault);
dd->default_factory = newdefault;
result = PyDict_Type.tp_init(self, newargs, kwds);
result = get_dict_type()->tp_init(self, newargs, kwds);
Py_DECREF(newargs);
Py_XDECREF(olddefault);
return result;
Expand Down Expand Up @@ -2250,7 +2257,7 @@ static PyTypeObject defdict_type = {
defdict_methods, /* tp_methods */
defdict_members, /* tp_members */
0, /* tp_getset */
DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
Expand Down Expand Up @@ -2298,9 +2305,9 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping,
* have not been overridden.
*/
mapping_get = _PyType_LookupId(Py_TYPE(mapping), &PyId_get);
dict_get = _PyType_LookupId(&PyDict_Type, &PyId_get);
dict_get = _PyType_LookupId(get_dict_type(), &PyId_get);
mapping_setitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___setitem__);
dict_setitem = _PyType_LookupId(&PyDict_Type, &PyId___setitem__);
dict_setitem = _PyType_LookupId(get_dict_type(), &PyId___setitem__);

if (mapping_get != NULL && mapping_get == dict_get &&
mapping_setitem != NULL && mapping_setitem == dict_setitem &&
Expand Down Expand Up @@ -2575,7 +2582,7 @@ collections_exec(PyObject *module) {
&tuplegetter_type
};

defdict_type.tp_base = &PyDict_Type;
defdict_type.tp_base = get_dict_type();

for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
if (PyModule_AddType(module, typelist[i]) < 0) {
Expand Down
6 changes: 3 additions & 3 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2866,7 +2866,7 @@ PyCData_setstate(PyObject *myself, PyObject *args)
PyObject *dict, *mydict;
CDataObject *self = (CDataObject *)myself;
if (!PyArg_ParseTuple(args, "O!s#",
&PyDict_Type, &dict, &data, &len))
_Py_GetDictType(), &dict, &data, &len))
{
return NULL;
}
Expand Down Expand Up @@ -5701,8 +5701,8 @@ _ctypes_add_types(PyObject *mod)
TYPE_READY(&PyCArg_Type);
TYPE_READY(&PyCThunk_Type);
TYPE_READY(&PyCData_Type);
/* StgDict is derived from PyDict_Type */
TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type);
/* StgDict is derived from dict */
TYPE_READY_BASE(&PyCStgDict_Type, _Py_GetDictType());

/*************************************************
*
Expand Down
4 changes: 2 additions & 2 deletions Modules/_ctypes/stgdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
static int
PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
{
if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
if (_Py_GetDictType()->tp_init((PyObject *)self, args, kwds) < 0)
return -1;
self->format = NULL;
self->ndim = 0;
Expand All @@ -45,7 +45,7 @@ PyCStgDict_dealloc(StgDictObject *self)
PyMem_Free(self->format);
PyMem_Free(self->shape);
PyMem_Free(self->ffi_type_pointer.elements);
PyDict_Type.tp_dealloc((PyObject *)self);
_Py_GetDictType()->tp_dealloc((PyObject *)self);
}

static PyObject *
Expand Down
9 changes: 5 additions & 4 deletions Modules/_decimal/_decimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -5857,13 +5857,14 @@ PyInit__decimal(void)
}

/* Init external C-API functions */
_py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
_py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
_py_long_power = PyLong_Type.tp_as_number->nb_power;
PyTypeObject *long_type = _Py_GetLongType();
_py_long_multiply = long_type->tp_as_number->nb_multiply;
_py_long_floor_divide = long_type->tp_as_number->nb_floor_divide;
_py_long_power = long_type->tp_as_number->nb_power;
_py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type,
"as_integer_ratio"));
ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length"));
ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(long_type, "bit_length"));


/* Init types */
Expand Down
4 changes: 2 additions & 2 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds)
PyObject *attrib = NULL;
ElementObject *self_elem;

if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib))
if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, _Py_GetDictType(), &attrib))
return -1;

if (attrib) {
Expand Down Expand Up @@ -595,7 +595,7 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds)
PyObject* attrib = NULL;
if (!PyArg_ParseTuple(args, "O!O|O!:SubElement",
&Element_Type, &parent, &tag,
&PyDict_Type, &attrib)) {
_Py_GetDictType(), &attrib)) {
return NULL;
}

Expand Down
6 changes: 3 additions & 3 deletions Modules/_json.c
Loading