Skip to content

Commit 7d3f8b6

Browse files
committed
optimize GetBaseByToken like GetModuleByDef
1 parent ccd5ede commit 7d3f8b6

File tree

2 files changed

+44
-41
lines changed

2 files changed

+44
-41
lines changed

Modules/_testcapi/heaptype.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,8 @@ pytype_getbasebytoken(PyObject *self, PyObject *args)
464464
}
465465
assert(PyType_Check(type));
466466

467-
PyObject *mro_save = NULL;
467+
PyObject *mro_save = type->tp_mro;
468468
if (use_mro != Py_True) {
469-
mro_save = type->tp_mro;
470469
type->tp_mro = NULL;
471470
}
472471

@@ -481,21 +480,26 @@ pytype_getbasebytoken(PyObject *self, PyObject *args)
481480
ret = PyType_GetBaseByToken(type, token, NULL);
482481
}
483482

484-
if (mro_save != NULL) {
485-
type->tp_mro = mro_save;
486-
}
487-
483+
type->tp_mro = mro_save;
488484
if (ret < 0) {
489485
return NULL;
490486
}
487+
PyObject *py_ret = PyLong_FromLong(ret);
488+
if (py_ret == NULL) {
489+
goto error;
490+
}
491491
PyObject *tuple = PyTuple_New(2);
492492
if (tuple == NULL) {
493-
Py_XDECREF(result);
494-
return NULL;
493+
goto error;
495494
}
496-
PyTuple_SET_ITEM(tuple, 0, PyLong_FromLong(ret));
495+
PyTuple_SET_ITEM(tuple, 0, py_ret);
497496
PyTuple_SET_ITEM(tuple, 1, result ? result : Py_None);
498497
return tuple;
498+
error:
499+
Py_XDECREF(py_ret);
500+
Py_XDECREF(result);
501+
return NULL;
502+
}
499503
}
500504

501505

Objects/typeobject.c

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5238,17 +5238,10 @@ _PyType_GetModuleByDef2(PyTypeObject *left, PyTypeObject *right,
52385238

52395239

52405240
static PyTypeObject *
5241-
get_base_by_token_recursive(PyTypeObject *type, void *token, int initial)
5241+
get_base_by_token_recursive(PyTypeObject *type, void *token)
52425242
{
5243-
if (initial) {
5244-
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
5245-
return NULL;
5246-
}
5247-
if (((PyHeapTypeObject*)type)->ht_token == token) {
5248-
return type;
5249-
}
5250-
}
52515243
PyObject *bases = type->tp_bases;
5244+
assert(bases != NULL);
52525245
Py_ssize_t n = PyTuple_GET_SIZE(bases);
52535246
for (Py_ssize_t i = 0; i < n; i++) {
52545247
PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
@@ -5258,17 +5251,25 @@ get_base_by_token_recursive(PyTypeObject *type, void *token, int initial)
52585251
if (((PyHeapTypeObject*)base)->ht_token == token) {
52595252
return base;
52605253
}
5261-
base = get_base_by_token_recursive(base, token, 0);
5254+
base = get_base_by_token_recursive(base, token);
52625255
if (base) {
52635256
return base;
52645257
}
52655258
}
52665259
return NULL;
52675260
}
52685261

5262+
static inline int
5263+
_token_found(PyTypeObject *type, PyTypeObject **result)
5264+
{
5265+
if (result != NULL) {
5266+
*result = (PyTypeObject *)Py_NewRef(type);
5267+
}
5268+
return 1;
5269+
}
5270+
52695271
int
5270-
PyType_GetBaseByToken(PyTypeObject *type, void *token,
5271-
PyTypeObject **result)
5272+
PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result)
52725273
{
52735274
if (result != NULL) {
52745275
*result = NULL;
@@ -5278,35 +5279,33 @@ PyType_GetBaseByToken(PyTypeObject *type, void *token,
52785279
return 0;
52795280
}
52805281
assert(PyType_Check(type));
5282+
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
5283+
// Static type MRO contains no heap type,
5284+
// which type_ready_mro() ensures.
5285+
return 0;
5286+
}
5287+
if (((PyHeapTypeObject*)type)->ht_token == token) {
5288+
return _token_found(type, result);
5289+
}
52815290
PyObject *mro = type->tp_mro;
52825291
if (mro == NULL) {
5283-
PyTypeObject *base = get_base_by_token_recursive(type, token, 1);
5284-
if (base == NULL) {
5285-
return 0;
5286-
}
5287-
if (result != NULL) {
5288-
*result = (PyTypeObject *)Py_NewRef(base);
5289-
}
5290-
return 1;
5292+
PyTypeObject *base = get_base_by_token_recursive(type, token, result);
5293+
return base ? _token_found(base, result) : 0;
52915294
}
52925295
assert(PyTuple_Check(mro));
5296+
// mro_invoke() ensures that the type MRO cannot be empty.
5297+
assert(PyTuple_GET_SIZE(mro) >= 1);
5298+
// Also, the first item in the MRO is the type itself, which
5299+
// we already checked above. We skip it in the loop.
5300+
assert(PyTuple_GET_ITEM(mro, 0) == (PyObject *)type);
52935301
Py_ssize_t n = PyTuple_GET_SIZE(mro);
5294-
for (Py_ssize_t i = 0; i < n; i++) {
5302+
for (Py_ssize_t i = 1; i < n; i++) {
52955303
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(mro, i));
52965304
if (!_PyType_HasFeature(base, Py_TPFLAGS_HEAPTYPE)) {
5297-
if (i) {
5298-
continue;
5299-
}
5300-
// Static type MRO contains no heap type,
5301-
// which type_ready_mro() ensures.
5302-
assert(base == type);
5303-
return 0;
5305+
continue;
53045306
}
53055307
if (((PyHeapTypeObject*)base)->ht_token == token) {
5306-
if (result != NULL) {
5307-
*result = (PyTypeObject *)Py_NewRef(base);
5308-
}
5309-
return 1;
5308+
return _token_found(base, result);
53105309
}
53115310
}
53125311
return 0;

0 commit comments

Comments
 (0)