From 021fc099bb06218984879f26e8b4b05c879ec331 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 24 Jul 2025 10:26:18 +0100 Subject: [PATCH] Add _CHECK_PERIODIC_AT_END and EXIT_IF_AFTER to better declare semantics of exits at ends of instructions/uops. --- Include/internal/pycore_opcode_metadata.h | 34 +- Include/internal/pycore_uop_ids.h | 390 +++++++++--------- Include/internal/pycore_uop_metadata.h | 6 +- Python/bytecodes.c | 62 +-- Python/ceval.c | 1 + Python/executor_cases.c.h | 10 + Python/generated_cases.c.h | 32 +- Python/optimizer.c | 21 +- Python/optimizer_cases.c.h | 6 + Tools/cases_generator/analyzer.py | 14 +- Tools/cases_generator/generators_common.py | 27 ++ .../opcode_metadata_generator.py | 3 +- Tools/cases_generator/tier1_generator.py | 2 +- Tools/cases_generator/tier2_generator.py | 2 + 14 files changed, 343 insertions(+), 267 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index dd1bf2d1d2b51a..b86106944b5142 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1028,10 +1028,9 @@ enum InstructionFormat { #define HAS_ESCAPES_FLAG (512) #define HAS_EXIT_FLAG (1024) #define HAS_PURE_FLAG (2048) -#define HAS_PASSTHROUGH_FLAG (4096) -#define HAS_OPARG_AND_1_FLAG (8192) -#define HAS_ERROR_NO_POP_FLAG (16384) -#define HAS_NO_SAVE_IP_FLAG (32768) +#define HAS_ERROR_NO_POP_FLAG (4096) +#define HAS_NO_SAVE_IP_FLAG (8192) +#define HAS_PERIODIC_FLAG (16384) #define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG)) #define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG)) #define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG)) @@ -1044,10 +1043,9 @@ enum InstructionFormat { #define OPCODE_HAS_ESCAPES(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ESCAPES_FLAG)) #define OPCODE_HAS_EXIT(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_EXIT_FLAG)) #define OPCODE_HAS_PURE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_PURE_FLAG)) -#define OPCODE_HAS_PASSTHROUGH(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_PASSTHROUGH_FLAG)) -#define OPCODE_HAS_OPARG_AND_1(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_OPARG_AND_1_FLAG)) #define OPCODE_HAS_ERROR_NO_POP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ERROR_NO_POP_FLAG)) #define OPCODE_HAS_NO_SAVE_IP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NO_SAVE_IP_FLAG)) +#define OPCODE_HAS_PERIODIC(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_PERIODIC_FLAG)) #define OPARG_SIMPLE 0 #define OPARG_CACHE_1 1 @@ -1347,27 +1345,27 @@ _PyOpcode_macro_expansion[256] = { [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 4, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_AND_ALLOCATE_OBJECT, 2, 1 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 10, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_BUILTIN_O] = { .nuops = 2, .uops = { { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, + [CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_O] = { .nuops = 2, .uops = { { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 } } }, [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_2, OPARG_SIMPLE, 0 } } }, [CALL_ISINSTANCE] = { .nuops = 3, .uops = { { _GUARD_THIRD_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_ISINSTANCE, OPARG_SIMPLE, 3 }, { _CALL_ISINSTANCE, OPARG_SIMPLE, 3 } } }, [CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, + [CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_KW_PY] = { .nuops = 5, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_LEN] = { .nuops = 3, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 } } }, [CALL_LIST_APPEND] = { .nuops = 4, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_NON_PY_GENERAL] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_NON_PY_GENERAL] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_PY_EXACT_ARGS] = { .nuops = 8, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_PY_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_STR_1] = { .nuops = 4, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_STR_1, OPARG_SIMPLE, 3 }, { _CALL_STR_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_TUPLE_1] = { .nuops = 4, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TUPLE_1, OPARG_SIMPLE, 3 }, { _CALL_TUPLE_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, + [CALL_STR_1] = { .nuops = 4, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_STR_1, OPARG_SIMPLE, 3 }, { _CALL_STR_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_TUPLE_1] = { .nuops = 4, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TUPLE_1, OPARG_SIMPLE, 3 }, { _CALL_TUPLE_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_TYPE_1] = { .nuops = 3, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TYPE_1, OPARG_SIMPLE, 3 }, { _CALL_TYPE_1, OPARG_SIMPLE, 3 } } }, [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { _CHECK_EG_MATCH, OPARG_SIMPLE, 0 } } }, [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { _CHECK_EXC_MATCH, OPARG_SIMPLE, 0 } } }, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index a9432401525ebb..4cc07dc5490b3d 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -76,104 +76,105 @@ extern "C" { #define _CHECK_METHOD_VERSION_KW 352 #define _CHECK_PEP_523 353 #define _CHECK_PERIODIC 354 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 355 -#define _CHECK_RECURSION_REMAINING 356 -#define _CHECK_STACK_SPACE 357 -#define _CHECK_STACK_SPACE_OPERAND 358 -#define _CHECK_VALIDITY 359 -#define _COMPARE_OP 360 -#define _COMPARE_OP_FLOAT 361 -#define _COMPARE_OP_INT 362 -#define _COMPARE_OP_STR 363 -#define _CONTAINS_OP 364 -#define _CONTAINS_OP_DICT 365 -#define _CONTAINS_OP_SET 366 +#define _CHECK_PERIODIC_AT_END 355 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 356 +#define _CHECK_RECURSION_REMAINING 357 +#define _CHECK_STACK_SPACE 358 +#define _CHECK_STACK_SPACE_OPERAND 359 +#define _CHECK_VALIDITY 360 +#define _COMPARE_OP 361 +#define _COMPARE_OP_FLOAT 362 +#define _COMPARE_OP_INT 363 +#define _COMPARE_OP_STR 364 +#define _CONTAINS_OP 365 +#define _CONTAINS_OP_DICT 366 +#define _CONTAINS_OP_SET 367 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 367 -#define _COPY_1 368 -#define _COPY_2 369 -#define _COPY_3 370 +#define _COPY 368 +#define _COPY_1 369 +#define _COPY_2 370 +#define _COPY_3 371 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 371 +#define _CREATE_INIT_FRAME 372 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 372 +#define _DEOPT 373 #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 373 -#define _DO_CALL_FUNCTION_EX 374 -#define _DO_CALL_KW 375 +#define _DO_CALL 374 +#define _DO_CALL_FUNCTION_EX 375 +#define _DO_CALL_KW 376 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 376 +#define _ERROR_POP_N 377 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 377 -#define _EXPAND_METHOD_KW 378 -#define _FATAL_ERROR 379 +#define _EXPAND_METHOD 378 +#define _EXPAND_METHOD_KW 379 +#define _FATAL_ERROR 380 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 380 -#define _FOR_ITER_GEN_FRAME 381 -#define _FOR_ITER_TIER_TWO 382 +#define _FOR_ITER 381 +#define _FOR_ITER_GEN_FRAME 382 +#define _FOR_ITER_TIER_TWO 383 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BINARY_OP_EXTEND 383 -#define _GUARD_CALLABLE_ISINSTANCE 384 -#define _GUARD_CALLABLE_LEN 385 -#define _GUARD_CALLABLE_LIST_APPEND 386 -#define _GUARD_CALLABLE_STR_1 387 -#define _GUARD_CALLABLE_TUPLE_1 388 -#define _GUARD_CALLABLE_TYPE_1 389 -#define _GUARD_DORV_NO_DICT 390 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 391 -#define _GUARD_GLOBALS_VERSION 392 -#define _GUARD_IS_FALSE_POP 393 -#define _GUARD_IS_NONE_POP 394 -#define _GUARD_IS_NOT_NONE_POP 395 -#define _GUARD_IS_TRUE_POP 396 -#define _GUARD_KEYS_VERSION 397 -#define _GUARD_NOS_DICT 398 -#define _GUARD_NOS_FLOAT 399 -#define _GUARD_NOS_INT 400 -#define _GUARD_NOS_LIST 401 -#define _GUARD_NOS_NOT_NULL 402 -#define _GUARD_NOS_NULL 403 -#define _GUARD_NOS_OVERFLOWED 404 -#define _GUARD_NOS_TUPLE 405 -#define _GUARD_NOS_UNICODE 406 -#define _GUARD_NOT_EXHAUSTED_LIST 407 -#define _GUARD_NOT_EXHAUSTED_RANGE 408 -#define _GUARD_NOT_EXHAUSTED_TUPLE 409 -#define _GUARD_THIRD_NULL 410 -#define _GUARD_TOS_ANY_SET 411 -#define _GUARD_TOS_DICT 412 -#define _GUARD_TOS_FLOAT 413 -#define _GUARD_TOS_INT 414 -#define _GUARD_TOS_LIST 415 -#define _GUARD_TOS_OVERFLOWED 416 -#define _GUARD_TOS_SLICE 417 -#define _GUARD_TOS_TUPLE 418 -#define _GUARD_TOS_UNICODE 419 -#define _GUARD_TYPE_VERSION 420 -#define _GUARD_TYPE_VERSION_AND_LOCK 421 +#define _GUARD_BINARY_OP_EXTEND 384 +#define _GUARD_CALLABLE_ISINSTANCE 385 +#define _GUARD_CALLABLE_LEN 386 +#define _GUARD_CALLABLE_LIST_APPEND 387 +#define _GUARD_CALLABLE_STR_1 388 +#define _GUARD_CALLABLE_TUPLE_1 389 +#define _GUARD_CALLABLE_TYPE_1 390 +#define _GUARD_DORV_NO_DICT 391 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 392 +#define _GUARD_GLOBALS_VERSION 393 +#define _GUARD_IS_FALSE_POP 394 +#define _GUARD_IS_NONE_POP 395 +#define _GUARD_IS_NOT_NONE_POP 396 +#define _GUARD_IS_TRUE_POP 397 +#define _GUARD_KEYS_VERSION 398 +#define _GUARD_NOS_DICT 399 +#define _GUARD_NOS_FLOAT 400 +#define _GUARD_NOS_INT 401 +#define _GUARD_NOS_LIST 402 +#define _GUARD_NOS_NOT_NULL 403 +#define _GUARD_NOS_NULL 404 +#define _GUARD_NOS_OVERFLOWED 405 +#define _GUARD_NOS_TUPLE 406 +#define _GUARD_NOS_UNICODE 407 +#define _GUARD_NOT_EXHAUSTED_LIST 408 +#define _GUARD_NOT_EXHAUSTED_RANGE 409 +#define _GUARD_NOT_EXHAUSTED_TUPLE 410 +#define _GUARD_THIRD_NULL 411 +#define _GUARD_TOS_ANY_SET 412 +#define _GUARD_TOS_DICT 413 +#define _GUARD_TOS_FLOAT 414 +#define _GUARD_TOS_INT 415 +#define _GUARD_TOS_LIST 416 +#define _GUARD_TOS_OVERFLOWED 417 +#define _GUARD_TOS_SLICE 418 +#define _GUARD_TOS_TUPLE 419 +#define _GUARD_TOS_UNICODE 420 +#define _GUARD_TYPE_VERSION 421 +#define _GUARD_TYPE_VERSION_AND_LOCK 422 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 422 -#define _INIT_CALL_PY_EXACT_ARGS 423 -#define _INIT_CALL_PY_EXACT_ARGS_0 424 -#define _INIT_CALL_PY_EXACT_ARGS_1 425 -#define _INIT_CALL_PY_EXACT_ARGS_2 426 -#define _INIT_CALL_PY_EXACT_ARGS_3 427 -#define _INIT_CALL_PY_EXACT_ARGS_4 428 -#define _INSERT_NULL 429 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 423 +#define _INIT_CALL_PY_EXACT_ARGS 424 +#define _INIT_CALL_PY_EXACT_ARGS_0 425 +#define _INIT_CALL_PY_EXACT_ARGS_1 426 +#define _INIT_CALL_PY_EXACT_ARGS_2 427 +#define _INIT_CALL_PY_EXACT_ARGS_3 428 +#define _INIT_CALL_PY_EXACT_ARGS_4 429 +#define _INSERT_NULL 430 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -183,177 +184,178 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 430 +#define _IS_NONE 431 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 431 -#define _ITER_CHECK_RANGE 432 -#define _ITER_CHECK_TUPLE 433 -#define _ITER_JUMP_LIST 434 -#define _ITER_JUMP_RANGE 435 -#define _ITER_JUMP_TUPLE 436 -#define _ITER_NEXT_LIST 437 -#define _ITER_NEXT_LIST_TIER_TWO 438 -#define _ITER_NEXT_RANGE 439 -#define _ITER_NEXT_TUPLE 440 -#define _JUMP_TO_TOP 441 +#define _ITER_CHECK_LIST 432 +#define _ITER_CHECK_RANGE 433 +#define _ITER_CHECK_TUPLE 434 +#define _ITER_JUMP_LIST 435 +#define _ITER_JUMP_RANGE 436 +#define _ITER_JUMP_TUPLE 437 +#define _ITER_NEXT_LIST 438 +#define _ITER_NEXT_LIST_TIER_TWO 439 +#define _ITER_NEXT_RANGE 440 +#define _ITER_NEXT_TUPLE 441 +#define _JUMP_TO_TOP 442 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 442 -#define _LOAD_ATTR_CLASS 443 +#define _LOAD_ATTR 443 +#define _LOAD_ATTR_CLASS 444 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 444 -#define _LOAD_ATTR_METHOD_LAZY_DICT 445 -#define _LOAD_ATTR_METHOD_NO_DICT 446 -#define _LOAD_ATTR_METHOD_WITH_VALUES 447 -#define _LOAD_ATTR_MODULE 448 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 449 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 450 -#define _LOAD_ATTR_PROPERTY_FRAME 451 -#define _LOAD_ATTR_SLOT 452 -#define _LOAD_ATTR_WITH_HINT 453 +#define _LOAD_ATTR_INSTANCE_VALUE 445 +#define _LOAD_ATTR_METHOD_LAZY_DICT 446 +#define _LOAD_ATTR_METHOD_NO_DICT 447 +#define _LOAD_ATTR_METHOD_WITH_VALUES 448 +#define _LOAD_ATTR_MODULE 449 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 450 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 451 +#define _LOAD_ATTR_PROPERTY_FRAME 452 +#define _LOAD_ATTR_SLOT 453 +#define _LOAD_ATTR_WITH_HINT 454 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 454 +#define _LOAD_BYTECODE 455 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 455 -#define _LOAD_CONST_INLINE_BORROW 456 -#define _LOAD_CONST_UNDER_INLINE 457 -#define _LOAD_CONST_UNDER_INLINE_BORROW 458 +#define _LOAD_CONST_INLINE 456 +#define _LOAD_CONST_INLINE_BORROW 457 +#define _LOAD_CONST_UNDER_INLINE 458 +#define _LOAD_CONST_UNDER_INLINE_BORROW 459 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 459 -#define _LOAD_FAST_0 460 -#define _LOAD_FAST_1 461 -#define _LOAD_FAST_2 462 -#define _LOAD_FAST_3 463 -#define _LOAD_FAST_4 464 -#define _LOAD_FAST_5 465 -#define _LOAD_FAST_6 466 -#define _LOAD_FAST_7 467 +#define _LOAD_FAST 460 +#define _LOAD_FAST_0 461 +#define _LOAD_FAST_1 462 +#define _LOAD_FAST_2 463 +#define _LOAD_FAST_3 464 +#define _LOAD_FAST_4 465 +#define _LOAD_FAST_5 466 +#define _LOAD_FAST_6 467 +#define _LOAD_FAST_7 468 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 468 -#define _LOAD_FAST_BORROW_0 469 -#define _LOAD_FAST_BORROW_1 470 -#define _LOAD_FAST_BORROW_2 471 -#define _LOAD_FAST_BORROW_3 472 -#define _LOAD_FAST_BORROW_4 473 -#define _LOAD_FAST_BORROW_5 474 -#define _LOAD_FAST_BORROW_6 475 -#define _LOAD_FAST_BORROW_7 476 +#define _LOAD_FAST_BORROW 469 +#define _LOAD_FAST_BORROW_0 470 +#define _LOAD_FAST_BORROW_1 471 +#define _LOAD_FAST_BORROW_2 472 +#define _LOAD_FAST_BORROW_3 473 +#define _LOAD_FAST_BORROW_4 474 +#define _LOAD_FAST_BORROW_5 475 +#define _LOAD_FAST_BORROW_6 476 +#define _LOAD_FAST_BORROW_7 477 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 477 -#define _LOAD_GLOBAL_BUILTINS 478 -#define _LOAD_GLOBAL_MODULE 479 +#define _LOAD_GLOBAL 478 +#define _LOAD_GLOBAL_BUILTINS 479 +#define _LOAD_GLOBAL_MODULE 480 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 480 -#define _LOAD_SMALL_INT_0 481 -#define _LOAD_SMALL_INT_1 482 -#define _LOAD_SMALL_INT_2 483 -#define _LOAD_SMALL_INT_3 484 -#define _LOAD_SPECIAL 485 +#define _LOAD_SMALL_INT 481 +#define _LOAD_SMALL_INT_0 482 +#define _LOAD_SMALL_INT_1 483 +#define _LOAD_SMALL_INT_2 484 +#define _LOAD_SMALL_INT_3 485 +#define _LOAD_SPECIAL 486 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 486 +#define _MAKE_CALLARGS_A_TUPLE 487 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 487 +#define _MAKE_WARM 488 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 488 -#define _MAYBE_EXPAND_METHOD_KW 489 -#define _MONITOR_CALL 490 -#define _MONITOR_CALL_KW 491 -#define _MONITOR_JUMP_BACKWARD 492 -#define _MONITOR_RESUME 493 +#define _MAYBE_EXPAND_METHOD 489 +#define _MAYBE_EXPAND_METHOD_KW 490 +#define _MONITOR_CALL 491 +#define _MONITOR_CALL_KW 492 +#define _MONITOR_JUMP_BACKWARD 493 +#define _MONITOR_RESUME 494 #define _NOP NOP -#define _POP_CALL 494 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 495 -#define _POP_CALL_ONE 496 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 497 -#define _POP_CALL_TWO 498 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 499 +#define _PERIODIC 495 +#define _POP_CALL 496 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 497 +#define _POP_CALL_ONE 498 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 499 +#define _POP_CALL_TWO 500 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 501 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 500 -#define _POP_JUMP_IF_TRUE 501 +#define _POP_JUMP_IF_FALSE 502 +#define _POP_JUMP_IF_TRUE 503 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 502 -#define _POP_TOP_INT 503 -#define _POP_TOP_LOAD_CONST_INLINE 504 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 505 -#define _POP_TOP_NOP 506 -#define _POP_TOP_UNICODE 507 -#define _POP_TWO 508 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 509 +#define _POP_TOP_FLOAT 504 +#define _POP_TOP_INT 505 +#define _POP_TOP_LOAD_CONST_INLINE 506 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 507 +#define _POP_TOP_NOP 508 +#define _POP_TOP_UNICODE 509 +#define _POP_TWO 510 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 511 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 510 +#define _PUSH_FRAME 512 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 511 -#define _PY_FRAME_GENERAL 512 -#define _PY_FRAME_KW 513 -#define _QUICKEN_RESUME 514 -#define _REPLACE_WITH_TRUE 515 +#define _PUSH_NULL_CONDITIONAL 513 +#define _PY_FRAME_GENERAL 514 +#define _PY_FRAME_KW 515 +#define _QUICKEN_RESUME 516 +#define _REPLACE_WITH_TRUE 517 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 516 -#define _SEND 517 -#define _SEND_GEN_FRAME 518 +#define _SAVE_RETURN_OFFSET 518 +#define _SEND 519 +#define _SEND_GEN_FRAME 520 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _START_EXECUTOR 519 -#define _STORE_ATTR 520 -#define _STORE_ATTR_INSTANCE_VALUE 521 -#define _STORE_ATTR_SLOT 522 -#define _STORE_ATTR_WITH_HINT 523 +#define _START_EXECUTOR 521 +#define _STORE_ATTR 522 +#define _STORE_ATTR_INSTANCE_VALUE 523 +#define _STORE_ATTR_SLOT 524 +#define _STORE_ATTR_WITH_HINT 525 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 524 -#define _STORE_FAST_0 525 -#define _STORE_FAST_1 526 -#define _STORE_FAST_2 527 -#define _STORE_FAST_3 528 -#define _STORE_FAST_4 529 -#define _STORE_FAST_5 530 -#define _STORE_FAST_6 531 -#define _STORE_FAST_7 532 +#define _STORE_FAST 526 +#define _STORE_FAST_0 527 +#define _STORE_FAST_1 528 +#define _STORE_FAST_2 529 +#define _STORE_FAST_3 530 +#define _STORE_FAST_4 531 +#define _STORE_FAST_5 532 +#define _STORE_FAST_6 533 +#define _STORE_FAST_7 534 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 533 -#define _STORE_SUBSCR 534 -#define _STORE_SUBSCR_DICT 535 -#define _STORE_SUBSCR_LIST_INT 536 -#define _SWAP 537 -#define _SWAP_2 538 -#define _SWAP_3 539 -#define _TIER2_RESUME_CHECK 540 -#define _TO_BOOL 541 +#define _STORE_SLICE 535 +#define _STORE_SUBSCR 536 +#define _STORE_SUBSCR_DICT 537 +#define _STORE_SUBSCR_LIST_INT 538 +#define _SWAP 539 +#define _SWAP_2 540 +#define _SWAP_3 541 +#define _TIER2_RESUME_CHECK 542 +#define _TO_BOOL 543 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 542 +#define _TO_BOOL_LIST 544 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 543 +#define _TO_BOOL_STR 545 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 544 -#define _UNPACK_SEQUENCE_LIST 545 -#define _UNPACK_SEQUENCE_TUPLE 546 -#define _UNPACK_SEQUENCE_TWO_TUPLE 547 +#define _UNPACK_SEQUENCE 546 +#define _UNPACK_SEQUENCE_LIST 547 +#define _UNPACK_SEQUENCE_TUPLE 548 +#define _UNPACK_SEQUENCE_TWO_TUPLE 549 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 547 +#define MAX_UOP_ID 549 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index ff7e800aa9bb1a..027475b127cb07 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -334,8 +334,9 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_MAKE_WARM] = 0, [_FATAL_ERROR] = 0, [_DEOPT] = 0, + [_PERIODIC] = HAS_ESCAPES_FLAG, [_ERROR_POP_N] = HAS_ARG_FLAG, - [_TIER2_RESUME_CHECK] = HAS_DEOPT_FLAG, + [_TIER2_RESUME_CHECK] = HAS_PERIODIC_FLAG, }; const ReplicationRange _PyUop_Replication[MAX_UOP_ID+1] = { @@ -588,6 +589,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_MAYBE_EXPAND_METHOD] = "_MAYBE_EXPAND_METHOD", [_MAYBE_EXPAND_METHOD_KW] = "_MAYBE_EXPAND_METHOD_KW", [_NOP] = "_NOP", + [_PERIODIC] = "_PERIODIC", [_POP_CALL] = "_POP_CALL", [_POP_CALL_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_LOAD_CONST_INLINE_BORROW", [_POP_CALL_ONE] = "_POP_CALL_ONE", @@ -1297,6 +1299,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _DEOPT: return 0; + case _PERIODIC: + return 0; case _ERROR_POP_N: return 0; case _TIER2_RESUME_CHECK: diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d9abc4c53d1f50..bc38e508d61641 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -161,6 +161,15 @@ dummy_func( } } + replaced op(_CHECK_PERIODIC_AT_END, (--)) { + _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); + QSBR_QUIESCENT_STATE(tstate); + if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + int err = _Py_HandlePending(tstate); + ERROR_IF(err != 0); + } + } + op(_CHECK_PERIODIC_IF_NOT_YIELD_FROM, (--)) { if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); @@ -3790,8 +3799,8 @@ dummy_func( ERROR_IF(err); } - macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC; - macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC; + macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC_AT_END; + macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC_AT_END; op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -3912,7 +3921,7 @@ dummy_func( unused/2 + _CHECK_IS_NOT_PY_CALLABLE + _CALL_NON_PY_GENERAL + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) { EXIT_IF(!PyStackRef_IsNull(null)); @@ -4069,7 +4078,7 @@ dummy_func( _GUARD_NOS_NULL + _GUARD_CALLABLE_STR_1 + _CALL_STR_1 + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_GUARD_CALLABLE_TUPLE_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4097,7 +4106,7 @@ dummy_func( _GUARD_NOS_NULL + _GUARD_CALLABLE_TUPLE_1 + _CALL_TUPLE_1 + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4193,7 +4202,7 @@ dummy_func( unused/1 + unused/2 + _CALL_BUILTIN_CLASS + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_O functions */ @@ -4228,7 +4237,7 @@ dummy_func( unused/1 + unused/2 + _CALL_BUILTIN_O + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_BUILTIN_FAST, (callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_FASTCALL functions, without keywords */ @@ -4265,7 +4274,7 @@ dummy_func( unused/1 + unused/2 + _CALL_BUILTIN_FAST + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ @@ -4301,7 +4310,7 @@ dummy_func( unused/1 + unused/2 + _CALL_BUILTIN_FAST_WITH_KEYWORDS + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; macro(CALL_LEN) = unused/1 + @@ -4439,7 +4448,7 @@ dummy_func( unused/1 + unused/2 + _CALL_METHOD_DESCRIPTOR_O + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4481,7 +4490,7 @@ dummy_func( unused/1 + unused/2 + _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) { assert(oparg == 0 || oparg == 1); @@ -4519,7 +4528,7 @@ dummy_func( unused/1 + unused/2 + _CALL_METHOD_DESCRIPTOR_NOARGS + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4560,7 +4569,7 @@ dummy_func( unused/1 + unused/2 + _CALL_METHOD_DESCRIPTOR_FAST + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; // Cache layout: counter/1, func_version/2 family(CALL_KW, INLINE_CACHE_ENTRIES_CALL_KW) = { @@ -4816,7 +4825,7 @@ dummy_func( unused/2 + _CHECK_IS_NOT_PY_CALLABLE_KW + _CALL_KW_NON_PY + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs -- func, unused, callargs, kwargs)) { PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs); @@ -4917,12 +4926,12 @@ dummy_func( macro(CALL_FUNCTION_EX) = _MAKE_CALLARGS_A_TUPLE + _DO_CALL_FUNCTION_EX + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; macro(INSTRUMENTED_CALL_FUNCTION_EX) = _MAKE_CALLARGS_A_TUPLE + _DO_CALL_FUNCTION_EX + - _CHECK_PERIODIC; + _CHECK_PERIODIC_AT_END; inst(MAKE_FUNCTION, (codeobj_st -- func)) { PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); @@ -5185,23 +5194,20 @@ dummy_func( op (_GUARD_IS_TRUE_POP, (flag -- )) { int is_true = PyStackRef_IsTrue(flag); DEAD(flag); - SYNC_SP(); - EXIT_IF(!is_true); + EXIT_IF_AFTER(!is_true); } op (_GUARD_IS_FALSE_POP, (flag -- )) { int is_false = PyStackRef_IsFalse(flag); DEAD(flag); - SYNC_SP(); - EXIT_IF(!is_false); + EXIT_IF_AFTER(!is_false); } op (_GUARD_IS_NONE_POP, (val -- )) { int is_none = PyStackRef_IsNone(val); if (!is_none) { PyStackRef_CLOSE(val); - SYNC_SP(); - EXIT_IF(1); + EXIT_IF_AFTER(1); } DEAD(val); } @@ -5209,8 +5215,7 @@ dummy_func( op (_GUARD_IS_NOT_NONE_POP, (val -- )) { int is_none = PyStackRef_IsNone(val); PyStackRef_CLOSE(val); - SYNC_SP(); - EXIT_IF(is_none); + EXIT_IF_AFTER(is_none); } op(_JUMP_TO_TOP, (--)) { @@ -5395,6 +5400,11 @@ dummy_func( GOTO_TIER_ONE(_PyFrame_GetBytecode(frame) + CURRENT_TARGET()); } + tier2 op(_PERIODIC, (--)) { + int err = _Py_HandlePending(tstate); + GOTO_TIER_ONE(err ? NULL : _PyFrame_GetBytecode(frame) + CURRENT_TARGET()); + } + tier2 op(_ERROR_POP_N, (target/2 --)) { assert(oparg == 0); frame->instr_ptr = _PyFrame_GetBytecode(frame) + target; @@ -5406,11 +5416,11 @@ dummy_func( * ENTER_EXECUTOR will not re-enter tier 2 with the eval breaker set. */ tier2 op(_TIER2_RESUME_CHECK, (--)) { #if defined(__EMSCRIPTEN__) - DEOPT_IF(_Py_emscripten_signal_clock == 0); + PERIODIC_IF(_Py_emscripten_signal_clock == 0); _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - DEOPT_IF(eval_breaker & _PY_EVAL_EVENTS_MASK); + PERIODIC_IF(eval_breaker & _PY_EVAL_EVENTS_MASK); assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); } diff --git a/Python/ceval.c b/Python/ceval.c index 291e753dec0ce5..85f09bf280c8d1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1207,6 +1207,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int printf(" @ %d -> %s]\n", (int)(next_uop - current_executor->trace - 1), _PyOpcode_OpName[frame->instr_ptr->op.code]); + fflush(stdout); } #endif assert(next_uop[-1].format == UOP_FORMAT_JUMP); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index e152865e4ec9e8..750691cb42b776 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -26,6 +26,8 @@ break; } + /* _CHECK_PERIODIC_AT_END is not a viable micro-op for tier 2 because it is replaced */ + case _CHECK_PERIODIC_IF_NOT_YIELD_FROM: { oparg = CURRENT_OPARG(); if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { @@ -7461,6 +7463,14 @@ break; } + case _PERIODIC: { + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); + GOTO_TIER_ONE(err ? NULL : _PyFrame_GetBytecode(frame) + CURRENT_TARGET()); + break; + } + case _ERROR_POP_N: { oparg = CURRENT_OPARG(); uint32_t target = (uint32_t)CURRENT_OPERAND0(); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index aa1eb373b7ba4b..d01abbc288840d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1670,7 +1670,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2175,7 +2175,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2292,7 +2292,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2409,7 +2409,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2501,7 +2501,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2676,7 +2676,7 @@ } result = PyStackRef_FromPyObjectSteal(result_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -3268,7 +3268,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -3659,7 +3659,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -3790,7 +3790,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -3891,7 +3891,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -4005,7 +4005,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -4128,7 +4128,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -4421,7 +4421,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -4501,7 +4501,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -6515,7 +6515,7 @@ } res = PyStackRef_FromPyObjectSteal(res_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -6690,7 +6690,7 @@ } result = PyStackRef_FromPyObjectSteal(result_o); } - // _CHECK_PERIODIC + // _CHECK_PERIODIC_AT_END { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); diff --git a/Python/optimizer.c b/Python/optimizer.c index 8d01d605ef4a2a..0411c376bdae5a 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -432,6 +432,7 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = { [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, [_FOR_ITER] = _FOR_ITER_TIER_TWO, [_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO, + [_CHECK_PERIODIC_AT_END] = _TIER2_RESUME_CHECK, }; static const uint8_t @@ -776,9 +777,12 @@ translate_bytecode_to_trace( case OPARG_REPLACED: uop = _PyUOp_Replacements[uop]; assert(uop != 0); + uint32_t next_inst = target + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + (oparg > 255); + if (uop == _TIER2_RESUME_CHECK) { + target = next_inst; + } #ifdef Py_DEBUG - { - uint32_t next_inst = target + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + (oparg > 255); + else { uint32_t jump_target = next_inst + oparg; assert(_Py_GetBaseCodeUnit(code, jump_target).op.code == END_FOR); assert(_Py_GetBaseCodeUnit(code, jump_target+1).op.code == POP_ITER); @@ -1043,9 +1047,15 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length) _PyUOpInstruction *inst = &buffer[i]; int opcode = inst->opcode; int32_t target = (int32_t)uop_get_target(inst); - if (_PyUop_Flags[opcode] & (HAS_EXIT_FLAG | HAS_DEOPT_FLAG)) { - uint16_t exit_op = (_PyUop_Flags[opcode] & HAS_EXIT_FLAG) ? - _EXIT_TRACE : _DEOPT; + uint16_t exit_flags = _PyUop_Flags[opcode] & (HAS_EXIT_FLAG | HAS_DEOPT_FLAG | HAS_PERIODIC_FLAG); + if (exit_flags) { + uint16_t exit_op = _EXIT_TRACE; + if (exit_flags & HAS_DEOPT_FLAG) { + exit_op = _DEOPT; + } + else if (exit_flags & HAS_PERIODIC_FLAG) { + exit_op = _PERIODIC; + } int32_t jump_target = target; if (is_for_iter_test[opcode]) { /* Target the POP_TOP immediately after the END_FOR, @@ -1159,6 +1169,7 @@ sanity_check(_PyExecutorObject *executor) uint16_t opcode = inst->opcode; CHECK( opcode == _DEOPT || + opcode == _PERIODIC || opcode == _EXIT_TRACE || opcode == _ERROR_POP_N); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 41402200c1683e..3089a6f0f5f902 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -11,6 +11,8 @@ break; } + /* _CHECK_PERIODIC_AT_END is not a viable micro-op for tier 2 */ + case _CHECK_PERIODIC_IF_NOT_YIELD_FROM: { break; } @@ -3037,6 +3039,10 @@ break; } + case _PERIODIC: { + break; + } + case _ERROR_POP_N: { break; } diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 6466d2615cd14e..99c95094a3f265 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -20,6 +20,7 @@ class Properties: error_with_pop: bool error_without_pop: bool deopts: bool + deopts_periodic: bool oparg: bool jumps: bool eval_breaker: bool @@ -58,6 +59,7 @@ def from_list(properties: list["Properties"]) -> "Properties": error_with_pop=any(p.error_with_pop for p in properties), error_without_pop=any(p.error_without_pop for p in properties), deopts=any(p.deopts for p in properties), + deopts_periodic=any(p.deopts_periodic for p in properties), oparg=any(p.oparg for p in properties), jumps=any(p.jumps for p in properties), eval_breaker=any(p.eval_breaker for p in properties), @@ -85,6 +87,7 @@ def infallible(self) -> bool: error_with_pop=False, error_without_pop=False, deopts=False, + deopts_periodic=False, oparg=False, jumps=False, eval_breaker=False, @@ -706,7 +709,7 @@ def visit(stmt: Stmt) -> None: in_if = 0 tkn_iter = iter(stmt.contents) for tkn in tkn_iter: - if tkn.kind == "IDENTIFIER" and tkn.text in ("DEOPT_IF", "ERROR_IF", "EXIT_IF"): + if tkn.kind == "IDENTIFIER" and tkn.text in ("DEOPT_IF", "ERROR_IF", "EXIT_IF", "PERIODIC_IF", "EXIT_IF_AFTER"): in_if = 1 next(tkn_iter) elif tkn.kind == "LPAREN": @@ -831,11 +834,13 @@ def compute_properties(op: parser.CodeDef) -> Properties: or variable_used(op, "PyCell_SwapTakeRef") ) deopts_if = variable_used(op, "DEOPT_IF") - exits_if = variable_used(op, "EXIT_IF") - if deopts_if and exits_if: + exits_if = variable_used(op, "EXIT_IF") or variable_used(op, "EXIT_IF_AFTER") + deopts_periodic = variable_used(op, "PERIODIC_IF") + exits_and_deopts = sum((deopts_if, exits_if, deopts_periodic)) + if exits_and_deopts > 1: tkn = op.tokens[0] raise lexer.make_syntax_error( - "Op cannot contain both EXIT_IF and DEOPT_IF", + "Op cannot contain more than one of EXIT_IF, DEOPT_IF and PERIODIC_IF", tkn.filename, tkn.line, tkn.column, @@ -852,6 +857,7 @@ def compute_properties(op: parser.CodeDef) -> Properties: error_with_pop=error_with_pop, error_without_pop=error_without_pop, deopts=deopts_if, + deopts_periodic=deopts_periodic, side_exit=exits_if, oparg=oparg_used(op), jumps=variable_used(op, "JUMPBY"), diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py index 4c210fbf8d28e9..2352755638c4b2 100644 --- a/Tools/cases_generator/generators_common.py +++ b/Tools/cases_generator/generators_common.py @@ -111,7 +111,9 @@ class Emitter: def __init__(self, out: CWriter, labels: dict[str, Label], cannot_escape: bool = False): self._replacers = { "EXIT_IF": self.exit_if, + "EXIT_IF_AFTER": self.exit_if_after, "DEOPT_IF": self.deopt_if, + "PERIODIC_IF": self.periodic_if, "ERROR_IF": self.error_if, "ERROR_NO_POP": self.error_no_pop, "DECREF_INPUTS": self.decref_inputs, @@ -171,6 +173,29 @@ def deopt_if( exit_if = deopt_if + def periodic_if( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: CodeSection, + storage: Storage, + inst: Instruction | None, + ) -> bool: + raise NotImplementedError("PERIODIC_IF not support in tier 1") + + def exit_if_after( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: CodeSection, + storage: Storage, + inst: Instruction | None, + ) -> bool: + storage.clear_inputs("in EXIT_IF_AFTER") + storage.flush(self.out) + storage.stack.clear(self.out) + return self.exit_if(tkn, tkn_iter, uop, storage, inst) + def goto_error(self, offset: int, storage: Storage) -> str: if offset > 0: return f"JUMP_TO_LABEL(pop_{offset}_error);" @@ -692,6 +717,8 @@ def cflags(p: Properties) -> str: flags.append("HAS_EVAL_BREAK_FLAG") if p.deopts: flags.append("HAS_DEOPT_FLAG") + if p.deopts_periodic: + flags.append("HAS_PERIODIC_FLAG") if p.side_exit: flags.append("HAS_EXIT_FLAG") if not p.infallible: diff --git a/Tools/cases_generator/opcode_metadata_generator.py b/Tools/cases_generator/opcode_metadata_generator.py index 0bcdc5395dcd8e..b649b38123388d 100644 --- a/Tools/cases_generator/opcode_metadata_generator.py +++ b/Tools/cases_generator/opcode_metadata_generator.py @@ -53,10 +53,9 @@ "ESCAPES", "EXIT", "PURE", - "PASSTHROUGH", - "OPARG_AND_1", "ERROR_NO_POP", "NO_SAVE_IP", + "PERIODIC", ] diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py index 32dc346d5e891a..5cb35a44fb6be6 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -132,7 +132,7 @@ def uses_this(inst: Instruction) -> bool: continue for tkn in uop.body.tokens(): if (tkn.kind == "IDENTIFIER" - and (tkn.text in {"DEOPT_IF", "EXIT_IF"})): + and (tkn.text in {"DEOPT_IF", "EXIT_IF", "EXIT_IF_AFTER"})): return True return False diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py index fc3bc47286f7f6..1bb5f48658ddfc 100644 --- a/Tools/cases_generator/tier2_generator.py +++ b/Tools/cases_generator/tier2_generator.py @@ -111,6 +111,8 @@ def exit_if( self.emit("}\n") return not always_true(first_tkn) + periodic_if = deopt_if + def oparg( self, tkn: Token, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy