Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
20 changes: 8 additions & 12 deletions Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2179,6 +2179,8 @@ typedef struct {
PyObject *default_factory;
} defdictobject;

static PyType_Spec defdict_spec;

PyDoc_STRVAR(defdict_missing_doc,
"__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\
if self.default_factory is None: raise KeyError((key,))\n\
Expand Down Expand Up @@ -2358,23 +2360,16 @@ defdict_or(PyObject* left, PyObject* right)
{
PyObject *self, *other;

// Find module state
PyTypeObject *tp = Py_TYPE(left);
PyObject *mod = PyType_GetModuleByDef(tp, &_collectionsmodule);
if (mod == NULL) {
PyErr_Clear();
tp = Py_TYPE(right);
mod = PyType_GetModuleByDef(tp, &_collectionsmodule);
int ret = PyType_GetBaseByToken(Py_TYPE(left), &defdict_spec, NULL);
if (ret < 0) {
return NULL;
}
assert(mod != NULL);
collections_state *state = get_module_state(mod);

if (PyObject_TypeCheck(left, state->defdict_type)) {
if (ret) {
self = left;
other = right;
}
else {
assert(PyObject_TypeCheck(right, state->defdict_type));
assert(PyType_GetBaseByToken(Py_TYPE(right), &defdict_spec, NULL) == 1);
self = right;
other = left;
}
Expand Down Expand Up @@ -2454,6 +2449,7 @@ passed to the dict constructor, including keyword arguments.\n\
#define DEFERRED_ADDRESS(ADDR) 0

static PyType_Slot defdict_slots[] = {
{Py_tp_token, Py_TP_USE_SPEC},
{Py_tp_dealloc, defdict_dealloc},
{Py_tp_repr, defdict_repr},
{Py_nb_or, defdict_or},
Expand Down
20 changes: 14 additions & 6 deletions Modules/_decimal/_decimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ get_module_state(PyObject *mod)
}

static struct PyModuleDef _decimal_module;
static PyType_Spec dec_spec;

static inline decimal_state *
get_module_state_by_def(PyTypeObject *tp)
Expand All @@ -134,10 +135,16 @@ get_module_state_by_def(PyTypeObject *tp)
static inline decimal_state *
find_state_left_or_right(PyObject *left, PyObject *right)
{
PyObject *mod = _PyType_GetModuleByDef2(Py_TYPE(left), Py_TYPE(right),
&_decimal_module);
assert(mod != NULL);
return get_module_state(mod);
PyTypeObject *base;
if (PyType_GetBaseByToken(Py_TYPE(left), &dec_spec, &base) != 1) {
assert(!PyErr_Occurred());
PyType_GetBaseByToken(Py_TYPE(right), &dec_spec, &base);
}
assert(base != NULL);
void *state = _PyType_GetModuleState(base);
assert(state != NULL);
Py_DECREF(base);
return (decimal_state *)state;
}


Expand Down Expand Up @@ -745,7 +752,7 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
{
PyObject *res = Py_NotImplemented;

decimal_state *state = find_state_left_or_right(v, w);
decimal_state *state = get_module_state_by_def(Py_TYPE(v));
assert(PyDecSignalDict_Check(state, v));

if ((SdFlagAddr(v) == NULL) || (SdFlagAddr(w) == NULL)) {
Expand Down Expand Up @@ -4653,7 +4660,7 @@ dec_richcompare(PyObject *v, PyObject *w, int op)
uint32_t status = 0;
int a_issnan, b_issnan;
int r;
decimal_state *state = find_state_left_or_right(v, w);
decimal_state *state = get_module_state_by_def(Py_TYPE(v));

#ifdef Py_DEBUG
assert(PyDec_Check(state, v));
Expand Down Expand Up @@ -5041,6 +5048,7 @@ static PyMethodDef dec_methods [] =
};

static PyType_Slot dec_slots[] = {
{Py_tp_token, Py_TP_USE_SPEC},
{Py_tp_dealloc, dec_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_traverse, dec_traverse},
Expand Down
24 changes: 13 additions & 11 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5297,7 +5297,7 @@ get_base_by_token_recursive(PyTypeObject *type, void *token)
Py_ssize_t n = PyTuple_GET_SIZE(bases);
for (Py_ssize_t i = 0; i < n; i++) {
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i));
if (!_PyType_HasFeature(base, Py_TPFLAGS_HEAPTYPE)) {
if (!PyType_HasFeature(base, Py_TPFLAGS_HEAPTYPE)) {
continue;
}
if (((PyHeapTypeObject*)base)->ht_token == token) {
Expand Down Expand Up @@ -5328,7 +5328,7 @@ get_base_by_token_from_mro(PyTypeObject *type, void *token)
Py_ssize_t n = PyTuple_GET_SIZE(mro);
for (Py_ssize_t i = 1; i < n; i++) {
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(mro, i));
if (!_PyType_HasFeature(base, Py_TPFLAGS_HEAPTYPE)) {
if (!PyType_HasFeature(base, Py_TPFLAGS_HEAPTYPE)) {
continue;
}
if (((PyHeapTypeObject*)base)->ht_token == token) {
Expand All @@ -5340,24 +5340,25 @@ get_base_by_token_from_mro(PyTypeObject *type, void *token)

static int
check_base_by_token(PyTypeObject *type, void *token) {
// Chain the branches, which will be optimized exclusive here
if (token == NULL) {
PyErr_Format(PyExc_SystemError,
"PyType_GetBaseByToken called with token=NULL");
return -1;
}
else if (!PyType_Check(type)) {
if (!PyType_Check(type)) {
PyErr_Format(PyExc_TypeError,
"expected a type, got a '%T' object", type);
return -1;
}
else if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
// Ensure the flag is checked by a function, not directly. PyType_Check()
// above also uses PyType_HasFeature() instead of the internal duplicate.
if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
return 0;
}
else if (((PyHeapTypeObject*)type)->ht_token == token) {
if (((PyHeapTypeObject*)type)->ht_token == token) {
return 1;
}
else if (type->tp_mro != NULL) {
if (type->tp_mro != NULL) {
// This will not be inlined
return get_base_by_token_from_mro(type, token) ? 1 : 0;
}
Expand All @@ -5374,14 +5375,15 @@ PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result)
// branches will become trivial to optimize.
return check_base_by_token(type, token);
}
PyTypeObject *base;
// Chain the branches below (not above), which will avoid being less
// pgoptimized by MSVC together with check_base_by_token() and other
// functions, unless they have if-else statements with similar conds.
if (token == NULL || !PyType_Check(type)) {
*result = NULL;
return check_base_by_token(type, token);
}

// Chain the branches, which will be optimized exclusive here
PyTypeObject *base;
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
else if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
// No static type has a heaptype superclass,
// which is ensured by type_ready_mro().
*result = NULL;
Expand Down
Loading