@@ -233,7 +233,7 @@ static uint8_t adaptive_opcodes[256] = {
233
233
static uint8_t cache_requirements [256 ] = {
234
234
[LOAD_ATTR ] = 2 , /* _PyAdaptiveEntry and _PyAttrCache */
235
235
[LOAD_GLOBAL ] = 2 , /* _PyAdaptiveEntry and _PyLoadGlobalCache */
236
- [LOAD_METHOD ] = 3 , /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
236
+ [LOAD_METHOD ] = 4 , /* _PyAdaptiveEntry, _PyAttrCache and 2 _PyObjectCache */
237
237
[BINARY_SUBSCR ] = 0 ,
238
238
[STORE_ATTR ] = 2 , /* _PyAdaptiveEntry and _PyAttrCache */
239
239
};
@@ -817,6 +817,7 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
817
817
_PyAdaptiveEntry * cache0 = & cache -> adaptive ;
818
818
_PyAttrCache * cache1 = & cache [-1 ].attr ;
819
819
_PyObjectCache * cache2 = & cache [-2 ].obj ;
820
+ _PyObjectCache * cache3 = & cache [-3 ].obj ;
820
821
821
822
PyTypeObject * owner_cls = Py_TYPE (owner );
822
823
if (PyModule_CheckExact (owner )) {
@@ -851,6 +852,10 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
851
852
int owner_is_class = PyType_Check (owner );
852
853
owner_cls = owner_is_class ? (PyTypeObject * )owner : owner_cls ;
853
854
855
+ if ((owner_cls -> tp_flags & Py_TPFLAGS_VALID_VERSION_TAG ) == 0 ) {
856
+ SPECIALIZATION_FAIL (LOAD_METHOD , SPEC_FAIL_OUT_OF_RANGE );
857
+ goto fail ;
858
+ }
854
859
PyObject * descr = NULL ;
855
860
DesciptorClassification kind = 0 ;
856
861
kind = analyze_descriptor (owner_cls , name , & descr , 0 );
@@ -875,8 +880,9 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
875
880
assert (kind == METHOD );
876
881
// If o.__dict__ changes, the method might be found in o.__dict__
877
882
// instead of old type lookup. So record o.__dict__'s keys.
883
+ // Not required for class methods -- tp_version_tag is enough for those.
878
884
uint32_t keys_version = UINT32_MAX ;
879
- if (owner_has_dict ) {
885
+ if (owner_has_dict && ! owner_is_class ) {
880
886
// _PyDictKeys_GetVersionForCurrentState isn't accurate for
881
887
// custom dict subclasses at the moment.
882
888
if (!PyDict_CheckExact (owner_dict )) {
@@ -923,6 +929,7 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
923
929
* battle-tested.
924
930
*/
925
931
cache2 -> obj = descr ;
932
+ cache3 -> obj = (PyObject * )owner_cls ; // borrowed - cache the type
926
933
cache1 -> dk_version_or_hint = keys_version ;
927
934
* instr = _Py_MAKECODEUNIT (owner_is_class ? LOAD_METHOD_CLASS :
928
935
LOAD_METHOD_CACHED , _Py_OPARG (* instr ));
0 commit comments