From ae7f4eada22c33fc346570367fe6f80ae90c3394 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Jan 2021 14:10:02 +0100 Subject: [PATCH] Add functions to get builtin types * Add _Py_GetDictType(): add _Py_dict_state.type * Add _Py_GetListType(): add _Py_list_stae.type * Add _Py_GetUnicodeType(): add _Py_unicode_state.type * Add _Py_GetLongType(): add _Py_long_state.type --- Include/dictobject.h | 6 ++- Include/internal/pycore_interp.h | 38 ++++++++++------- Include/internal/pycore_long.h | 2 +- Include/listobject.h | 3 +- Include/longobject.h | 6 ++- Include/unicodeobject.h | 6 ++- Modules/_collectionsmodule.c | 25 +++++++---- Modules/_ctypes/_ctypes.c | 6 +-- Modules/_ctypes/stgdict.c | 4 +- Modules/_decimal/_decimal.c | 9 ++-- Modules/_elementtree.c | 4 +- Modules/_json.c | 6 +-- Modules/_pickle.c | 29 ++++++------- Modules/_sqlite/connection.c | 7 ++-- Modules/_sqlite/cursor.c | 2 +- Modules/_sqlite/module.c | 4 +- Modules/_testcapimodule.c | 25 +++++------ Modules/_testmultiphase.c | 2 +- Modules/cjkcodecs/multibytecodec.c | 2 +- Modules/socketmodule.c | 5 ++- Modules/xxlimited.c | 2 +- Modules/xxlimited_35.c | 2 +- Modules/xxmodule.c | 2 +- Modules/xxsubtype.c | 6 +-- Objects/boolobject.c | 8 ++-- Objects/dictobject.c | 28 ++++++++++--- Objects/floatobject.c | 2 +- Objects/listobject.c | 24 +++++++---- Objects/longobject.c | 66 ++++++++++++++++++++++-------- Objects/object.c | 2 + Objects/odictobject.c | 19 ++++++--- Objects/typeobject.c | 10 ++--- Objects/unicodeobject.c | 37 +++++++++++++---- Python/bltinmodule.c | 6 +-- Python/compile.c | 4 +- Python/pylifecycle.c | 6 +++ Python/pystate.c | 4 +- 37 files changed, 272 insertions(+), 147 deletions(-) diff --git a/Include/dictobject.h b/Include/dictobject.h index da5a36ba07f32e..12ec5d2dc1ce77 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -13,10 +13,14 @@ extern "C" { */ PyAPI_DATA(PyTypeObject) PyDict_Type; +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyTypeObject*) _Py_GetDictType(void); +#endif #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) -#define PyDict_CheckExact(op) Py_IS_TYPE(op, &PyDict_Type) +PyAPI_FUNC(int) _PyDict_CheckExact(PyObject *op); +#define PyDict_CheckExact(op) _PyDict_CheckExact(_PyObject_CAST(op)) PyAPI_FUNC(PyObject *) PyDict_New(void); PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 58b1126712646d..a807be5bf63012 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -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 { @@ -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 @@ -125,6 +146,7 @@ struct _Py_tuple_state { #endif struct _Py_list_state { + PyTypeObject *type; // borrowed reference PyListObject *free_list[PyList_MAXFREELIST]; int numfree; }; @@ -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; @@ -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 { @@ -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; diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index ec95786531c850..7f013d94a6659a 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -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); diff --git a/Include/listobject.h b/Include/listobject.h index 2a8a25525d1d7b..07aa8393a06b66 100644 --- a/Include/listobject.h +++ b/Include/listobject.h @@ -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 *); diff --git a/Include/longobject.h b/Include/longobject.h index e2301d7abfcccf..2ee08dacc3db84 100644 --- a/Include/longobject.h +++ b/Include/longobject.h @@ -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); diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index b0ac086a6be23d..d418c507de84d2 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -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 ---------------------------------------------------------- */ diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 90bafb0ea86d92..d63433839d5284 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -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; @@ -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 * @@ -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) @@ -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 @@ -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; @@ -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 */ @@ -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 && @@ -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) { diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 5f8a723f6373ae..b3e811c2b79047 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -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; } @@ -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()); /************************************************* * diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 747339dee352eb..dc430bdaf74f83 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -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; @@ -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 * diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 9c85d76c6b5b8a..6320c3e16942d9 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -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 */ diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 85fdfa7e5ed42c..f7ff89da16e9a7 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -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) { @@ -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; } diff --git a/Modules/_json.c b/Modules/_json.c index faa3944eedd74c..93dd403c15c7d0 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -981,7 +981,7 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ if (is_float && s->parse_float != (PyObject *)&PyFloat_Type) custom_func = s->parse_float; - else if (!is_float && s->parse_int != (PyObject *) &PyLong_Type) + else if (!is_float && s->parse_int != (PyObject *)_Py_GetLongType()) custom_func = s->parse_int; else custom_func = NULL; @@ -1414,7 +1414,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, return _steal_accumulate(acc, encoded); } else if (PyLong_Check(obj)) { - PyObject *encoded = PyLong_Type.tp_repr(obj); + PyObject *encoded = _Py_GetLongType()->tp_repr(obj); if (encoded == NULL) return -1; return _steal_accumulate(acc, encoded); @@ -1578,7 +1578,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, goto bail; } else if (PyLong_Check(key)) { - kstr = PyLong_Type.tp_repr(key); + kstr = _Py_GetLongType()->tp_repr(key); if (kstr == NULL) { goto bail; } diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 5a8aad9de7679d..671784a491363c 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4273,8 +4273,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save) return status; } - type = Py_TYPE(obj); - /* The old cPickle had an optimization that used switch-case statement dispatching on the first letter of the type name. This has was removed since benchmarks shown that this optimization was actually slowing @@ -4285,13 +4283,13 @@ save(PicklerObject *self, PyObject *obj, int pers_save) if (obj == Py_None) { return save_none(self, obj); } - else if (obj == Py_False || obj == Py_True) { + else if (PyBool_Check(obj)) { return save_bool(self, obj); } - else if (type == &PyLong_Type) { + else if (PyLong_CheckExact(obj)) { return save_long(self, obj); } - else if (type == &PyFloat_Type) { + else if (PyFloat_CheckExact(obj)) { return save_float(self, obj); } @@ -4302,10 +4300,10 @@ save(PicklerObject *self, PyObject *obj, int pers_save) return memo_get(self, obj); } - if (type == &PyBytes_Type) { + if (PyBytes_CheckExact(obj)) { return save_bytes(self, obj); } - else if (type == &PyUnicode_Type) { + else if (PyUnicode_CheckExact(obj)) { return save_unicode(self, obj); } @@ -4315,7 +4313,8 @@ save(PicklerObject *self, PyObject *obj, int pers_save) return -1; } - if (type == &PyDict_Type) { + type = Py_TYPE(obj); + if (PyDict_CheckExact(obj)) { status = save_dict(self, obj); goto done; } @@ -4323,19 +4322,19 @@ save(PicklerObject *self, PyObject *obj, int pers_save) status = save_set(self, obj); goto done; } - else if (type == &PyFrozenSet_Type) { + else if (PyFrozenSet_CheckExact(obj)) { status = save_frozenset(self, obj); goto done; } - else if (type == &PyList_Type) { + else if (PyList_CheckExact(obj)) { status = save_list(self, obj); goto done; } - else if (type == &PyTuple_Type) { + else if (PyTuple_CheckExact(obj)) { status = save_tuple(self, obj); goto done; } - else if (type == &PyByteArray_Type) { + else if (PyByteArray_CheckExact(obj)) { status = save_bytearray(self, obj); goto done; } @@ -4869,8 +4868,7 @@ _pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self) return NULL; } PyTuple_SET_ITEM(dict_args, 0, contents); - Py_INCREF((PyObject *)&PyDict_Type); - PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type); + PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef((PyObject *)_Py_GetDictType())); PyTuple_SET_ITEM(reduce_value, 1, dict_args); return reduce_value; } @@ -7381,8 +7379,7 @@ _pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self) return NULL; } PyTuple_SET_ITEM(constructor_args, 0, contents); - Py_INCREF((PyObject *)&PyDict_Type); - PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type); + PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef((PyObject *)_Py_GetDictType())); PyTuple_SET_ITEM(reduce_value, 1, constructor_args); return reduce_value; } diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 1e23daca445582..37ad951f139cfc 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -98,8 +98,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject Py_INCREF(Py_None); Py_XSETREF(self->row_factory, Py_None); - Py_INCREF(&PyUnicode_Type); - Py_XSETREF(self->text_factory, (PyObject*)&PyUnicode_Type); + Py_XSETREF(self->text_factory, Py_NewRef((PyObject*)_Py_GetUnicodeType())); #ifdef SQLITE_OPEN_URI Py_BEGIN_ALLOW_THREADS @@ -1259,7 +1258,7 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso } uppercase_level = _PyObject_CallMethodIdOneArg( - (PyObject *)&PyUnicode_Type, &PyId_upper, + (PyObject *)_Py_GetUnicodeType(), &PyId_upper, isolation_level); if (!uppercase_level) { return -1; @@ -1751,7 +1750,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self, goto finally; } - uppercase_name = _PyObject_CallMethodIdOneArg((PyObject *)&PyUnicode_Type, + uppercase_name = _PyObject_CallMethodIdOneArg((PyObject *)_Py_GetUnicodeType(), &PyId_upper, name); if (!uppercase_name) { goto finally; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 13385f6d5005c9..2148f40128a97e 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -292,7 +292,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) } else if (coltype == SQLITE_TEXT) { val_str = (const char*)sqlite3_column_text(self->statement->st, i); nbytes = sqlite3_column_bytes(self->statement->st, i); - if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) { + if (self->connection->text_factory == (PyObject*)_Py_GetUnicodeType()) { converted = PyUnicode_FromStringAndSize(val_str, nbytes); if (!converted && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { PyErr_Clear(); diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index cd2eb576c7b214..bbf8f044c45c4b 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -172,8 +172,8 @@ pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, /* a basic type is adapted; there's a performance optimization if that's not the case * (99 % of all usages) */ - if (type == &PyLong_Type || type == &PyFloat_Type - || type == &PyUnicode_Type || type == &PyByteArray_Type) { + if (type == _Py_GetLongType() || type == &PyFloat_Type + || type == _Py_GetUnicodeType() || type == &PyByteArray_Type) { pysqlite_BaseTypeAdapted = 1; } diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 4f97927fa23229..1f0ed7339b8f56 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1021,43 +1021,44 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { - newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); - if (PyLong_Type.tp_new != tp_new) { + PyTypeObject *long_type = _Py_GetLongType(); + newfunc tp_new = PyType_GetSlot(long_type, Py_tp_new); + if (long_type->tp_new != tp_new) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_new of long"); return NULL; } - reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); - if (PyLong_Type.tp_repr != tp_repr) { + reprfunc tp_repr = PyType_GetSlot(long_type, Py_tp_repr); + if (long_type->tp_repr != tp_repr) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_repr of long"); return NULL; } - ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call); + ternaryfunc tp_call = PyType_GetSlot(long_type, Py_tp_call); if (tp_call != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_call of long"); return NULL; } - binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add); - if (PyLong_Type.tp_as_number->nb_add != nb_add) { + binaryfunc nb_add = PyType_GetSlot(long_type, Py_nb_add); + if (long_type->tp_as_number->nb_add != nb_add) { PyErr_SetString(PyExc_AssertionError, "mismatch: nb_add of long"); return NULL; } - lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length); + lenfunc mp_length = PyType_GetSlot(long_type, Py_mp_length); if (mp_length != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: mp_length of long"); return NULL; } - void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); + void *over_value = PyType_GetSlot(long_type, Py_bf_releasebuffer + 1); if (over_value != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: max+1 of long"); return NULL; } - tp_new = PyType_GetSlot(&PyLong_Type, 0); + tp_new = PyType_GetSlot(long_type, 0); if (tp_new != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: slot 0 of long"); return NULL; @@ -5090,7 +5091,7 @@ dict_get_version(PyObject *self, PyObject *args) PyDictObject *dict; uint64_t version; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict)) + if (!PyArg_ParseTuple(args, "O!", _Py_GetDictType(), &dict)) return NULL; version = dict->ma_version_tag; @@ -5591,7 +5592,7 @@ meth_fastcall_keywords(PyObject* self, PyObject* const* args, if (pyargs == NULL) { return NULL; } - PyObject *pykwargs = PyObject_Vectorcall((PyObject*)&PyDict_Type, + PyObject *pykwargs = PyObject_Vectorcall((PyObject*)_Py_GetDictType(), args + nargs, 0, kwargs); return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs); } diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index ad60f32f7e7a62..4efba1357e5535 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -357,7 +357,7 @@ static int execfunc(PyObject *m) /* Due to cross platform compiler issues the slots must be filled * here. It's required for portability to Windows without requiring * C++. */ - Str_Type_slots[0].pfunc = &PyUnicode_Type; + Str_Type_slots[0].pfunc = _Py_GetUnicodeType(); /* Add a custom type */ temp = PyType_FromSpec(&Example_Type_spec); diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index 9208b86b0c9055..310eb86a59cfd1 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1250,7 +1250,7 @@ _multibytecodec_MultibyteIncrementalDecoder_setstate_impl(MultibyteIncrementalDe unsigned char statebytes[8]; if (!PyArg_ParseTuple(state, "SO!;setstate(): illegal state argument", - &buffer, &PyLong_Type, &statelong)) + &buffer, _Py_GetLongType(), &statelong)) { return NULL; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c686286d779dcc..ac33a10d76dda3 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4656,11 +4656,12 @@ sock_sendmsg_afalg(PySocketSockObject *self, PyObject *args, PyObject *kwds) return NULL; } + PyTypeObject *long_type = _Py_GetLongType(); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O$O!y*O!i:sendmsg_afalg", keywords, &data_arg, - &PyLong_Type, &opobj, &iv, - &PyLong_Type, &assoclenobj, &flags)) { + long_type, &opobj, &iv, + long_type, &assoclenobj, &flags)) { return NULL; } diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 883c8a9b5e1833..0055f52bc56b4b 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -318,7 +318,7 @@ xx_modexec(PyObject *m) // It does not inherit from "object" (PyObject_Type), but from "str" // (PyUnincode_Type). PyObject *Str_Type = PyType_FromModuleAndSpec( - m, &Str_Type_spec, (PyObject *)&PyUnicode_Type); + m, &Str_Type_spec, (PyObject *)_Py_GetUnicodeType()); if (Str_Type == NULL) { return -1; } diff --git a/Modules/xxlimited_35.c b/Modules/xxlimited_35.c index ce96e8c90efd47..1ff4a91b5f1e10 100644 --- a/Modules/xxlimited_35.c +++ b/Modules/xxlimited_35.c @@ -236,7 +236,7 @@ xx_modexec(PyObject *m) * C++. */ Null_Type_slots[0].pfunc = &PyBaseObject_Type; Null_Type_slots[1].pfunc = PyType_GenericNew; - Str_Type_slots[0].pfunc = &PyUnicode_Type; + Str_Type_slots[0].pfunc = _Py_GetUnicodeType(); Xxo_Type = PyType_FromSpec(&Xxo_Type_spec); if (Xxo_Type == NULL) diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c index edcd62157c02f3..e8f7abd95a11c3 100644 --- a/Modules/xxmodule.c +++ b/Modules/xxmodule.c @@ -354,7 +354,7 @@ xx_exec(PyObject *m) behavior. */ Null_Type.tp_base = &PyBaseObject_Type; - Str_Type.tp_base = &PyUnicode_Type; + Str_Type.tp_base = _Py_GetUnicodeType(); /* Finalize the type object including setting type of the new type * object; doing it here is required for portability, too. */ diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c index 7200337724e080..993e9312a105fc 100644 --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -179,7 +179,7 @@ static PyMethodDef spamdict_methods[] = { static int spamdict_init(spamdictobject *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->state = 0; return 0; @@ -222,7 +222,7 @@ static PyTypeObject spamdict_type = { spamdict_methods, /* tp_methods */ spamdict_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 */ @@ -264,7 +264,7 @@ xxsubtype_exec(PyObject* m) PyType_Ready() is called. Note that PyType_Ready() automatically initializes the ob.ob_type field to &PyType_Type if it's NULL, so it's not necessary to fill in ob_type first. */ - spamdict_type.tp_base = &PyDict_Type; + spamdict_type.tp_base = _Py_GetDictType(); if (PyType_Ready(&spamdict_type) < 0) return -1; diff --git a/Objects/boolobject.c b/Objects/boolobject.c index b786966533e1d6..0885e45179042d 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -85,7 +85,7 @@ static PyObject * bool_and(PyObject *a, PyObject *b) { if (!PyBool_Check(a) || !PyBool_Check(b)) - return PyLong_Type.tp_as_number->nb_and(a, b); + return _Py_GetLongType()->tp_as_number->nb_and(a, b); return PyBool_FromLong((a == Py_True) & (b == Py_True)); } @@ -93,7 +93,7 @@ static PyObject * bool_or(PyObject *a, PyObject *b) { if (!PyBool_Check(a) || !PyBool_Check(b)) - return PyLong_Type.tp_as_number->nb_or(a, b); + return _Py_GetLongType()->tp_as_number->nb_or(a, b); return PyBool_FromLong((a == Py_True) | (b == Py_True)); } @@ -101,7 +101,7 @@ static PyObject * bool_xor(PyObject *a, PyObject *b) { if (!PyBool_Check(a) || !PyBool_Check(b)) - return PyLong_Type.tp_as_number->nb_xor(a, b); + return _Py_GetLongType()->tp_as_number->nb_xor(a, b); return PyBool_FromLong((a == Py_True) ^ (b == Py_True)); } @@ -186,7 +186,7 @@ PyTypeObject PyBool_Type = { 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - &PyLong_Type, /* tp_base */ + 0, /* _PyTypes_Init() sets it to &PyLong_Type: tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 35e881fe272308..23c62cbb5c8799 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -259,6 +259,22 @@ get_dict_state(void) } +PyTypeObject* +_Py_GetDictType(void) +{ + struct _Py_dict_state *state = get_dict_state(); + return state->type; +} + + +int +_PyDict_CheckExact(PyObject *op) +{ + struct _Py_dict_state *state = get_dict_state(); + return Py_IS_TYPE(op, state->type); +} + + void _PyDict_ClearFreeList(PyThreadState *tstate) { @@ -656,11 +672,11 @@ new_dict(PyDictKeysObject *keys, PyObject **values) if (state->numfree) { mp = state->free_list[--state->numfree]; assert (mp != NULL); - assert (Py_IS_TYPE(mp, &PyDict_Type)); + assert (Py_IS_TYPE(mp, state->type)); _Py_NewReference((PyObject *)mp); } else { - mp = PyObject_GC_New(PyDictObject, &PyDict_Type); + mp = PyObject_GC_New(PyDictObject, state->type); if (mp == NULL) { dictkeys_decref(keys); if (values != empty_values) { @@ -2107,7 +2123,7 @@ dict_dealloc(PyDictObject *mp) // new_dict() must not be called after _PyDict_Fini() assert(state->numfree != -1); #endif - if (state->numfree < PyDict_MAXFREELIST && Py_IS_TYPE(mp, &PyDict_Type)) { + if (state->numfree < PyDict_MAXFREELIST && Py_IS_TYPE(mp, state->type)) { state->free_list[state->numfree++] = mp; } else { @@ -2797,7 +2813,8 @@ PyDict_Copy(PyObject *o) newvalues = new_values(size); if (newvalues == NULL) return PyErr_NoMemory(); - split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type); + struct _Py_dict_state *state = get_dict_state(); + split_copy = PyObject_GC_New(PyDictObject, state->type); if (split_copy == NULL) { free_values(newvalues); return NULL; @@ -3487,7 +3504,8 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) d = (PyDictObject *)self; /* The object has been implicitly tracked by tp_alloc */ - if (type == &PyDict_Type) { + struct _Py_dict_state *state = get_dict_state(); + if (type == state->type) { _PyObject_GC_UNTRACK(d); } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 34fb57a946afa5..92e617a8bd195a 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1542,7 +1542,7 @@ float_as_integer_ratio_impl(PyObject *self) PyObject *numerator = NULL; PyObject *denominator = NULL; PyObject *result_pair = NULL; - PyNumberMethods *long_methods = PyLong_Type.tp_as_number; + PyNumberMethods *long_methods = _Py_GetLongType()->tp_as_number; CONVERT_TO_DOUBLE(self, self_double); diff --git a/Objects/listobject.c b/Objects/listobject.c index ca9df599a0bd44..583e326f8e24f4 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -28,6 +28,14 @@ get_list_state(void) } +int +_PyList_CheckExact(PyObject *op) +{ + struct _Py_list_state *state = get_list_state(); + return Py_IS_TYPE(op, state->type); +} + + /* Ensure ob_item has room for at least newsize elements, and set * ob_size to newsize. If newsize > ob_size on entry, the content * of the new slots at exit is undefined heap trash; it's the caller's @@ -2064,8 +2072,8 @@ unsafe_latin_compare(PyObject *v, PyObject *w, MergeState *ms) int res; /* Modified from Objects/unicodeobject.c:unicode_compare, assuming: */ - assert(Py_IS_TYPE(v, &PyUnicode_Type)); - assert(Py_IS_TYPE(w, &PyUnicode_Type)); + assert(PyUnicode_CheckExact(v)); + assert(PyUnicode_CheckExact(w)); assert(PyUnicode_KIND(v) == PyUnicode_KIND(w)); assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND); @@ -2087,8 +2095,8 @@ unsafe_long_compare(PyObject *v, PyObject *w, MergeState *ms) PyLongObject *vl, *wl; sdigit v0, w0; int res; /* Modified from Objects/longobject.c:long_compare, assuming: */ - assert(Py_IS_TYPE(v, &PyLong_Type)); - assert(Py_IS_TYPE(w, &PyLong_Type)); + assert(PyLong_CheckExact(v)); + assert(PyLong_CheckExact(w)); assert(Py_ABS(Py_SIZE(v)) <= 1); assert(Py_ABS(Py_SIZE(w)) <= 1); @@ -2297,13 +2305,13 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) } if (keys_are_all_same_type) { - if (key_type == &PyLong_Type && + if (PyLong_CheckExact(key_type) && ints_are_bounded && Py_ABS(Py_SIZE(key)) > 1) { ints_are_bounded = 0; } - else if (key_type == &PyUnicode_Type && + else if (key_type == _Py_GetUnicodeType() && strings_are_latin && PyUnicode_KIND(key) != PyUnicode_1BYTE_KIND) { @@ -2315,10 +2323,10 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) /* Choose the best compare, given what we now know about the keys. */ if (keys_are_all_same_type) { - if (key_type == &PyUnicode_Type && strings_are_latin) { + if (key_type == _Py_GetUnicodeType() && strings_are_latin) { ms.key_compare = unsafe_latin_compare; } - else if (key_type == &PyLong_Type && ints_are_bounded) { + else if (PyLong_CheckExact(key_type) && ints_are_bounded) { ms.key_compare = unsafe_long_compare; } else if (key_type == &PyFloat_Type) { diff --git a/Objects/longobject.c b/Objects/longobject.c index 240e92a41e0ec0..55a1760abe60fc 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -26,6 +26,31 @@ class int "PyObject *" "&PyLong_Type" _Py_IDENTIFIER(little); _Py_IDENTIFIER(big); + +static struct _Py_long_state * +get_long_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->long_state; +} + + +PyTypeObject* +_Py_GetLongType(void) +{ + struct _Py_long_state *state = get_long_state(); + return state->type; +} + + +int +_PyLong_CheckExact(PyObject *op) +{ + struct _Py_long_state *state = get_long_state(); + return Py_IS_TYPE(op, state->type); +} + + /* convert a PyLong of size 1, 0 or -1 to an sdigit */ #define MEDIUM_VALUE(x) (assert(-1 <= Py_SIZE(x) && Py_SIZE(x) <= 1), \ Py_SIZE(x) < 0 ? -(sdigit)(x)->ob_digit[0] : \ @@ -120,7 +145,6 @@ long_normalize(PyLongObject *v) PyLongObject * _PyLong_New(Py_ssize_t size) { - PyLongObject *result; /* Number of bytes needed is: offsetof(PyLongObject, ob_digit) + sizeof(digit)*size. Previous incarnations of this code used sizeof(PyVarObject) instead of the offsetof, but this risks being @@ -131,13 +155,15 @@ _PyLong_New(Py_ssize_t size) "too many digits in integer"); return NULL; } - result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) + - size*sizeof(digit)); + + PyLongObject *result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) + + size * sizeof(digit)); if (!result) { PyErr_NoMemory(); return NULL; } - _PyObject_InitVar((PyVarObject*)result, &PyLong_Type, size); + struct _Py_long_state *state = get_long_state(); + _PyObject_InitVar((PyVarObject*)result, state->type, size); return result; } @@ -4917,7 +4943,8 @@ long_float(PyObject *v) } static PyObject * -long_subtype_new(PyTypeObject *type, PyObject *x, PyObject *obase); +long_subtype_new(struct _Py_long_state *state, PyTypeObject *type, + PyObject *x, PyObject *obase); /*[clinic input] @classmethod @@ -4931,10 +4958,11 @@ static PyObject * long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase) /*[clinic end generated code: output=e47cfe777ab0f24c input=81c98f418af9eb6f]*/ { - Py_ssize_t base; + struct _Py_long_state *state = get_long_state(); + if (type != state->type) { + return long_subtype_new(state, type, x, obase); /* Wimp out */ + } - if (type != &PyLong_Type) - return long_subtype_new(type, x, obase); /* Wimp out */ if (x == NULL) { if (obase != NULL) { PyErr_SetString(PyExc_TypeError, @@ -4943,10 +4971,12 @@ long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase) } return PyLong_FromLong(0L); } - if (obase == NULL) + + if (obase == NULL) { return PyNumber_Long(x); + } - base = PyNumber_AsSsize_t(obase, NULL); + Py_ssize_t base = PyNumber_AsSsize_t(obase, NULL); if (base == -1 && PyErr_Occurred()) return NULL; if ((base != 0 && base < 2) || base > 36) { @@ -4978,13 +5008,14 @@ long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase) the regular int. The regular int is then thrown away. */ static PyObject * -long_subtype_new(PyTypeObject *type, PyObject *x, PyObject *obase) +long_subtype_new(struct _Py_long_state *state, PyTypeObject *type, + PyObject *x, PyObject *obase) { PyLongObject *tmp, *newobj; Py_ssize_t i, n; - assert(PyType_IsSubtype(type, &PyLong_Type)); - tmp = (PyLongObject *)long_new_impl(&PyLong_Type, x, obase); + assert(PyType_IsSubtype(type, state->type)); + tmp = (PyLongObject *)long_new_impl(state->type, x, obase); if (tmp == NULL) return NULL; assert(PyLong_Check(tmp)); @@ -5511,7 +5542,8 @@ int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj, little_endian, is_signed); Py_DECREF(bytes); - if (long_obj != NULL && type != &PyLong_Type) { + struct _Py_long_state *state = get_long_state(); + if (long_obj != NULL && type != state->type) { Py_SETREF(long_obj, PyObject_CallOneArg((PyObject *)type, long_obj)); } @@ -5704,6 +5736,7 @@ PyLong_GetInfo(void) int _PyLong_Init(PyThreadState *tstate) { + struct _Py_long_state *state = &tstate->interp->long_state; for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) { sdigit ival = (sdigit)i - NSMALLNEGINTS; int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); @@ -5716,7 +5749,7 @@ _PyLong_Init(PyThreadState *tstate) Py_SET_SIZE(v, size); v->ob_digit[0] = (digit)abs(ival); - tstate->interp->small_ints[i] = v; + state->small_ints[i] = v; } if (_Py_IsMainInterpreter(tstate)) { @@ -5734,7 +5767,8 @@ _PyLong_Init(PyThreadState *tstate) void _PyLong_Fini(PyThreadState *tstate) { + struct _Py_long_state *state = &tstate->interp->long_state; for (Py_ssize_t i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) { - Py_CLEAR(tstate->interp->small_ints[i]); + Py_CLEAR(state->small_ints[i]); } } diff --git a/Objects/object.c b/Objects/object.c index 0a8621b3503b31..a3bdcf8de29d8c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1741,6 +1741,7 @@ _PyTypes_Init(void) INIT_TYPE(&_PyWeakref_CallableProxyType, "callable weakref proxy"); INIT_TYPE(&_PyWeakref_ProxyType, "weakref proxy"); INIT_TYPE(&PyLong_Type, "int"); + PyBool_Type.tp_base = _Py_GetLongType(); INIT_TYPE(&PyBool_Type, "bool"); INIT_TYPE(&PyByteArray_Type, "bytearray"); INIT_TYPE(&PyBytes_Type, "str"); @@ -1757,6 +1758,7 @@ _PyTypes_Init(void) INIT_TYPE(&PyDictRevIterKey_Type, "reversed dict keys"); INIT_TYPE(&PyDictRevIterValue_Type, "reversed dict values"); INIT_TYPE(&PyDictRevIterItem_Type, "reversed dict items"); + PyODict_Type.tp_base = _Py_GetDictType(); INIT_TYPE(&PyODict_Type, "OrderedDict"); INIT_TYPE(&PyODictKeys_Type, "odict_keys"); INIT_TYPE(&PyODictItems_Type, "odict_items"); diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 6c7f1175cd652c..eb75dfb1db5d0c 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -527,6 +527,15 @@ struct _odictnode { _Py_IDENTIFIER(items); + +static PyTypeObject* +get_dict_type(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return interp->dict_state.type; +} + + /* Return the index into the hash table, regardless of a valid node. */ static Py_ssize_t _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash) @@ -1412,7 +1421,7 @@ odict_dealloc(PyODictObject *self) PyObject_ClearWeakRefs((PyObject *)self); _odict_clear_nodes(self); - PyDict_Type.tp_dealloc((PyObject *)self); + get_dict_type()->tp_dealloc((PyObject *)self); Py_TRASHCAN_END } @@ -1504,7 +1513,7 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg) _odict_FOREACH(od, node) { Py_VISIT(_odictnode_KEY(node)); } - return PyDict_Type.tp_traverse((PyObject *)od, visit, arg); + return get_dict_type()->tp_traverse((PyObject *)od, visit, arg); } /* tp_clear */ @@ -1531,7 +1540,7 @@ odict_richcompare(PyObject *v, PyObject *w, int op) PyObject *res, *cmp; int eq; - cmp = PyDict_Type.tp_richcompare(v, w, op); + cmp = get_dict_type()->tp_richcompare(v, w, op); if (cmp == NULL) return NULL; if (!PyODict_Check(w)) @@ -1622,7 +1631,7 @@ PyTypeObject PyODict_Type = { odict_methods, /* tp_methods */ 0, /* tp_members */ odict_getset, /* tp_getset */ - &PyDict_Type, /* tp_base */ + 0, /* _PyTypes_Init() sets it to &PyDict_Type: tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -1641,7 +1650,7 @@ PyTypeObject PyODict_Type = { PyObject * PyODict_New(void) { - return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL); + return get_dict_type()->tp_new(&PyODict_Type, NULL, NULL); } static int diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3498f0d484e01e..e859120346cea8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2416,7 +2416,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) /* Check arguments: (name, bases, dict) */ if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type, - &bases, &PyDict_Type, &orig_dict)) + &bases, _Py_GetDictType(), &orig_dict)) return NULL; /* Adjust for empty tuple bases */ @@ -5231,17 +5231,17 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS; else if (PyType_IsSubtype(base, &PyType_Type)) type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS; - else if (PyType_IsSubtype(base, &PyLong_Type)) + else if (PyType_IsSubtype(base, _Py_GetLongType())) type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS; else if (PyType_IsSubtype(base, &PyBytes_Type)) type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS; - else if (PyType_IsSubtype(base, &PyUnicode_Type)) + else if (PyType_IsSubtype(base, _Py_GetUnicodeType())) type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS; else if (PyType_IsSubtype(base, &PyTuple_Type)) type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS; else if (PyType_IsSubtype(base, &PyList_Type)) type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS; - else if (PyType_IsSubtype(base, &PyDict_Type)) + else if (PyType_IsSubtype(base, _Py_GetDictType())) type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; } @@ -6787,7 +6787,7 @@ slot_tp_hash(PyObject *self) use any sufficiently bit-mixing transformation; long.__hash__ will do nicely. */ PyErr_Clear(); - h = PyLong_Type.tp_hash(res); + h = _Py_GetLongType()->tp_hash(res); } /* -1 is reserved for errors. */ if (h == -1) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 64fd408085d5e5..89225912173456 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -215,6 +215,21 @@ get_unicode_state(void) } +PyTypeObject* +_Py_GetUnicodeType(void) +{ + struct _Py_unicode_state *state = get_unicode_state(); + return state->type; +} + + +int +_PyUnicode_CheckExact(PyObject *op) +{ + return Py_IS_TYPE(op, _Py_GetUnicodeType()); +} + + // Return a borrowed reference to the empty string singleton. static inline PyObject* unicode_get_empty(void) { @@ -230,8 +245,7 @@ static inline PyObject* unicode_get_empty(void) static inline PyObject* unicode_new_empty(void) { PyObject *empty = unicode_get_empty(); - Py_INCREF(empty); - return empty; + return Py_NewRef(empty); } #define _Py_RETURN_UNICODE_EMPTY() \ @@ -1225,7 +1239,8 @@ _PyUnicode_New(Py_ssize_t length) return NULL; } - unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type); + struct _Py_unicode_state *state = get_unicode_state(); + unicode = PyObject_New(PyUnicodeObject, state->type); if (unicode == NULL) return NULL; new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); @@ -1443,7 +1458,8 @@ PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar) if (obj == NULL) { return PyErr_NoMemory(); } - _PyObject_Init(obj, &PyUnicode_Type); + struct _Py_unicode_state *state = get_unicode_state(); + _PyObject_Init(obj, state->type); unicode = (PyCompactUnicodeObject *)obj; if (is_ascii) @@ -15495,7 +15511,8 @@ PyUnicode_Format(PyObject *format, PyObject *args) } static PyObject * -unicode_subtype_new(PyTypeObject *type, PyObject *unicode); +unicode_subtype_new(struct _Py_unicode_state *state, PyTypeObject *type, + PyObject *unicode); /*[clinic input] @classmethod @@ -15523,14 +15540,16 @@ unicode_new_impl(PyTypeObject *type, PyObject *x, const char *encoding, unicode = PyUnicode_FromEncodedObject(x, encoding, errors); } - if (unicode != NULL && type != &PyUnicode_Type) { - Py_SETREF(unicode, unicode_subtype_new(type, unicode)); + struct _Py_unicode_state *state = get_unicode_state(); + if (unicode != NULL && type != state->type) { + Py_SETREF(unicode, unicode_subtype_new(state, type, unicode)); } return unicode; } static PyObject * -unicode_subtype_new(PyTypeObject *type, PyObject *unicode) +unicode_subtype_new(struct _Py_unicode_state *state, PyTypeObject *type, + PyObject *unicode) { PyObject *self; Py_ssize_t length, char_size; @@ -15538,7 +15557,7 @@ unicode_subtype_new(PyTypeObject *type, PyObject *unicode) unsigned int kind; void *data; - assert(PyType_IsSubtype(type, &PyUnicode_Type)); + assert(PyType_IsSubtype(type, state->type)); assert(_PyUnicode_CHECK(unicode)); if (PyUnicode_READY(unicode) == -1) { return NULL; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 352fb83d55e053..c13c65fa992ec7 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2896,13 +2896,13 @@ _PyBuiltin_Init(PyThreadState *tstate) SETBUILTIN("bytes", &PyBytes_Type); SETBUILTIN("classmethod", &PyClassMethod_Type); SETBUILTIN("complex", &PyComplex_Type); - SETBUILTIN("dict", &PyDict_Type); + SETBUILTIN("dict", _Py_GetDictType()); SETBUILTIN("enumerate", &PyEnum_Type); SETBUILTIN("filter", &PyFilter_Type); SETBUILTIN("float", &PyFloat_Type); SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); - SETBUILTIN("int", &PyLong_Type); + SETBUILTIN("int", _Py_GetLongType()); SETBUILTIN("list", &PyList_Type); SETBUILTIN("map", &PyMap_Type); SETBUILTIN("object", &PyBaseObject_Type); @@ -2911,7 +2911,7 @@ _PyBuiltin_Init(PyThreadState *tstate) SETBUILTIN("set", &PySet_Type); SETBUILTIN("slice", &PySlice_Type); SETBUILTIN("staticmethod", &PyStaticMethod_Type); - SETBUILTIN("str", &PyUnicode_Type); + SETBUILTIN("str", _Py_GetUnicodeType()); SETBUILTIN("super", &PySuper_Type); SETBUILTIN("tuple", &PyTuple_Type); SETBUILTIN("type", &PyType_Type); diff --git a/Python/compile.c b/Python/compile.c index 54bd166c64e59e..ad063bc40d5029 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3927,7 +3927,7 @@ infer_type(expr_ty e) return &PyList_Type; case Dict_kind: case DictComp_kind: - return &PyDict_Type; + return _Py_GetDictType(); case Set_kind: case SetComp_kind: return &PySet_Type; @@ -3937,7 +3937,7 @@ infer_type(expr_ty e) return &PyFunction_Type; case JoinedStr_kind: case FormattedValue_kind: - return &PyUnicode_Type; + return _Py_GetUnicodeType(); case Constant_kind: return Py_TYPE(e->v.Constant.value); default: diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 9828dffad5c630..d84b675ff59d3a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -625,6 +625,12 @@ pycore_init_types(PyThreadState *tstate) { PyStatus status; int is_main_interp = _Py_IsMainInterpreter(tstate); + PyInterpreterState *interp = tstate->interp; + + interp->long_state.type = &PyLong_Type; + interp->list.type = &PyList_Type; + interp->dict_state.type = &PyDict_Type; + interp->unicode.type = &PyUnicode_Type; status = _PyGC_Init(tstate); if (_PyStatus_EXCEPTION(status)) { diff --git a/Python/pystate.c b/Python/pystate.c index c791b239993833..4708ab6a947215 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1893,7 +1893,7 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) } // int - if (_register_xidata(xidregistry, &PyLong_Type, _long_shared) != 0) { + if (_register_xidata(xidregistry, _Py_GetLongType(), _long_shared) != 0) { Py_FatalError("could not register int for cross-interpreter sharing"); } @@ -1903,7 +1903,7 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) } // str - if (_register_xidata(xidregistry, &PyUnicode_Type, _str_shared) != 0) { + if (_register_xidata(xidregistry, _Py_GetUnicodeType(), _str_shared) != 0) { Py_FatalError("could not register str for cross-interpreter sharing"); } }