mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
gh-104909: Split some more insts into ops (#109943)
These are the most popular specializations of `LOAD_ATTR` and `STORE_ATTR` that weren't already viable uops: * Split LOAD_ATTR_METHOD_WITH_VALUES * Split LOAD_ATTR_METHOD_NO_DICT * Split LOAD_ATTR_SLOT * Split STORE_ATTR_SLOT * Split STORE_ATTR_INSTANCE_VALUE Also: * Add `-v` flag to code generator which prints a list of non-viable uops (easter-egg: it can print execution counts -- see source) * Double _Py_UOP_MAX_TRACE_LENGTH to 128 I had dropped one of the DEOPT_IF() calls! :-(
This commit is contained in:
parent
45cf5b0c69
commit
5bb6f0fcba
8 changed files with 519 additions and 115 deletions
120
Include/internal/pycore_opcode_metadata.h
generated
120
Include/internal/pycore_opcode_metadata.h
generated
|
@ -46,31 +46,40 @@
|
||||||
#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 _IS_NONE 321
|
#define _LOAD_ATTR_SLOT 321
|
||||||
#define _ITER_CHECK_LIST 322
|
#define _GUARD_DORV_VALUES 322
|
||||||
#define _ITER_JUMP_LIST 323
|
#define _STORE_ATTR_INSTANCE_VALUE 323
|
||||||
#define _IS_ITER_EXHAUSTED_LIST 324
|
#define _GUARD_TYPE_VERSION_STORE 324
|
||||||
#define _ITER_NEXT_LIST 325
|
#define _STORE_ATTR_SLOT 325
|
||||||
#define _ITER_CHECK_TUPLE 326
|
#define _IS_NONE 326
|
||||||
#define _ITER_JUMP_TUPLE 327
|
#define _ITER_CHECK_LIST 327
|
||||||
#define _IS_ITER_EXHAUSTED_TUPLE 328
|
#define _ITER_JUMP_LIST 328
|
||||||
#define _ITER_NEXT_TUPLE 329
|
#define _IS_ITER_EXHAUSTED_LIST 329
|
||||||
#define _ITER_CHECK_RANGE 330
|
#define _ITER_NEXT_LIST 330
|
||||||
#define _ITER_JUMP_RANGE 331
|
#define _ITER_CHECK_TUPLE 331
|
||||||
#define _IS_ITER_EXHAUSTED_RANGE 332
|
#define _ITER_JUMP_TUPLE 332
|
||||||
#define _ITER_NEXT_RANGE 333
|
#define _IS_ITER_EXHAUSTED_TUPLE 333
|
||||||
#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 334
|
#define _ITER_NEXT_TUPLE 334
|
||||||
#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 335
|
#define _ITER_CHECK_RANGE 335
|
||||||
#define _CHECK_PEP_523 336
|
#define _ITER_JUMP_RANGE 336
|
||||||
#define _CHECK_FUNCTION_EXACT_ARGS 337
|
#define _IS_ITER_EXHAUSTED_RANGE 337
|
||||||
#define _CHECK_STACK_SPACE 338
|
#define _ITER_NEXT_RANGE 338
|
||||||
#define _INIT_CALL_PY_EXACT_ARGS 339
|
#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 339
|
||||||
#define _PUSH_FRAME 340
|
#define _GUARD_KEYS_VERSION 340
|
||||||
#define _POP_JUMP_IF_FALSE 341
|
#define _LOAD_ATTR_METHOD_WITH_VALUES 341
|
||||||
#define _POP_JUMP_IF_TRUE 342
|
#define _LOAD_ATTR_METHOD_NO_DICT 342
|
||||||
#define _JUMP_TO_TOP 343
|
#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 343
|
||||||
#define _SAVE_CURRENT_IP 344
|
#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 344
|
||||||
#define _INSERT 345
|
#define _CHECK_PEP_523 345
|
||||||
|
#define _CHECK_FUNCTION_EXACT_ARGS 346
|
||||||
|
#define _CHECK_STACK_SPACE 347
|
||||||
|
#define _INIT_CALL_PY_EXACT_ARGS 348
|
||||||
|
#define _PUSH_FRAME 349
|
||||||
|
#define _POP_JUMP_IF_FALSE 350
|
||||||
|
#define _POP_JUMP_IF_TRUE 351
|
||||||
|
#define _JUMP_TO_TOP 352
|
||||||
|
#define _SAVE_CURRENT_IP 353
|
||||||
|
#define _INSERT 354
|
||||||
|
|
||||||
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
|
||||||
|
@ -356,6 +365,8 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 1;
|
return 1;
|
||||||
case LOAD_ATTR_WITH_HINT:
|
case LOAD_ATTR_WITH_HINT:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _LOAD_ATTR_SLOT:
|
||||||
|
return 1;
|
||||||
case LOAD_ATTR_SLOT:
|
case LOAD_ATTR_SLOT:
|
||||||
return 1;
|
return 1;
|
||||||
case LOAD_ATTR_CLASS:
|
case LOAD_ATTR_CLASS:
|
||||||
|
@ -364,10 +375,18 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 1;
|
return 1;
|
||||||
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
|
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _GUARD_DORV_VALUES:
|
||||||
|
return 1;
|
||||||
|
case _STORE_ATTR_INSTANCE_VALUE:
|
||||||
|
return 2;
|
||||||
case STORE_ATTR_INSTANCE_VALUE:
|
case STORE_ATTR_INSTANCE_VALUE:
|
||||||
return 2;
|
return 2;
|
||||||
case STORE_ATTR_WITH_HINT:
|
case STORE_ATTR_WITH_HINT:
|
||||||
return 2;
|
return 2;
|
||||||
|
case _GUARD_TYPE_VERSION_STORE:
|
||||||
|
return 1;
|
||||||
|
case _STORE_ATTR_SLOT:
|
||||||
|
return 2;
|
||||||
case STORE_ATTR_SLOT:
|
case STORE_ATTR_SLOT:
|
||||||
return 2;
|
return 2;
|
||||||
case COMPARE_OP:
|
case COMPARE_OP:
|
||||||
|
@ -478,8 +497,16 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case PUSH_EXC_INFO:
|
case PUSH_EXC_INFO:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT:
|
||||||
|
return 1;
|
||||||
|
case _GUARD_KEYS_VERSION:
|
||||||
|
return 1;
|
||||||
|
case _LOAD_ATTR_METHOD_WITH_VALUES:
|
||||||
|
return 1;
|
||||||
case LOAD_ATTR_METHOD_WITH_VALUES:
|
case LOAD_ATTR_METHOD_WITH_VALUES:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _LOAD_ATTR_METHOD_NO_DICT:
|
||||||
|
return 1;
|
||||||
case LOAD_ATTR_METHOD_NO_DICT:
|
case LOAD_ATTR_METHOD_NO_DICT:
|
||||||
return 1;
|
return 1;
|
||||||
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
|
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
|
||||||
|
@ -896,18 +923,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_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:
|
||||||
|
return (oparg & 1 ? 1 : 0) + 1;
|
||||||
case LOAD_ATTR_CLASS:
|
case LOAD_ATTR_CLASS:
|
||||||
return ((oparg & 1) ? 1 : 0) + 1;
|
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:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _GUARD_DORV_VALUES:
|
||||||
|
return 1;
|
||||||
|
case _STORE_ATTR_INSTANCE_VALUE:
|
||||||
|
return 0;
|
||||||
case STORE_ATTR_INSTANCE_VALUE:
|
case STORE_ATTR_INSTANCE_VALUE:
|
||||||
return 0;
|
return 0;
|
||||||
case STORE_ATTR_WITH_HINT:
|
case STORE_ATTR_WITH_HINT:
|
||||||
return 0;
|
return 0;
|
||||||
|
case _GUARD_TYPE_VERSION_STORE:
|
||||||
|
return 1;
|
||||||
|
case _STORE_ATTR_SLOT:
|
||||||
|
return 0;
|
||||||
case STORE_ATTR_SLOT:
|
case STORE_ATTR_SLOT:
|
||||||
return 0;
|
return 0;
|
||||||
case COMPARE_OP:
|
case COMPARE_OP:
|
||||||
|
@ -1018,8 +1055,16 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case PUSH_EXC_INFO:
|
case PUSH_EXC_INFO:
|
||||||
return 2;
|
return 2;
|
||||||
|
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT:
|
||||||
|
return 1;
|
||||||
|
case _GUARD_KEYS_VERSION:
|
||||||
|
return 1;
|
||||||
|
case _LOAD_ATTR_METHOD_WITH_VALUES:
|
||||||
|
return 2;
|
||||||
case LOAD_ATTR_METHOD_WITH_VALUES:
|
case LOAD_ATTR_METHOD_WITH_VALUES:
|
||||||
return 2;
|
return 2;
|
||||||
|
case _LOAD_ATTR_METHOD_NO_DICT:
|
||||||
|
return 2;
|
||||||
case LOAD_ATTR_METHOD_NO_DICT:
|
case LOAD_ATTR_METHOD_NO_DICT:
|
||||||
return 2;
|
return 2;
|
||||||
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
|
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
|
||||||
|
@ -1359,12 +1404,17 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[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 },
|
||||||
[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 },
|
||||||
[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_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
[LOAD_ATTR_SLOT] = { 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_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 },
|
||||||
|
[_GUARD_DORV_VALUES] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
|
||||||
|
[_STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC, 0 },
|
||||||
[STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
|
[STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
|
||||||
[STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
|
[STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
|
||||||
|
[_GUARD_TYPE_VERSION_STORE] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
|
||||||
|
[_STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC, 0 },
|
||||||
[STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
|
[STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
|
||||||
[COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
[COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
||||||
[COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
[COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
||||||
|
@ -1420,7 +1470,11 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[SETUP_WITH] = { true, INSTR_FMT_IX, 0 },
|
[SETUP_WITH] = { true, INSTR_FMT_IX, 0 },
|
||||||
[POP_BLOCK] = { true, INSTR_FMT_IX, 0 },
|
[POP_BLOCK] = { true, INSTR_FMT_IX, 0 },
|
||||||
[PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 },
|
[PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 },
|
||||||
|
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
|
||||||
|
[_GUARD_KEYS_VERSION] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
|
||||||
|
[_LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG },
|
||||||
[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_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_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_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
||||||
|
@ -1583,6 +1637,9 @@ 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_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 } } },
|
||||||
|
[STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION_STORE, 2, 1 }, { _GUARD_DORV_VALUES, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } },
|
||||||
|
[STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION_STORE, 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 } } },
|
||||||
[COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { COMPARE_OP_FLOAT, 0, 0 } } },
|
[COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { COMPARE_OP_FLOAT, 0, 0 } } },
|
||||||
[COMPARE_OP_INT] = { .nuops = 1, .uops = { { COMPARE_OP_INT, 0, 0 } } },
|
[COMPARE_OP_INT] = { .nuops = 1, .uops = { { COMPARE_OP_INT, 0, 0 } } },
|
||||||
|
@ -1600,6 +1657,8 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
||||||
[GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } },
|
[GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } },
|
||||||
[WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } },
|
[WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } },
|
||||||
[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_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_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 } } },
|
||||||
|
@ -1652,6 +1711,11 @@ 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",
|
||||||
|
[_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT",
|
||||||
|
[_GUARD_DORV_VALUES] = "_GUARD_DORV_VALUES",
|
||||||
|
[_STORE_ATTR_INSTANCE_VALUE] = "_STORE_ATTR_INSTANCE_VALUE",
|
||||||
|
[_GUARD_TYPE_VERSION_STORE] = "_GUARD_TYPE_VERSION_STORE",
|
||||||
|
[_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
|
||||||
[_IS_NONE] = "_IS_NONE",
|
[_IS_NONE] = "_IS_NONE",
|
||||||
[_ITER_CHECK_LIST] = "_ITER_CHECK_LIST",
|
[_ITER_CHECK_LIST] = "_ITER_CHECK_LIST",
|
||||||
[_ITER_JUMP_LIST] = "_ITER_JUMP_LIST",
|
[_ITER_JUMP_LIST] = "_ITER_JUMP_LIST",
|
||||||
|
@ -1665,6 +1729,10 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
|
||||||
[_ITER_JUMP_RANGE] = "_ITER_JUMP_RANGE",
|
[_ITER_JUMP_RANGE] = "_ITER_JUMP_RANGE",
|
||||||
[_IS_ITER_EXHAUSTED_RANGE] = "_IS_ITER_EXHAUSTED_RANGE",
|
[_IS_ITER_EXHAUSTED_RANGE] = "_IS_ITER_EXHAUSTED_RANGE",
|
||||||
[_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE",
|
[_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE",
|
||||||
|
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = "_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT",
|
||||||
|
[_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION",
|
||||||
|
[_LOAD_ATTR_METHOD_WITH_VALUES] = "_LOAD_ATTR_METHOD_WITH_VALUES",
|
||||||
|
[_LOAD_ATTR_METHOD_NO_DICT] = "_LOAD_ATTR_METHOD_NO_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",
|
||||||
|
|
|
@ -10,7 +10,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "pycore_frame.h" // _PyInterpreterFrame
|
#include "pycore_frame.h" // _PyInterpreterFrame
|
||||||
|
|
||||||
#define _Py_UOP_MAX_TRACE_LENGTH 64
|
#define _Py_UOP_MAX_TRACE_LENGTH 128
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
|
|
47
Python/abstract_interp_cases.c.h
generated
47
Python/abstract_interp_cases.c.h
generated
|
@ -474,6 +474,31 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _LOAD_ATTR_SLOT: {
|
||||||
|
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: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _STORE_ATTR_INSTANCE_VALUE: {
|
||||||
|
STACK_SHRINK(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_TYPE_VERSION_STORE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _STORE_ATTR_SLOT: {
|
||||||
|
STACK_SHRINK(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case COMPARE_OP: {
|
case COMPARE_OP: {
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
|
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
|
||||||
|
@ -627,6 +652,28 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_KEYS_VERSION: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _LOAD_ATTR_METHOD_WITH_VALUES: {
|
||||||
|
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 _LOAD_ATTR_METHOD_NO_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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1939,10 +1939,7 @@ dummy_func(
|
||||||
DECREF_INPUTS();
|
DECREF_INPUTS();
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- attr, null if (oparg & 1))) {
|
op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
|
||||||
PyTypeObject *tp = Py_TYPE(owner);
|
|
||||||
assert(type_version != 0);
|
|
||||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
|
||||||
char *addr = (char *)owner + index;
|
char *addr = (char *)owner + index;
|
||||||
attr = *(PyObject **)addr;
|
attr = *(PyObject **)addr;
|
||||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||||
|
@ -1952,6 +1949,12 @@ dummy_func(
|
||||||
DECREF_INPUTS();
|
DECREF_INPUTS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro(LOAD_ATTR_SLOT) =
|
||||||
|
unused/1 +
|
||||||
|
_GUARD_TYPE_VERSION +
|
||||||
|
_LOAD_ATTR_SLOT + // NOTE: This action may also deopt
|
||||||
|
unused/5;
|
||||||
|
|
||||||
inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, null if (oparg & 1))) {
|
inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, null if (oparg & 1))) {
|
||||||
|
|
||||||
DEOPT_IF(!PyType_Check(owner), LOAD_ATTR);
|
DEOPT_IF(!PyType_Check(owner), LOAD_ATTR);
|
||||||
|
@ -2019,13 +2022,15 @@ dummy_func(
|
||||||
DISPATCH_INLINED(new_frame);
|
DISPATCH_INLINED(new_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(STORE_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, value, owner --)) {
|
op(_GUARD_DORV_VALUES, (owner -- owner)) {
|
||||||
PyTypeObject *tp = Py_TYPE(owner);
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
assert(type_version != 0);
|
|
||||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
|
||||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) {
|
||||||
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
STAT_INC(STORE_ATTR, hit);
|
STAT_INC(STORE_ATTR, hit);
|
||||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||||
PyObject *old_value = values->values[index];
|
PyObject *old_value = values->values[index];
|
||||||
|
@ -2039,6 +2044,12 @@ dummy_func(
|
||||||
Py_DECREF(owner);
|
Py_DECREF(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro(STORE_ATTR_INSTANCE_VALUE) =
|
||||||
|
unused/1 +
|
||||||
|
_GUARD_TYPE_VERSION_STORE +
|
||||||
|
_GUARD_DORV_VALUES +
|
||||||
|
_STORE_ATTR_INSTANCE_VALUE;
|
||||||
|
|
||||||
inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {
|
inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {
|
||||||
PyTypeObject *tp = Py_TYPE(owner);
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
assert(type_version != 0);
|
assert(type_version != 0);
|
||||||
|
@ -2080,10 +2091,13 @@ dummy_func(
|
||||||
Py_DECREF(owner);
|
Py_DECREF(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(STORE_ATTR_SLOT, (unused/1, type_version/2, index/1, value, owner --)) {
|
op(_GUARD_TYPE_VERSION_STORE, (type_version/2, owner -- owner)) {
|
||||||
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, STORE_ATTR);
|
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
op(_STORE_ATTR_SLOT, (index/1, value, owner --)) {
|
||||||
char *addr = (char *)owner + index;
|
char *addr = (char *)owner + index;
|
||||||
STAT_INC(STORE_ATTR, hit);
|
STAT_INC(STORE_ATTR, hit);
|
||||||
PyObject *old_value = *(PyObject **)addr;
|
PyObject *old_value = *(PyObject **)addr;
|
||||||
|
@ -2092,6 +2106,11 @@ dummy_func(
|
||||||
Py_DECREF(owner);
|
Py_DECREF(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro(STORE_ATTR_SLOT) =
|
||||||
|
unused/1 +
|
||||||
|
_GUARD_TYPE_VERSION_STORE +
|
||||||
|
_STORE_ATTR_SLOT;
|
||||||
|
|
||||||
family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
|
family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
|
||||||
COMPARE_OP_FLOAT,
|
COMPARE_OP_FLOAT,
|
||||||
COMPARE_OP_INT,
|
COMPARE_OP_INT,
|
||||||
|
@ -2769,20 +2788,25 @@ dummy_func(
|
||||||
exc_info->exc_value = Py_NewRef(new_exc);
|
exc_info->exc_value = Py_NewRef(new_exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, owner -- attr, self if (1))) {
|
op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) {
|
||||||
assert(oparg & 1);
|
|
||||||
/* Cached method object */
|
|
||||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
assert(type_version != 0);
|
|
||||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
|
||||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
assert(owner_cls->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) &&
|
||||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||||
LOAD_ATTR);
|
LOAD_ATTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) {
|
||||||
|
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 !=
|
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||||
keys_version, LOAD_ATTR);
|
keys_version, LOAD_ATTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
|
||||||
|
assert(oparg & 1);
|
||||||
|
/* Cached method object */
|
||||||
STAT_INC(LOAD_ATTR, hit);
|
STAT_INC(LOAD_ATTR, hit);
|
||||||
assert(descr != NULL);
|
assert(descr != NULL);
|
||||||
attr = Py_NewRef(descr);
|
attr = Py_NewRef(descr);
|
||||||
|
@ -2790,10 +2814,16 @@ dummy_func(
|
||||||
self = owner;
|
self = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, self if (1))) {
|
macro(LOAD_ATTR_METHOD_WITH_VALUES) =
|
||||||
|
unused/1 +
|
||||||
|
_GUARD_TYPE_VERSION +
|
||||||
|
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
|
||||||
|
_GUARD_KEYS_VERSION +
|
||||||
|
_LOAD_ATTR_METHOD_WITH_VALUES;
|
||||||
|
|
||||||
|
op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
|
||||||
assert(oparg & 1);
|
assert(oparg & 1);
|
||||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
|
||||||
assert(owner_cls->tp_dictoffset == 0);
|
assert(owner_cls->tp_dictoffset == 0);
|
||||||
STAT_INC(LOAD_ATTR, hit);
|
STAT_INC(LOAD_ATTR, hit);
|
||||||
assert(descr != NULL);
|
assert(descr != NULL);
|
||||||
|
@ -2802,6 +2832,12 @@ dummy_func(
|
||||||
self = owner;
|
self = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro(LOAD_ATTR_METHOD_NO_DICT) =
|
||||||
|
unused/1 +
|
||||||
|
_GUARD_TYPE_VERSION +
|
||||||
|
unused/2 +
|
||||||
|
_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))) {
|
inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, owner -- attr, unused if (0))) {
|
||||||
assert((oparg & 1) == 0);
|
assert((oparg & 1) == 0);
|
||||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
|
|
139
Python/executor_cases.c.h
generated
139
Python/executor_cases.c.h
generated
|
@ -1714,6 +1714,83 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _LOAD_ATTR_SLOT: {
|
||||||
|
PyObject *owner;
|
||||||
|
PyObject *attr;
|
||||||
|
PyObject *null = NULL;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
uint16_t index = (uint16_t)operand;
|
||||||
|
char *addr = (char *)owner + index;
|
||||||
|
attr = *(PyObject **)addr;
|
||||||
|
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||||
|
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 _GUARD_DORV_VALUES: {
|
||||||
|
PyObject *owner;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
|
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||||
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
|
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _STORE_ATTR_INSTANCE_VALUE: {
|
||||||
|
PyObject *owner;
|
||||||
|
PyObject *value;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
value = stack_pointer[-2];
|
||||||
|
uint16_t index = (uint16_t)operand;
|
||||||
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
|
STAT_INC(STORE_ATTR, hit);
|
||||||
|
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||||
|
PyObject *old_value = values->values[index];
|
||||||
|
values->values[index] = value;
|
||||||
|
if (old_value == NULL) {
|
||||||
|
_PyDictValues_AddToInsertionOrder(values, index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(old_value);
|
||||||
|
}
|
||||||
|
Py_DECREF(owner);
|
||||||
|
STACK_SHRINK(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_TYPE_VERSION_STORE: {
|
||||||
|
PyObject *owner;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
uint32_t type_version = (uint32_t)operand;
|
||||||
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
|
assert(type_version != 0);
|
||||||
|
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _STORE_ATTR_SLOT: {
|
||||||
|
PyObject *owner;
|
||||||
|
PyObject *value;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
value = stack_pointer[-2];
|
||||||
|
uint16_t index = (uint16_t)operand;
|
||||||
|
char *addr = (char *)owner + index;
|
||||||
|
STAT_INC(STORE_ATTR, hit);
|
||||||
|
PyObject *old_value = *(PyObject **)addr;
|
||||||
|
*(PyObject **)addr = value;
|
||||||
|
Py_XDECREF(old_value);
|
||||||
|
Py_DECREF(owner);
|
||||||
|
STACK_SHRINK(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case COMPARE_OP: {
|
case COMPARE_OP: {
|
||||||
PyObject *right;
|
PyObject *right;
|
||||||
PyObject *left;
|
PyObject *left;
|
||||||
|
@ -2219,6 +2296,68 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: {
|
||||||
|
PyObject *owner;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
|
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||||
|
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||||
|
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||||
|
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||||
|
LOAD_ATTR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_KEYS_VERSION: {
|
||||||
|
PyObject *owner;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
uint32_t keys_version = (uint32_t)operand;
|
||||||
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
|
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||||
|
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||||
|
keys_version, LOAD_ATTR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _LOAD_ATTR_METHOD_WITH_VALUES: {
|
||||||
|
PyObject *owner;
|
||||||
|
PyObject *attr;
|
||||||
|
PyObject *self;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
PyObject *descr = (PyObject *)operand;
|
||||||
|
assert(oparg & 1);
|
||||||
|
/* Cached method object */
|
||||||
|
STAT_INC(LOAD_ATTR, hit);
|
||||||
|
assert(descr != NULL);
|
||||||
|
attr = Py_NewRef(descr);
|
||||||
|
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||||
|
self = owner;
|
||||||
|
STACK_GROW(1);
|
||||||
|
stack_pointer[-2] = attr;
|
||||||
|
stack_pointer[-1] = self;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _LOAD_ATTR_METHOD_NO_DICT: {
|
||||||
|
PyObject *owner;
|
||||||
|
PyObject *attr;
|
||||||
|
PyObject *self;
|
||||||
|
owner = stack_pointer[-1];
|
||||||
|
PyObject *descr = (PyObject *)operand;
|
||||||
|
assert(oparg & 1);
|
||||||
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
|
assert(owner_cls->tp_dictoffset == 0);
|
||||||
|
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;
|
||||||
|
|
191
Python/generated_cases.c.h
generated
191
Python/generated_cases.c.h
generated
|
@ -2504,19 +2504,25 @@
|
||||||
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);
|
{
|
||||||
uint16_t index = read_u16(&next_instr[3].cache);
|
uint32_t type_version = read_u32(&next_instr[1].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);
|
||||||
char *addr = (char *)owner + index;
|
}
|
||||||
attr = *(PyObject **)addr;
|
// _LOAD_ATTR_SLOT
|
||||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
{
|
||||||
STAT_INC(LOAD_ATTR, hit);
|
uint16_t index = read_u16(&next_instr[3].cache);
|
||||||
Py_INCREF(attr);
|
char *addr = (char *)owner + index;
|
||||||
null = NULL;
|
attr = *(PyObject **)addr;
|
||||||
Py_DECREF(owner);
|
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||||
|
STAT_INC(LOAD_ATTR, hit);
|
||||||
|
Py_INCREF(attr);
|
||||||
|
null = NULL;
|
||||||
|
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; }
|
||||||
|
@ -2615,27 +2621,38 @@
|
||||||
TARGET(STORE_ATTR_INSTANCE_VALUE) {
|
TARGET(STORE_ATTR_INSTANCE_VALUE) {
|
||||||
PyObject *owner;
|
PyObject *owner;
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
|
// _GUARD_TYPE_VERSION_STORE
|
||||||
owner = stack_pointer[-1];
|
owner = stack_pointer[-1];
|
||||||
|
{
|
||||||
|
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, STORE_ATTR);
|
||||||
|
}
|
||||||
|
// _GUARD_DORV_VALUES
|
||||||
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
|
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||||
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
|
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||||
|
}
|
||||||
|
// _STORE_ATTR_INSTANCE_VALUE
|
||||||
value = stack_pointer[-2];
|
value = stack_pointer[-2];
|
||||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
{
|
||||||
uint16_t index = read_u16(&next_instr[3].cache);
|
uint16_t index = read_u16(&next_instr[3].cache);
|
||||||
PyTypeObject *tp = Py_TYPE(owner);
|
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||||
assert(type_version != 0);
|
STAT_INC(STORE_ATTR, hit);
|
||||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
PyObject *old_value = values->values[index];
|
||||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
values->values[index] = value;
|
||||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
if (old_value == NULL) {
|
||||||
STAT_INC(STORE_ATTR, hit);
|
_PyDictValues_AddToInsertionOrder(values, index);
|
||||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
}
|
||||||
PyObject *old_value = values->values[index];
|
else {
|
||||||
values->values[index] = value;
|
Py_DECREF(old_value);
|
||||||
if (old_value == NULL) {
|
}
|
||||||
_PyDictValues_AddToInsertionOrder(values, index);
|
Py_DECREF(owner);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Py_DECREF(old_value);
|
|
||||||
}
|
|
||||||
Py_DECREF(owner);
|
|
||||||
STACK_SHRINK(2);
|
STACK_SHRINK(2);
|
||||||
next_instr += 4;
|
next_instr += 4;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -2694,19 +2711,25 @@
|
||||||
TARGET(STORE_ATTR_SLOT) {
|
TARGET(STORE_ATTR_SLOT) {
|
||||||
PyObject *owner;
|
PyObject *owner;
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
|
// _GUARD_TYPE_VERSION_STORE
|
||||||
owner = stack_pointer[-1];
|
owner = stack_pointer[-1];
|
||||||
|
{
|
||||||
|
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, STORE_ATTR);
|
||||||
|
}
|
||||||
|
// _STORE_ATTR_SLOT
|
||||||
value = stack_pointer[-2];
|
value = stack_pointer[-2];
|
||||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
{
|
||||||
uint16_t index = read_u16(&next_instr[3].cache);
|
uint16_t index = read_u16(&next_instr[3].cache);
|
||||||
PyTypeObject *tp = Py_TYPE(owner);
|
char *addr = (char *)owner + index;
|
||||||
assert(type_version != 0);
|
STAT_INC(STORE_ATTR, hit);
|
||||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
PyObject *old_value = *(PyObject **)addr;
|
||||||
char *addr = (char *)owner + index;
|
*(PyObject **)addr = value;
|
||||||
STAT_INC(STORE_ATTR, hit);
|
Py_XDECREF(old_value);
|
||||||
PyObject *old_value = *(PyObject **)addr;
|
Py_DECREF(owner);
|
||||||
*(PyObject **)addr = value;
|
}
|
||||||
Py_XDECREF(old_value);
|
|
||||||
Py_DECREF(owner);
|
|
||||||
STACK_SHRINK(2);
|
STACK_SHRINK(2);
|
||||||
next_instr += 4;
|
next_instr += 4;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -3557,28 +3580,42 @@
|
||||||
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 keys_version = read_u32(&next_instr[3].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);
|
||||||
/* Cached method object */
|
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
}
|
||||||
assert(type_version != 0);
|
// _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
|
||||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
{
|
||||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||||
LOAD_ATTR);
|
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
LOAD_ATTR);
|
||||||
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
}
|
||||||
keys_version, LOAD_ATTR);
|
// _GUARD_KEYS_VERSION
|
||||||
STAT_INC(LOAD_ATTR, hit);
|
{
|
||||||
assert(descr != NULL);
|
uint32_t keys_version = read_u32(&next_instr[3].cache);
|
||||||
attr = Py_NewRef(descr);
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||||
self = owner;
|
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||||
|
keys_version, LOAD_ATTR);
|
||||||
|
}
|
||||||
|
// _LOAD_ATTR_METHOD_WITH_VALUES
|
||||||
|
{
|
||||||
|
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||||
|
assert(oparg & 1);
|
||||||
|
/* Cached method object */
|
||||||
|
STAT_INC(LOAD_ATTR, hit);
|
||||||
|
assert(descr != NULL);
|
||||||
|
attr = Py_NewRef(descr);
|
||||||
|
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||||
|
self = owner;
|
||||||
|
}
|
||||||
STACK_GROW(1);
|
STACK_GROW(1);
|
||||||
stack_pointer[-2] = attr;
|
stack_pointer[-2] = attr;
|
||||||
stack_pointer[-1] = self;
|
stack_pointer[-1] = self;
|
||||||
|
@ -3590,18 +3627,26 @@
|
||||||
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);
|
{
|
||||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||||
assert(oparg & 1);
|
PyTypeObject *tp = Py_TYPE(owner);
|
||||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
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_dictoffset == 0);
|
}
|
||||||
STAT_INC(LOAD_ATTR, hit);
|
// _LOAD_ATTR_METHOD_NO_DICT
|
||||||
assert(descr != NULL);
|
{
|
||||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||||
attr = Py_NewRef(descr);
|
assert(oparg & 1);
|
||||||
self = owner;
|
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||||
|
assert(owner_cls->tp_dictoffset == 0);
|
||||||
|
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_GROW(1);
|
||||||
stack_pointer[-2] = attr;
|
stack_pointer[-2] = attr;
|
||||||
stack_pointer[-1] = self;
|
stack_pointer[-1] = self;
|
||||||
|
|
|
@ -414,3 +414,61 @@ class Analyzer:
|
||||||
case _:
|
case _:
|
||||||
assert_never(uop)
|
assert_never(uop)
|
||||||
return components
|
return components
|
||||||
|
|
||||||
|
def report_non_viable_uops(self, jsonfile: str) -> None:
|
||||||
|
print("The following ops are not viable uops:")
|
||||||
|
skips = {
|
||||||
|
"CACHE",
|
||||||
|
"RESERVED",
|
||||||
|
"INTERPRETER_EXIT",
|
||||||
|
"JUMP_BACKWARD",
|
||||||
|
"LOAD_FAST_LOAD_FAST",
|
||||||
|
"LOAD_CONST_LOAD_FAST",
|
||||||
|
"STORE_FAST_STORE_FAST",
|
||||||
|
"_BINARY_OP_INPLACE_ADD_UNICODE",
|
||||||
|
"POP_JUMP_IF_TRUE",
|
||||||
|
"POP_JUMP_IF_FALSE",
|
||||||
|
"_ITER_JUMP_LIST",
|
||||||
|
"_ITER_JUMP_TUPLE",
|
||||||
|
"_ITER_JUMP_RANGE",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
# Secret feature: if bmraw.json exists, print and sort by execution count
|
||||||
|
counts = load_execution_counts(jsonfile)
|
||||||
|
except FileNotFoundError as err:
|
||||||
|
counts = {}
|
||||||
|
non_viable = [
|
||||||
|
instr
|
||||||
|
for instr in self.instrs.values()
|
||||||
|
if instr.name not in skips
|
||||||
|
and not instr.name.startswith("INSTRUMENTED_")
|
||||||
|
and not instr.is_viable_uop()
|
||||||
|
]
|
||||||
|
non_viable.sort(key=lambda instr: (-counts.get(instr.name, 0), instr.name))
|
||||||
|
for instr in non_viable:
|
||||||
|
if instr.name in counts:
|
||||||
|
scount = f"{counts[instr.name]:,}"
|
||||||
|
else:
|
||||||
|
scount = ""
|
||||||
|
print(f" {scount:>15} {instr.name:<35}", end="")
|
||||||
|
if instr.name in self.families:
|
||||||
|
print(" (unspecialized)", end="")
|
||||||
|
elif instr.family is not None:
|
||||||
|
print(f" (specialization of {instr.family.name})", end="")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def load_execution_counts(jsonfile: str) -> dict[str, int]:
|
||||||
|
import json
|
||||||
|
|
||||||
|
with open(jsonfile) as f:
|
||||||
|
jsondata = json.load(f)
|
||||||
|
|
||||||
|
# Look for keys like "opcode[LOAD_FAST].execution_count"
|
||||||
|
prefix = "opcode["
|
||||||
|
suffix = "].execution_count"
|
||||||
|
res: dict[str, int] = {}
|
||||||
|
for key, value in jsondata.items():
|
||||||
|
if key.startswith(prefix) and key.endswith(suffix):
|
||||||
|
res[key[len(prefix) : -len(suffix)]] = value
|
||||||
|
return res
|
||||||
|
|
|
@ -92,6 +92,13 @@ arg_parser = argparse.ArgumentParser(
|
||||||
description="Generate the code for the interpreter switch.",
|
description="Generate the code for the interpreter switch.",
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
help="Print list of non-viable uops and exit",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
"-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT
|
"-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT
|
||||||
)
|
)
|
||||||
|
@ -865,6 +872,10 @@ def main() -> None:
|
||||||
a.analyze() # Prints messages and sets a.errors on failure
|
a.analyze() # Prints messages and sets a.errors on failure
|
||||||
if a.errors:
|
if a.errors:
|
||||||
sys.exit(f"Found {a.errors} errors")
|
sys.exit(f"Found {a.errors} errors")
|
||||||
|
if args.verbose:
|
||||||
|
# Load execution counts from bmraw.json, if it exists
|
||||||
|
a.report_non_viable_uops("bmraw.json")
|
||||||
|
return
|
||||||
|
|
||||||
# These raise OSError if output can't be written
|
# These raise OSError if output can't be written
|
||||||
a.write_instructions(args.output, args.emit_line_directives)
|
a.write_instructions(args.output, args.emit_line_directives)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue