mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-104909: Split more LOAD_ATTR specializations (GH-110317)
* Split LOAD_ATTR_MODULE * Split LOAD_ATTR_WITH_HINT * Split _GUARD_TYPE_VERSION out of the latter * Split LOAD_ATTR_CLASS * Split LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES * Fix indent of DEOPT_IF in macros * Split LOAD_ATTR_METHOD_LAZY_DICT * Split LOAD_ATTR_NONDESCRIPTOR_NO_DICT * Fix omission of _CHECK_ATTR_METHOD_LAZY_DICT
This commit is contained in:
		
							parent
							
								
									d8c00d2a60
								
							
						
					
					
						commit
						7c149a76b2
					
				
					 6 changed files with 598 additions and 219 deletions
				
			
		
							
								
								
									
										146
									
								
								Include/internal/pycore_opcode_metadata.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										146
									
								
								Include/internal/pycore_opcode_metadata.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -46,39 +46,49 @@
 | 
				
			||||||
#define _GUARD_TYPE_VERSION 318
 | 
					#define _GUARD_TYPE_VERSION 318
 | 
				
			||||||
#define _CHECK_MANAGED_OBJECT_HAS_VALUES 319
 | 
					#define _CHECK_MANAGED_OBJECT_HAS_VALUES 319
 | 
				
			||||||
#define _LOAD_ATTR_INSTANCE_VALUE 320
 | 
					#define _LOAD_ATTR_INSTANCE_VALUE 320
 | 
				
			||||||
#define _LOAD_ATTR_SLOT 321
 | 
					#define _CHECK_ATTR_MODULE 321
 | 
				
			||||||
#define _GUARD_DORV_VALUES 322
 | 
					#define _LOAD_ATTR_MODULE 322
 | 
				
			||||||
#define _STORE_ATTR_INSTANCE_VALUE 323
 | 
					#define _CHECK_ATTR_WITH_HINT 323
 | 
				
			||||||
#define _STORE_ATTR_SLOT 324
 | 
					#define _LOAD_ATTR_WITH_HINT 324
 | 
				
			||||||
#define _IS_NONE 325
 | 
					#define _LOAD_ATTR_SLOT 325
 | 
				
			||||||
#define _ITER_CHECK_LIST 326
 | 
					#define _CHECK_ATTR_CLASS 326
 | 
				
			||||||
#define _ITER_JUMP_LIST 327
 | 
					#define _LOAD_ATTR_CLASS 327
 | 
				
			||||||
#define _IS_ITER_EXHAUSTED_LIST 328
 | 
					#define _GUARD_DORV_VALUES 328
 | 
				
			||||||
#define _ITER_NEXT_LIST 329
 | 
					#define _STORE_ATTR_INSTANCE_VALUE 329
 | 
				
			||||||
#define _ITER_CHECK_TUPLE 330
 | 
					#define _STORE_ATTR_SLOT 330
 | 
				
			||||||
#define _ITER_JUMP_TUPLE 331
 | 
					#define _IS_NONE 331
 | 
				
			||||||
#define _IS_ITER_EXHAUSTED_TUPLE 332
 | 
					#define _ITER_CHECK_LIST 332
 | 
				
			||||||
#define _ITER_NEXT_TUPLE 333
 | 
					#define _ITER_JUMP_LIST 333
 | 
				
			||||||
#define _ITER_CHECK_RANGE 334
 | 
					#define _IS_ITER_EXHAUSTED_LIST 334
 | 
				
			||||||
#define _ITER_JUMP_RANGE 335
 | 
					#define _ITER_NEXT_LIST 335
 | 
				
			||||||
#define _IS_ITER_EXHAUSTED_RANGE 336
 | 
					#define _ITER_CHECK_TUPLE 336
 | 
				
			||||||
#define _ITER_NEXT_RANGE 337
 | 
					#define _ITER_JUMP_TUPLE 337
 | 
				
			||||||
#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 338
 | 
					#define _IS_ITER_EXHAUSTED_TUPLE 338
 | 
				
			||||||
#define _GUARD_KEYS_VERSION 339
 | 
					#define _ITER_NEXT_TUPLE 339
 | 
				
			||||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 340
 | 
					#define _ITER_CHECK_RANGE 340
 | 
				
			||||||
#define _LOAD_ATTR_METHOD_NO_DICT 341
 | 
					#define _ITER_JUMP_RANGE 341
 | 
				
			||||||
#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 342
 | 
					#define _IS_ITER_EXHAUSTED_RANGE 342
 | 
				
			||||||
#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 343
 | 
					#define _ITER_NEXT_RANGE 343
 | 
				
			||||||
#define _CHECK_PEP_523 344
 | 
					#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 344
 | 
				
			||||||
#define _CHECK_FUNCTION_EXACT_ARGS 345
 | 
					#define _GUARD_KEYS_VERSION 345
 | 
				
			||||||
#define _CHECK_STACK_SPACE 346
 | 
					#define _LOAD_ATTR_METHOD_WITH_VALUES 346
 | 
				
			||||||
#define _INIT_CALL_PY_EXACT_ARGS 347
 | 
					#define _LOAD_ATTR_METHOD_NO_DICT 347
 | 
				
			||||||
#define _PUSH_FRAME 348
 | 
					#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 348
 | 
				
			||||||
#define _POP_JUMP_IF_FALSE 349
 | 
					#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 349
 | 
				
			||||||
#define _POP_JUMP_IF_TRUE 350
 | 
					#define _CHECK_ATTR_METHOD_LAZY_DICT 350
 | 
				
			||||||
#define _JUMP_TO_TOP 351
 | 
					#define _LOAD_ATTR_METHOD_LAZY_DICT 351
 | 
				
			||||||
#define _SAVE_CURRENT_IP 352
 | 
					#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 352
 | 
				
			||||||
#define _INSERT 353
 | 
					#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 353
 | 
				
			||||||
 | 
					#define _CHECK_PEP_523 354
 | 
				
			||||||
 | 
					#define _CHECK_FUNCTION_EXACT_ARGS 355
 | 
				
			||||||
 | 
					#define _CHECK_STACK_SPACE 356
 | 
				
			||||||
 | 
					#define _INIT_CALL_PY_EXACT_ARGS 357
 | 
				
			||||||
 | 
					#define _PUSH_FRAME 358
 | 
				
			||||||
 | 
					#define _POP_JUMP_IF_FALSE 359
 | 
				
			||||||
 | 
					#define _POP_JUMP_IF_TRUE 360
 | 
				
			||||||
 | 
					#define _JUMP_TO_TOP 361
 | 
				
			||||||
 | 
					#define _SAVE_CURRENT_IP 362
 | 
				
			||||||
 | 
					#define _INSERT 363
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
 | 
					extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
 | 
				
			||||||
#ifdef NEED_OPCODE_METADATA
 | 
					#ifdef NEED_OPCODE_METADATA
 | 
				
			||||||
| 
						 | 
					@ -360,14 +370,26 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump)  {
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_INSTANCE_VALUE:
 | 
					        case LOAD_ATTR_INSTANCE_VALUE:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_MODULE:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_MODULE:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_MODULE:
 | 
					        case LOAD_ATTR_MODULE:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_WITH_HINT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_WITH_HINT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_WITH_HINT:
 | 
					        case LOAD_ATTR_WITH_HINT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case _LOAD_ATTR_SLOT:
 | 
					        case _LOAD_ATTR_SLOT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_SLOT:
 | 
					        case LOAD_ATTR_SLOT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_CLASS:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_CLASS:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_CLASS:
 | 
					        case LOAD_ATTR_CLASS:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_PROPERTY:
 | 
					        case LOAD_ATTR_PROPERTY:
 | 
				
			||||||
| 
						 | 
					@ -506,10 +528,18 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump)  {
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_METHOD_NO_DICT:
 | 
					        case LOAD_ATTR_METHOD_NO_DICT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
					        case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
					        case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_METHOD_LAZY_DICT:
 | 
					        case LOAD_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case INSTRUMENTED_CALL:
 | 
					        case INSTRUMENTED_CALL:
 | 
				
			||||||
| 
						 | 
					@ -916,16 +946,28 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump)  {
 | 
				
			||||||
            return ((oparg & 1) ? 1 : 0) + 1;
 | 
					            return ((oparg & 1) ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_INSTANCE_VALUE:
 | 
					        case LOAD_ATTR_INSTANCE_VALUE:
 | 
				
			||||||
            return (oparg & 1 ? 1 : 0) + 1;
 | 
					            return (oparg & 1 ? 1 : 0) + 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_MODULE:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_MODULE:
 | 
				
			||||||
 | 
					            return ((oparg & 1) ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_MODULE:
 | 
					        case LOAD_ATTR_MODULE:
 | 
				
			||||||
 | 
					            return (oparg & 1 ? 1 : 0) + 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_WITH_HINT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_WITH_HINT:
 | 
				
			||||||
            return ((oparg & 1) ? 1 : 0) + 1;
 | 
					            return ((oparg & 1) ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_WITH_HINT:
 | 
					        case LOAD_ATTR_WITH_HINT:
 | 
				
			||||||
            return ((oparg & 1) ? 1 : 0) + 1;
 | 
					            return (oparg & 1 ? 1 : 0) + 1;
 | 
				
			||||||
        case _LOAD_ATTR_SLOT:
 | 
					        case _LOAD_ATTR_SLOT:
 | 
				
			||||||
            return ((oparg & 1) ? 1 : 0) + 1;
 | 
					            return ((oparg & 1) ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_SLOT:
 | 
					        case LOAD_ATTR_SLOT:
 | 
				
			||||||
            return (oparg & 1 ? 1 : 0) + 1;
 | 
					            return (oparg & 1 ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_CLASS:
 | 
					        case _CHECK_ATTR_CLASS:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_CLASS:
 | 
				
			||||||
            return ((oparg & 1) ? 1 : 0) + 1;
 | 
					            return ((oparg & 1) ? 1 : 0) + 1;
 | 
				
			||||||
 | 
					        case LOAD_ATTR_CLASS:
 | 
				
			||||||
 | 
					            return (oparg & 1 ? 1 : 0) + 1;
 | 
				
			||||||
        case LOAD_ATTR_PROPERTY:
 | 
					        case LOAD_ATTR_PROPERTY:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
 | 
					        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
 | 
				
			||||||
| 
						 | 
					@ -1062,10 +1104,18 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump)  {
 | 
				
			||||||
            return 2;
 | 
					            return 2;
 | 
				
			||||||
        case LOAD_ATTR_METHOD_NO_DICT:
 | 
					        case LOAD_ATTR_METHOD_NO_DICT:
 | 
				
			||||||
            return 2;
 | 
					            return 2;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
					        case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
					        case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
 | 
					            return 2;
 | 
				
			||||||
        case LOAD_ATTR_METHOD_LAZY_DICT:
 | 
					        case LOAD_ATTR_METHOD_LAZY_DICT:
 | 
				
			||||||
            return 2;
 | 
					            return 2;
 | 
				
			||||||
        case INSTRUMENTED_CALL:
 | 
					        case INSTRUMENTED_CALL:
 | 
				
			||||||
| 
						 | 
					@ -1397,10 +1447,16 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
 | 
				
			||||||
    [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
 | 
					    [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
 | 
				
			||||||
    [_LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [_LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_MODULE] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_WITH_HINT] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [_LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [_LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_CLASS] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
| 
						 | 
					@ -1470,8 +1526,12 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
 | 
				
			||||||
    [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [_LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
					    [_LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
 | 
				
			||||||
    [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
					    [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
 | 
				
			||||||
    [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
 | 
					    [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
 | 
				
			||||||
    [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
 | 
					    [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
 | 
				
			||||||
| 
						 | 
					@ -1631,7 +1691,10 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
 | 
				
			||||||
    [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_METHOD, 0, 0 } } },
 | 
					    [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_METHOD, 0, 0 } } },
 | 
				
			||||||
    [LOAD_ATTR] = { .nuops = 1, .uops = { { LOAD_ATTR, 0, 0 } } },
 | 
					    [LOAD_ATTR] = { .nuops = 1, .uops = { { LOAD_ATTR, 0, 0 } } },
 | 
				
			||||||
    [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } },
 | 
					    [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_MODULE] = { .nuops = 2, .uops = { { _CHECK_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, 1, 3 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_WITH_HINT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_WITH_HINT, 0, 0 }, { _LOAD_ATTR_WITH_HINT, 1, 3 } } },
 | 
				
			||||||
    [LOAD_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 } } },
 | 
					    [LOAD_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_CLASS] = { .nuops = 2, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 } } },
 | 
				
			||||||
    [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } },
 | 
					    [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } },
 | 
				
			||||||
    [STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 } } },
 | 
					    [STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 } } },
 | 
				
			||||||
    [COMPARE_OP] = { .nuops = 1, .uops = { { COMPARE_OP, 0, 0 } } },
 | 
					    [COMPARE_OP] = { .nuops = 1, .uops = { { COMPARE_OP, 0, 0 } } },
 | 
				
			||||||
| 
						 | 
					@ -1653,6 +1716,9 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
 | 
				
			||||||
    [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } },
 | 
					    [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } },
 | 
				
			||||||
    [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } },
 | 
					    [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } },
 | 
				
			||||||
    [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } },
 | 
					    [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } },
 | 
				
			||||||
 | 
					    [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 0, 0 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } },
 | 
				
			||||||
    [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 9, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SET_IP, 7, 3 }, { _SAVE_CURRENT_IP, 0, 0 }, { _PUSH_FRAME, 0, 0 } } },
 | 
					    [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 9, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SET_IP, 7, 3 }, { _SAVE_CURRENT_IP, 0, 0 }, { _PUSH_FRAME, 0, 0 } } },
 | 
				
			||||||
    [CALL_PY_EXACT_ARGS] = { .nuops = 7, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SET_IP, 7, 3 }, { _SAVE_CURRENT_IP, 0, 0 }, { _PUSH_FRAME, 0, 0 } } },
 | 
					    [CALL_PY_EXACT_ARGS] = { .nuops = 7, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SET_IP, 7, 3 }, { _SAVE_CURRENT_IP, 0, 0 }, { _PUSH_FRAME, 0, 0 } } },
 | 
				
			||||||
    [CALL_TYPE_1] = { .nuops = 1, .uops = { { CALL_TYPE_1, 0, 0 } } },
 | 
					    [CALL_TYPE_1] = { .nuops = 1, .uops = { { CALL_TYPE_1, 0, 0 } } },
 | 
				
			||||||
| 
						 | 
					@ -1705,7 +1771,13 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
 | 
				
			||||||
    [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION",
 | 
					    [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION",
 | 
				
			||||||
    [_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
 | 
					    [_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
 | 
				
			||||||
    [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE",
 | 
					    [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE",
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_MODULE] = "_CHECK_ATTR_MODULE",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_MODULE] = "_LOAD_ATTR_MODULE",
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_WITH_HINT] = "_CHECK_ATTR_WITH_HINT",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT",
 | 
				
			||||||
    [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT",
 | 
					    [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT",
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_CLASS] = "_CHECK_ATTR_CLASS",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_CLASS] = "_LOAD_ATTR_CLASS",
 | 
				
			||||||
    [_GUARD_DORV_VALUES] = "_GUARD_DORV_VALUES",
 | 
					    [_GUARD_DORV_VALUES] = "_GUARD_DORV_VALUES",
 | 
				
			||||||
    [_STORE_ATTR_INSTANCE_VALUE] = "_STORE_ATTR_INSTANCE_VALUE",
 | 
					    [_STORE_ATTR_INSTANCE_VALUE] = "_STORE_ATTR_INSTANCE_VALUE",
 | 
				
			||||||
    [_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
 | 
					    [_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
 | 
				
			||||||
| 
						 | 
					@ -1726,6 +1798,10 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
 | 
				
			||||||
    [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION",
 | 
					    [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION",
 | 
				
			||||||
    [_LOAD_ATTR_METHOD_WITH_VALUES] = "_LOAD_ATTR_METHOD_WITH_VALUES",
 | 
					    [_LOAD_ATTR_METHOD_WITH_VALUES] = "_LOAD_ATTR_METHOD_WITH_VALUES",
 | 
				
			||||||
    [_LOAD_ATTR_METHOD_NO_DICT] = "_LOAD_ATTR_METHOD_NO_DICT",
 | 
					    [_LOAD_ATTR_METHOD_NO_DICT] = "_LOAD_ATTR_METHOD_NO_DICT",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "_LOAD_ATTR_NONDESCRIPTOR_NO_DICT",
 | 
				
			||||||
 | 
					    [_CHECK_ATTR_METHOD_LAZY_DICT] = "_CHECK_ATTR_METHOD_LAZY_DICT",
 | 
				
			||||||
 | 
					    [_LOAD_ATTR_METHOD_LAZY_DICT] = "_LOAD_ATTR_METHOD_LAZY_DICT",
 | 
				
			||||||
    [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = "_CHECK_CALL_BOUND_METHOD_EXACT_ARGS",
 | 
					    [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = "_CHECK_CALL_BOUND_METHOD_EXACT_ARGS",
 | 
				
			||||||
    [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = "_INIT_CALL_BOUND_METHOD_EXACT_ARGS",
 | 
					    [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = "_INIT_CALL_BOUND_METHOD_EXACT_ARGS",
 | 
				
			||||||
    [_CHECK_PEP_523] = "_CHECK_PEP_523",
 | 
					    [_CHECK_PEP_523] = "_CHECK_PEP_523",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								Python/abstract_interp_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										56
									
								
								Python/abstract_interp_cases.c.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -474,6 +474,28 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_MODULE: {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_MODULE: {
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_WITH_HINT: {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_WITH_HINT: {
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _LOAD_ATTR_SLOT: {
 | 
					        case _LOAD_ATTR_SLOT: {
 | 
				
			||||||
            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
| 
						 | 
					@ -481,6 +503,17 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_CLASS: {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_CLASS: {
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _GUARD_DORV_VALUES: {
 | 
					        case _GUARD_DORV_VALUES: {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -670,6 +703,29 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(0)), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(0)), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_METHOD_LAZY_DICT: {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_METHOD_LAZY_DICT: {
 | 
				
			||||||
 | 
					            STACK_GROW(1);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
 | 
				
			||||||
 | 
					            PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
 | 
					        case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1887,11 +1887,15 @@ dummy_func(
 | 
				
			||||||
            _LOAD_ATTR_INSTANCE_VALUE +
 | 
					            _LOAD_ATTR_INSTANCE_VALUE +
 | 
				
			||||||
            unused/5;  // Skip over rest of cache
 | 
					            unused/5;  // Skip over rest of cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- attr, null if (oparg & 1))) {
 | 
					        op(_CHECK_ATTR_MODULE, (type_version/2, owner -- owner)) {
 | 
				
			||||||
            DEOPT_IF(!PyModule_CheckExact(owner));
 | 
					            DEOPT_IF(!PyModule_CheckExact(owner));
 | 
				
			||||||
            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
					            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
            assert(dict != NULL);
 | 
					            assert(dict != NULL);
 | 
				
			||||||
            DEOPT_IF(dict->ma_keys->dk_version != type_version);
 | 
					            DEOPT_IF(dict->ma_keys->dk_version != type_version);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
            assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
 | 
					            assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
 | 
				
			||||||
            assert(index < dict->ma_keys->dk_nentries);
 | 
					            assert(index < dict->ma_keys->dk_nentries);
 | 
				
			||||||
            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
 | 
					            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
 | 
				
			||||||
| 
						 | 
					@ -1903,19 +1907,26 @@ dummy_func(
 | 
				
			||||||
            DECREF_INPUTS();
 | 
					            DECREF_INPUTS();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_WITH_HINT, (unused/1, type_version/2, index/1, unused/5, owner -- attr, null if (oparg & 1))) {
 | 
					        macro(LOAD_ATTR_MODULE) =
 | 
				
			||||||
            PyTypeObject *tp = Py_TYPE(owner);
 | 
					            unused/1 +
 | 
				
			||||||
            assert(type_version != 0);
 | 
					            _CHECK_ATTR_MODULE +
 | 
				
			||||||
            DEOPT_IF(tp->tp_version_tag != type_version);
 | 
					            _LOAD_ATTR_MODULE +
 | 
				
			||||||
            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
					            unused/5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_CHECK_ATTR_WITH_HINT, (owner -- owner)) {
 | 
				
			||||||
 | 
					            assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
				
			||||||
            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
					            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
            DEOPT_IF(_PyDictOrValues_IsValues(dorv));
 | 
					            DEOPT_IF(_PyDictOrValues_IsValues(dorv));
 | 
				
			||||||
            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
					            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
            DEOPT_IF(dict == NULL);
 | 
					            DEOPT_IF(dict == NULL);
 | 
				
			||||||
            assert(PyDict_CheckExact((PyObject *)dict));
 | 
					            assert(PyDict_CheckExact((PyObject *)dict));
 | 
				
			||||||
            PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
 | 
					        }
 | 
				
			||||||
            uint16_t hint = index;
 | 
					
 | 
				
			||||||
 | 
					        op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) {
 | 
				
			||||||
 | 
					            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
 | 
					            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
 | 
				
			||||||
 | 
					            PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
 | 
				
			||||||
            if (DK_IS_UNICODE(dict->ma_keys)) {
 | 
					            if (DK_IS_UNICODE(dict->ma_keys)) {
 | 
				
			||||||
                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
 | 
					                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
 | 
				
			||||||
                DEOPT_IF(ep->me_key != name);
 | 
					                DEOPT_IF(ep->me_key != name);
 | 
				
			||||||
| 
						 | 
					@ -1933,6 +1944,13 @@ dummy_func(
 | 
				
			||||||
            DECREF_INPUTS();
 | 
					            DECREF_INPUTS();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        macro(LOAD_ATTR_WITH_HINT) =
 | 
				
			||||||
 | 
					            unused/1 +
 | 
				
			||||||
 | 
					            _GUARD_TYPE_VERSION +
 | 
				
			||||||
 | 
					            _CHECK_ATTR_WITH_HINT +
 | 
				
			||||||
 | 
					            _LOAD_ATTR_WITH_HINT +
 | 
				
			||||||
 | 
					            unused/5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
 | 
					        op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
 | 
				
			||||||
            char *addr = (char *)owner + index;
 | 
					            char *addr = (char *)owner + index;
 | 
				
			||||||
            attr = *(PyObject **)addr;
 | 
					            attr = *(PyObject **)addr;
 | 
				
			||||||
| 
						 | 
					@ -1949,20 +1967,27 @@ dummy_func(
 | 
				
			||||||
            _LOAD_ATTR_SLOT +  // NOTE: This action may also deopt
 | 
					            _LOAD_ATTR_SLOT +  // NOTE: This action may also deopt
 | 
				
			||||||
            unused/5;
 | 
					            unused/5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, null if (oparg & 1))) {
 | 
					        op(_CHECK_ATTR_CLASS, (type_version/2, owner -- owner)) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
            DEOPT_IF(!PyType_Check(owner));
 | 
					            DEOPT_IF(!PyType_Check(owner));
 | 
				
			||||||
            DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version);
 | 
					 | 
				
			||||||
            assert(type_version != 0);
 | 
					            assert(type_version != 0);
 | 
				
			||||||
 | 
					            DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
 | 
				
			||||||
            STAT_INC(LOAD_ATTR, hit);
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            assert(descr != NULL);
 | 
				
			||||||
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
            null = NULL;
 | 
					            null = NULL;
 | 
				
			||||||
            attr = descr;
 | 
					 | 
				
			||||||
            assert(attr != NULL);
 | 
					 | 
				
			||||||
            Py_INCREF(attr);
 | 
					 | 
				
			||||||
            DECREF_INPUTS();
 | 
					            DECREF_INPUTS();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        macro(LOAD_ATTR_CLASS) =
 | 
				
			||||||
 | 
					            unused/1 +
 | 
				
			||||||
 | 
					            _CHECK_ATTR_CLASS +
 | 
				
			||||||
 | 
					            unused/2 +
 | 
				
			||||||
 | 
					            _LOAD_ATTR_CLASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused, unused if (0))) {
 | 
					        inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused, unused if (0))) {
 | 
				
			||||||
            assert((oparg & 1) == 0);
 | 
					            assert((oparg & 1) == 0);
 | 
				
			||||||
            DEOPT_IF(tstate->interp->eval_frame);
 | 
					            DEOPT_IF(tstate->interp->eval_frame);
 | 
				
			||||||
| 
						 | 
					@ -2819,43 +2844,46 @@ dummy_func(
 | 
				
			||||||
            unused/2 +
 | 
					            unused/2 +
 | 
				
			||||||
            _LOAD_ATTR_METHOD_NO_DICT;
 | 
					            _LOAD_ATTR_METHOD_NO_DICT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, owner -- attr, unused if (0))) {
 | 
					        op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr, unused if (0))) {
 | 
				
			||||||
            assert((oparg & 1) == 0);
 | 
					            assert((oparg & 1) == 0);
 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					 | 
				
			||||||
            assert(type_version != 0);
 | 
					 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version);
 | 
					 | 
				
			||||||
            assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
					 | 
				
			||||||
            PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
 | 
					 | 
				
			||||||
            DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv));
 | 
					 | 
				
			||||||
            PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
 | 
					 | 
				
			||||||
            DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version);
 | 
					 | 
				
			||||||
            STAT_INC(LOAD_ATTR, hit);
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
            assert(descr != NULL);
 | 
					            assert(descr != NULL);
 | 
				
			||||||
            DECREF_INPUTS();
 | 
					            DECREF_INPUTS();
 | 
				
			||||||
            attr = Py_NewRef(descr);
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, unused if (0))) {
 | 
					        macro(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) =
 | 
				
			||||||
 | 
					            unused/1 +
 | 
				
			||||||
 | 
					            _GUARD_TYPE_VERSION +
 | 
				
			||||||
 | 
					            _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
 | 
				
			||||||
 | 
					            _GUARD_KEYS_VERSION +
 | 
				
			||||||
 | 
					            _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr, unused if (0))) {
 | 
				
			||||||
            assert((oparg & 1) == 0);
 | 
					            assert((oparg & 1) == 0);
 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					            assert(Py_TYPE(owner)->tp_dictoffset == 0);
 | 
				
			||||||
            assert(type_version != 0);
 | 
					 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version);
 | 
					 | 
				
			||||||
            assert(owner_cls->tp_dictoffset == 0);
 | 
					 | 
				
			||||||
            STAT_INC(LOAD_ATTR, hit);
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
            assert(descr != NULL);
 | 
					            assert(descr != NULL);
 | 
				
			||||||
            DECREF_INPUTS();
 | 
					            DECREF_INPUTS();
 | 
				
			||||||
            attr = Py_NewRef(descr);
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, self if (1))) {
 | 
					        macro(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) =
 | 
				
			||||||
            assert(oparg & 1);
 | 
					            unused/1 +
 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					            _GUARD_TYPE_VERSION +
 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version);
 | 
					            unused/2 +
 | 
				
			||||||
            Py_ssize_t dictoffset = owner_cls->tp_dictoffset;
 | 
					            _LOAD_ATTR_NONDESCRIPTOR_NO_DICT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_CHECK_ATTR_METHOD_LAZY_DICT, (owner -- owner)) {
 | 
				
			||||||
 | 
					            Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
 | 
				
			||||||
            assert(dictoffset > 0);
 | 
					            assert(dictoffset > 0);
 | 
				
			||||||
            PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
 | 
					            PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
 | 
				
			||||||
            /* This object has a __dict__, just not yet created */
 | 
					            /* This object has a __dict__, just not yet created */
 | 
				
			||||||
            DEOPT_IF(dict != NULL);
 | 
					            DEOPT_IF(dict != NULL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
 | 
				
			||||||
 | 
					            assert(oparg & 1);
 | 
				
			||||||
            STAT_INC(LOAD_ATTR, hit);
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
            assert(descr != NULL);
 | 
					            assert(descr != NULL);
 | 
				
			||||||
            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
 | 
					            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
 | 
				
			||||||
| 
						 | 
					@ -2863,6 +2891,13 @@ dummy_func(
 | 
				
			||||||
            self = owner;
 | 
					            self = owner;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        macro(LOAD_ATTR_METHOD_LAZY_DICT) =
 | 
				
			||||||
 | 
					            unused/1 +
 | 
				
			||||||
 | 
					            _GUARD_TYPE_VERSION +
 | 
				
			||||||
 | 
					            _CHECK_ATTR_METHOD_LAZY_DICT +
 | 
				
			||||||
 | 
					            unused/2 +
 | 
				
			||||||
 | 
					            _LOAD_ATTR_METHOD_LAZY_DICT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inst(INSTRUMENTED_CALL, ( -- )) {
 | 
					        inst(INSTRUMENTED_CALL, ( -- )) {
 | 
				
			||||||
            int is_meth = PEEK(oparg + 1) != NULL;
 | 
					            int is_meth = PEEK(oparg + 1) != NULL;
 | 
				
			||||||
            int total_args = oparg + is_meth;
 | 
					            int total_args = oparg + is_meth;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										161
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										161
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -1711,6 +1711,82 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_MODULE: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            uint32_t type_version = (uint32_t)operand;
 | 
				
			||||||
 | 
					            DEOPT_IF(!PyModule_CheckExact(owner), _CHECK_ATTR_MODULE);
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
 | 
					            assert(dict != NULL);
 | 
				
			||||||
 | 
					            DEOPT_IF(dict->ma_keys->dk_version != type_version, _CHECK_ATTR_MODULE);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_MODULE: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            uint16_t index = (uint16_t)operand;
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
 | 
					            assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
 | 
				
			||||||
 | 
					            assert(index < dict->ma_keys->dk_nentries);
 | 
				
			||||||
 | 
					            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
 | 
				
			||||||
 | 
					            attr = ep->me_value;
 | 
				
			||||||
 | 
					            DEOPT_IF(attr == NULL, _LOAD_ATTR_MODULE);
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            Py_INCREF(attr);
 | 
				
			||||||
 | 
					            null = NULL;
 | 
				
			||||||
 | 
					            Py_DECREF(owner);
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_WITH_HINT: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
				
			||||||
 | 
					            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
 | 
					            DEOPT_IF(_PyDictOrValues_IsValues(dorv), _CHECK_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
 | 
					            DEOPT_IF(dict == NULL, _CHECK_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					            assert(PyDict_CheckExact((PyObject *)dict));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_WITH_HINT: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            uint16_t hint = (uint16_t)operand;
 | 
				
			||||||
 | 
					            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
 | 
					            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
 | 
					            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, _LOAD_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					            PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
 | 
				
			||||||
 | 
					            if (DK_IS_UNICODE(dict->ma_keys)) {
 | 
				
			||||||
 | 
					                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
 | 
				
			||||||
 | 
					                DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					                attr = ep->me_value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
 | 
				
			||||||
 | 
					                DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					                attr = ep->me_value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            DEOPT_IF(attr == NULL, _LOAD_ATTR_WITH_HINT);
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            Py_INCREF(attr);
 | 
				
			||||||
 | 
					            null = NULL;
 | 
				
			||||||
 | 
					            Py_DECREF(owner);
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _LOAD_ATTR_SLOT: {
 | 
					        case _LOAD_ATTR_SLOT: {
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
| 
						 | 
					@ -1730,6 +1806,33 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_CLASS: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            uint32_t type_version = (uint32_t)operand;
 | 
				
			||||||
 | 
					            DEOPT_IF(!PyType_Check(owner), _CHECK_ATTR_CLASS);
 | 
				
			||||||
 | 
					            assert(type_version != 0);
 | 
				
			||||||
 | 
					            DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, _CHECK_ATTR_CLASS);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_CLASS: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            PyObject *descr = (PyObject *)operand;
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            assert(descr != NULL);
 | 
				
			||||||
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            null = NULL;
 | 
				
			||||||
 | 
					            Py_DECREF(owner);
 | 
				
			||||||
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _GUARD_DORV_VALUES: {
 | 
					        case _GUARD_DORV_VALUES: {
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
| 
						 | 
					@ -2339,6 +2442,64 @@
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            PyObject *descr = (PyObject *)operand;
 | 
				
			||||||
 | 
					            assert((oparg & 1) == 0);
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            assert(descr != NULL);
 | 
				
			||||||
 | 
					            Py_DECREF(owner);
 | 
				
			||||||
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            stack_pointer[-1] = attr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            PyObject *descr = (PyObject *)operand;
 | 
				
			||||||
 | 
					            assert((oparg & 1) == 0);
 | 
				
			||||||
 | 
					            assert(Py_TYPE(owner)->tp_dictoffset == 0);
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            assert(descr != NULL);
 | 
				
			||||||
 | 
					            Py_DECREF(owner);
 | 
				
			||||||
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            stack_pointer[-1] = attr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _CHECK_ATTR_METHOD_LAZY_DICT: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
 | 
				
			||||||
 | 
					            assert(dictoffset > 0);
 | 
				
			||||||
 | 
					            PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
 | 
				
			||||||
 | 
					            /* This object has a __dict__, just not yet created */
 | 
				
			||||||
 | 
					            DEOPT_IF(dict != NULL, _CHECK_ATTR_METHOD_LAZY_DICT);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case _LOAD_ATTR_METHOD_LAZY_DICT: {
 | 
				
			||||||
 | 
					            PyObject *owner;
 | 
				
			||||||
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            PyObject *self;
 | 
				
			||||||
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            PyObject *descr = (PyObject *)operand;
 | 
				
			||||||
 | 
					            assert(oparg & 1);
 | 
				
			||||||
 | 
					            STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					            assert(descr != NULL);
 | 
				
			||||||
 | 
					            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
 | 
				
			||||||
 | 
					            attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            self = owner;
 | 
				
			||||||
 | 
					            STACK_GROW(1);
 | 
				
			||||||
 | 
					            stack_pointer[-2] = attr;
 | 
				
			||||||
 | 
					            stack_pointer[-1] = self;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
 | 
					        case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
 | 
				
			||||||
            PyObject *null;
 | 
					            PyObject *null;
 | 
				
			||||||
            PyObject *callable;
 | 
					            PyObject *callable;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										103
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										103
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -2432,13 +2432,19 @@
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
            PyObject *null = NULL;
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            // _CHECK_ATTR_MODULE
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
            uint16_t index = read_u16(&next_instr[3].cache);
 | 
					 | 
				
			||||||
                DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
 | 
					                DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
 | 
				
			||||||
                PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
					                PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
                assert(dict != NULL);
 | 
					                assert(dict != NULL);
 | 
				
			||||||
                DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR);
 | 
					                DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _LOAD_ATTR_MODULE
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                uint16_t index = read_u16(&next_instr[3].cache);
 | 
				
			||||||
 | 
					                PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
 | 
				
			||||||
                assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
 | 
					                assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
 | 
				
			||||||
                assert(index < dict->ma_keys->dk_nentries);
 | 
					                assert(index < dict->ma_keys->dk_nentries);
 | 
				
			||||||
                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
 | 
					                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
 | 
				
			||||||
| 
						 | 
					@ -2448,6 +2454,7 @@
 | 
				
			||||||
                Py_INCREF(attr);
 | 
					                Py_INCREF(attr);
 | 
				
			||||||
                null = NULL;
 | 
					                null = NULL;
 | 
				
			||||||
                Py_DECREF(owner);
 | 
					                Py_DECREF(owner);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
| 
						 | 
					@ -2459,21 +2466,30 @@
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
            PyObject *null = NULL;
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            // _GUARD_TYPE_VERSION
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
            uint16_t index = read_u16(&next_instr[3].cache);
 | 
					 | 
				
			||||||
                PyTypeObject *tp = Py_TYPE(owner);
 | 
					                PyTypeObject *tp = Py_TYPE(owner);
 | 
				
			||||||
                assert(type_version != 0);
 | 
					                assert(type_version != 0);
 | 
				
			||||||
                DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
 | 
					                DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
 | 
				
			||||||
            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
					            }
 | 
				
			||||||
 | 
					            // _CHECK_ATTR_WITH_HINT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
				
			||||||
                PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
					                PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
                DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
 | 
					                DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
 | 
				
			||||||
                PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
					                PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
                DEOPT_IF(dict == NULL, LOAD_ATTR);
 | 
					                DEOPT_IF(dict == NULL, LOAD_ATTR);
 | 
				
			||||||
                assert(PyDict_CheckExact((PyObject *)dict));
 | 
					                assert(PyDict_CheckExact((PyObject *)dict));
 | 
				
			||||||
            PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
 | 
					            }
 | 
				
			||||||
            uint16_t hint = index;
 | 
					            // _LOAD_ATTR_WITH_HINT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                uint16_t hint = read_u16(&next_instr[3].cache);
 | 
				
			||||||
 | 
					                PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
 | 
					                PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
 | 
				
			||||||
                DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
 | 
					                DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
 | 
				
			||||||
 | 
					                PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
 | 
				
			||||||
                if (DK_IS_UNICODE(dict->ma_keys)) {
 | 
					                if (DK_IS_UNICODE(dict->ma_keys)) {
 | 
				
			||||||
                    PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
 | 
					                    PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
 | 
				
			||||||
                    DEOPT_IF(ep->me_key != name, LOAD_ATTR);
 | 
					                    DEOPT_IF(ep->me_key != name, LOAD_ATTR);
 | 
				
			||||||
| 
						 | 
					@ -2489,6 +2505,7 @@
 | 
				
			||||||
                Py_INCREF(attr);
 | 
					                Py_INCREF(attr);
 | 
				
			||||||
                null = NULL;
 | 
					                null = NULL;
 | 
				
			||||||
                Py_DECREF(owner);
 | 
					                Py_DECREF(owner);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
| 
						 | 
					@ -2530,20 +2547,23 @@
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
            PyObject *null = NULL;
 | 
					            PyObject *null = NULL;
 | 
				
			||||||
 | 
					            // _CHECK_ATTR_CLASS
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
            PyObject *descr = read_obj(&next_instr[5].cache);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                DEOPT_IF(!PyType_Check(owner), LOAD_ATTR);
 | 
					                DEOPT_IF(!PyType_Check(owner), LOAD_ATTR);
 | 
				
			||||||
            DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, LOAD_ATTR);
 | 
					 | 
				
			||||||
                assert(type_version != 0);
 | 
					                assert(type_version != 0);
 | 
				
			||||||
 | 
					                DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _LOAD_ATTR_CLASS
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                PyObject *descr = read_obj(&next_instr[5].cache);
 | 
				
			||||||
                STAT_INC(LOAD_ATTR, hit);
 | 
					                STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
 | 
					                assert(descr != NULL);
 | 
				
			||||||
 | 
					                attr = Py_NewRef(descr);
 | 
				
			||||||
                null = NULL;
 | 
					                null = NULL;
 | 
				
			||||||
            attr = descr;
 | 
					 | 
				
			||||||
            assert(attr != NULL);
 | 
					 | 
				
			||||||
            Py_INCREF(attr);
 | 
					 | 
				
			||||||
                Py_DECREF(owner);
 | 
					                Py_DECREF(owner);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
					            STACK_GROW(((oparg & 1) ? 1 : 0));
 | 
				
			||||||
            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
					            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
 | 
				
			||||||
            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
					            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
 | 
				
			||||||
| 
						 | 
					@ -3646,23 +3666,36 @@
 | 
				
			||||||
        TARGET(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) {
 | 
					        TARGET(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES) {
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            // _GUARD_TYPE_VERSION
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
            uint32_t keys_version = read_u32(&next_instr[3].cache);
 | 
					                PyTypeObject *tp = Py_TYPE(owner);
 | 
				
			||||||
            PyObject *descr = read_obj(&next_instr[5].cache);
 | 
					 | 
				
			||||||
            assert((oparg & 1) == 0);
 | 
					 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					 | 
				
			||||||
                assert(type_version != 0);
 | 
					                assert(type_version != 0);
 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
 | 
					                DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
 | 
				
			||||||
            assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
					            }
 | 
				
			||||||
 | 
					            // _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
 | 
				
			||||||
                PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
 | 
					                PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
 | 
				
			||||||
                DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR);
 | 
					                DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _GUARD_KEYS_VERSION
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                uint32_t keys_version = read_u32(&next_instr[3].cache);
 | 
				
			||||||
 | 
					                PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
				
			||||||
                PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
 | 
					                PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
 | 
				
			||||||
                DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, LOAD_ATTR);
 | 
					                DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                PyObject *descr = read_obj(&next_instr[5].cache);
 | 
				
			||||||
 | 
					                assert((oparg & 1) == 0);
 | 
				
			||||||
                STAT_INC(LOAD_ATTR, hit);
 | 
					                STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
                assert(descr != NULL);
 | 
					                assert(descr != NULL);
 | 
				
			||||||
                Py_DECREF(owner);
 | 
					                Py_DECREF(owner);
 | 
				
			||||||
                attr = Py_NewRef(descr);
 | 
					                attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            stack_pointer[-1] = attr;
 | 
					            stack_pointer[-1] = attr;
 | 
				
			||||||
            next_instr += 9;
 | 
					            next_instr += 9;
 | 
				
			||||||
            DISPATCH();
 | 
					            DISPATCH();
 | 
				
			||||||
| 
						 | 
					@ -3671,18 +3704,24 @@
 | 
				
			||||||
        TARGET(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) {
 | 
					        TARGET(LOAD_ATTR_NONDESCRIPTOR_NO_DICT) {
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
 | 
					            // _GUARD_TYPE_VERSION
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
 | 
					                PyTypeObject *tp = Py_TYPE(owner);
 | 
				
			||||||
 | 
					                assert(type_version != 0);
 | 
				
			||||||
 | 
					                DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _LOAD_ATTR_NONDESCRIPTOR_NO_DICT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                PyObject *descr = read_obj(&next_instr[5].cache);
 | 
					                PyObject *descr = read_obj(&next_instr[5].cache);
 | 
				
			||||||
                assert((oparg & 1) == 0);
 | 
					                assert((oparg & 1) == 0);
 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					                assert(Py_TYPE(owner)->tp_dictoffset == 0);
 | 
				
			||||||
            assert(type_version != 0);
 | 
					 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
 | 
					 | 
				
			||||||
            assert(owner_cls->tp_dictoffset == 0);
 | 
					 | 
				
			||||||
                STAT_INC(LOAD_ATTR, hit);
 | 
					                STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
                assert(descr != NULL);
 | 
					                assert(descr != NULL);
 | 
				
			||||||
                Py_DECREF(owner);
 | 
					                Py_DECREF(owner);
 | 
				
			||||||
                attr = Py_NewRef(descr);
 | 
					                attr = Py_NewRef(descr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            stack_pointer[-1] = attr;
 | 
					            stack_pointer[-1] = attr;
 | 
				
			||||||
            next_instr += 9;
 | 
					            next_instr += 9;
 | 
				
			||||||
            DISPATCH();
 | 
					            DISPATCH();
 | 
				
			||||||
| 
						 | 
					@ -3692,22 +3731,32 @@
 | 
				
			||||||
            PyObject *owner;
 | 
					            PyObject *owner;
 | 
				
			||||||
            PyObject *attr;
 | 
					            PyObject *attr;
 | 
				
			||||||
            PyObject *self;
 | 
					            PyObject *self;
 | 
				
			||||||
 | 
					            // _GUARD_TYPE_VERSION
 | 
				
			||||||
            owner = stack_pointer[-1];
 | 
					            owner = stack_pointer[-1];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
					                uint32_t type_version = read_u32(&next_instr[1].cache);
 | 
				
			||||||
            PyObject *descr = read_obj(&next_instr[5].cache);
 | 
					                PyTypeObject *tp = Py_TYPE(owner);
 | 
				
			||||||
            assert(oparg & 1);
 | 
					                assert(type_version != 0);
 | 
				
			||||||
            PyTypeObject *owner_cls = Py_TYPE(owner);
 | 
					                DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
 | 
				
			||||||
            DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
 | 
					            }
 | 
				
			||||||
            Py_ssize_t dictoffset = owner_cls->tp_dictoffset;
 | 
					            // _CHECK_ATTR_METHOD_LAZY_DICT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
 | 
				
			||||||
                assert(dictoffset > 0);
 | 
					                assert(dictoffset > 0);
 | 
				
			||||||
                PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
 | 
					                PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
 | 
				
			||||||
                /* This object has a __dict__, just not yet created */
 | 
					                /* This object has a __dict__, just not yet created */
 | 
				
			||||||
                DEOPT_IF(dict != NULL, LOAD_ATTR);
 | 
					                DEOPT_IF(dict != NULL, LOAD_ATTR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // _LOAD_ATTR_METHOD_LAZY_DICT
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                PyObject *descr = read_obj(&next_instr[5].cache);
 | 
				
			||||||
 | 
					                assert(oparg & 1);
 | 
				
			||||||
                STAT_INC(LOAD_ATTR, hit);
 | 
					                STAT_INC(LOAD_ATTR, hit);
 | 
				
			||||||
                assert(descr != NULL);
 | 
					                assert(descr != NULL);
 | 
				
			||||||
                assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
 | 
					                assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
 | 
				
			||||||
                attr = Py_NewRef(descr);
 | 
					                attr = Py_NewRef(descr);
 | 
				
			||||||
                self = owner;
 | 
					                self = owner;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            STACK_GROW(1);
 | 
					            STACK_GROW(1);
 | 
				
			||||||
            stack_pointer[-2] = attr;
 | 
					            stack_pointer[-2] = attr;
 | 
				
			||||||
            stack_pointer[-1] = self;
 | 
					            stack_pointer[-1] = self;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,12 +210,14 @@ def write_body(
 | 
				
			||||||
                    out.write_raw(f"{space}if ({cond}) goto {label};\n")
 | 
					                    out.write_raw(f"{space}if ({cond}) goto {label};\n")
 | 
				
			||||||
            elif m := re.match(r"(\s*)DEOPT_IF\((.+)\);\s*(?://.*)?$", line):
 | 
					            elif m := re.match(r"(\s*)DEOPT_IF\((.+)\);\s*(?://.*)?$", line):
 | 
				
			||||||
                space, cond = m.groups()
 | 
					                space, cond = m.groups()
 | 
				
			||||||
 | 
					                space = extra + space
 | 
				
			||||||
                target = family.name if family else self.name
 | 
					                target = family.name if family else self.name
 | 
				
			||||||
                out.write_raw(f"{space}DEOPT_IF({cond}, {target});\n")
 | 
					                out.write_raw(f"{space}DEOPT_IF({cond}, {target});\n")
 | 
				
			||||||
            elif "DEOPT" in line:
 | 
					            elif "DEOPT" in line:
 | 
				
			||||||
                filename = context.owner.filename
 | 
					                filename = context.owner.filename
 | 
				
			||||||
                lineno = context.owner.tokens[context.begin].line
 | 
					                lineno = context.owner.tokens[context.begin].line
 | 
				
			||||||
                print(f"{filename}:{lineno}: ERROR: DEOPT_IF() must be all on one line")
 | 
					                print(f"{filename}:{lineno}: ERROR: DEOPT_IF() must be all on one line")
 | 
				
			||||||
 | 
					                out.write_raw(extra + line)
 | 
				
			||||||
            elif m := re.match(r"(\s*)DECREF_INPUTS\(\);\s*(?://.*)?$", line):
 | 
					            elif m := re.match(r"(\s*)DECREF_INPUTS\(\);\s*(?://.*)?$", line):
 | 
				
			||||||
                out.reset_lineno()
 | 
					                out.reset_lineno()
 | 
				
			||||||
                space = extra + m.group(1)
 | 
					                space = extra + m.group(1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue