@@ -5269,124 +5269,87 @@ PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def)
5269
5269
5270
5270
5271
5271
static PyTypeObject *
5272
- get_base_by_token_recursive (PyTypeObject * type , void * token )
5272
+ get_base_by_token_recursive (PyObject * bases , void * token )
5273
5273
{
5274
- assert (PyType_GetSlot (type , Py_tp_token ) != token );
5275
- PyObject * bases = lookup_tp_bases (type );
5276
5274
assert (bases != NULL );
5275
+ PyTypeObject * res = NULL ;
5277
5276
Py_ssize_t n = PyTuple_GET_SIZE (bases );
5278
5277
for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
5279
5278
PyTypeObject * base = _PyType_CAST (PyTuple_GET_ITEM (bases , i ));
5280
5279
if (!_PyType_HasFeature (base , Py_TPFLAGS_HEAPTYPE )) {
5281
5280
continue ;
5282
5281
}
5283
5282
if (((PyHeapTypeObject * )base )-> ht_token == token ) {
5284
- return base ;
5283
+ res = base ;
5284
+ break ;
5285
5285
}
5286
- base = get_base_by_token_recursive (base , token );
5286
+ base = get_base_by_token_recursive (lookup_tp_bases ( base ) , token );
5287
5287
if (base != NULL ) {
5288
- return base ;
5288
+ res = base ;
5289
+ break ;
5289
5290
}
5290
5291
}
5291
- return NULL ;
5292
+ return res ; // Prefer to return recursively from one place
5292
5293
}
5293
5294
5294
- static inline PyTypeObject *
5295
- get_base_by_token_from_mro (PyTypeObject * type , void * token )
5295
+ int
5296
+ PyType_GetBaseByToken (PyTypeObject * type , void * token , PyTypeObject * * result )
5296
5297
{
5297
- // Bypass lookup_tp_mro() as PyType_IsSubtype() does
5298
- PyObject * mro = type -> tp_mro ;
5299
- assert (mro != NULL );
5300
- assert (PyTuple_Check (mro ));
5301
- // mro_invoke() ensures that the type MRO cannot be empty.
5302
- assert (PyTuple_GET_SIZE (mro ) >= 1 );
5303
- // Also, the first item in the MRO is the type itself, which is supposed
5304
- // to be already checked by the caller. We skip it in the loop.
5305
- assert (PyTuple_GET_ITEM (mro , 0 ) == (PyObject * )type );
5306
- assert (PyType_GetSlot (type , Py_tp_token ) != token );
5307
-
5308
- Py_ssize_t n = PyTuple_GET_SIZE (mro );
5309
- for (Py_ssize_t i = 1 ; i < n ; i ++ ) {
5310
- PyTypeObject * base = _PyType_CAST (PyTuple_GET_ITEM (mro , i ));
5311
- if (!_PyType_HasFeature (base , Py_TPFLAGS_HEAPTYPE )) {
5312
- continue ;
5313
- }
5314
- if (((PyHeapTypeObject * )base )-> ht_token == token ) {
5315
- return base ;
5316
- }
5298
+ if (result != NULL ) {
5299
+ * result = NULL ;
5317
5300
}
5318
- return NULL ;
5319
- }
5320
5301
5321
- static int
5322
- check_base_by_token (PyTypeObject * type , void * token ) {
5323
- // Chain the branches, which will be optimized exclusive here
5324
5302
if (token == NULL ) {
5325
5303
PyErr_Format (PyExc_SystemError ,
5326
5304
"PyType_GetBaseByToken called with token=NULL" );
5327
5305
return -1 ;
5328
5306
}
5329
- else if (!PyType_Check (type )) {
5307
+ if (!PyType_Check (type )) {
5330
5308
PyErr_Format (PyExc_TypeError ,
5331
5309
"expected a type, got a '%T' object" , type );
5332
5310
return -1 ;
5333
5311
}
5334
- else if (!_PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
5335
- return 0 ;
5336
- }
5337
- else if (((PyHeapTypeObject * )type )-> ht_token == token ) {
5338
- return 1 ;
5339
- }
5340
- else if (type -> tp_mro != NULL ) {
5341
- // This will not be inlined
5342
- return get_base_by_token_from_mro (type , token ) ? 1 : 0 ;
5343
- }
5344
- else {
5345
- return get_base_by_token_recursive (type , token ) ? 1 : 0 ;
5346
- }
5347
- }
5348
5312
5349
- int
5350
- PyType_GetBaseByToken (PyTypeObject * type , void * token , PyTypeObject * * result )
5351
- {
5352
- if (result == NULL ) {
5353
- // If the `result` is checked only once here, the subsequent
5354
- // branches will become trivial to optimize.
5355
- return check_base_by_token (type , token );
5356
- }
5357
- if (token == NULL || !PyType_Check (type )) {
5358
- * result = NULL ;
5359
- return check_base_by_token (type , token );
5360
- }
5361
-
5362
- // Chain the branches, which will be optimized exclusive here
5363
- PyTypeObject * base ;
5364
5313
if (!_PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
5365
5314
// No static type has a heaptype superclass,
5366
5315
// which is ensured by type_ready_mro().
5367
- * result = NULL ;
5368
5316
return 0 ;
5369
5317
}
5370
- else if (((PyHeapTypeObject * )type )-> ht_token == token ) {
5371
- * result = (PyTypeObject * )Py_NewRef (type );
5318
+ if (((PyHeapTypeObject * )type )-> ht_token == token ) {
5319
+ found :
5320
+ if (result != NULL ) {
5321
+ * result = (PyTypeObject * )Py_NewRef (type );
5322
+ }
5372
5323
return 1 ;
5373
5324
}
5374
- else if (type -> tp_mro != NULL ) {
5375
- // Expect this to be inlined
5376
- base = get_base_by_token_from_mro (type , token );
5377
- }
5378
- else {
5379
- base = get_base_by_token_recursive (type , token );
5380
- }
5381
5325
5382
- if (base != NULL ) {
5383
- * result = (PyTypeObject * )Py_NewRef (base );
5384
- return 1 ;
5385
- }
5386
- else {
5387
- * result = NULL ;
5326
+ PyObject * mro = type -> tp_mro ; // No lookup, following PyType_IsSubtype()
5327
+ if (mro == NULL ) {
5328
+ PyTypeObject * base ;
5329
+ base = get_base_by_token_recursive (lookup_tp_bases (type ), token );
5330
+ if (base != NULL ) {
5331
+ // Copying the given type can cause a slowdown,
5332
+ // unlike the overwrite below.
5333
+ type = base ;
5334
+ goto found ;
5335
+ }
5388
5336
return 0 ;
5389
5337
}
5338
+ // mro_invoke() ensures that the type MRO cannot be empty.
5339
+ assert (PyTuple_GET_SIZE (mro ) >= 1 );
5340
+ // Also, the first item in the MRO is the type itself, which
5341
+ // we already checked above. We skip it in the loop.
5342
+ assert (PyTuple_GET_ITEM (mro , 0 ) == (PyObject * )type );
5343
+ Py_ssize_t n = PyTuple_GET_SIZE (mro );
5344
+ for (Py_ssize_t i = 1 ; i < n ; i ++ ) {
5345
+ PyTypeObject * base = (PyTypeObject * )PyTuple_GET_ITEM (mro , i );
5346
+ if (_PyType_HasFeature (base , Py_TPFLAGS_HEAPTYPE )
5347
+ && ((PyHeapTypeObject * )base )-> ht_token == token ) {
5348
+ type = base ;
5349
+ goto found ;
5350
+ }
5351
+ }
5352
+ return 0 ;
5390
5353
}
5391
5354
5392
5355
0 commit comments