@@ -2367,35 +2367,39 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
2367
2367
& bases , & PyDict_Type , & orig_dict ))
2368
2368
return NULL ;
2369
2369
2370
- /* Determine the proper metatype to deal with this: */
2371
- winner = _PyType_CalculateMetaclass (metatype , bases );
2372
- if (winner == NULL ) {
2373
- return NULL ;
2374
- }
2375
-
2376
- if (winner != metatype ) {
2377
- if (winner -> tp_new != type_new ) /* Pass it to the winner */
2378
- return winner -> tp_new (winner , args , kwds );
2379
- metatype = winner ;
2380
- }
2381
-
2382
2370
/* Adjust for empty tuple bases */
2383
2371
nbases = PyTuple_GET_SIZE (bases );
2384
2372
if (nbases == 0 ) {
2385
- bases = PyTuple_Pack (1 , & PyBaseObject_Type );
2373
+ base = & PyBaseObject_Type ;
2374
+ bases = PyTuple_Pack (1 , base );
2386
2375
if (bases == NULL )
2387
- goto error ;
2376
+ return NULL ;
2388
2377
nbases = 1 ;
2389
2378
}
2390
- else
2391
- Py_INCREF (bases );
2379
+ else {
2380
+ /* Search the bases for the proper metatype to deal with this: */
2381
+ winner = _PyType_CalculateMetaclass (metatype , bases );
2382
+ if (winner == NULL ) {
2383
+ return NULL ;
2384
+ }
2392
2385
2393
- /* Calculate best base, and check that all bases are type objects */
2394
- base = best_base (bases );
2395
- if (base == NULL ) {
2396
- goto error ;
2386
+ if (winner != metatype ) {
2387
+ if (winner -> tp_new != type_new ) /* Pass it to the winner */
2388
+ return winner -> tp_new (winner , args , kwds );
2389
+ metatype = winner ;
2390
+ }
2391
+
2392
+ /* Calculate best base, and check that all bases are type objects */
2393
+ base = best_base (bases );
2394
+ if (base == NULL ) {
2395
+ return NULL ;
2396
+ }
2397
+
2398
+ Py_INCREF (bases );
2397
2399
}
2398
2400
2401
+ /* Use "goto error" from this point on as we now own the reference to "bases". */
2402
+
2399
2403
dict = PyDict_Copy (orig_dict );
2400
2404
if (dict == NULL )
2401
2405
goto error ;
@@ -2945,54 +2949,46 @@ PyType_GetSlot(PyTypeObject *type, int slot)
2945
2949
return * (void * * )(((char * )type ) + slotoffsets [slot ]);
2946
2950
}
2947
2951
2948
- /* Internal API to look for a name through the MRO.
2949
- This returns a borrowed reference, and doesn't set an exception! */
2950
- PyObject *
2951
- _PyType_Lookup (PyTypeObject * type , PyObject * name )
2952
+ /* Internal API to look for a name through the MRO, bypassing the method cache.
2953
+ This returns a borrowed reference, and might set an exception.
2954
+ 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
2955
+ static PyObject *
2956
+ find_name_in_mro (PyTypeObject * type , PyObject * name , int * error )
2952
2957
{
2953
2958
Py_ssize_t i , n ;
2954
2959
PyObject * mro , * res , * base , * dict ;
2955
- unsigned int h ;
2960
+ Py_hash_t hash ;
2956
2961
2957
- if (MCACHE_CACHEABLE_NAME (name ) &&
2958
- PyType_HasFeature (type , Py_TPFLAGS_VALID_VERSION_TAG )) {
2959
- /* fast path */
2960
- h = MCACHE_HASH_METHOD (type , name );
2961
- if (method_cache [h ].version == type -> tp_version_tag &&
2962
- method_cache [h ].name == name ) {
2963
- #if MCACHE_STATS
2964
- method_cache_hits ++ ;
2965
- #endif
2966
- return method_cache [h ].value ;
2962
+ if (!PyUnicode_CheckExact (name ) ||
2963
+ (hash = ((PyASCIIObject * ) name )-> hash ) == -1 )
2964
+ {
2965
+ hash = PyObject_Hash (name );
2966
+ if (hash == -1 ) {
2967
+ * error = -1 ;
2968
+ return NULL ;
2967
2969
}
2968
2970
}
2969
2971
2970
2972
/* Look in tp_dict of types in MRO */
2971
2973
mro = type -> tp_mro ;
2972
2974
2973
2975
if (mro == NULL ) {
2974
- if ((type -> tp_flags & Py_TPFLAGS_READYING ) == 0 &&
2975
- PyType_Ready (type ) < 0 ) {
2976
- /* It's not ideal to clear the error condition,
2977
- but this function is documented as not setting
2978
- an exception, and I don't want to change that.
2979
- When PyType_Ready() can't proceed, it won't
2980
- set the "ready" flag, so future attempts to ready
2981
- the same type will call it again -- hopefully
2982
- in a context that propagates the exception out.
2983
- */
2984
- PyErr_Clear ();
2985
- return NULL ;
2976
+ if ((type -> tp_flags & Py_TPFLAGS_READYING ) == 0 ) {
2977
+ if (PyType_Ready (type ) < 0 ) {
2978
+ * error = -1 ;
2979
+ return NULL ;
2980
+ }
2981
+ mro = type -> tp_mro ;
2986
2982
}
2987
- mro = type -> tp_mro ;
2988
2983
if (mro == NULL ) {
2984
+ * error = 1 ;
2989
2985
return NULL ;
2990
2986
}
2991
2987
}
2992
2988
2993
2989
res = NULL ;
2994
- /* keep a strong reference to mro because type->tp_mro can be replaced
2995
- during PyDict_GetItem( dict, name) */
2990
+ /* Keep a strong reference to mro because type->tp_mro can be replaced
2991
+ during dict lookup, e.g. when comparing to non-string keys. */
2996
2992
Py_INCREF (mro );
2997
2993
assert (PyTuple_Check (mro ));
2998
2994
n = PyTuple_GET_SIZE (mro );
@@ -3001,11 +2997,61 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
3001
2997
assert (PyType_Check (base ));
3002
2998
dict = ((PyTypeObject * )base )-> tp_dict ;
3003
2999
assert (dict && PyDict_Check (dict ));
3004
- res = PyDict_GetItem (dict , name );
3000
+ res = _PyDict_GetItem_KnownHash (dict , name , hash );
3005
3001
if (res != NULL )
3006
3002
break ;
3003
+ if (PyErr_Occurred ()) {
3004
+ * error = -1 ;
3005
+ goto done ;
3006
+ }
3007
3007
}
3008
+ * error = 0 ;
3009
+ done :
3008
3010
Py_DECREF (mro );
3011
+ return res ;
3012
+ }
3013
+
3014
+ /* Internal API to look for a name through the MRO.
3015
+ This returns a borrowed reference, and doesn't set an exception! */
3016
+ PyObject *
3017
+ _PyType_Lookup (PyTypeObject * type , PyObject * name )
3018
+ {
3019
+ PyObject * res ;
3020
+ int error ;
3021
+ unsigned int h ;
3022
+
3023
+ if (MCACHE_CACHEABLE_NAME (name ) &&
3024
+ PyType_HasFeature (type , Py_TPFLAGS_VALID_VERSION_TAG )) {
3025
+ /* fast path */
3026
+ h = MCACHE_HASH_METHOD (type , name );
3027
+ if (method_cache [h ].version == type -> tp_version_tag &&
3028
+ method_cache [h ].name == name ) {
3029
+ #if MCACHE_STATS
3030
+ method_cache_hits ++ ;
3031
+ #endif
3032
+ return method_cache [h ].value ;
3033
+ }
3034
+ }
3035
+
3036
+ /* We may end up clearing live exceptions below, so make sure it's ours. */
3037
+ assert (!PyErr_Occurred ());
3038
+
3039
+ res = find_name_in_mro (type , name , & error );
3040
+ /* Only put NULL results into cache if there was no error. */
3041
+ if (error ) {
3042
+ /* It's not ideal to clear the error condition,
3043
+ but this function is documented as not setting
3044
+ an exception, and I don't want to change that.
3045
+ E.g., when PyType_Ready() can't proceed, it won't
3046
+ set the "ready" flag, so future attempts to ready
3047
+ the same type will call it again -- hopefully
3048
+ in a context that propagates the exception out.
3049
+ */
3050
+ if (error == -1 ) {
3051
+ PyErr_Clear ();
3052
+ }
3053
+ return NULL ;
3054
+ }
3009
3055
3010
3056
if (MCACHE_CACHEABLE_NAME (name ) && assign_version_tag (type )) {
3011
3057
h = MCACHE_HASH_METHOD (type , name );
@@ -6965,6 +7011,7 @@ update_one_slot(PyTypeObject *type, slotdef *p)
6965
7011
void * generic = NULL , * specific = NULL ;
6966
7012
int use_generic = 0 ;
6967
7013
int offset = p -> offset ;
7014
+ int error ;
6968
7015
void * * ptr = slotptr (type , offset );
6969
7016
6970
7017
if (ptr == NULL ) {
@@ -6973,9 +7020,18 @@ update_one_slot(PyTypeObject *type, slotdef *p)
6973
7020
} while (p -> offset == offset );
6974
7021
return p ;
6975
7022
}
7023
+ /* We may end up clearing live exceptions below, so make sure it's ours. */
7024
+ assert (!PyErr_Occurred ());
6976
7025
do {
6977
- descr = _PyType_Lookup (type , p -> name_strobj );
7026
+ /* Use faster uncached lookup as we won't get any cache hits during type setup. */
7027
+ descr = find_name_in_mro (type , p -> name_strobj , & error );
6978
7028
if (descr == NULL ) {
7029
+ if (error == -1 ) {
7030
+ /* It is unlikely by not impossible that there has been an exception
7031
+ during lookup. Since this function originally expected no errors,
7032
+ we ignore them here in order to keep up the interface. */
7033
+ PyErr_Clear ();
7034
+ }
6979
7035
if (ptr == (void * * )& type -> tp_iternext ) {
6980
7036
specific = (void * )_PyObject_NextNotImplemented ;
6981
7037
}
0 commit comments