@@ -3626,7 +3626,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
36263626 }
36273627
36283628 TARGET (LOAD_ATTR_CLASS ) {
3629- /* LOAD_METHOD, for class methods */
36303629 assert (cframe .use_tracing == 0 );
36313630 _PyLoadMethodCache * cache = (_PyLoadMethodCache * )next_instr ;
36323631
@@ -3649,6 +3648,46 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
36493648 NOTRACE_DISPATCH ();
36503649 }
36513650
3651+ TARGET (LOAD_ATTR_PROPERTY ) {
3652+ assert (cframe .use_tracing == 0 );
3653+ DEOPT_IF (tstate -> interp -> eval_frame , LOAD_ATTR );
3654+ _PyLoadMethodCache * cache = (_PyLoadMethodCache * )next_instr ;
3655+
3656+ PyObject * owner = TOP ();
3657+ PyTypeObject * cls = Py_TYPE (owner );
3658+ uint32_t type_version = read_u32 (cache -> type_version );
3659+ DEOPT_IF (cls -> tp_version_tag != type_version , LOAD_ATTR );
3660+ assert (type_version != 0 );
3661+ PyObject * fget = read_obj (cache -> descr );
3662+ PyFunctionObject * f = (PyFunctionObject * )fget ;
3663+ uint32_t func_version = read_u32 (cache -> keys_version );
3664+ assert (func_version != 0 );
3665+ DEOPT_IF (f -> func_version != func_version , LOAD_ATTR );
3666+ PyCodeObject * code = (PyCodeObject * )f -> func_code ;
3667+ assert (code -> co_argcount == 1 );
3668+ STAT_INC (LOAD_ATTR , hit );
3669+
3670+ Py_INCREF (fget );
3671+ _PyInterpreterFrame * new_frame = _PyFrame_Push (tstate , f );
3672+ if (new_frame == NULL ) {
3673+ goto error ;
3674+ }
3675+ SET_TOP (NULL );
3676+ int push_null = !(oparg & 1 );
3677+ STACK_SHRINK (push_null );
3678+ new_frame -> localsplus [0 ] = owner ;
3679+ for (int i = 1 ; i < code -> co_nlocalsplus ; i ++ ) {
3680+ new_frame -> localsplus [i ] = NULL ;
3681+ }
3682+ _PyFrame_SetStackPointer (frame , stack_pointer );
3683+ JUMPBY (INLINE_CACHE_ENTRIES_LOAD_ATTR );
3684+ frame -> prev_instr = next_instr - 1 ;
3685+ new_frame -> previous = frame ;
3686+ frame = cframe .current_frame = new_frame ;
3687+ CALL_STAT_INC (inlined_py_calls );
3688+ goto start_frame ;
3689+ }
3690+
36523691 TARGET (STORE_ATTR_ADAPTIVE ) {
36533692 assert (cframe .use_tracing == 0 );
36543693 _PyAttrCache * cache = (_PyAttrCache * )next_instr ;
@@ -4548,7 +4587,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
45484587 }
45494588
45504589 TARGET (LOAD_ATTR_METHOD_WITH_VALUES ) {
4551- /* LOAD_METHOD, with cached method object */
4590+ /* Cached method object */
45524591 assert (cframe .use_tracing == 0 );
45534592 PyObject * self = TOP ();
45544593 PyTypeObject * self_cls = Py_TYPE (self );
@@ -4574,8 +4613,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
45744613 }
45754614
45764615 TARGET (LOAD_ATTR_METHOD_WITH_DICT ) {
4577- /* LOAD_METHOD, with a dict
4578- Can be either a managed dict, or a tp_dictoffset offset.*/
4616+ /* Can be either a managed dict, or a tp_dictoffset offset.*/
45794617 assert (cframe .use_tracing == 0 );
45804618 PyObject * self = TOP ();
45814619 PyTypeObject * self_cls = Py_TYPE (self );
0 commit comments