From ce5eb99f054e935ca0233216327fbbb8d142efd6 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Sun, 10 Sep 2023 06:05:30 +0100 Subject: [PATCH 1/2] Break instrumented instructions into micro-ops. Label instrumented instructed and calls to monitoring functions are tier 1 only. --- Include/internal/pycore_opcode_metadata.h | 112 +++++--- Include/opcode_ids.h | 276 +++++++++---------- Lib/_opcode_metadata.py | 276 +++++++++---------- Programs/test_frozenmain.h | 22 +- Python/abstract_interp_cases.c.h | 4 + Python/bytecodes.c | 126 ++++----- Python/executor_cases.c.h | 12 + Python/generated_cases.c.h | 316 ++++++++++++++++------ Python/opcode_targets.h | 16 +- 9 files changed, 678 insertions(+), 482 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index f70b75a56c150c..ad779cc31bddc3 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -39,38 +39,42 @@ #define _BINARY_OP_ADD_UNICODE 311 #define _BINARY_OP_INPLACE_ADD_UNICODE 312 #define _POP_FRAME 313 -#define _GUARD_GLOBALS_VERSION 314 -#define _GUARD_BUILTINS_VERSION 315 -#define _LOAD_GLOBAL_MODULE 316 -#define _LOAD_GLOBAL_BUILTINS 317 -#define _GUARD_TYPE_VERSION 318 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 319 -#define _LOAD_ATTR_INSTANCE_VALUE 320 -#define IS_NONE 321 -#define _ITER_CHECK_LIST 322 -#define _ITER_JUMP_LIST 323 -#define _IS_ITER_EXHAUSTED_LIST 324 -#define _ITER_NEXT_LIST 325 -#define _ITER_CHECK_TUPLE 326 -#define _ITER_JUMP_TUPLE 327 -#define _IS_ITER_EXHAUSTED_TUPLE 328 -#define _ITER_NEXT_TUPLE 329 -#define _ITER_CHECK_RANGE 330 -#define _ITER_JUMP_RANGE 331 -#define _IS_ITER_EXHAUSTED_RANGE 332 -#define _ITER_NEXT_RANGE 333 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 334 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 335 -#define _CHECK_PEP_523 336 -#define _CHECK_FUNCTION_EXACT_ARGS 337 -#define _CHECK_STACK_SPACE 338 -#define _INIT_CALL_PY_EXACT_ARGS 339 -#define _PUSH_FRAME 340 -#define _POP_JUMP_IF_FALSE 341 -#define _POP_JUMP_IF_TRUE 342 -#define JUMP_TO_TOP 343 -#define SAVE_CURRENT_IP 344 -#define INSERT 345 +#define _MONITOR_RETURN 314 +#define _SUSPEND_GENERATOR 315 +#define _MONITOR_YIELD_VALUE 316 +#define _DO_YIELD 317 +#define _GUARD_GLOBALS_VERSION 318 +#define _GUARD_BUILTINS_VERSION 319 +#define _LOAD_GLOBAL_MODULE 320 +#define _LOAD_GLOBAL_BUILTINS 321 +#define _GUARD_TYPE_VERSION 322 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 323 +#define _LOAD_ATTR_INSTANCE_VALUE 324 +#define IS_NONE 325 +#define _ITER_CHECK_LIST 326 +#define _ITER_JUMP_LIST 327 +#define _IS_ITER_EXHAUSTED_LIST 328 +#define _ITER_NEXT_LIST 329 +#define _ITER_CHECK_TUPLE 330 +#define _ITER_JUMP_TUPLE 331 +#define _IS_ITER_EXHAUSTED_TUPLE 332 +#define _ITER_NEXT_TUPLE 333 +#define _ITER_CHECK_RANGE 334 +#define _ITER_JUMP_RANGE 335 +#define _IS_ITER_EXHAUSTED_RANGE 336 +#define _ITER_NEXT_RANGE 337 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 338 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 339 +#define _CHECK_PEP_523 340 +#define _CHECK_FUNCTION_EXACT_ARGS 341 +#define _CHECK_STACK_SPACE 342 +#define _INIT_CALL_PY_EXACT_ARGS 343 +#define _PUSH_FRAME 344 +#define _POP_JUMP_IF_FALSE 345 +#define _POP_JUMP_IF_TRUE 346 +#define JUMP_TO_TOP 347 +#define SAVE_CURRENT_IP 348 +#define INSERT 349 extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); #ifdef NEED_OPCODE_METADATA @@ -110,10 +114,14 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 0; case END_FOR: return 2; + case _END_FOR_MONITOR: + return 2; case INSTRUMENTED_END_FOR: return 2; case END_SEND: return 2; + case _END_SEND_MONITOR: + return 2; case INSTRUMENTED_END_SEND: return 2; case UNARY_NEGATIVE: @@ -228,10 +236,12 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 2; case SEND_GEN: return 2; - case INSTRUMENTED_YIELD_VALUE: + case _SUSPEND_GENERATOR: return 1; case YIELD_VALUE: return 1; + case INSTRUMENTED_YIELD_VALUE: + return 1; case POP_EXCEPT: return 1; case RERAISE: @@ -640,10 +650,14 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 1; case END_FOR: return 0; + case _END_FOR_MONITOR: + return 2; case INSTRUMENTED_END_FOR: return 0; case END_SEND: return 1; + case _END_SEND_MONITOR: + return 2; case INSTRUMENTED_END_SEND: return 1; case UNARY_NEGATIVE: @@ -758,10 +772,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 2; case SEND_GEN: return 2; - case INSTRUMENTED_YIELD_VALUE: + case _SUSPEND_GENERATOR: return 1; case YIELD_VALUE: return 1; + case INSTRUMENTED_YIELD_VALUE: + return 1; case POP_EXCEPT: return 0; case RERAISE: @@ -1216,8 +1232,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [POP_TOP] = { true, INSTR_FMT_IX, 0 }, [PUSH_NULL] = { true, INSTR_FMT_IX, 0 }, [END_FOR] = { true, INSTR_FMT_IX, 0 }, + [_END_FOR_MONITOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [END_SEND] = { true, INSTR_FMT_IX, 0 }, + [_END_SEND_MONITOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [UNARY_NEGATIVE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [UNARY_NOT] = { true, INSTR_FMT_IX, 0 }, @@ -1268,6 +1286,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, 0 }, [_POP_FRAME] = { true, INSTR_FMT_IX, 0 }, [RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, + [_MONITOR_RETURN] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ERROR_FLAG }, @@ -1276,8 +1295,11 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG }, [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, - [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, + [_SUSPEND_GENERATOR] = { true, INSTR_FMT_IX, 0 }, + [_MONITOR_YIELD_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, + [_DO_YIELD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, + [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, [POP_EXCEPT] = { true, INSTR_FMT_IX, 0 }, [RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, [END_ASYNC_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, @@ -1621,6 +1643,10 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", [_BINARY_OP_INPLACE_ADD_UNICODE] = "_BINARY_OP_INPLACE_ADD_UNICODE", [_POP_FRAME] = "_POP_FRAME", + [_MONITOR_RETURN] = "_MONITOR_RETURN", + [_SUSPEND_GENERATOR] = "_SUSPEND_GENERATOR", + [_MONITOR_YIELD_VALUE] = "_MONITOR_YIELD_VALUE", + [_DO_YIELD] = "_DO_YIELD", [_GUARD_GLOBALS_VERSION] = "_GUARD_GLOBALS_VERSION", [_GUARD_BUILTINS_VERSION] = "_GUARD_BUILTINS_VERSION", [_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE", @@ -1728,6 +1754,8 @@ const char *const _PyOpcode_OpName[268] = { [UNARY_NEGATIVE] = "UNARY_NEGATIVE", [UNARY_NOT] = "UNARY_NOT", [WITH_EXCEPT_START] = "WITH_EXCEPT_START", + [_END_FOR_MONITOR] = "_END_FOR_MONITOR", + [_END_SEND_MONITOR] = "_END_SEND_MONITOR", [BINARY_OP] = "BINARY_OP", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_LIST] = "BUILD_LIST", @@ -1849,11 +1877,6 @@ const char *const _PyOpcode_OpName[268] = { [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", [YIELD_VALUE] = "YIELD_VALUE", [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME", - [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR", - [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND", - [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE", - [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST", - [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE", [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR", [INSTRUMENTED_FOR_ITER] = "INSTRUMENTED_FOR_ITER", [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL", @@ -1865,6 +1888,11 @@ const char *const _PyOpcode_OpName[268] = { [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE", [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE", [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", + [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR", + [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND", + [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE", + [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST", + [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE", [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE", [JUMP] = "JUMP", [JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT", @@ -2111,12 +2139,12 @@ const uint8_t _PyOpcode_Deopt[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, [WITH_EXCEPT_START] = WITH_EXCEPT_START, [YIELD_VALUE] = YIELD_VALUE, + [_END_FOR_MONITOR] = _END_FOR_MONITOR, + [_END_SEND_MONITOR] = _END_SEND_MONITOR, }; #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ - case 189: \ - case 190: \ case 191: \ case 192: \ case 193: \ diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index eabdf4bc020ef7..bbb15278c4edd7 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -78,146 +78,148 @@ extern "C" { #define UNARY_NEGATIVE 65 #define UNARY_NOT 66 #define WITH_EXCEPT_START 67 -#define HAVE_ARGUMENT 68 -#define BINARY_OP 68 -#define BUILD_CONST_KEY_MAP 69 -#define BUILD_LIST 70 -#define BUILD_MAP 71 -#define BUILD_SET 72 -#define BUILD_SLICE 73 -#define BUILD_STRING 74 -#define BUILD_TUPLE 75 -#define CALL 76 -#define CALL_BOUND_METHOD_EXACT_ARGS 77 -#define CALL_BUILTIN_CLASS 78 -#define CALL_BUILTIN_FAST_WITH_KEYWORDS 79 -#define CALL_FUNCTION_EX 80 -#define CALL_INTRINSIC_1 81 -#define CALL_INTRINSIC_2 82 -#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 83 -#define CALL_NO_KW_ALLOC_AND_ENTER_INIT 84 -#define CALL_NO_KW_BUILTIN_FAST 85 -#define CALL_NO_KW_BUILTIN_O 86 -#define CALL_NO_KW_ISINSTANCE 87 -#define CALL_NO_KW_LEN 88 -#define CALL_NO_KW_LIST_APPEND 89 -#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 90 -#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 91 -#define CALL_NO_KW_METHOD_DESCRIPTOR_O 92 -#define CALL_NO_KW_STR_1 93 -#define CALL_NO_KW_TUPLE_1 94 -#define CALL_NO_KW_TYPE_1 95 -#define CALL_PY_EXACT_ARGS 96 -#define CALL_PY_WITH_DEFAULTS 97 -#define COMPARE_OP 98 -#define COMPARE_OP_FLOAT 99 -#define COMPARE_OP_INT 100 -#define COMPARE_OP_STR 101 -#define CONTAINS_OP 102 -#define CONVERT_VALUE 103 -#define COPY 104 -#define COPY_FREE_VARS 105 -#define DELETE_ATTR 106 -#define DELETE_DEREF 107 -#define DELETE_FAST 108 -#define DELETE_GLOBAL 109 -#define DELETE_NAME 110 -#define DICT_MERGE 111 -#define DICT_UPDATE 112 -#define ENTER_EXECUTOR 113 -#define EXTENDED_ARG 114 -#define FOR_ITER 115 -#define FOR_ITER_GEN 116 -#define FOR_ITER_LIST 117 -#define FOR_ITER_RANGE 118 -#define FOR_ITER_TUPLE 119 -#define GET_AWAITABLE 120 -#define IMPORT_FROM 121 -#define IMPORT_NAME 122 -#define IS_OP 123 -#define JUMP_BACKWARD 124 -#define JUMP_BACKWARD_NO_INTERRUPT 125 -#define JUMP_FORWARD 126 -#define KW_NAMES 127 -#define LIST_APPEND 128 -#define LIST_EXTEND 129 -#define LOAD_ATTR 130 -#define LOAD_ATTR_CLASS 131 -#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 132 -#define LOAD_ATTR_INSTANCE_VALUE 133 -#define LOAD_ATTR_METHOD_LAZY_DICT 134 -#define LOAD_ATTR_METHOD_NO_DICT 135 -#define LOAD_ATTR_METHOD_WITH_VALUES 136 -#define LOAD_ATTR_MODULE 137 -#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 138 -#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 139 -#define LOAD_ATTR_PROPERTY 140 -#define LOAD_ATTR_SLOT 141 -#define LOAD_ATTR_WITH_HINT 142 -#define LOAD_CONST 143 -#define LOAD_DEREF 144 -#define LOAD_FAST 145 -#define LOAD_FAST_AND_CLEAR 146 -#define LOAD_FAST_CHECK 147 -#define LOAD_FAST_LOAD_FAST 148 -#define LOAD_FROM_DICT_OR_DEREF 149 -#define LOAD_FROM_DICT_OR_GLOBALS 150 -#define LOAD_GLOBAL 151 -#define LOAD_GLOBAL_BUILTIN 152 -#define LOAD_GLOBAL_MODULE 153 -#define LOAD_NAME 154 -#define LOAD_SUPER_ATTR 155 -#define LOAD_SUPER_ATTR_ATTR 156 -#define LOAD_SUPER_ATTR_METHOD 157 -#define MAKE_CELL 158 -#define MAP_ADD 159 -#define MATCH_CLASS 160 -#define POP_JUMP_IF_FALSE 161 -#define POP_JUMP_IF_NONE 162 -#define POP_JUMP_IF_NOT_NONE 163 -#define POP_JUMP_IF_TRUE 164 -#define RAISE_VARARGS 165 +#define _END_FOR_MONITOR 68 +#define _END_SEND_MONITOR 69 +#define HAVE_ARGUMENT 70 +#define BINARY_OP 70 +#define BUILD_CONST_KEY_MAP 71 +#define BUILD_LIST 72 +#define BUILD_MAP 73 +#define BUILD_SET 74 +#define BUILD_SLICE 75 +#define BUILD_STRING 76 +#define BUILD_TUPLE 77 +#define CALL 78 +#define CALL_BOUND_METHOD_EXACT_ARGS 79 +#define CALL_BUILTIN_CLASS 80 +#define CALL_BUILTIN_FAST_WITH_KEYWORDS 81 +#define CALL_FUNCTION_EX 82 +#define CALL_INTRINSIC_1 83 +#define CALL_INTRINSIC_2 84 +#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 85 +#define CALL_NO_KW_ALLOC_AND_ENTER_INIT 86 +#define CALL_NO_KW_BUILTIN_FAST 87 +#define CALL_NO_KW_BUILTIN_O 88 +#define CALL_NO_KW_ISINSTANCE 89 +#define CALL_NO_KW_LEN 90 +#define CALL_NO_KW_LIST_APPEND 91 +#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 92 +#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 93 +#define CALL_NO_KW_METHOD_DESCRIPTOR_O 94 +#define CALL_NO_KW_STR_1 95 +#define CALL_NO_KW_TUPLE_1 96 +#define CALL_NO_KW_TYPE_1 97 +#define CALL_PY_EXACT_ARGS 98 +#define CALL_PY_WITH_DEFAULTS 99 +#define COMPARE_OP 100 +#define COMPARE_OP_FLOAT 101 +#define COMPARE_OP_INT 102 +#define COMPARE_OP_STR 103 +#define CONTAINS_OP 104 +#define CONVERT_VALUE 105 +#define COPY 106 +#define COPY_FREE_VARS 107 +#define DELETE_ATTR 108 +#define DELETE_DEREF 109 +#define DELETE_FAST 110 +#define DELETE_GLOBAL 111 +#define DELETE_NAME 112 +#define DICT_MERGE 113 +#define DICT_UPDATE 114 +#define ENTER_EXECUTOR 115 +#define EXTENDED_ARG 116 +#define FOR_ITER 117 +#define FOR_ITER_GEN 118 +#define FOR_ITER_LIST 119 +#define FOR_ITER_RANGE 120 +#define FOR_ITER_TUPLE 121 +#define GET_AWAITABLE 122 +#define IMPORT_FROM 123 +#define IMPORT_NAME 124 +#define IS_OP 125 +#define JUMP_BACKWARD 126 +#define JUMP_BACKWARD_NO_INTERRUPT 127 +#define JUMP_FORWARD 128 +#define KW_NAMES 129 +#define LIST_APPEND 130 +#define LIST_EXTEND 131 +#define LOAD_ATTR 132 +#define LOAD_ATTR_CLASS 133 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 134 +#define LOAD_ATTR_INSTANCE_VALUE 135 +#define LOAD_ATTR_METHOD_LAZY_DICT 136 +#define LOAD_ATTR_METHOD_NO_DICT 137 +#define LOAD_ATTR_METHOD_WITH_VALUES 138 +#define LOAD_ATTR_MODULE 139 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 140 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 141 +#define LOAD_ATTR_PROPERTY 142 +#define LOAD_ATTR_SLOT 143 +#define LOAD_ATTR_WITH_HINT 144 +#define LOAD_CONST 145 +#define LOAD_DEREF 146 +#define LOAD_FAST 147 +#define LOAD_FAST_AND_CLEAR 148 +#define LOAD_FAST_CHECK 149 +#define LOAD_FAST_LOAD_FAST 150 +#define LOAD_FROM_DICT_OR_DEREF 151 +#define LOAD_FROM_DICT_OR_GLOBALS 152 +#define LOAD_GLOBAL 153 +#define LOAD_GLOBAL_BUILTIN 154 +#define LOAD_GLOBAL_MODULE 155 +#define LOAD_NAME 156 +#define LOAD_SUPER_ATTR 157 +#define LOAD_SUPER_ATTR_ATTR 158 +#define LOAD_SUPER_ATTR_METHOD 159 +#define MAKE_CELL 160 +#define MAP_ADD 161 +#define MATCH_CLASS 162 +#define POP_JUMP_IF_FALSE 163 +#define POP_JUMP_IF_NONE 164 +#define POP_JUMP_IF_NOT_NONE 165 #define RESUME 166 -#define RERAISE 167 -#define RETURN_CONST 168 -#define SEND 169 -#define SEND_GEN 170 -#define SET_ADD 171 -#define SET_FUNCTION_ATTRIBUTE 172 -#define SET_UPDATE 173 -#define STORE_ATTR 174 -#define STORE_ATTR_WITH_HINT 175 -#define STORE_DEREF 176 -#define STORE_FAST 177 -#define STORE_FAST_LOAD_FAST 178 -#define STORE_FAST_STORE_FAST 179 -#define STORE_GLOBAL 180 -#define STORE_NAME 181 -#define SWAP 182 -#define UNPACK_EX 183 -#define UNPACK_SEQUENCE 184 -#define UNPACK_SEQUENCE_LIST 185 -#define UNPACK_SEQUENCE_TUPLE 186 -#define UNPACK_SEQUENCE_TWO_TUPLE 187 -#define YIELD_VALUE 188 +#define POP_JUMP_IF_TRUE 167 +#define RAISE_VARARGS 168 +#define RERAISE 169 +#define RETURN_CONST 170 +#define SEND 171 +#define SEND_GEN 172 +#define SET_ADD 173 +#define SET_FUNCTION_ATTRIBUTE 174 +#define SET_UPDATE 175 +#define STORE_ATTR 176 +#define STORE_ATTR_WITH_HINT 177 +#define STORE_DEREF 178 +#define STORE_FAST 179 +#define STORE_FAST_LOAD_FAST 180 +#define STORE_FAST_STORE_FAST 181 +#define STORE_GLOBAL 182 +#define STORE_NAME 183 +#define SWAP 184 +#define UNPACK_EX 185 +#define UNPACK_SEQUENCE 186 +#define UNPACK_SEQUENCE_LIST 187 +#define UNPACK_SEQUENCE_TUPLE 188 +#define UNPACK_SEQUENCE_TWO_TUPLE 189 +#define YIELD_VALUE 190 #define MIN_INSTRUMENTED_OPCODE 237 #define INSTRUMENTED_RESUME 237 -#define INSTRUMENTED_END_FOR 238 -#define INSTRUMENTED_END_SEND 239 -#define INSTRUMENTED_RETURN_VALUE 240 -#define INSTRUMENTED_RETURN_CONST 241 -#define INSTRUMENTED_YIELD_VALUE 242 -#define INSTRUMENTED_LOAD_SUPER_ATTR 243 -#define INSTRUMENTED_FOR_ITER 244 -#define INSTRUMENTED_CALL 245 -#define INSTRUMENTED_CALL_FUNCTION_EX 246 -#define INSTRUMENTED_INSTRUCTION 247 -#define INSTRUMENTED_JUMP_FORWARD 248 -#define INSTRUMENTED_JUMP_BACKWARD 249 -#define INSTRUMENTED_POP_JUMP_IF_TRUE 250 -#define INSTRUMENTED_POP_JUMP_IF_FALSE 251 -#define INSTRUMENTED_POP_JUMP_IF_NONE 252 -#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 253 +#define INSTRUMENTED_LOAD_SUPER_ATTR 238 +#define INSTRUMENTED_FOR_ITER 239 +#define INSTRUMENTED_CALL 240 +#define INSTRUMENTED_CALL_FUNCTION_EX 241 +#define INSTRUMENTED_INSTRUCTION 242 +#define INSTRUMENTED_JUMP_FORWARD 243 +#define INSTRUMENTED_JUMP_BACKWARD 244 +#define INSTRUMENTED_POP_JUMP_IF_TRUE 245 +#define INSTRUMENTED_POP_JUMP_IF_FALSE 246 +#define INSTRUMENTED_POP_JUMP_IF_NONE 247 +#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 248 +#define INSTRUMENTED_END_FOR 249 +#define INSTRUMENTED_END_SEND 250 +#define INSTRUMENTED_RETURN_VALUE 251 +#define INSTRUMENTED_RETURN_CONST 252 +#define INSTRUMENTED_YIELD_VALUE 253 #define INSTRUMENTED_LINE 254 #define JUMP 256 #define JUMP_NO_INTERRUPT 257 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 20975ffb4c5321..c914f949e612b0 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -131,52 +131,52 @@ 'TO_BOOL_LIST': 61, 'TO_BOOL_NONE': 62, 'TO_BOOL_STR': 63, - 'CALL_BOUND_METHOD_EXACT_ARGS': 77, - 'CALL_BUILTIN_CLASS': 78, - 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 79, - 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 83, - 'CALL_NO_KW_ALLOC_AND_ENTER_INIT': 84, - 'CALL_NO_KW_BUILTIN_FAST': 85, - 'CALL_NO_KW_BUILTIN_O': 86, - 'CALL_NO_KW_ISINSTANCE': 87, - 'CALL_NO_KW_LEN': 88, - 'CALL_NO_KW_LIST_APPEND': 89, - 'CALL_NO_KW_METHOD_DESCRIPTOR_FAST': 90, - 'CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS': 91, - 'CALL_NO_KW_METHOD_DESCRIPTOR_O': 92, - 'CALL_NO_KW_STR_1': 93, - 'CALL_NO_KW_TUPLE_1': 94, - 'CALL_NO_KW_TYPE_1': 95, - 'CALL_PY_EXACT_ARGS': 96, - 'CALL_PY_WITH_DEFAULTS': 97, - 'COMPARE_OP_FLOAT': 99, - 'COMPARE_OP_INT': 100, - 'COMPARE_OP_STR': 101, - 'FOR_ITER_GEN': 116, - 'FOR_ITER_LIST': 117, - 'FOR_ITER_RANGE': 118, - 'FOR_ITER_TUPLE': 119, - 'LOAD_ATTR_CLASS': 131, - 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 132, - 'LOAD_ATTR_INSTANCE_VALUE': 133, - 'LOAD_ATTR_METHOD_LAZY_DICT': 134, - 'LOAD_ATTR_METHOD_NO_DICT': 135, - 'LOAD_ATTR_METHOD_WITH_VALUES': 136, - 'LOAD_ATTR_MODULE': 137, - 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 138, - 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 139, - 'LOAD_ATTR_PROPERTY': 140, - 'LOAD_ATTR_SLOT': 141, - 'LOAD_ATTR_WITH_HINT': 142, - 'LOAD_GLOBAL_BUILTIN': 152, - 'LOAD_GLOBAL_MODULE': 153, - 'LOAD_SUPER_ATTR_ATTR': 156, - 'LOAD_SUPER_ATTR_METHOD': 157, - 'SEND_GEN': 170, - 'STORE_ATTR_WITH_HINT': 175, - 'UNPACK_SEQUENCE_LIST': 185, - 'UNPACK_SEQUENCE_TUPLE': 186, - 'UNPACK_SEQUENCE_TWO_TUPLE': 187, + 'CALL_BOUND_METHOD_EXACT_ARGS': 79, + 'CALL_BUILTIN_CLASS': 80, + 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 81, + 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 85, + 'CALL_NO_KW_ALLOC_AND_ENTER_INIT': 86, + 'CALL_NO_KW_BUILTIN_FAST': 87, + 'CALL_NO_KW_BUILTIN_O': 88, + 'CALL_NO_KW_ISINSTANCE': 89, + 'CALL_NO_KW_LEN': 90, + 'CALL_NO_KW_LIST_APPEND': 91, + 'CALL_NO_KW_METHOD_DESCRIPTOR_FAST': 92, + 'CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS': 93, + 'CALL_NO_KW_METHOD_DESCRIPTOR_O': 94, + 'CALL_NO_KW_STR_1': 95, + 'CALL_NO_KW_TUPLE_1': 96, + 'CALL_NO_KW_TYPE_1': 97, + 'CALL_PY_EXACT_ARGS': 98, + 'CALL_PY_WITH_DEFAULTS': 99, + 'COMPARE_OP_FLOAT': 101, + 'COMPARE_OP_INT': 102, + 'COMPARE_OP_STR': 103, + 'FOR_ITER_GEN': 118, + 'FOR_ITER_LIST': 119, + 'FOR_ITER_RANGE': 120, + 'FOR_ITER_TUPLE': 121, + 'LOAD_ATTR_CLASS': 133, + 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 134, + 'LOAD_ATTR_INSTANCE_VALUE': 135, + 'LOAD_ATTR_METHOD_LAZY_DICT': 136, + 'LOAD_ATTR_METHOD_NO_DICT': 137, + 'LOAD_ATTR_METHOD_WITH_VALUES': 138, + 'LOAD_ATTR_MODULE': 139, + 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 140, + 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 141, + 'LOAD_ATTR_PROPERTY': 142, + 'LOAD_ATTR_SLOT': 143, + 'LOAD_ATTR_WITH_HINT': 144, + 'LOAD_GLOBAL_BUILTIN': 154, + 'LOAD_GLOBAL_MODULE': 155, + 'LOAD_SUPER_ATTR_ATTR': 158, + 'LOAD_SUPER_ATTR_METHOD': 159, + 'SEND_GEN': 172, + 'STORE_ATTR_WITH_HINT': 177, + 'UNPACK_SEQUENCE_LIST': 187, + 'UNPACK_SEQUENCE_TUPLE': 188, + 'UNPACK_SEQUENCE_TWO_TUPLE': 189, } opmap = { @@ -224,98 +224,100 @@ 'UNARY_NEGATIVE': 65, 'UNARY_NOT': 66, 'WITH_EXCEPT_START': 67, - 'BINARY_OP': 68, - 'BUILD_CONST_KEY_MAP': 69, - 'BUILD_LIST': 70, - 'BUILD_MAP': 71, - 'BUILD_SET': 72, - 'BUILD_SLICE': 73, - 'BUILD_STRING': 74, - 'BUILD_TUPLE': 75, - 'CALL': 76, - 'CALL_FUNCTION_EX': 80, - 'CALL_INTRINSIC_1': 81, - 'CALL_INTRINSIC_2': 82, - 'COMPARE_OP': 98, - 'CONTAINS_OP': 102, - 'CONVERT_VALUE': 103, - 'COPY': 104, - 'COPY_FREE_VARS': 105, - 'DELETE_ATTR': 106, - 'DELETE_DEREF': 107, - 'DELETE_FAST': 108, - 'DELETE_GLOBAL': 109, - 'DELETE_NAME': 110, - 'DICT_MERGE': 111, - 'DICT_UPDATE': 112, - 'ENTER_EXECUTOR': 113, - 'EXTENDED_ARG': 114, - 'FOR_ITER': 115, - 'GET_AWAITABLE': 120, - 'IMPORT_FROM': 121, - 'IMPORT_NAME': 122, - 'IS_OP': 123, - 'JUMP_BACKWARD': 124, - 'JUMP_BACKWARD_NO_INTERRUPT': 125, - 'JUMP_FORWARD': 126, - 'KW_NAMES': 127, - 'LIST_APPEND': 128, - 'LIST_EXTEND': 129, - 'LOAD_ATTR': 130, - 'LOAD_CONST': 143, - 'LOAD_DEREF': 144, - 'LOAD_FAST': 145, - 'LOAD_FAST_AND_CLEAR': 146, - 'LOAD_FAST_CHECK': 147, - 'LOAD_FAST_LOAD_FAST': 148, - 'LOAD_FROM_DICT_OR_DEREF': 149, - 'LOAD_FROM_DICT_OR_GLOBALS': 150, - 'LOAD_GLOBAL': 151, - 'LOAD_NAME': 154, - 'LOAD_SUPER_ATTR': 155, - 'MAKE_CELL': 158, - 'MAP_ADD': 159, - 'MATCH_CLASS': 160, - 'POP_JUMP_IF_FALSE': 161, - 'POP_JUMP_IF_NONE': 162, - 'POP_JUMP_IF_NOT_NONE': 163, - 'POP_JUMP_IF_TRUE': 164, - 'RAISE_VARARGS': 165, + '_END_FOR_MONITOR': 68, + '_END_SEND_MONITOR': 69, + 'BINARY_OP': 70, + 'BUILD_CONST_KEY_MAP': 71, + 'BUILD_LIST': 72, + 'BUILD_MAP': 73, + 'BUILD_SET': 74, + 'BUILD_SLICE': 75, + 'BUILD_STRING': 76, + 'BUILD_TUPLE': 77, + 'CALL': 78, + 'CALL_FUNCTION_EX': 82, + 'CALL_INTRINSIC_1': 83, + 'CALL_INTRINSIC_2': 84, + 'COMPARE_OP': 100, + 'CONTAINS_OP': 104, + 'CONVERT_VALUE': 105, + 'COPY': 106, + 'COPY_FREE_VARS': 107, + 'DELETE_ATTR': 108, + 'DELETE_DEREF': 109, + 'DELETE_FAST': 110, + 'DELETE_GLOBAL': 111, + 'DELETE_NAME': 112, + 'DICT_MERGE': 113, + 'DICT_UPDATE': 114, + 'ENTER_EXECUTOR': 115, + 'EXTENDED_ARG': 116, + 'FOR_ITER': 117, + 'GET_AWAITABLE': 122, + 'IMPORT_FROM': 123, + 'IMPORT_NAME': 124, + 'IS_OP': 125, + 'JUMP_BACKWARD': 126, + 'JUMP_BACKWARD_NO_INTERRUPT': 127, + 'JUMP_FORWARD': 128, + 'KW_NAMES': 129, + 'LIST_APPEND': 130, + 'LIST_EXTEND': 131, + 'LOAD_ATTR': 132, + 'LOAD_CONST': 145, + 'LOAD_DEREF': 146, + 'LOAD_FAST': 147, + 'LOAD_FAST_AND_CLEAR': 148, + 'LOAD_FAST_CHECK': 149, + 'LOAD_FAST_LOAD_FAST': 150, + 'LOAD_FROM_DICT_OR_DEREF': 151, + 'LOAD_FROM_DICT_OR_GLOBALS': 152, + 'LOAD_GLOBAL': 153, + 'LOAD_NAME': 156, + 'LOAD_SUPER_ATTR': 157, + 'MAKE_CELL': 160, + 'MAP_ADD': 161, + 'MATCH_CLASS': 162, + 'POP_JUMP_IF_FALSE': 163, + 'POP_JUMP_IF_NONE': 164, + 'POP_JUMP_IF_NOT_NONE': 165, 'RESUME': 166, - 'RERAISE': 167, - 'RETURN_CONST': 168, - 'SEND': 169, - 'SET_ADD': 171, - 'SET_FUNCTION_ATTRIBUTE': 172, - 'SET_UPDATE': 173, - 'STORE_ATTR': 174, - 'STORE_DEREF': 176, - 'STORE_FAST': 177, - 'STORE_FAST_LOAD_FAST': 178, - 'STORE_FAST_STORE_FAST': 179, - 'STORE_GLOBAL': 180, - 'STORE_NAME': 181, - 'SWAP': 182, - 'UNPACK_EX': 183, - 'UNPACK_SEQUENCE': 184, - 'YIELD_VALUE': 188, + 'POP_JUMP_IF_TRUE': 167, + 'RAISE_VARARGS': 168, + 'RERAISE': 169, + 'RETURN_CONST': 170, + 'SEND': 171, + 'SET_ADD': 173, + 'SET_FUNCTION_ATTRIBUTE': 174, + 'SET_UPDATE': 175, + 'STORE_ATTR': 176, + 'STORE_DEREF': 178, + 'STORE_FAST': 179, + 'STORE_FAST_LOAD_FAST': 180, + 'STORE_FAST_STORE_FAST': 181, + 'STORE_GLOBAL': 182, + 'STORE_NAME': 183, + 'SWAP': 184, + 'UNPACK_EX': 185, + 'UNPACK_SEQUENCE': 186, + 'YIELD_VALUE': 190, 'INSTRUMENTED_RESUME': 237, - 'INSTRUMENTED_END_FOR': 238, - 'INSTRUMENTED_END_SEND': 239, - 'INSTRUMENTED_RETURN_VALUE': 240, - 'INSTRUMENTED_RETURN_CONST': 241, - 'INSTRUMENTED_YIELD_VALUE': 242, - 'INSTRUMENTED_LOAD_SUPER_ATTR': 243, - 'INSTRUMENTED_FOR_ITER': 244, - 'INSTRUMENTED_CALL': 245, - 'INSTRUMENTED_CALL_FUNCTION_EX': 246, - 'INSTRUMENTED_INSTRUCTION': 247, - 'INSTRUMENTED_JUMP_FORWARD': 248, - 'INSTRUMENTED_JUMP_BACKWARD': 249, - 'INSTRUMENTED_POP_JUMP_IF_TRUE': 250, - 'INSTRUMENTED_POP_JUMP_IF_FALSE': 251, - 'INSTRUMENTED_POP_JUMP_IF_NONE': 252, - 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 253, + 'INSTRUMENTED_LOAD_SUPER_ATTR': 238, + 'INSTRUMENTED_FOR_ITER': 239, + 'INSTRUMENTED_CALL': 240, + 'INSTRUMENTED_CALL_FUNCTION_EX': 241, + 'INSTRUMENTED_INSTRUCTION': 242, + 'INSTRUMENTED_JUMP_FORWARD': 243, + 'INSTRUMENTED_JUMP_BACKWARD': 244, + 'INSTRUMENTED_POP_JUMP_IF_TRUE': 245, + 'INSTRUMENTED_POP_JUMP_IF_FALSE': 246, + 'INSTRUMENTED_POP_JUMP_IF_NONE': 247, + 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 248, + 'INSTRUMENTED_END_FOR': 249, + 'INSTRUMENTED_END_SEND': 250, + 'INSTRUMENTED_RETURN_VALUE': 251, + 'INSTRUMENTED_RETURN_CONST': 252, + 'INSTRUMENTED_YIELD_VALUE': 253, 'INSTRUMENTED_LINE': 254, 'JUMP': 256, 'JUMP_NO_INTERRUPT': 257, @@ -331,4 +333,4 @@ 'STORE_FAST_MAYBE_NULL': 267, } MIN_INSTRUMENTED_OPCODE = 237 -HAVE_ARGUMENT = 68 +HAVE_ARGUMENT = 70 diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 7590e87ab1eadd..bdf5dad2b002b8 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,17 +1,17 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,243,164,0,0,0,166,0,143,0,143,1, - 122,0,181,0,143,0,143,1,122,1,181,1,154,2,46,0, - 143,2,76,1,0,0,0,0,0,0,44,0,154,2,46,0, - 143,3,154,0,130,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,76,2,0,0,0,0,0,0, - 44,0,154,1,130,8,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,46,0,76,0,0,0,0,0, - 0,0,143,4,12,0,0,0,181,5,143,5,31,0,115,20, - 0,0,181,6,154,2,46,0,143,6,154,6,27,0,143,7, - 154,5,154,6,12,0,0,0,27,0,74,4,76,1,0,0, - 0,0,0,0,44,0,124,22,0,0,24,0,168,1,41,8, + 0,0,0,0,0,243,164,0,0,0,166,0,145,0,145,1, + 124,0,183,0,145,0,145,1,124,1,183,1,156,2,46,0, + 145,2,78,1,0,0,0,0,0,0,44,0,156,2,46,0, + 145,3,156,0,132,6,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,78,2,0,0,0,0,0,0, + 44,0,156,1,132,8,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,46,0,78,0,0,0,0,0, + 0,0,145,4,12,0,0,0,183,5,145,5,31,0,117,20, + 0,0,183,6,156,2,46,0,145,6,156,6,27,0,145,7, + 156,5,156,6,12,0,0,0,27,0,76,4,78,1,0,0, + 0,0,0,0,44,0,126,22,0,0,24,0,170,1,41,8, 233,0,0,0,0,78,122,18,70,114,111,122,101,110,32,72, 101,108,108,111,32,87,111,114,108,100,122,8,115,121,115,46, 97,114,103,118,218,6,99,111,110,102,105,103,41,5,218,12, diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h index 398c04616bc091..8dab875b5a30b5 100644 --- a/Python/abstract_interp_cases.c.h +++ b/Python/abstract_interp_cases.c.h @@ -216,6 +216,10 @@ break; } + case _SUSPEND_GENERATOR: { + break; + } + case POP_EXCEPT: { STACK_SHRINK(1); break; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ff95f37b900da6..e4fbe65da1e3b2 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -164,14 +164,13 @@ dummy_func( } inst(INSTRUMENTED_RESUME, (--)) { + TIER_ONE_ONLY; /* Possible performance enhancement: * We need to check the eval breaker anyway, can we * combine the instrument verison check and the eval breaker test? */ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { - if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { - goto error; - } + ERROR_IF(_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp), error); next_instr--; } else { @@ -260,34 +259,34 @@ dummy_func( macro(END_FOR) = POP_TOP + POP_TOP; - inst(INSTRUMENTED_END_FOR, (receiver, value --)) { + inst(_END_FOR_MONITOR, (receiver, value -- receiver, value)) { + TIER_ONE_ONLY; /* Need to create a fake StopIteration error here, * to conform to PEP 380 */ if (PyGen_Check(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } + ERROR_IF(monitor_stop_iteration(tstate, frame, next_instr-1), error); PyErr_SetRaisedException(NULL); } - DECREF_INPUTS(); } + macro(INSTRUMENTED_END_FOR) = _END_FOR_MONITOR + POP_TOP + POP_TOP; + inst(END_SEND, (receiver, value -- value)) { Py_DECREF(receiver); } - inst(INSTRUMENTED_END_SEND, (receiver, value -- value)) { + inst(_END_SEND_MONITOR, (receiver, value -- receiver, value)) { + TIER_ONE_ONLY; if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } + ERROR_IF(monitor_stop_iteration(tstate, frame, next_instr-1), error); PyErr_SetRaisedException(NULL); } - Py_DECREF(receiver); } + macro(INSTRUMENTED_END_SEND) = _END_SEND_MONITOR + END_SEND; + inst(UNARY_NEGATIVE, (value -- res)) { res = PyNumber_Negative(value); DECREF_INPUTS(); @@ -742,6 +741,7 @@ dummy_func( } inst(RAISE_VARARGS, (args[oparg] -- )) { + TIER_ONE_ONLY; PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -807,50 +807,32 @@ dummy_func( SAVE_CURRENT_IP + // Sets frame->prev_instr _POP_FRAME; - inst(INSTRUMENTED_RETURN_VALUE, (retval --)) { + op(_MONITOR_RETURN, (retval -- retval)) { + TIER_ONE_ONLY; int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, next_instr-1, retval); - if (err) goto error; - STACK_SHRINK(1); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + ERROR_IF(err, error); } + macro(INSTRUMENTED_RETURN_VALUE) = + _MONITOR_RETURN + + SAVE_IP + // Tier 2 only; special-cased oparg + SAVE_CURRENT_IP + // Sets frame->prev_instr + _POP_FRAME; + macro(RETURN_CONST) = LOAD_CONST + SAVE_IP + // Tier 2 only; special-cased oparg SAVE_CURRENT_IP + // Sets frame->prev_instr _POP_FRAME; - inst(INSTRUMENTED_RETURN_CONST, (--)) { - PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; - Py_INCREF(retval); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; - } + macro(INSTRUMENTED_RETURN_CONST) = + LOAD_CONST + + _MONITOR_RETURN + + SAVE_IP + // Tier 2 only; special-cased oparg + SAVE_CURRENT_IP + // Sets frame->prev_instr + _POP_FRAME; inst(GET_AITER, (obj -- iter)) { unaryfunc getter = NULL; @@ -961,6 +943,7 @@ dummy_func( }; inst(SEND, (unused/1, receiver, v -- receiver, retval)) { + TIER_ONE_ONLY; #if ENABLE_SPECIALIZATION _PySendCache *cache = (_PySendCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1027,35 +1010,29 @@ dummy_func( DISPATCH_INLINED(gen_frame); } - inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) { + op(_SUSPEND_GENERATOR, (val -- val)) { +#if TIER_ONE assert(frame != &entry_frame); - assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ +#endif PyGenObject *gen = _PyFrame_GetGenerator(frame); gen->gi_frame_state = FRAME_SUSPENDED; _PyFrame_SetStackPointer(frame, stack_pointer - 1); + } + + op(_MONITOR_YIELD_VALUE, (val -- val)) { + TIER_ONE_ONLY; int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, - frame, next_instr-1, retval); - if (err) goto error; - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = tstate->current_frame = frame->previous; - gen_frame->previous = NULL; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + frame, next_instr-1, val); + ERROR_IF(err, error); } - inst(YIELD_VALUE, (retval -- unused)) { + op(_DO_YIELD, (retval -- unused)) { // NOTE: It's important that YIELD_VALUE never raises an exception! // The compiler treats any exception raised here as a failed close() // or throw() call. assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ - assert(frame != &entry_frame); PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer - 1); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); @@ -1066,12 +1043,22 @@ dummy_func( goto resume_frame; } + macro(YIELD_VALUE) = + _SUSPEND_GENERATOR + + _DO_YIELD; + + macro(INSTRUMENTED_YIELD_VALUE) = + _SUSPEND_GENERATOR + + _MONITOR_YIELD_VALUE + + _DO_YIELD; + inst(POP_EXCEPT, (exc_value -- )) { _PyErr_StackItem *exc_info = tstate->exc_info; Py_XSETREF(exc_info->exc_value, exc_value); } inst(RERAISE, (values[oparg], exc -- values[oparg])) { + TIER_ONE_ONLY; assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1093,6 +1080,7 @@ dummy_func( } inst(END_ASYNC_FOR, (awaitable, exc -- )) { + TIER_ONE_ONLY; assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { DECREF_INPUTS(); @@ -1106,6 +1094,7 @@ dummy_func( } inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- none, value)) { + TIER_ONE_ONLY; assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -1133,7 +1122,6 @@ dummy_func( } } - inst(STORE_NAME, (v -- )) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); @@ -1691,6 +1679,7 @@ dummy_func( } inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/9, unused, unused, unused -- unused, unused if (oparg & 1))) { + TIER_ONE_ONLY; _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we // don't want to specialize instrumented instructions @@ -2412,6 +2401,7 @@ dummy_func( }; inst(FOR_ITER, (unused/1, iter -- iter, next)) { + TIER_ONE_ONLY; #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2446,6 +2436,7 @@ dummy_func( } inst(INSTRUMENTED_FOR_ITER, ( -- )) { + TIER_ONE_ONLY; _Py_CODEUNIT *here = next_instr-1; _Py_CODEUNIT *target; PyObject *iter = TOP(); @@ -2856,6 +2847,7 @@ dummy_func( } inst(INSTRUMENTED_CALL, ( -- )) { + TIER_ONE_ONLY; int is_meth = PEEK(oparg + 1) != NULL; int total_args = oparg + is_meth; PyObject *function = PEEK(oparg + 2); @@ -3528,6 +3520,7 @@ dummy_func( } inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) { + TIER_ONE_ONLY; GO_TO_INSTRUCTION(CALL_FUNCTION_EX); } @@ -3729,6 +3722,7 @@ dummy_func( } inst(INSTRUMENTED_INSTRUCTION, ( -- )) { + TIER_ONE_ONLY; int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, next_instr-1); ERROR_IF(next_opcode < 0, error); @@ -3743,15 +3737,18 @@ dummy_func( } inst(INSTRUMENTED_JUMP_FORWARD, ( -- )) { + TIER_ONE_ONLY; INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); } inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) { + TIER_ONE_ONLY; CHECK_EVAL_BREAKER(); INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP); } inst(INSTRUMENTED_POP_JUMP_IF_TRUE, ( -- )) { + TIER_ONE_ONLY; PyObject *cond = POP(); assert(PyBool_Check(cond)); _Py_CODEUNIT *here = next_instr - 1; @@ -3760,6 +3757,7 @@ dummy_func( } inst(INSTRUMENTED_POP_JUMP_IF_FALSE, ( -- )) { + TIER_ONE_ONLY; PyObject *cond = POP(); assert(PyBool_Check(cond)); _Py_CODEUNIT *here = next_instr - 1; @@ -3768,6 +3766,7 @@ dummy_func( } inst(INSTRUMENTED_POP_JUMP_IF_NONE, ( -- )) { + TIER_ONE_ONLY; PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -3782,6 +3781,7 @@ dummy_func( } inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, ( -- )) { + TIER_ONE_ONLY; PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 918991dca7dd25..6c053fbdc2ce0f 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -825,6 +825,18 @@ break; } + case _SUSPEND_GENERATOR: { + PyObject *val; + val = stack_pointer[-1]; +#if TIER_ONE + assert(frame != &entry_frame); +#endif + PyGenObject *gen = _PyFrame_GetGenerator(frame); + gen->gi_frame_state = FRAME_SUSPENDED; + _PyFrame_SetStackPointer(frame, stack_pointer - 1); + break; + } + case POP_EXCEPT: { PyObject *exc_value; exc_value = stack_pointer[-1]; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index e84599d87a6968..e18b50730fe3cf 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -39,14 +39,13 @@ } TARGET(INSTRUMENTED_RESUME) { + TIER_ONE_ONLY; /* Possible performance enhancement: * We need to check the eval breaker anyway, can we * combine the instrument verison check and the eval breaker test? */ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { - if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { - goto error; - } + if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) goto error; next_instr--; } else { @@ -187,22 +186,47 @@ DISPATCH(); } - TARGET(INSTRUMENTED_END_FOR) { + TARGET(_END_FOR_MONITOR) { PyObject *value; PyObject *receiver; value = stack_pointer[-1]; receiver = stack_pointer[-2]; + TIER_ONE_ONLY; /* Need to create a fake StopIteration error here, * to conform to PEP 380 */ if (PyGen_Check(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } + if (monitor_stop_iteration(tstate, frame, next_instr-1)) goto error; PyErr_SetRaisedException(NULL); } - Py_DECREF(receiver); - Py_DECREF(value); + DISPATCH(); + } + + TARGET(INSTRUMENTED_END_FOR) { + PyObject *value; + PyObject *receiver; + // _END_FOR_MONITOR + value = stack_pointer[-1]; + receiver = stack_pointer[-2]; + { + TIER_ONE_ONLY; + /* Need to create a fake StopIteration error here, + * to conform to PEP 380 */ + if (PyGen_Check(receiver)) { + PyErr_SetObject(PyExc_StopIteration, value); + if (monitor_stop_iteration(tstate, frame, next_instr-1)) goto error; + PyErr_SetRaisedException(NULL); + } + } + // POP_TOP + { + Py_DECREF(value); + } + // POP_TOP + value = receiver; + { + Py_DECREF(value); + } STACK_SHRINK(2); DISPATCH(); } @@ -218,19 +242,38 @@ DISPATCH(); } - TARGET(INSTRUMENTED_END_SEND) { + TARGET(_END_SEND_MONITOR) { PyObject *value; PyObject *receiver; value = stack_pointer[-1]; receiver = stack_pointer[-2]; + TIER_ONE_ONLY; if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); - if (monitor_stop_iteration(tstate, frame, next_instr-1)) { - goto error; - } + if (monitor_stop_iteration(tstate, frame, next_instr-1)) goto error; PyErr_SetRaisedException(NULL); } - Py_DECREF(receiver); + DISPATCH(); + } + + TARGET(INSTRUMENTED_END_SEND) { + PyObject *value; + PyObject *receiver; + // _END_SEND_MONITOR + value = stack_pointer[-1]; + receiver = stack_pointer[-2]; + { + TIER_ONE_ONLY; + if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { + PyErr_SetObject(PyExc_StopIteration, value); + if (monitor_stop_iteration(tstate, frame, next_instr-1)) goto error; + PyErr_SetRaisedException(NULL); + } + } + // END_SEND + { + Py_DECREF(receiver); + } STACK_SHRINK(1); stack_pointer[-1] = value; DISPATCH(); @@ -948,6 +991,7 @@ TARGET(RAISE_VARARGS) { PyObject **args; args = stack_pointer - oparg; + TIER_ONE_ONLY; PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -1027,24 +1071,50 @@ TARGET(INSTRUMENTED_RETURN_VALUE) { PyObject *retval; + // _MONITOR_RETURN retval = stack_pointer[-1]; - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; - STACK_SHRINK(1); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + { + TIER_ONE_ONLY; + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_RETURN, + frame, next_instr-1, retval); + if (err) goto error; + } + // SAVE_CURRENT_IP + { + #if TIER_ONE + frame->prev_instr = next_instr - 1; + #endif + #if TIER_TWO + // Relies on a preceding SAVE_IP + frame->prev_instr--; + #endif + } + // _POP_FRAME STACK_SHRINK(1); + { + assert(EMPTY()); + #if TIER_ONE + assert(frame != &entry_frame); + #endif + STORE_SP(); + _Py_LeaveRecursiveCallPy(tstate); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + frame->prev_instr += frame->return_offset; + _PyFrame_StackPush(frame, retval); + LOAD_SP(); + LOAD_IP(); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif + } + DISPATCH(); } TARGET(RETURN_CONST) { @@ -1093,23 +1163,56 @@ } TARGET(INSTRUMENTED_RETURN_CONST) { - PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_RETURN, - frame, next_instr-1, retval); - if (err) goto error; - Py_INCREF(retval); - assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_LeaveRecursiveCallPy(tstate); - assert(frame != &entry_frame); - // GH-99729: We need to unlink the frame *before* clearing it: - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - frame->prev_instr += frame->return_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + PyObject *value; + PyObject *retval; + // LOAD_CONST + { + value = GETITEM(FRAME_CO_CONSTS, oparg); + Py_INCREF(value); + } + // _MONITOR_RETURN + retval = value; + { + TIER_ONE_ONLY; + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_RETURN, + frame, next_instr-1, retval); + if (err) goto error; + } + // SAVE_CURRENT_IP + { + #if TIER_ONE + frame->prev_instr = next_instr - 1; + #endif + #if TIER_TWO + // Relies on a preceding SAVE_IP + frame->prev_instr--; + #endif + } + // _POP_FRAME + { + assert(EMPTY()); + #if TIER_ONE + assert(frame != &entry_frame); + #endif + STORE_SP(); + _Py_LeaveRecursiveCallPy(tstate); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + frame->prev_instr += frame->return_offset; + _PyFrame_StackPush(frame, retval); + LOAD_SP(); + LOAD_IP(); + #if LLTRACE && TIER_ONE + lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); + if (lltrace < 0) { + goto exit_unwind; + } + #endif + } + DISPATCH(); } TARGET(GET_AITER) { @@ -1240,6 +1343,7 @@ PyObject *retval; v = stack_pointer[-1]; receiver = stack_pointer[-2]; + TIER_ONE_ONLY; #if ENABLE_SPECIALIZATION _PySendCache *cache = (_PySendCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1313,47 +1417,76 @@ DISPATCH_INLINED(gen_frame); } - TARGET(INSTRUMENTED_YIELD_VALUE) { + TARGET(YIELD_VALUE) { + PyObject *val; PyObject *retval; - retval = stack_pointer[-1]; - assert(frame != &entry_frame); - assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ - PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer - 1); - int err = _Py_call_instrumentation_arg( - tstate, PY_MONITORING_EVENT_PY_YIELD, - frame, next_instr-1, retval); - if (err) goto error; - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = tstate->current_frame = frame->previous; - gen_frame->previous = NULL; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + // _SUSPEND_GENERATOR + val = stack_pointer[-1]; + { + #if TIER_ONE + assert(frame != &entry_frame); + #endif + PyGenObject *gen = _PyFrame_GetGenerator(frame); + gen->gi_frame_state = FRAME_SUSPENDED; + _PyFrame_SetStackPointer(frame, stack_pointer - 1); + } + // _DO_YIELD + retval = val; + { + // NOTE: It's important that YIELD_VALUE never raises an exception! + // The compiler treats any exception raised here as a failed close() + // or throw() call. + assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ + PyGenObject *gen = _PyFrame_GetGenerator(frame); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } } - TARGET(YIELD_VALUE) { + TARGET(INSTRUMENTED_YIELD_VALUE) { + PyObject *val; PyObject *retval; - retval = stack_pointer[-1]; - // NOTE: It's important that YIELD_VALUE never raises an exception! - // The compiler treats any exception raised here as a failed close() - // or throw() call. - assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ - assert(frame != &entry_frame); - PyGenObject *gen = _PyFrame_GetGenerator(frame); - gen->gi_frame_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer - 1); - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = tstate->current_frame = frame->previous; - gen_frame->previous = NULL; - _PyFrame_StackPush(frame, retval); - goto resume_frame; + // _SUSPEND_GENERATOR + val = stack_pointer[-1]; + { + #if TIER_ONE + assert(frame != &entry_frame); + #endif + PyGenObject *gen = _PyFrame_GetGenerator(frame); + gen->gi_frame_state = FRAME_SUSPENDED; + _PyFrame_SetStackPointer(frame, stack_pointer - 1); + } + // _MONITOR_YIELD_VALUE + { + TIER_ONE_ONLY; + int err = _Py_call_instrumentation_arg( + tstate, PY_MONITORING_EVENT_PY_YIELD, + frame, next_instr-1, val); + if (err) goto error; + } + // _DO_YIELD + retval = val; + { + // NOTE: It's important that YIELD_VALUE never raises an exception! + // The compiler treats any exception raised here as a failed close() + // or throw() call. + assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ + PyGenObject *gen = _PyFrame_GetGenerator(frame); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } } TARGET(POP_EXCEPT) { @@ -1370,6 +1503,7 @@ PyObject **values; exc = stack_pointer[-1]; values = stack_pointer - 1 - oparg; + TIER_ONE_ONLY; assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1396,6 +1530,7 @@ PyObject *awaitable; exc = stack_pointer[-1]; awaitable = stack_pointer[-2]; + TIER_ONE_ONLY; assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { Py_DECREF(awaitable); @@ -1420,6 +1555,7 @@ exc_value = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; sub_iter = stack_pointer[-3]; + TIER_ONE_ONLY; assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -2208,6 +2344,7 @@ } TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) { + TIER_ONE_ONLY; _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we // don't want to specialize instrumented instructions @@ -3197,6 +3334,7 @@ PyObject *iter; PyObject *next; iter = stack_pointer[-1]; + TIER_ONE_ONLY; #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -3235,6 +3373,7 @@ } TARGET(INSTRUMENTED_FOR_ITER) { + TIER_ONE_ONLY; _Py_CODEUNIT *here = next_instr-1; _Py_CODEUNIT *target; PyObject *iter = TOP(); @@ -3687,6 +3826,7 @@ } TARGET(INSTRUMENTED_CALL) { + TIER_ONE_ONLY; int is_meth = PEEK(oparg + 1) != NULL; int total_args = oparg + is_meth; PyObject *function = PEEK(oparg + 2); @@ -4611,6 +4751,7 @@ } TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { + TIER_ONE_ONLY; GO_TO_INSTRUCTION(CALL_FUNCTION_EX); } @@ -4893,6 +5034,7 @@ } TARGET(INSTRUMENTED_INSTRUCTION) { + TIER_ONE_ONLY; int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, next_instr-1); if (next_opcode < 0) goto error; @@ -4907,17 +5049,20 @@ } TARGET(INSTRUMENTED_JUMP_FORWARD) { + TIER_ONE_ONLY; INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); DISPATCH(); } TARGET(INSTRUMENTED_JUMP_BACKWARD) { + TIER_ONE_ONLY; CHECK_EVAL_BREAKER(); INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP); DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { + TIER_ONE_ONLY; PyObject *cond = POP(); assert(PyBool_Check(cond)); _Py_CODEUNIT *here = next_instr - 1; @@ -4927,6 +5072,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { + TIER_ONE_ONLY; PyObject *cond = POP(); assert(PyBool_Check(cond)); _Py_CODEUNIT *here = next_instr - 1; @@ -4936,6 +5082,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { + TIER_ONE_ONLY; PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -4951,6 +5098,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { + TIER_ONE_ONLY; PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 413bb884dcf752..2ea02edadaa6b5 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -67,6 +67,8 @@ static void *opcode_targets[256] = { &&TARGET_UNARY_NEGATIVE, &&TARGET_UNARY_NOT, &&TARGET_WITH_EXCEPT_START, + &&TARGET__END_FOR_MONITOR, + &&TARGET__END_SEND_MONITOR, &&TARGET_BINARY_OP, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_LIST, @@ -163,9 +165,9 @@ static void *opcode_targets[256] = { &&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_NONE, &&TARGET_POP_JUMP_IF_NOT_NONE, + &&TARGET_RESUME, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_RAISE_VARARGS, - &&TARGET_RESUME, &&TARGET_RERAISE, &&TARGET_RETURN_CONST, &&TARGET_SEND, @@ -234,14 +236,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_RESUME, - &&TARGET_INSTRUMENTED_END_FOR, - &&TARGET_INSTRUMENTED_END_SEND, - &&TARGET_INSTRUMENTED_RETURN_VALUE, - &&TARGET_INSTRUMENTED_RETURN_CONST, - &&TARGET_INSTRUMENTED_YIELD_VALUE, &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, &&TARGET_INSTRUMENTED_FOR_ITER, &&TARGET_INSTRUMENTED_CALL, @@ -253,5 +248,10 @@ static void *opcode_targets[256] = { &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE, + &&TARGET_INSTRUMENTED_END_FOR, + &&TARGET_INSTRUMENTED_END_SEND, + &&TARGET_INSTRUMENTED_RETURN_VALUE, + &&TARGET_INSTRUMENTED_RETURN_CONST, + &&TARGET_INSTRUMENTED_YIELD_VALUE, &&TARGET_INSTRUMENTED_LINE, &&_unknown_opcode}; From d8ae98346bc4c0d633557ca5e834032d5c552489 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Sun, 10 Sep 2023 18:26:17 +0100 Subject: [PATCH 2/2] Add news --- .../2023-09-10-18-26-03.gh-issue-104909.OWEgB8.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-09-10-18-26-03.gh-issue-104909.OWEgB8.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-10-18-26-03.gh-issue-104909.OWEgB8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-10-18-26-03.gh-issue-104909.OWEgB8.rst new file mode 100644 index 00000000000000..49e3a8305e2124 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-09-10-18-26-03.gh-issue-104909.OWEgB8.rst @@ -0,0 +1,2 @@ +Implement instrumented instructions in terms of micro-ops and make it +explicit that instrumented instructions are tier 1 only.