From 29a99f480c1cfcc1d09b8ef621e9909a7811ba91 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 26 Feb 2026 18:02:28 +0000 Subject: [PATCH] Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER --- Include/internal/pycore_ceval.h | 1 + Include/internal/pycore_interpframe.h | 6 +- Include/internal/pycore_magic_number.h | 5 +- Include/internal/pycore_opcode_metadata.h | 32 +- Include/internal/pycore_opcode_utils.h | 4 + Include/internal/pycore_uop_ids.h | 507 +++++++++++----------- Include/internal/pycore_uop_metadata.h | 39 +- Include/opcode_ids.h | 209 +++++---- Lib/_opcode_metadata.py | 209 +++++---- Lib/test/test_dis.py | 20 +- Lib/test/test_peepholer.py | 38 +- Modules/_remote_debugging/asyncio.c | 2 +- Modules/_testinternalcapi/test_cases.c.h | 191 ++++---- Modules/_testinternalcapi/test_targets.h | 13 +- Objects/codeobject.c | 9 +- Objects/genobject.c | 8 +- Programs/test_frozenmain.h | 26 +- Python/bytecodes.c | 130 +++--- Python/ceval.c | 36 ++ Python/codegen.c | 18 +- Python/executor_cases.c.h | 121 ++---- Python/flowgraph.c | 12 +- Python/generated_cases.c.h | 191 ++++---- Python/opcode_targets.h | 13 +- Python/optimizer_bytecodes.c | 8 +- Python/optimizer_cases.c.h | 24 +- Python/record_functions.c.h | 28 +- Python/specialize.c | 27 +- Tools/cases_generator/analyzer.py | 2 +- 29 files changed, 941 insertions(+), 988 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index f27ec4350bb2c8..16913289a02f59 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -342,6 +342,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg); PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name); PyAPI_FUNC(int) _Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args); +PyAPI_FUNC(_PyStackRef) _PyEval_GetIter(_PyStackRef iterable, _PyStackRef *null_or_index, int yield_from); /* * Indicate whether a special method of given 'oparg' can use the (improved) diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index 14e2f245834dca..8db1aebdc11401 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -102,10 +102,10 @@ static inline _PyStackRef *_PyFrame_Stackbase(_PyInterpreterFrame *f) { return (f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus); } -static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f) { +static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f, int depth) { assert(f->stackpointer > _PyFrame_Stackbase(f)); - assert(!PyStackRef_IsNull(f->stackpointer[-1])); - return f->stackpointer[-1]; + assert(!PyStackRef_IsNull(f->stackpointer[-depth])); + return f->stackpointer[-depth]; } static inline _PyStackRef _PyFrame_StackPop(_PyInterpreterFrame *f) { diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index ec9cfe432371c7..9d36165c8a8ffb 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -292,7 +292,8 @@ Known values: Python 3.15a4 3659 (Add CALL_FUNCTION_EX specialization) Python 3.15a4 3660 (Change generator preamble code) Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes) - Python 3.15a6 3662 (Add counter to RESUME) + Python 3.15a8 3662 (Add counter to RESUME) + Python 3.15a8 3663 (Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER) Python 3.16 will start with 3700 @@ -306,7 +307,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3662 +#define PYC_MAGIC_NUMBER 3663 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index c46015c4d98239..ce8a7dc26762b7 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -157,7 +157,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case CHECK_EXC_MATCH: return 2; case CLEANUP_THROW: - return 3; + return 4; case COMPARE_OP: return 2; case COMPARE_OP_FLOAT: @@ -199,7 +199,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case END_FOR: return 1; case END_SEND: - return 2; + return 3; case ENTER_EXECUTOR: return 0; case EXIT_INIT_CHECK: @@ -230,8 +230,6 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case GET_LEN: return 1; - case GET_YIELD_FROM_ITER: - return 1; case IMPORT_FROM: return 1; case IMPORT_NAME: @@ -247,7 +245,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case INSTRUMENTED_END_FOR: return 3; case INSTRUMENTED_END_SEND: - return 2; + return 3; case INSTRUMENTED_FOR_ITER: return 2; case INSTRUMENTED_INSTRUCTION: @@ -433,9 +431,9 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case RETURN_VALUE: return 1; case SEND: - return 2; + return 3; case SEND_GEN: - return 2; + return 3; case SETUP_ANNOTATIONS: return 0; case SETUP_CLEANUP: @@ -650,7 +648,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case CHECK_EXC_MATCH: return 2; case CLEANUP_THROW: - return 2; + return 3; case COMPARE_OP: return 1; case COMPARE_OP_FLOAT: @@ -723,8 +721,6 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 2; case GET_LEN: return 2; - case GET_YIELD_FROM_ITER: - return 1; case IMPORT_FROM: return 2; case IMPORT_NAME: @@ -926,9 +922,9 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case RETURN_VALUE: return 1; case SEND: - return 2; + return 3; case SEND_GEN: - return 1; + return 2; case SETUP_ANNOTATIONS: return 0; case SETUP_CLEANUP: @@ -1190,9 +1186,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [GET_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_LEN] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, @@ -1287,7 +1282,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [RESUME_CHECK_JIT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1438,7 +1433,6 @@ _PyOpcode_macro_expansion[256] = { [GET_AWAITABLE] = { .nuops = 1, .uops = { { _GET_AWAITABLE, OPARG_SIMPLE, 0 } } }, [GET_ITER] = { .nuops = 1, .uops = { { _GET_ITER, OPARG_SIMPLE, 0 } } }, [GET_LEN] = { .nuops = 1, .uops = { { _GET_LEN, OPARG_SIMPLE, 0 } } }, - [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { _GET_YIELD_FROM_ITER, OPARG_SIMPLE, 0 } } }, [IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } }, [IMPORT_NAME] = { .nuops = 1, .uops = { { _IMPORT_NAME, OPARG_SIMPLE, 0 } } }, [IS_OP] = { .nuops = 3, .uops = { { _IS_OP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, @@ -1501,7 +1495,7 @@ _PyOpcode_macro_expansion[256] = { [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 1 } } }, [RETURN_GENERATOR] = { .nuops = 1, .uops = { { _RETURN_GENERATOR, OPARG_SIMPLE, 0 } } }, [RETURN_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, - [SEND_GEN] = { .nuops = 4, .uops = { { _RECORD_NOS_GEN_FUNC, OPARG_SIMPLE, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, + [SEND_GEN] = { .nuops = 4, .uops = { { _RECORD_3OS_GEN_FUNC, OPARG_SIMPLE, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { _SETUP_ANNOTATIONS, OPARG_SIMPLE, 0 } } }, [SET_ADD] = { .nuops = 1, .uops = { { _SET_ADD, OPARG_SIMPLE, 0 } } }, [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { _SET_FUNCTION_ATTRIBUTE, OPARG_SIMPLE, 0 } } }, @@ -1641,7 +1635,6 @@ const char *_PyOpcode_OpName[267] = { [GET_AWAITABLE] = "GET_AWAITABLE", [GET_ITER] = "GET_ITER", [GET_LEN] = "GET_LEN", - [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [IMPORT_FROM] = "IMPORT_FROM", [IMPORT_NAME] = "IMPORT_NAME", [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL", @@ -1818,6 +1811,7 @@ const uint8_t _PyOpcode_Caches[256] = { PyAPI_DATA(const uint8_t) _PyOpcode_Deopt[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Deopt[256] = { + [120] = 120, [121] = 121, [122] = 122, [123] = 123, @@ -1940,7 +1934,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [GET_AWAITABLE] = GET_AWAITABLE, [GET_ITER] = GET_ITER, [GET_LEN] = GET_LEN, - [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, [IMPORT_FROM] = IMPORT_FROM, [IMPORT_NAME] = IMPORT_NAME, [INSTRUMENTED_CALL] = INSTRUMENTED_CALL, @@ -2079,6 +2072,7 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ + case 120: \ case 121: \ case 122: \ case 123: \ diff --git a/Include/internal/pycore_opcode_utils.h b/Include/internal/pycore_opcode_utils.h index e4d859fcc47d02..69178381993fba 100644 --- a/Include/internal/pycore_opcode_utils.h +++ b/Include/internal/pycore_opcode_utils.h @@ -86,6 +86,10 @@ extern "C" { #define RESUME_OPARG_LOCATION_MASK 0x3 #define RESUME_OPARG_DEPTH1_MASK 0x4 +#define GET_ITER_YIELD_FROM 1 +#define GET_ITER_YIELD_FROM_NO_CHECK 2 +#define GET_ITER_YIELD_FROM_CORO_CHECK 3 + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index b00e522c09a49a..be1b5d961d1837 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -128,7 +128,6 @@ extern "C" { #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 388 #define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 389 #define _GUARD_BIT_IS_SET_POP 390 @@ -333,271 +332,271 @@ extern "C" { #define _PY_FRAME_EX 550 #define _PY_FRAME_GENERAL 551 #define _PY_FRAME_KW 552 -#define _RECORD_4OS 553 -#define _RECORD_BOUND_METHOD 554 -#define _RECORD_CALLABLE 555 -#define _RECORD_CODE 556 -#define _RECORD_NOS 557 -#define _RECORD_NOS_GEN_FUNC 558 -#define _RECORD_TOS 559 -#define _RECORD_TOS_TYPE 560 -#define _REPLACE_WITH_TRUE 561 -#define _RESUME_CHECK 562 +#define _RECORD_3OS_GEN_FUNC 553 +#define _RECORD_4OS 554 +#define _RECORD_BOUND_METHOD 555 +#define _RECORD_CALLABLE 556 +#define _RECORD_CODE 557 +#define _RECORD_NOS 558 +#define _RECORD_NOS_GEN_FUNC 559 +#define _RECORD_TOS 560 +#define _RECORD_TOS_TYPE 561 +#define _REPLACE_WITH_TRUE 562 +#define _RESUME_CHECK 563 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 563 -#define _SAVE_RETURN_OFFSET 564 -#define _SEND 565 -#define _SEND_GEN_FRAME 566 +#define _RETURN_VALUE 564 +#define _SAVE_RETURN_OFFSET 565 +#define _SEND 566 +#define _SEND_GEN_FRAME 567 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 567 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 568 -#define _SPILL_OR_RELOAD 569 -#define _START_EXECUTOR 570 -#define _STORE_ATTR 571 -#define _STORE_ATTR_INSTANCE_VALUE 572 -#define _STORE_ATTR_SLOT 573 -#define _STORE_ATTR_WITH_HINT 574 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 568 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 569 +#define _SPILL_OR_RELOAD 570 +#define _START_EXECUTOR 571 +#define _STORE_ATTR 572 +#define _STORE_ATTR_INSTANCE_VALUE 573 +#define _STORE_ATTR_SLOT 574 +#define _STORE_ATTR_WITH_HINT 575 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 575 -#define _STORE_SUBSCR 576 -#define _STORE_SUBSCR_DICT 577 -#define _STORE_SUBSCR_LIST_INT 578 -#define _SWAP 579 -#define _SWAP_2 580 -#define _SWAP_3 581 -#define _SWAP_FAST 582 -#define _SWAP_FAST_0 583 -#define _SWAP_FAST_1 584 -#define _SWAP_FAST_2 585 -#define _SWAP_FAST_3 586 -#define _SWAP_FAST_4 587 -#define _SWAP_FAST_5 588 -#define _SWAP_FAST_6 589 -#define _SWAP_FAST_7 590 -#define _TIER2_RESUME_CHECK 591 -#define _TO_BOOL 592 +#define _STORE_SLICE 576 +#define _STORE_SUBSCR 577 +#define _STORE_SUBSCR_DICT 578 +#define _STORE_SUBSCR_LIST_INT 579 +#define _SWAP 580 +#define _SWAP_2 581 +#define _SWAP_3 582 +#define _SWAP_FAST 583 +#define _SWAP_FAST_0 584 +#define _SWAP_FAST_1 585 +#define _SWAP_FAST_2 586 +#define _SWAP_FAST_3 587 +#define _SWAP_FAST_4 588 +#define _SWAP_FAST_5 589 +#define _SWAP_FAST_6 590 +#define _SWAP_FAST_7 591 +#define _TIER2_RESUME_CHECK 592 +#define _TO_BOOL 593 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 593 -#define _TO_BOOL_LIST 594 +#define _TO_BOOL_INT 594 +#define _TO_BOOL_LIST 595 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 595 +#define _TO_BOOL_STR 596 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 596 -#define _UNARY_NEGATIVE 597 +#define _UNARY_INVERT 597 +#define _UNARY_NEGATIVE 598 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 598 -#define _UNPACK_SEQUENCE_LIST 599 -#define _UNPACK_SEQUENCE_TUPLE 600 -#define _UNPACK_SEQUENCE_TWO_TUPLE 601 +#define _UNPACK_SEQUENCE 599 +#define _UNPACK_SEQUENCE_LIST 600 +#define _UNPACK_SEQUENCE_TUPLE 601 +#define _UNPACK_SEQUENCE_TWO_TUPLE 602 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 602 -#define MAX_UOP_ID 602 -#define _BINARY_OP_r23 603 -#define _BINARY_OP_ADD_FLOAT_r03 604 -#define _BINARY_OP_ADD_FLOAT_r13 605 -#define _BINARY_OP_ADD_FLOAT_r23 606 -#define _BINARY_OP_ADD_INT_r03 607 -#define _BINARY_OP_ADD_INT_r13 608 -#define _BINARY_OP_ADD_INT_r23 609 -#define _BINARY_OP_ADD_UNICODE_r03 610 -#define _BINARY_OP_ADD_UNICODE_r13 611 -#define _BINARY_OP_ADD_UNICODE_r23 612 -#define _BINARY_OP_EXTEND_r23 613 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 614 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 615 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 616 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 617 -#define _BINARY_OP_MULTIPLY_INT_r03 618 -#define _BINARY_OP_MULTIPLY_INT_r13 619 -#define _BINARY_OP_MULTIPLY_INT_r23 620 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 621 -#define _BINARY_OP_SUBSCR_DICT_r23 622 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 623 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 624 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 625 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 626 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 627 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 628 -#define _BINARY_OP_SUBSCR_STR_INT_r23 629 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 630 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 631 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 632 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 633 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 634 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 635 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 636 -#define _BINARY_OP_SUBTRACT_INT_r03 637 -#define _BINARY_OP_SUBTRACT_INT_r13 638 -#define _BINARY_OP_SUBTRACT_INT_r23 639 -#define _BINARY_SLICE_r31 640 -#define _BUILD_INTERPOLATION_r01 641 -#define _BUILD_LIST_r01 642 -#define _BUILD_MAP_r01 643 -#define _BUILD_SET_r01 644 -#define _BUILD_SLICE_r01 645 -#define _BUILD_STRING_r01 646 -#define _BUILD_TEMPLATE_r21 647 -#define _BUILD_TUPLE_r01 648 -#define _CALL_BUILTIN_CLASS_r01 649 -#define _CALL_BUILTIN_FAST_r01 650 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 651 -#define _CALL_BUILTIN_O_r03 652 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 653 -#define _CALL_INTRINSIC_1_r12 654 -#define _CALL_INTRINSIC_2_r21 655 -#define _CALL_ISINSTANCE_r31 656 -#define _CALL_KW_NON_PY_r11 657 -#define _CALL_LEN_r33 658 -#define _CALL_LIST_APPEND_r03 659 -#define _CALL_LIST_APPEND_r13 660 -#define _CALL_LIST_APPEND_r23 661 -#define _CALL_LIST_APPEND_r33 662 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 663 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 664 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 665 -#define _CALL_METHOD_DESCRIPTOR_O_r03 666 -#define _CALL_NON_PY_GENERAL_r01 667 -#define _CALL_STR_1_r32 668 -#define _CALL_TUPLE_1_r32 669 -#define _CALL_TYPE_1_r02 670 -#define _CALL_TYPE_1_r12 671 -#define _CALL_TYPE_1_r22 672 -#define _CALL_TYPE_1_r32 673 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 674 -#define _CHECK_ATTR_CLASS_r01 675 -#define _CHECK_ATTR_CLASS_r11 676 -#define _CHECK_ATTR_CLASS_r22 677 -#define _CHECK_ATTR_CLASS_r33 678 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 679 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 680 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 681 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 682 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 683 -#define _CHECK_EG_MATCH_r22 684 -#define _CHECK_EXC_MATCH_r22 685 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 686 -#define _CHECK_FUNCTION_VERSION_r00 687 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 688 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 689 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 690 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 691 -#define _CHECK_FUNCTION_VERSION_KW_r11 692 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 693 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 694 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 695 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 696 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 697 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 698 -#define _CHECK_IS_PY_CALLABLE_EX_r03 699 -#define _CHECK_IS_PY_CALLABLE_EX_r13 700 -#define _CHECK_IS_PY_CALLABLE_EX_r23 701 -#define _CHECK_IS_PY_CALLABLE_EX_r33 702 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 703 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 704 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 705 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 706 -#define _CHECK_METHOD_VERSION_r00 707 -#define _CHECK_METHOD_VERSION_KW_r11 708 -#define _CHECK_PEP_523_r00 709 -#define _CHECK_PEP_523_r11 710 -#define _CHECK_PEP_523_r22 711 -#define _CHECK_PEP_523_r33 712 -#define _CHECK_PERIODIC_r00 713 -#define _CHECK_PERIODIC_AT_END_r00 714 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 715 -#define _CHECK_RECURSION_REMAINING_r00 716 -#define _CHECK_RECURSION_REMAINING_r11 717 -#define _CHECK_RECURSION_REMAINING_r22 718 -#define _CHECK_RECURSION_REMAINING_r33 719 -#define _CHECK_STACK_SPACE_r00 720 -#define _CHECK_STACK_SPACE_OPERAND_r00 721 -#define _CHECK_STACK_SPACE_OPERAND_r11 722 -#define _CHECK_STACK_SPACE_OPERAND_r22 723 -#define _CHECK_STACK_SPACE_OPERAND_r33 724 -#define _CHECK_VALIDITY_r00 725 -#define _CHECK_VALIDITY_r11 726 -#define _CHECK_VALIDITY_r22 727 -#define _CHECK_VALIDITY_r33 728 -#define _COLD_DYNAMIC_EXIT_r00 729 -#define _COLD_EXIT_r00 730 -#define _COMPARE_OP_r21 731 -#define _COMPARE_OP_FLOAT_r03 732 -#define _COMPARE_OP_FLOAT_r13 733 -#define _COMPARE_OP_FLOAT_r23 734 -#define _COMPARE_OP_INT_r23 735 -#define _COMPARE_OP_STR_r23 736 -#define _CONTAINS_OP_r23 737 -#define _CONTAINS_OP_DICT_r23 738 -#define _CONTAINS_OP_SET_r23 739 -#define _CONVERT_VALUE_r11 740 -#define _COPY_r01 741 -#define _COPY_1_r02 742 -#define _COPY_1_r12 743 -#define _COPY_1_r23 744 -#define _COPY_2_r03 745 -#define _COPY_2_r13 746 -#define _COPY_2_r23 747 -#define _COPY_3_r03 748 -#define _COPY_3_r13 749 -#define _COPY_3_r23 750 -#define _COPY_3_r33 751 -#define _COPY_FREE_VARS_r00 752 -#define _COPY_FREE_VARS_r11 753 -#define _COPY_FREE_VARS_r22 754 -#define _COPY_FREE_VARS_r33 755 -#define _CREATE_INIT_FRAME_r01 756 -#define _DELETE_ATTR_r10 757 -#define _DELETE_DEREF_r00 758 -#define _DELETE_FAST_r00 759 -#define _DELETE_GLOBAL_r00 760 -#define _DELETE_NAME_r00 761 -#define _DELETE_SUBSCR_r20 762 -#define _DEOPT_r00 763 -#define _DEOPT_r10 764 -#define _DEOPT_r20 765 -#define _DEOPT_r30 766 -#define _DICT_MERGE_r10 767 -#define _DICT_UPDATE_r10 768 -#define _DO_CALL_r01 769 -#define _DO_CALL_FUNCTION_EX_r31 770 -#define _DO_CALL_KW_r11 771 -#define _DYNAMIC_EXIT_r00 772 -#define _DYNAMIC_EXIT_r10 773 -#define _DYNAMIC_EXIT_r20 774 -#define _DYNAMIC_EXIT_r30 775 -#define _END_FOR_r10 776 -#define _END_SEND_r21 777 -#define _ERROR_POP_N_r00 778 -#define _EXIT_INIT_CHECK_r10 779 -#define _EXIT_TRACE_r00 780 -#define _EXIT_TRACE_r10 781 -#define _EXIT_TRACE_r20 782 -#define _EXIT_TRACE_r30 783 -#define _EXPAND_METHOD_r00 784 -#define _EXPAND_METHOD_KW_r11 785 -#define _FATAL_ERROR_r00 786 -#define _FATAL_ERROR_r11 787 -#define _FATAL_ERROR_r22 788 -#define _FATAL_ERROR_r33 789 -#define _FORMAT_SIMPLE_r11 790 -#define _FORMAT_WITH_SPEC_r21 791 -#define _FOR_ITER_r23 792 -#define _FOR_ITER_GEN_FRAME_r03 793 -#define _FOR_ITER_GEN_FRAME_r13 794 -#define _FOR_ITER_GEN_FRAME_r23 795 -#define _FOR_ITER_TIER_TWO_r23 796 -#define _GET_AITER_r11 797 -#define _GET_ANEXT_r12 798 -#define _GET_AWAITABLE_r11 799 -#define _GET_ITER_r12 800 -#define _GET_LEN_r12 801 -#define _GET_YIELD_FROM_ITER_r11 802 +#define _YIELD_VALUE 603 +#define MAX_UOP_ID 603 +#define _BINARY_OP_r23 604 +#define _BINARY_OP_ADD_FLOAT_r03 605 +#define _BINARY_OP_ADD_FLOAT_r13 606 +#define _BINARY_OP_ADD_FLOAT_r23 607 +#define _BINARY_OP_ADD_INT_r03 608 +#define _BINARY_OP_ADD_INT_r13 609 +#define _BINARY_OP_ADD_INT_r23 610 +#define _BINARY_OP_ADD_UNICODE_r03 611 +#define _BINARY_OP_ADD_UNICODE_r13 612 +#define _BINARY_OP_ADD_UNICODE_r23 613 +#define _BINARY_OP_EXTEND_r23 614 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 615 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 616 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 617 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 618 +#define _BINARY_OP_MULTIPLY_INT_r03 619 +#define _BINARY_OP_MULTIPLY_INT_r13 620 +#define _BINARY_OP_MULTIPLY_INT_r23 621 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 622 +#define _BINARY_OP_SUBSCR_DICT_r23 623 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 624 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 625 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 626 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 627 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 628 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 629 +#define _BINARY_OP_SUBSCR_STR_INT_r23 630 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 631 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 632 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 633 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 634 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 635 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 636 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 637 +#define _BINARY_OP_SUBTRACT_INT_r03 638 +#define _BINARY_OP_SUBTRACT_INT_r13 639 +#define _BINARY_OP_SUBTRACT_INT_r23 640 +#define _BINARY_SLICE_r31 641 +#define _BUILD_INTERPOLATION_r01 642 +#define _BUILD_LIST_r01 643 +#define _BUILD_MAP_r01 644 +#define _BUILD_SET_r01 645 +#define _BUILD_SLICE_r01 646 +#define _BUILD_STRING_r01 647 +#define _BUILD_TEMPLATE_r21 648 +#define _BUILD_TUPLE_r01 649 +#define _CALL_BUILTIN_CLASS_r01 650 +#define _CALL_BUILTIN_FAST_r01 651 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 652 +#define _CALL_BUILTIN_O_r03 653 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 654 +#define _CALL_INTRINSIC_1_r12 655 +#define _CALL_INTRINSIC_2_r21 656 +#define _CALL_ISINSTANCE_r31 657 +#define _CALL_KW_NON_PY_r11 658 +#define _CALL_LEN_r33 659 +#define _CALL_LIST_APPEND_r03 660 +#define _CALL_LIST_APPEND_r13 661 +#define _CALL_LIST_APPEND_r23 662 +#define _CALL_LIST_APPEND_r33 663 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 664 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 665 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 666 +#define _CALL_METHOD_DESCRIPTOR_O_r03 667 +#define _CALL_NON_PY_GENERAL_r01 668 +#define _CALL_STR_1_r32 669 +#define _CALL_TUPLE_1_r32 670 +#define _CALL_TYPE_1_r02 671 +#define _CALL_TYPE_1_r12 672 +#define _CALL_TYPE_1_r22 673 +#define _CALL_TYPE_1_r32 674 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 675 +#define _CHECK_ATTR_CLASS_r01 676 +#define _CHECK_ATTR_CLASS_r11 677 +#define _CHECK_ATTR_CLASS_r22 678 +#define _CHECK_ATTR_CLASS_r33 679 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 680 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 681 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 682 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 683 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 684 +#define _CHECK_EG_MATCH_r22 685 +#define _CHECK_EXC_MATCH_r22 686 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 687 +#define _CHECK_FUNCTION_VERSION_r00 688 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 689 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 690 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 691 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 692 +#define _CHECK_FUNCTION_VERSION_KW_r11 693 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 694 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 695 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 696 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 697 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 698 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 699 +#define _CHECK_IS_PY_CALLABLE_EX_r03 700 +#define _CHECK_IS_PY_CALLABLE_EX_r13 701 +#define _CHECK_IS_PY_CALLABLE_EX_r23 702 +#define _CHECK_IS_PY_CALLABLE_EX_r33 703 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 704 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 705 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 706 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 707 +#define _CHECK_METHOD_VERSION_r00 708 +#define _CHECK_METHOD_VERSION_KW_r11 709 +#define _CHECK_PEP_523_r00 710 +#define _CHECK_PEP_523_r11 711 +#define _CHECK_PEP_523_r22 712 +#define _CHECK_PEP_523_r33 713 +#define _CHECK_PERIODIC_r00 714 +#define _CHECK_PERIODIC_AT_END_r00 715 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 716 +#define _CHECK_RECURSION_REMAINING_r00 717 +#define _CHECK_RECURSION_REMAINING_r11 718 +#define _CHECK_RECURSION_REMAINING_r22 719 +#define _CHECK_RECURSION_REMAINING_r33 720 +#define _CHECK_STACK_SPACE_r00 721 +#define _CHECK_STACK_SPACE_OPERAND_r00 722 +#define _CHECK_STACK_SPACE_OPERAND_r11 723 +#define _CHECK_STACK_SPACE_OPERAND_r22 724 +#define _CHECK_STACK_SPACE_OPERAND_r33 725 +#define _CHECK_VALIDITY_r00 726 +#define _CHECK_VALIDITY_r11 727 +#define _CHECK_VALIDITY_r22 728 +#define _CHECK_VALIDITY_r33 729 +#define _COLD_DYNAMIC_EXIT_r00 730 +#define _COLD_EXIT_r00 731 +#define _COMPARE_OP_r21 732 +#define _COMPARE_OP_FLOAT_r03 733 +#define _COMPARE_OP_FLOAT_r13 734 +#define _COMPARE_OP_FLOAT_r23 735 +#define _COMPARE_OP_INT_r23 736 +#define _COMPARE_OP_STR_r23 737 +#define _CONTAINS_OP_r23 738 +#define _CONTAINS_OP_DICT_r23 739 +#define _CONTAINS_OP_SET_r23 740 +#define _CONVERT_VALUE_r11 741 +#define _COPY_r01 742 +#define _COPY_1_r02 743 +#define _COPY_1_r12 744 +#define _COPY_1_r23 745 +#define _COPY_2_r03 746 +#define _COPY_2_r13 747 +#define _COPY_2_r23 748 +#define _COPY_3_r03 749 +#define _COPY_3_r13 750 +#define _COPY_3_r23 751 +#define _COPY_3_r33 752 +#define _COPY_FREE_VARS_r00 753 +#define _COPY_FREE_VARS_r11 754 +#define _COPY_FREE_VARS_r22 755 +#define _COPY_FREE_VARS_r33 756 +#define _CREATE_INIT_FRAME_r01 757 +#define _DELETE_ATTR_r10 758 +#define _DELETE_DEREF_r00 759 +#define _DELETE_FAST_r00 760 +#define _DELETE_GLOBAL_r00 761 +#define _DELETE_NAME_r00 762 +#define _DELETE_SUBSCR_r20 763 +#define _DEOPT_r00 764 +#define _DEOPT_r10 765 +#define _DEOPT_r20 766 +#define _DEOPT_r30 767 +#define _DICT_MERGE_r10 768 +#define _DICT_UPDATE_r10 769 +#define _DO_CALL_r01 770 +#define _DO_CALL_FUNCTION_EX_r31 771 +#define _DO_CALL_KW_r11 772 +#define _DYNAMIC_EXIT_r00 773 +#define _DYNAMIC_EXIT_r10 774 +#define _DYNAMIC_EXIT_r20 775 +#define _DYNAMIC_EXIT_r30 776 +#define _END_FOR_r10 777 +#define _END_SEND_r31 778 +#define _ERROR_POP_N_r00 779 +#define _EXIT_INIT_CHECK_r10 780 +#define _EXIT_TRACE_r00 781 +#define _EXIT_TRACE_r10 782 +#define _EXIT_TRACE_r20 783 +#define _EXIT_TRACE_r30 784 +#define _EXPAND_METHOD_r00 785 +#define _EXPAND_METHOD_KW_r11 786 +#define _FATAL_ERROR_r00 787 +#define _FATAL_ERROR_r11 788 +#define _FATAL_ERROR_r22 789 +#define _FATAL_ERROR_r33 790 +#define _FORMAT_SIMPLE_r11 791 +#define _FORMAT_WITH_SPEC_r21 792 +#define _FOR_ITER_r23 793 +#define _FOR_ITER_GEN_FRAME_r03 794 +#define _FOR_ITER_GEN_FRAME_r13 795 +#define _FOR_ITER_GEN_FRAME_r23 796 +#define _FOR_ITER_TIER_TWO_r23 797 +#define _GET_AITER_r11 798 +#define _GET_ANEXT_r12 799 +#define _GET_AWAITABLE_r11 800 +#define _GET_ITER_r12 801 +#define _GET_LEN_r12 802 #define _GUARD_BINARY_OP_EXTEND_r22 803 #define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 804 #define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 805 @@ -1168,8 +1167,8 @@ extern "C" { #define _SAVE_RETURN_OFFSET_r11 1370 #define _SAVE_RETURN_OFFSET_r22 1371 #define _SAVE_RETURN_OFFSET_r33 1372 -#define _SEND_r22 1373 -#define _SEND_GEN_FRAME_r22 1374 +#define _SEND_r33 1373 +#define _SEND_GEN_FRAME_r33 1374 #define _SETUP_ANNOTATIONS_r00 1375 #define _SET_ADD_r10 1376 #define _SET_FUNCTION_ATTRIBUTE_r01 1377 diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index c804dbb87f7ccd..73691084d7d87d 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -229,8 +229,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_MATCH_MAPPING] = 0, [_MATCH_SEQUENCE] = 0, [_MATCH_KEYS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GET_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GET_YIELD_FROM_ITER] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GET_ITER] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_ITER_CHECK_LIST] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG, @@ -389,6 +388,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_RECORD_TOS_TYPE] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_3OS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, [_RECORD_4OS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_CALLABLE] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, [_RECORD_BOUND_METHOD] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, @@ -841,12 +841,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_END_SEND] = { - .best = { 2, 2, 2, 2 }, + .best = { 3, 3, 3, 3 }, .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _END_SEND_r21 }, { -1, -1, -1 }, + { 1, 3, _END_SEND_r31 }, }, }, [_UNARY_NEGATIVE] = { @@ -1417,12 +1417,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_SEND_GEN_FRAME] = { - .best = { 2, 2, 2, 2 }, + .best = { 3, 3, 3, 3 }, .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 2, 2, _SEND_GEN_FRAME_r22 }, { -1, -1, -1 }, + { 3, 3, _SEND_GEN_FRAME_r33 }, }, }, [_YIELD_VALUE] = { @@ -2163,15 +2163,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_GET_YIELD_FROM_ITER] = { - .best = { 1, 1, 1, 1 }, - .entries = { - { -1, -1, -1 }, - { 1, 1, _GET_YIELD_FROM_ITER_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - }, - }, [_FOR_ITER_TIER_TWO] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -3699,7 +3690,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_PUSH_NULL_r23] = _PUSH_NULL, [_END_FOR_r10] = _END_FOR, [_POP_ITER_r20] = _POP_ITER, - [_END_SEND_r21] = _END_SEND, + [_END_SEND_r31] = _END_SEND, [_UNARY_NEGATIVE_r12] = _UNARY_NEGATIVE, [_UNARY_NOT_r01] = _UNARY_NOT, [_UNARY_NOT_r11] = _UNARY_NOT, @@ -3862,7 +3853,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GET_AITER_r11] = _GET_AITER, [_GET_ANEXT_r12] = _GET_ANEXT, [_GET_AWAITABLE_r11] = _GET_AWAITABLE, - [_SEND_GEN_FRAME_r22] = _SEND_GEN_FRAME, + [_SEND_GEN_FRAME_r33] = _SEND_GEN_FRAME, [_YIELD_VALUE_r11] = _YIELD_VALUE, [_POP_EXCEPT_r10] = _POP_EXCEPT, [_LOAD_COMMON_CONSTANT_r01] = _LOAD_COMMON_CONSTANT, @@ -3994,7 +3985,6 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_MATCH_SEQUENCE_r23] = _MATCH_SEQUENCE, [_MATCH_KEYS_r23] = _MATCH_KEYS, [_GET_ITER_r12] = _GET_ITER, - [_GET_YIELD_FROM_ITER_r11] = _GET_YIELD_FROM_ITER, [_FOR_ITER_TIER_TWO_r23] = _FOR_ITER_TIER_TWO, [_ITER_CHECK_LIST_r02] = _ITER_CHECK_LIST, [_ITER_CHECK_LIST_r12] = _ITER_CHECK_LIST, @@ -4667,7 +4657,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_END_FOR] = "_END_FOR", [_END_FOR_r10] = "_END_FOR_r10", [_END_SEND] = "_END_SEND", - [_END_SEND_r21] = "_END_SEND_r21", + [_END_SEND_r31] = "_END_SEND_r31", [_ERROR_POP_N] = "_ERROR_POP_N", [_ERROR_POP_N_r00] = "_ERROR_POP_N_r00", [_EXIT_INIT_CHECK] = "_EXIT_INIT_CHECK", @@ -4706,8 +4696,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GET_ITER_r12] = "_GET_ITER_r12", [_GET_LEN] = "_GET_LEN", [_GET_LEN_r12] = "_GET_LEN_r12", - [_GET_YIELD_FROM_ITER] = "_GET_YIELD_FROM_ITER", - [_GET_YIELD_FROM_ITER_r11] = "_GET_YIELD_FROM_ITER_r11", [_GUARD_BINARY_OP_EXTEND] = "_GUARD_BINARY_OP_EXTEND", [_GUARD_BINARY_OP_EXTEND_r22] = "_GUARD_BINARY_OP_EXTEND_r22", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS", @@ -5386,6 +5374,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_PY_FRAME_GENERAL_r01] = "_PY_FRAME_GENERAL_r01", [_PY_FRAME_KW] = "_PY_FRAME_KW", [_PY_FRAME_KW_r11] = "_PY_FRAME_KW_r11", + [_RECORD_3OS_GEN_FUNC] = "_RECORD_3OS_GEN_FUNC", [_RECORD_4OS] = "_RECORD_4OS", [_RECORD_BOUND_METHOD] = "_RECORD_BOUND_METHOD", [_RECORD_CALLABLE] = "_RECORD_CALLABLE", @@ -5413,7 +5402,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_SAVE_RETURN_OFFSET_r22] = "_SAVE_RETURN_OFFSET_r22", [_SAVE_RETURN_OFFSET_r33] = "_SAVE_RETURN_OFFSET_r33", [_SEND_GEN_FRAME] = "_SEND_GEN_FRAME", - [_SEND_GEN_FRAME_r22] = "_SEND_GEN_FRAME_r22", + [_SEND_GEN_FRAME_r33] = "_SEND_GEN_FRAME_r33", [_SETUP_ANNOTATIONS] = "_SETUP_ANNOTATIONS", [_SETUP_ANNOTATIONS_r00] = "_SETUP_ANNOTATIONS_r00", [_SET_ADD] = "_SET_ADD", @@ -5687,7 +5676,7 @@ int _PyUop_num_popped(int opcode, int oparg) case _POP_ITER: return 2; case _END_SEND: - return 2; + return 3; case _UNARY_NEGATIVE: return 1; case _UNARY_NOT: @@ -5980,8 +5969,6 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GET_ITER: return 1; - case _GET_YIELD_FROM_ITER: - return 1; case _FOR_ITER_TIER_TWO: return 0; case _ITER_CHECK_LIST: @@ -6298,6 +6285,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _RECORD_NOS_GEN_FUNC: return 0; + case _RECORD_3OS_GEN_FUNC: + return 0; case _RECORD_4OS: return 0; case _RECORD_CALLABLE: diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index f9173fd83c295e..ac6d4d964d3b5e 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -26,111 +26,110 @@ extern "C" { #define FORMAT_WITH_SPEC 13 #define GET_AITER 14 #define GET_ANEXT 15 -#define GET_ITER 16 +#define GET_LEN 16 #define RESERVED 17 -#define GET_LEN 18 -#define GET_YIELD_FROM_ITER 19 -#define INTERPRETER_EXIT 20 -#define LOAD_BUILD_CLASS 21 -#define LOAD_LOCALS 22 -#define MAKE_FUNCTION 23 -#define MATCH_KEYS 24 -#define MATCH_MAPPING 25 -#define MATCH_SEQUENCE 26 -#define NOP 27 -#define NOT_TAKEN 28 -#define POP_EXCEPT 29 -#define POP_ITER 30 -#define POP_TOP 31 -#define PUSH_EXC_INFO 32 -#define PUSH_NULL 33 -#define RETURN_GENERATOR 34 -#define RETURN_VALUE 35 -#define SETUP_ANNOTATIONS 36 -#define STORE_SLICE 37 -#define STORE_SUBSCR 38 -#define TO_BOOL 39 -#define UNARY_INVERT 40 -#define UNARY_NEGATIVE 41 -#define UNARY_NOT 42 -#define WITH_EXCEPT_START 43 -#define BINARY_OP 44 -#define BUILD_INTERPOLATION 45 -#define BUILD_LIST 46 -#define BUILD_MAP 47 -#define BUILD_SET 48 -#define BUILD_SLICE 49 -#define BUILD_STRING 50 -#define BUILD_TUPLE 51 -#define CALL 52 -#define CALL_INTRINSIC_1 53 -#define CALL_INTRINSIC_2 54 -#define CALL_KW 55 -#define COMPARE_OP 56 -#define CONTAINS_OP 57 -#define CONVERT_VALUE 58 -#define COPY 59 -#define COPY_FREE_VARS 60 -#define DELETE_ATTR 61 -#define DELETE_DEREF 62 -#define DELETE_FAST 63 -#define DELETE_GLOBAL 64 -#define DELETE_NAME 65 -#define DICT_MERGE 66 -#define DICT_UPDATE 67 -#define END_ASYNC_FOR 68 -#define EXTENDED_ARG 69 -#define FOR_ITER 70 -#define GET_AWAITABLE 71 -#define IMPORT_FROM 72 -#define IMPORT_NAME 73 -#define IS_OP 74 -#define JUMP_BACKWARD 75 -#define JUMP_BACKWARD_NO_INTERRUPT 76 -#define JUMP_FORWARD 77 -#define LIST_APPEND 78 -#define LIST_EXTEND 79 -#define LOAD_ATTR 80 -#define LOAD_COMMON_CONSTANT 81 -#define LOAD_CONST 82 -#define LOAD_DEREF 83 -#define LOAD_FAST 84 -#define LOAD_FAST_AND_CLEAR 85 -#define LOAD_FAST_BORROW 86 -#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 87 -#define LOAD_FAST_CHECK 88 -#define LOAD_FAST_LOAD_FAST 89 -#define LOAD_FROM_DICT_OR_DEREF 90 -#define LOAD_FROM_DICT_OR_GLOBALS 91 -#define LOAD_GLOBAL 92 -#define LOAD_NAME 93 -#define LOAD_SMALL_INT 94 -#define LOAD_SPECIAL 95 -#define LOAD_SUPER_ATTR 96 -#define MAKE_CELL 97 -#define MAP_ADD 98 -#define MATCH_CLASS 99 -#define POP_JUMP_IF_FALSE 100 -#define POP_JUMP_IF_NONE 101 -#define POP_JUMP_IF_NOT_NONE 102 -#define POP_JUMP_IF_TRUE 103 -#define RAISE_VARARGS 104 -#define RERAISE 105 -#define SEND 106 -#define SET_ADD 107 -#define SET_FUNCTION_ATTRIBUTE 108 -#define SET_UPDATE 109 -#define STORE_ATTR 110 -#define STORE_DEREF 111 -#define STORE_FAST 112 -#define STORE_FAST_LOAD_FAST 113 -#define STORE_FAST_STORE_FAST 114 -#define STORE_GLOBAL 115 -#define STORE_NAME 116 -#define SWAP 117 -#define UNPACK_EX 118 -#define UNPACK_SEQUENCE 119 -#define YIELD_VALUE 120 +#define INTERPRETER_EXIT 18 +#define LOAD_BUILD_CLASS 19 +#define LOAD_LOCALS 20 +#define MAKE_FUNCTION 21 +#define MATCH_KEYS 22 +#define MATCH_MAPPING 23 +#define MATCH_SEQUENCE 24 +#define NOP 25 +#define NOT_TAKEN 26 +#define POP_EXCEPT 27 +#define POP_ITER 28 +#define POP_TOP 29 +#define PUSH_EXC_INFO 30 +#define PUSH_NULL 31 +#define RETURN_GENERATOR 32 +#define RETURN_VALUE 33 +#define SETUP_ANNOTATIONS 34 +#define STORE_SLICE 35 +#define STORE_SUBSCR 36 +#define TO_BOOL 37 +#define UNARY_INVERT 38 +#define UNARY_NEGATIVE 39 +#define UNARY_NOT 40 +#define WITH_EXCEPT_START 41 +#define BINARY_OP 42 +#define BUILD_INTERPOLATION 43 +#define BUILD_LIST 44 +#define BUILD_MAP 45 +#define BUILD_SET 46 +#define BUILD_SLICE 47 +#define BUILD_STRING 48 +#define BUILD_TUPLE 49 +#define CALL 50 +#define CALL_INTRINSIC_1 51 +#define CALL_INTRINSIC_2 52 +#define CALL_KW 53 +#define COMPARE_OP 54 +#define CONTAINS_OP 55 +#define CONVERT_VALUE 56 +#define COPY 57 +#define COPY_FREE_VARS 58 +#define DELETE_ATTR 59 +#define DELETE_DEREF 60 +#define DELETE_FAST 61 +#define DELETE_GLOBAL 62 +#define DELETE_NAME 63 +#define DICT_MERGE 64 +#define DICT_UPDATE 65 +#define END_ASYNC_FOR 66 +#define EXTENDED_ARG 67 +#define FOR_ITER 68 +#define GET_AWAITABLE 69 +#define GET_ITER 70 +#define IMPORT_FROM 71 +#define IMPORT_NAME 72 +#define IS_OP 73 +#define JUMP_BACKWARD 74 +#define JUMP_BACKWARD_NO_INTERRUPT 75 +#define JUMP_FORWARD 76 +#define LIST_APPEND 77 +#define LIST_EXTEND 78 +#define LOAD_ATTR 79 +#define LOAD_COMMON_CONSTANT 80 +#define LOAD_CONST 81 +#define LOAD_DEREF 82 +#define LOAD_FAST 83 +#define LOAD_FAST_AND_CLEAR 84 +#define LOAD_FAST_BORROW 85 +#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 86 +#define LOAD_FAST_CHECK 87 +#define LOAD_FAST_LOAD_FAST 88 +#define LOAD_FROM_DICT_OR_DEREF 89 +#define LOAD_FROM_DICT_OR_GLOBALS 90 +#define LOAD_GLOBAL 91 +#define LOAD_NAME 92 +#define LOAD_SMALL_INT 93 +#define LOAD_SPECIAL 94 +#define LOAD_SUPER_ATTR 95 +#define MAKE_CELL 96 +#define MAP_ADD 97 +#define MATCH_CLASS 98 +#define POP_JUMP_IF_FALSE 99 +#define POP_JUMP_IF_NONE 100 +#define POP_JUMP_IF_NOT_NONE 101 +#define POP_JUMP_IF_TRUE 102 +#define RAISE_VARARGS 103 +#define RERAISE 104 +#define SEND 105 +#define SET_ADD 106 +#define SET_FUNCTION_ATTRIBUTE 107 +#define SET_UPDATE 108 +#define STORE_ATTR 109 +#define STORE_DEREF 110 +#define STORE_FAST 111 +#define STORE_FAST_LOAD_FAST 112 +#define STORE_FAST_STORE_FAST 113 +#define STORE_GLOBAL 114 +#define STORE_NAME 115 +#define SWAP 116 +#define UNPACK_EX 117 +#define UNPACK_SEQUENCE 118 +#define YIELD_VALUE 119 #define RESUME 128 #define BINARY_OP_ADD_FLOAT 129 #define BINARY_OP_ADD_INT 130 @@ -252,7 +251,7 @@ extern "C" { #define SETUP_WITH 265 #define STORE_FAST_MAYBE_NULL 266 -#define HAVE_ARGUMENT 43 +#define HAVE_ARGUMENT 41 #define MIN_SPECIALIZED_OPCODE 129 #define MIN_INSTRUMENTED_OPCODE 233 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 8d2c1ece8bc6a8..f5954e4372a980 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -235,110 +235,109 @@ FORMAT_WITH_SPEC=13, GET_AITER=14, GET_ANEXT=15, - GET_ITER=16, - GET_LEN=18, - GET_YIELD_FROM_ITER=19, - INTERPRETER_EXIT=20, - LOAD_BUILD_CLASS=21, - LOAD_LOCALS=22, - MAKE_FUNCTION=23, - MATCH_KEYS=24, - MATCH_MAPPING=25, - MATCH_SEQUENCE=26, - NOP=27, - NOT_TAKEN=28, - POP_EXCEPT=29, - POP_ITER=30, - POP_TOP=31, - PUSH_EXC_INFO=32, - PUSH_NULL=33, - RETURN_GENERATOR=34, - RETURN_VALUE=35, - SETUP_ANNOTATIONS=36, - STORE_SLICE=37, - STORE_SUBSCR=38, - TO_BOOL=39, - UNARY_INVERT=40, - UNARY_NEGATIVE=41, - UNARY_NOT=42, - WITH_EXCEPT_START=43, - BINARY_OP=44, - BUILD_INTERPOLATION=45, - BUILD_LIST=46, - BUILD_MAP=47, - BUILD_SET=48, - BUILD_SLICE=49, - BUILD_STRING=50, - BUILD_TUPLE=51, - CALL=52, - CALL_INTRINSIC_1=53, - CALL_INTRINSIC_2=54, - CALL_KW=55, - COMPARE_OP=56, - CONTAINS_OP=57, - CONVERT_VALUE=58, - COPY=59, - COPY_FREE_VARS=60, - DELETE_ATTR=61, - DELETE_DEREF=62, - DELETE_FAST=63, - DELETE_GLOBAL=64, - DELETE_NAME=65, - DICT_MERGE=66, - DICT_UPDATE=67, - END_ASYNC_FOR=68, - EXTENDED_ARG=69, - FOR_ITER=70, - GET_AWAITABLE=71, - IMPORT_FROM=72, - IMPORT_NAME=73, - IS_OP=74, - JUMP_BACKWARD=75, - JUMP_BACKWARD_NO_INTERRUPT=76, - JUMP_FORWARD=77, - LIST_APPEND=78, - LIST_EXTEND=79, - LOAD_ATTR=80, - LOAD_COMMON_CONSTANT=81, - LOAD_CONST=82, - LOAD_DEREF=83, - LOAD_FAST=84, - LOAD_FAST_AND_CLEAR=85, - LOAD_FAST_BORROW=86, - LOAD_FAST_BORROW_LOAD_FAST_BORROW=87, - LOAD_FAST_CHECK=88, - LOAD_FAST_LOAD_FAST=89, - LOAD_FROM_DICT_OR_DEREF=90, - LOAD_FROM_DICT_OR_GLOBALS=91, - LOAD_GLOBAL=92, - LOAD_NAME=93, - LOAD_SMALL_INT=94, - LOAD_SPECIAL=95, - LOAD_SUPER_ATTR=96, - MAKE_CELL=97, - MAP_ADD=98, - MATCH_CLASS=99, - POP_JUMP_IF_FALSE=100, - POP_JUMP_IF_NONE=101, - POP_JUMP_IF_NOT_NONE=102, - POP_JUMP_IF_TRUE=103, - RAISE_VARARGS=104, - RERAISE=105, - SEND=106, - SET_ADD=107, - SET_FUNCTION_ATTRIBUTE=108, - SET_UPDATE=109, - STORE_ATTR=110, - STORE_DEREF=111, - STORE_FAST=112, - STORE_FAST_LOAD_FAST=113, - STORE_FAST_STORE_FAST=114, - STORE_GLOBAL=115, - STORE_NAME=116, - SWAP=117, - UNPACK_EX=118, - UNPACK_SEQUENCE=119, - YIELD_VALUE=120, + GET_LEN=16, + INTERPRETER_EXIT=18, + LOAD_BUILD_CLASS=19, + LOAD_LOCALS=20, + MAKE_FUNCTION=21, + MATCH_KEYS=22, + MATCH_MAPPING=23, + MATCH_SEQUENCE=24, + NOP=25, + NOT_TAKEN=26, + POP_EXCEPT=27, + POP_ITER=28, + POP_TOP=29, + PUSH_EXC_INFO=30, + PUSH_NULL=31, + RETURN_GENERATOR=32, + RETURN_VALUE=33, + SETUP_ANNOTATIONS=34, + STORE_SLICE=35, + STORE_SUBSCR=36, + TO_BOOL=37, + UNARY_INVERT=38, + UNARY_NEGATIVE=39, + UNARY_NOT=40, + WITH_EXCEPT_START=41, + BINARY_OP=42, + BUILD_INTERPOLATION=43, + BUILD_LIST=44, + BUILD_MAP=45, + BUILD_SET=46, + BUILD_SLICE=47, + BUILD_STRING=48, + BUILD_TUPLE=49, + CALL=50, + CALL_INTRINSIC_1=51, + CALL_INTRINSIC_2=52, + CALL_KW=53, + COMPARE_OP=54, + CONTAINS_OP=55, + CONVERT_VALUE=56, + COPY=57, + COPY_FREE_VARS=58, + DELETE_ATTR=59, + DELETE_DEREF=60, + DELETE_FAST=61, + DELETE_GLOBAL=62, + DELETE_NAME=63, + DICT_MERGE=64, + DICT_UPDATE=65, + END_ASYNC_FOR=66, + EXTENDED_ARG=67, + FOR_ITER=68, + GET_AWAITABLE=69, + GET_ITER=70, + IMPORT_FROM=71, + IMPORT_NAME=72, + IS_OP=73, + JUMP_BACKWARD=74, + JUMP_BACKWARD_NO_INTERRUPT=75, + JUMP_FORWARD=76, + LIST_APPEND=77, + LIST_EXTEND=78, + LOAD_ATTR=79, + LOAD_COMMON_CONSTANT=80, + LOAD_CONST=81, + LOAD_DEREF=82, + LOAD_FAST=83, + LOAD_FAST_AND_CLEAR=84, + LOAD_FAST_BORROW=85, + LOAD_FAST_BORROW_LOAD_FAST_BORROW=86, + LOAD_FAST_CHECK=87, + LOAD_FAST_LOAD_FAST=88, + LOAD_FROM_DICT_OR_DEREF=89, + LOAD_FROM_DICT_OR_GLOBALS=90, + LOAD_GLOBAL=91, + LOAD_NAME=92, + LOAD_SMALL_INT=93, + LOAD_SPECIAL=94, + LOAD_SUPER_ATTR=95, + MAKE_CELL=96, + MAP_ADD=97, + MATCH_CLASS=98, + POP_JUMP_IF_FALSE=99, + POP_JUMP_IF_NONE=100, + POP_JUMP_IF_NOT_NONE=101, + POP_JUMP_IF_TRUE=102, + RAISE_VARARGS=103, + RERAISE=104, + SEND=105, + SET_ADD=106, + SET_FUNCTION_ATTRIBUTE=107, + SET_UPDATE=108, + STORE_ATTR=109, + STORE_DEREF=110, + STORE_FAST=111, + STORE_FAST_LOAD_FAST=112, + STORE_FAST_STORE_FAST=113, + STORE_GLOBAL=114, + STORE_NAME=115, + SWAP=116, + UNPACK_EX=117, + UNPACK_SEQUENCE=118, + YIELD_VALUE=119, INSTRUMENTED_END_FOR=233, INSTRUMENTED_POP_ITER=234, INSTRUMENTED_END_SEND=235, @@ -372,5 +371,5 @@ STORE_FAST_MAYBE_NULL=266, ) -HAVE_ARGUMENT = 43 +HAVE_ARGUMENT = 41 MIN_INSTRUMENTED_OPCODE = 233 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index f4210db5bd788e..f8bbcd35ca7c09 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -174,7 +174,7 @@ def bug708901(): %3d LOAD_SMALL_INT 10 %3d CALL 2 - GET_ITER + GET_ITER 0 L1: FOR_ITER 3 (to L2) STORE_FAST 0 (res) @@ -616,6 +616,7 @@ async def _asyncwith(c): LOAD_SPECIAL 2 (__aenter__) CALL 0 GET_AWAITABLE 1 + PUSH_NULL LOAD_CONST 0 (None) L2: SEND 4 (to L5) L3: YIELD_VALUE 1 @@ -632,6 +633,7 @@ async def _asyncwith(c): LOAD_CONST 0 (None) CALL 3 GET_AWAITABLE 2 + PUSH_NULL LOAD_CONST 0 (None) L8: SEND 4 (to L11) L9: YIELD_VALUE 1 @@ -646,12 +648,13 @@ async def _asyncwith(c): RETURN_VALUE %4d L12: CLEANUP_THROW - L13: JUMP_BACKWARD_NO_INTERRUPT 27 (to L5) + L13: JUMP_BACKWARD_NO_INTERRUPT 28 (to L5) L14: CLEANUP_THROW L15: JUMP_BACKWARD_NO_INTERRUPT 10 (to L11) L16: PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 + PUSH_NULL LOAD_CONST 0 (None) L17: SEND 5 (to L21) L18: YIELD_VALUE 1 @@ -681,15 +684,15 @@ async def _asyncwith(c): RERAISE 1 ExceptionTable: L1 to L3 -> L27 [0] lasti - L3 to L4 -> L12 [4] + L3 to L4 -> L12 [5] L4 to L6 -> L27 [0] lasti L6 to L7 -> L16 [2] lasti L7 to L9 -> L27 [0] lasti - L9 to L10 -> L14 [2] + L9 to L10 -> L14 [3] L10 to L13 -> L27 [0] lasti L14 to L15 -> L27 [0] lasti L16 to L18 -> L26 [4] lasti - L18 to L19 -> L20 [7] + L18 to L19 -> L20 [8] L19 to L22 -> L26 [4] lasti L23 to L25 -> L26 [4] lasti L25 to L27 -> L27 [0] lasti @@ -876,7 +879,7 @@ def foo(x): -- COPY_FREE_VARS 1 %4d LOAD_FAST 0 (.0) - GET_ITER + GET_ITER 0 RETURN_GENERATOR POP_TOP L1: RESUME 0 @@ -933,7 +936,7 @@ def loop_test(): LIST_EXTEND 1 LOAD_SMALL_INT 3 BINARY_OP 5 (*) - GET_ITER + GET_ITER 0 L1: FOR_ITER_LIST 14 (to L2) STORE_FAST 0 (i) @@ -1035,6 +1038,7 @@ def test_widths(self): long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT', 'LOAD_FAST_BORROW_LOAD_FAST_BORROW', 'INSTRUMENTED_CALL_FUNCTION_EX', + 'YIELD_FROM_CORO_CHECK', 'ANNOTATIONS_PLACEHOLDER']) for op, opname in enumerate(dis.opname): if opname in long_opcodes or opname.startswith("INSTRUMENTED"): @@ -1855,7 +1859,7 @@ def _prepare_test_cases(): make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=4, start_offset=4, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3), make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), + make_inst(opname='GET_ITER', arg=0, argval=0, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), make_inst(opname='FOR_ITER', arg=33, argval=96, argrepr='to L4', offset=26, start_offset=26, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3), make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 88d20bbb028d6f..e0cc010f15513b 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -1470,7 +1470,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_SMALL_INT', 2, 0), ('BUILD_LIST', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1483,7 +1483,7 @@ def test_optimize_literal_list_for_iter(self): ] after = [ ('LOAD_CONST', 1, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1501,7 +1501,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_LIST', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1516,7 +1516,7 @@ def test_optimize_literal_list_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_TUPLE', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1535,7 +1535,7 @@ def test_optimize_literal_set_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_SMALL_INT', 2, 0), ('BUILD_SET', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1548,7 +1548,7 @@ def test_optimize_literal_set_for_iter(self): ] after = [ ('LOAD_CONST', 1, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -1567,7 +1567,7 @@ def test_optimize_literal_set_for_iter(self): ('LOAD_SMALL_INT', 1, 0), ('LOAD_NAME', 0, 0), ('BUILD_SET', 2, 0), - ('GET_ITER', None, 0), + ('GET_ITER', 0, 0), start := self.Label(), ('FOR_ITER', end := self.Label(), 0), ('STORE_FAST', 0, 0), @@ -2356,7 +2356,7 @@ def test_list_to_tuple_get_iter(self): ("LOAD_FAST", 1, 4), ("LIST_EXTEND", 1, 5), ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6), - ("GET_ITER", None, 7), + ("GET_ITER", 0, 7), top := self.Label(), ("FOR_ITER", end := self.Label(), 8), ("STORE_FAST", 2, 9), @@ -2374,7 +2374,7 @@ def test_list_to_tuple_get_iter(self): ("LOAD_FAST_BORROW", 1, 4), ("LIST_EXTEND", 1, 5), ("NOP", None, 6), # ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6), - ("GET_ITER", None, 7), + ("GET_ITER", 0, 7), top := self.Label(), ("FOR_ITER", end := self.Label(), 8), ("STORE_FAST", 2, 9), @@ -2677,20 +2677,20 @@ def test_set_function_attribute(self): self.cfg_optimization_test(insts, expected, consts=[None]) def test_get_yield_from_iter(self): - # GET_YIELD_FROM_ITER may leave its operand on the stack insts = [ ("LOAD_FAST", 0, 1), - ("GET_YIELD_FROM_ITER", None, 2), - ("LOAD_CONST", 0, 3), + ("GET_ITER", 1, 2), + ("PUSH_NULL", None, 3), + ("LOAD_CONST", 0, 4), send := self.Label(), - ("SEND", end := self.Label(), 5), - ("YIELD_VALUE", 1, 6), - ("RESUME", 2, 7), - ("JUMP", send, 8), + ("SEND", end := self.Label(), 6), + ("YIELD_VALUE", 1, 7), + ("RESUME", 2, 8), + ("JUMP", send, 9), end, - ("END_SEND", None, 9), - ("LOAD_CONST", 0, 10), - ("RETURN_VALUE", None, 11), + ("END_SEND", None, 10), + ("LOAD_CONST", 0, 11), + ("RETURN_VALUE", None, 12), ] self.cfg_optimization_test(insts, insts, consts=[None]) diff --git a/Modules/_remote_debugging/asyncio.c b/Modules/_remote_debugging/asyncio.c index 69478634de6926..67a97a53db6415 100644 --- a/Modules/_remote_debugging/asyncio.c +++ b/Modules/_remote_debugging/asyncio.c @@ -265,7 +265,7 @@ handle_yield_from_frame( uintptr_t gi_await_addr; err = read_py_ptr( unwinder, - stackpointer_addr - sizeof(void*), + stackpointer_addr - sizeof(void*) * 2, &gi_await_addr); if (err) { set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read gi_await address"); diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 948a413d98ddcd..7f3d23e5889b36 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -4737,13 +4737,16 @@ next_instr += 1; INSTRUCTION_STATS(CLEANUP_THROW); _PyStackRef sub_iter; + _PyStackRef null_in; _PyStackRef last_sent_val; _PyStackRef exc_value_st; _PyStackRef none; + _PyStackRef null_out; _PyStackRef value; exc_value_st = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; - sub_iter = stack_pointer[-3]; + null_in = stack_pointer[-3]; + sub_iter = stack_pointer[-4]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); @@ -4757,7 +4760,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef tmp = sub_iter; sub_iter = value; - stack_pointer[-3] = sub_iter; + stack_pointer[-4] = sub_iter; PyStackRef_CLOSE(tmp); tmp = exc_value_st; exc_value_st = PyStackRef_NULL; @@ -4767,9 +4770,14 @@ last_sent_val = PyStackRef_NULL; stack_pointer[-2] = last_sent_val; PyStackRef_CLOSE(tmp); + tmp = null_in; + null_in = PyStackRef_NULL; + stack_pointer[-3] = null_in; + PyStackRef_XCLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; + stack_pointer += -4; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + null_out = null_in; none = PyStackRef_None; } else { @@ -4779,8 +4787,9 @@ JUMP_TO_LABEL(exception_unwind); } stack_pointer[0] = none; - stack_pointer[1] = value; - stack_pointer += 2; + stack_pointer[1] = null_out; + stack_pointer[2] = value; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -5665,13 +5674,16 @@ next_instr += 1; INSTRUCTION_STATS(END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -6291,31 +6303,15 @@ _PyStackRef index_or_null; iterable = stack_pointer[-1]; #ifdef Py_STATS - _PyFrame_SetStackPointer(frame, stack_pointer); _Py_GatherStats_GetIter(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - stack_pointer += 1; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); } + iter = result; stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; @@ -6351,51 +6347,6 @@ DISPATCH(); } - TARGET(GET_YIELD_FROM_ITER) { - #if _Py_TAIL_CALL_INTERP - int opcode = GET_YIELD_FROM_ITER; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(GET_YIELD_FROM_ITER); - _PyStackRef iterable; - _PyStackRef iter; - iterable = stack_pointer[-1]; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - stack_pointer[-1] = iter; - DISPATCH(); - } - TARGET(IMPORT_FROM) { #if _Py_TAIL_CALL_INTERP int opcode = IMPORT_FROM; @@ -6999,10 +6950,12 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7013,8 +6966,9 @@ } } val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -10733,11 +10687,12 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef receiver; + _PyStackRef null_or_index; _PyStackRef v; _PyStackRef retval; // _SPECIALIZE_SEND { - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION @@ -10755,6 +10710,7 @@ // _SEND { v = stack_pointer[-1]; + null_or_index = stack_pointer[-2]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -10775,53 +10731,66 @@ gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + if (!PyStackRef_IsNull(null_or_index)) { _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg); + stack_pointer[-2] = null_or_index; + DISPATCH(); + } + retval = item; } else { - _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - if (retval_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_MonitorRaise(tstate, frame, this_instr); + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); stack_pointer = _PyFrame_GetStackPointer(frame); } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyGen_FetchStopIterationValue(&retval_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); - } else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(v); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } + if (retval_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_MonitorRaise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyGen_FetchStopIterationValue(&retval_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + } + retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + stack_pointer[-2] = null_or_index; + stack_pointer[-1] = retval; _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); stack_pointer = _PyFrame_GetStackPointer(frame); - retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer[0] = retval; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10852,7 +10821,7 @@ // _SEND_GEN_FRAME { v = stack_pointer[-1]; - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UPDATE_MISS_STATS(SEND); diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index def462bacec176..48fe9c14f4e2dd 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -16,10 +16,8 @@ static void *opcode_targets_table[256] = { &&TARGET_FORMAT_WITH_SPEC, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, - &&TARGET_GET_ITER, - &&TARGET_RESERVED, &&TARGET_GET_LEN, - &&TARGET_GET_YIELD_FROM_ITER, + &&TARGET_RESERVED, &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, @@ -72,6 +70,7 @@ static void *opcode_targets_table[256] = { &&TARGET_EXTENDED_ARG, &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, + &&TARGET_GET_ITER, &&TARGET_IMPORT_FROM, &&TARGET_IMPORT_NAME, &&TARGET_IS_OP, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -379,7 +379,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -626,7 +626,6 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS); @@ -868,7 +867,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, [GET_LEN] = _TAIL_CALL_GET_LEN, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, [INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL, @@ -1002,6 +1000,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1126,7 +1125,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, [INSTRUMENTED_CALL] = _TAIL_CALL_TRACE_RECORD, @@ -1260,6 +1258,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Objects/codeobject.c b/Objects/codeobject.c index fbf0985e9050dd..84a712b2b2c05d 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -501,7 +501,7 @@ _PyCode_Validate(struct _PyCodeConstructor *con) } extern void -_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters); +_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters, int flags); #ifdef Py_GIL_DISABLED static _PyCodeArray * _PyCodeArray_New(Py_ssize_t size); @@ -579,11 +579,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) entry_point++; } co->_co_firsttraceable = entry_point; + #ifdef Py_GIL_DISABLED int enable_counters = interp->config.tlbc_enabled && interp->opt_config.specialization_enabled; - _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), enable_counters); + _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), enable_counters, co->co_flags); #else - _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), interp->opt_config.specialization_enabled); + _PyCode_Quicken(_PyCode_CODE(co), Py_SIZE(co), interp->opt_config.specialization_enabled, co->co_flags); #endif notify_code_watchers(PY_CODE_EVENT_CREATE, co); return 0; @@ -3460,7 +3461,7 @@ copy_code(PyInterpreterState *interp, _Py_CODEUNIT *dst, PyCodeObject *co) for (int i = 0; i < code_len; i += _PyInstruction_GetLength(co, i)) { dst[i] = deopt_code_unit(co, i); } - _PyCode_Quicken(dst, code_len, interp->opt_config.specialization_enabled); + _PyCode_Quicken(dst, code_len, interp->opt_config.specialization_enabled, co->co_flags); } static Py_ssize_t diff --git a/Objects/genobject.c b/Objects/genobject.c index 9dece8a7700cab..2895833b4ff933 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -490,7 +490,7 @@ gen_close(PyObject *self, PyObject *args) int err = 0; _PyInterpreterFrame *frame = &gen->gi_iframe; if (frame_state == FRAME_SUSPENDED_YIELD_FROM) { - PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame)); + PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame, 2)); err = gen_close_iter(yf); Py_DECREF(yf); } @@ -649,7 +649,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, if (frame_state == FRAME_SUSPENDED_YIELD_FROM) { _PyInterpreterFrame *frame = &gen->gi_iframe; - PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame)); + PyObject *yf = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(frame, 2)); PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && @@ -898,7 +898,7 @@ gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored)) } } while (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_SUSPENDED_YIELD_FROM_LOCKED)); - PyObject *result = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); + PyObject *result = PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe, 2)); _Py_atomic_store_int8_release(&gen->gi_frame_state, FRAME_SUSPENDED_YIELD_FROM); return result; #else @@ -906,7 +906,7 @@ gen_getyieldfrom(PyObject *self, void *Py_UNUSED(ignored)) if (frame_state != FRAME_SUSPENDED_YIELD_FROM) { Py_RETURN_NONE; } - return PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe)); + return PyStackRef_AsPyObjectNew(_PyFrame_StackPeek(&gen->gi_iframe, 2)); #endif } diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 1411eb1718b683..d550740b1105dd 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,19 +1,19 @@ // 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,9,0,0, - 0,0,0,0,0,243,186,0,0,0,128,0,0,0,94,0, - 82,1,73,0,116,0,94,0,82,1,73,4,116,1,93,2, - 33,0,82,2,52,1,0,0,0,0,0,0,31,0,93,2, - 33,0,82,3,93,0,80,6,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,52,2,0,0,0,0, - 0,0,31,0,93,1,80,8,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,33,0,52,0,0,0, - 0,0,0,0,82,4,44,26,0,0,0,0,0,0,0,0, - 0,0,116,5,82,7,16,0,70,24,0,0,116,6,93,2, - 33,0,82,5,93,6,12,0,82,6,93,5,93,6,44,26, - 0,0,0,0,0,0,0,0,0,0,12,0,50,4,52,1, - 0,0,0,0,0,0,31,0,75,26,0,0,9,0,30,0, - 82,1,35,0,41,8,233,0,0,0,0,78,122,18,70,114, + 0,0,0,0,0,243,186,0,0,0,128,0,0,0,93,0, + 81,1,72,0,115,0,93,0,81,1,72,4,115,1,92,2, + 31,0,81,2,50,1,0,0,0,0,0,0,29,0,92,2, + 31,0,81,3,92,0,79,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,50,2,0,0,0,0, + 0,0,29,0,92,1,79,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,31,0,50,0,0,0, + 0,0,0,0,81,4,42,26,0,0,0,0,0,0,0,0, + 0,0,115,5,81,7,70,0,68,24,0,0,115,6,92,2, + 31,0,81,5,92,6,12,0,81,6,92,5,92,6,42,26, + 0,0,0,0,0,0,0,0,0,0,12,0,48,4,50,1, + 0,0,0,0,0,0,29,0,74,26,0,0,9,0,28,0, + 81,1,33,0,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,122,7,99,111,110,102,105,103,32,122,2,58,32,41, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 2fb2c33428255a..5fce1c2a43d495 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -425,13 +425,15 @@ dummy_func( PyStackRef_CLOSE(iter); } - pure inst(END_SEND, (receiver, value -- val)) { + pure inst(END_SEND, (receiver, index_or_null, value -- val)) { val = value; + (void)index_or_null; DEAD(value); + DEAD(index_or_null); PyStackRef_CLOSE(receiver); } - tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- val)) { + tier1 inst(INSTRUMENTED_END_SEND, (receiver, index_or_null, value -- val)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); @@ -440,6 +442,8 @@ dummy_func( } } val = value; + (void)index_or_null; + DEAD(index_or_null); DEAD(value); PyStackRef_CLOSE(receiver); } @@ -1407,7 +1411,7 @@ dummy_func( SEND_GEN, }; - specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) { + specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused, unused -- receiver, unused, unused)) { #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; @@ -1419,7 +1423,7 @@ dummy_func( #endif /* ENABLE_SPECIALIZATION */ } - op(_SEND, (receiver, v -- receiver, retval)) { + op(_SEND, (receiver, null_or_index, v -- receiver, null_or_index, retval)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -1440,36 +1444,49 @@ dummy_func( gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + if (!PyStackRef_IsNull(null_or_index)) { + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + ERROR_NO_POP(); + } + JUMPBY(oparg); + DISPATCH(); + } + retval = item; } else { - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - } - if (retval_o == NULL) { - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - if (matches) { - _PyEval_MonitorRaise(tstate, frame, this_instr); - } - int err = _PyGen_FetchStopIterationValue(&retval_o); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); } else { - PyStackRef_CLOSE(v); - ERROR_IF(true); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); + } + if (retval_o == NULL) { + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + if (matches) { + _PyEval_MonitorRaise(tstate, frame, this_instr); + } + int err = _PyGen_FetchStopIterationValue(&retval_o); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + PyStackRef_CLOSE(v); + ERROR_IF(true); + } } + retval = PyStackRef_FromPyObjectSteal(retval_o); } PyStackRef_CLOSE(v); - retval = PyStackRef_FromPyObjectSteal(retval_o); } macro(SEND) = _SPECIALIZE_SEND + _SEND; - op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) { + op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); EXIT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); EXIT_IF(!gen_try_set_executing((PyGenObject *)gen)); @@ -1487,7 +1504,7 @@ dummy_func( macro(SEND_GEN) = unused/1 + - _RECORD_NOS_GEN_FUNC + + _RECORD_3OS_GEN_FUNC + _CHECK_PEP_523 + _SEND_GEN_FRAME + _PUSH_FRAME; @@ -1599,17 +1616,17 @@ dummy_func( macro(END_ASYNC_FOR) = _END_ASYNC_FOR; - tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- none, value)) { + tier1 inst(CLEANUP_THROW, (sub_iter, null_in, last_sent_val, exc_value_st -- none, null_out, value)) { PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); #endif assert(exc_value && PyExceptionInstance_Check(exc_value)); - int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); if (matches) { value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); DECREF_INPUTS(); + null_out = null_in; none = PyStackRef_None; } else { @@ -3327,52 +3344,10 @@ dummy_func( #ifdef Py_STATS _Py_GatherStats_GetIter(iterable); #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - /* Leave iterable on stack and pushed tagged 0 */ - iter = iterable; - DEAD(iterable); - index_or_null = PyStackRef_TagInt(0); - } - else { - /* Pop iterable, and push iterator then NULL */ - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - PyStackRef_CLOSE(iterable); - ERROR_IF(iter_o == NULL); - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - } - } - - inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - /* `iterable` is a coroutine */ - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - /* and it is used in a 'yield from' expression of a - regular generator. */ - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - ERROR_NO_POP(); - } - iter = iterable; - DEAD(iterable); - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - DEAD(iterable); - } - else { - /* `iterable` is not a generator. */ - PyObject *iter_o = PyObject_GetIter(iterable_o); - if (iter_o == NULL) { - ERROR_NO_POP(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - DECREF_INPUTS(); - } + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + DEAD(iterable); + ERROR_IF(PyStackRef_IsError(result)); + iter = result; } // Most members of this family are "secretly" super-instructions. @@ -5849,6 +5824,17 @@ dummy_func( } } + tier2 op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) { + PyObject *obj = PyStackRef_AsPyObjectBorrow(gen); + if (PyGen_Check(obj)) { + PyGenObject *gen_obj = (PyGenObject *)obj; + _PyStackRef func = gen_obj->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } + } + } + tier2 op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) { RECORD_VALUE(PyStackRef_AsPyObjectBorrow(value)); } diff --git a/Python/ceval.c b/Python/ceval.c index 29f81317722a80..eff57778285836 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1165,6 +1165,42 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame) #include "generated_cases.c.h" #endif + +_PyStackRef +_PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from) +{ + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp == &PyTuple_Type || tp == &PyList_Type) { + /* Leave iterable on stack and pushed tagged 0 */ + *index_or_null = PyStackRef_TagInt(0); + return iterable; + } + *index_or_null = PyStackRef_NULL; + if (tp->tp_iter == PyObject_SelfIter) { + return iterable; + } + if (yield_from && tp == &PyCoro_Type) { + assert(yield_from != GET_ITER_YIELD_FROM); + if (yield_from == GET_ITER_YIELD_FROM_CORO_CHECK) { + /* `iterable` is a coroutine and it is used in a 'yield from' + * expression of a regular generator. */ + PyErr_SetString(PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + PyStackRef_CLOSE(iterable); + return PyStackRef_ERROR; + } + return iterable; + } + /* Pop iterable, and push iterator then NULL */ + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + PyStackRef_CLOSE(iterable); + if (iter_o == NULL) { + return PyStackRef_ERROR; + } + return PyStackRef_FromPyObjectSteal(iter_o); +} + #if (defined(__GNUC__) && __GNUC__ >= 10 && !defined(__clang__)) && defined(__x86_64__) /* * gh-129987: The SLP autovectorizer can cause poor code generation for diff --git a/Python/codegen.c b/Python/codegen.c index 5749b615386717..d300d77e0f73b0 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -606,6 +606,7 @@ codegen_unwind_fblock(compiler *c, location *ploc, RETURN_IF_ERROR(codegen_call_exit_with_nones(c, *ploc)); if (info->fb_type == COMPILE_FBLOCK_ASYNC_WITH) { ADDOP_I(c, *ploc, GET_AWAITABLE, 2); + ADDOP(c, *ploc, PUSH_NULL); ADDOP_LOAD_CONST(c, *ploc, Py_None); ADD_YIELD_FROM(c, *ploc, 1); } @@ -2124,7 +2125,7 @@ codegen_for(compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); loc = LOC(s->v.For.iter); - ADDOP(c, loc, GET_ITER); + ADDOP_I(c, loc, GET_ITER, 0); USE_LABEL(c, start); ADDOP_JUMP(c, loc, FOR_ITER, cleanup); @@ -2175,6 +2176,7 @@ codegen_async_for(compiler *c, stmt_ty s) /* SETUP_FINALLY to guard the __anext__ call */ ADDOP_JUMP(c, loc, SETUP_FINALLY, except); ADDOP(c, loc, GET_ANEXT); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); USE_LABEL(c, send); ADD_YIELD_FROM(c, loc, 1); @@ -4540,7 +4542,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc, if (IS_JUMP_TARGET_LABEL(start)) { if (iter_pos != ITERATOR_ON_STACK) { - ADDOP(c, LOC(gen->iter), GET_ITER); + ADDOP_I(c, LOC(gen->iter), GET_ITER, 0); depth += 1; } USE_LABEL(c, start); @@ -4574,7 +4576,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc, NEW_JUMP_TARGET_LABEL(c, unpack_start); NEW_JUMP_TARGET_LABEL(c, unpack_end); VISIT(c, expr, elt->v.Starred.value); - ADDOP(c, elt_loc, GET_ITER); + ADDOP_I(c, elt_loc, GET_ITER, 0); USE_LABEL(c, unpack_start); ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end); ADDOP_YIELD(c, elt_loc); @@ -4686,6 +4688,7 @@ codegen_async_comprehension_generator(compiler *c, location loc, ADDOP_JUMP(c, loc, SETUP_FINALLY, except); ADDOP(c, loc, GET_ANEXT); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); USE_LABEL(c, send); ADD_YIELD_FROM(c, loc, 1); @@ -4716,7 +4719,7 @@ codegen_async_comprehension_generator(compiler *c, location loc, NEW_JUMP_TARGET_LABEL(c, unpack_start); NEW_JUMP_TARGET_LABEL(c, unpack_end); VISIT(c, expr, elt->v.Starred.value); - ADDOP(c, elt_loc, GET_ITER); + ADDOP_I(c, elt_loc, GET_ITER, 0); USE_LABEL(c, unpack_start); ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end); ADDOP_YIELD(c, elt_loc); @@ -5039,6 +5042,7 @@ codegen_comprehension(compiler *c, expr_ty e, int type, if (is_async_comprehension && type != COMP_GENEXP) { ADDOP_I(c, loc, GET_AWAITABLE, 0); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); } @@ -5178,6 +5182,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___AENTER__); ADDOP_I(c, loc, CALL, 0); ADDOP_I(c, loc, GET_AWAITABLE, 1); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); @@ -5214,6 +5219,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) */ RETURN_IF_ERROR(codegen_call_exit_with_nones(c, loc)); ADDOP_I(c, loc, GET_AWAITABLE, 2); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); @@ -5228,6 +5234,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos) ADDOP(c, loc, PUSH_EXC_INFO); ADDOP(c, loc, WITH_EXCEPT_START); ADDOP_I(c, loc, GET_AWAITABLE, 2); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); RETURN_IF_ERROR(codegen_with_except_finish(c, cleanup)); @@ -5408,13 +5415,14 @@ codegen_visit_expr(compiler *c, expr_ty e) return _PyCompile_Error(c, loc, "'yield from' inside async function"); } VISIT(c, expr, e->v.YieldFrom.value); - ADDOP(c, loc, GET_YIELD_FROM_ITER); + ADDOP_I(c, loc, GET_ITER, GET_ITER_YIELD_FROM); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 0); break; case Await_kind: VISIT(c, expr, e->v.Await.value); ADDOP_I(c, loc, GET_AWAITABLE, 0); + ADDOP(c, loc, PUSH_NULL); ADDOP_LOAD_CONST(c, loc, Py_None); ADD_YIELD_FROM(c, loc, 1); break; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index d89d512fd5630a..92d6d0772f8d33 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -2602,17 +2602,21 @@ break; } - case _END_SEND_r21: { - CHECK_CURRENT_CACHED_VALUES(2); + case _END_SEND_r31: { + CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef value; + _PyStackRef index_or_null; _PyStackRef receiver; _PyStackRef val; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; - value = _stack_item_1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + index_or_null = _stack_item_1; receiver = _stack_item_0; val = value; + (void)index_or_null; stack_pointer[0] = val; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -7123,30 +7127,33 @@ /* _SEND is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ - case _SEND_GEN_FRAME_r22: { - CHECK_CURRENT_CACHED_VALUES(2); + case _SEND_GEN_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef v; _PyStackRef receiver; _PyStackRef gen_frame; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; oparg = CURRENT_OPARG(); - v = _stack_item_1; + v = _stack_item_2; receiver = _stack_item_0; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UOP_STAT_INC(uopcode, miss); - _tos_cache1 = v; + _tos_cache2 = v; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } if (!gen_try_set_executing((PyGenObject *)gen)) { UOP_STAT_INC(uopcode, miss); - _tos_cache1 = v; + _tos_cache2 = v; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } STAT_INC(SEND, hit); @@ -7158,10 +7165,10 @@ frame->return_offset = (uint16_t)( 2u + oparg); pushed_frame->previous = frame; gen_frame = PyStackRef_Wrap(pushed_frame); - _tos_cache1 = gen_frame; + _tos_cache2 = gen_frame; + _tos_cache1 = _stack_item_1; _tos_cache0 = receiver; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(2); + SET_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -11485,98 +11492,30 @@ _PyStackRef iter; _PyStackRef index_or_null; _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); iterable = _stack_item_0; #ifdef Py_STATS + _Py_GatherStats_GetIter(iterable); + #endif stack_pointer[0] = iterable; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_GatherStats_GetIter(iterable); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); } + iter = result; _tos_cache1 = index_or_null; _tos_cache0 = iter; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _GET_YIELD_FROM_ITER_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef iterable; - _PyStackRef iter; - _PyStackRef _stack_item_0 = _tos_cache0; - iterable = _stack_item_0; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - stack_pointer[0] = iterable; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - } - _tos_cache0 = iter; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 04234a6025468e..f446a87ee69432 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -2884,7 +2884,6 @@ optimize_load_fast(cfg_builder *g) case GET_ANEXT: case GET_ITER: case GET_LEN: - case GET_YIELD_FROM_ITER: case IMPORT_FROM: case MATCH_KEYS: case MATCH_MAPPING: @@ -2919,7 +2918,16 @@ optimize_load_fast(cfg_builder *g) break; } - case END_SEND: + case END_SEND: { + assert(_PyOpcode_num_popped(opcode, oparg) == 3); + assert(_PyOpcode_num_pushed(opcode, oparg) == 1); + ref tos = ref_stack_pop(&refs); + ref_stack_pop(&refs); + ref_stack_pop(&refs); + PUSH_REF(tos.instr, tos.local); + break; + } + case SET_FUNCTION_ATTRIBUTE: { assert(_PyOpcode_num_popped(opcode, oparg) == 2); assert(_PyOpcode_num_pushed(opcode, oparg) == 1); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a66d6ccff2d82d..c7b47b431339a5 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -4737,13 +4737,16 @@ next_instr += 1; INSTRUCTION_STATS(CLEANUP_THROW); _PyStackRef sub_iter; + _PyStackRef null_in; _PyStackRef last_sent_val; _PyStackRef exc_value_st; _PyStackRef none; + _PyStackRef null_out; _PyStackRef value; exc_value_st = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; - sub_iter = stack_pointer[-3]; + null_in = stack_pointer[-3]; + sub_iter = stack_pointer[-4]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #if !_Py_TAIL_CALL_INTERP assert(throwflag); @@ -4757,7 +4760,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef tmp = sub_iter; sub_iter = value; - stack_pointer[-3] = sub_iter; + stack_pointer[-4] = sub_iter; PyStackRef_CLOSE(tmp); tmp = exc_value_st; exc_value_st = PyStackRef_NULL; @@ -4767,9 +4770,14 @@ last_sent_val = PyStackRef_NULL; stack_pointer[-2] = last_sent_val; PyStackRef_CLOSE(tmp); + tmp = null_in; + null_in = PyStackRef_NULL; + stack_pointer[-3] = null_in; + PyStackRef_XCLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; + stack_pointer += -4; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + null_out = null_in; none = PyStackRef_None; } else { @@ -4779,8 +4787,9 @@ JUMP_TO_LABEL(exception_unwind); } stack_pointer[0] = none; - stack_pointer[1] = value; - stack_pointer += 2; + stack_pointer[1] = null_out; + stack_pointer[2] = value; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -5665,13 +5674,16 @@ next_instr += 1; INSTRUCTION_STATS(END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -6291,31 +6303,15 @@ _PyStackRef index_or_null; iterable = stack_pointer[-1]; #ifdef Py_STATS - _PyFrame_SetStackPointer(frame, stack_pointer); _Py_GatherStats_GetIter(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); #endif - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - stack_pointer += 1; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); } + iter = result; stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; @@ -6351,51 +6347,6 @@ DISPATCH(); } - TARGET(GET_YIELD_FROM_ITER) { - #if _Py_TAIL_CALL_INTERP - int opcode = GET_YIELD_FROM_ITER; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(GET_YIELD_FROM_ITER); - _PyStackRef iterable; - _PyStackRef iter; - iterable = stack_pointer[-1]; - PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); - if (PyCoro_CheckExact(iterable_o)) { - if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyErr_SetString(tstate, PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - iter = iterable; - } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - stack_pointer[-1] = iter; - DISPATCH(); - } - TARGET(IMPORT_FROM) { #if _Py_TAIL_CALL_INTERP int opcode = IMPORT_FROM; @@ -6999,10 +6950,12 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_END_SEND); _PyStackRef receiver; + _PyStackRef index_or_null; _PyStackRef value; _PyStackRef val; value = stack_pointer[-1]; - receiver = stack_pointer[-2]; + index_or_null = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7013,8 +6966,9 @@ } } val = value; - stack_pointer[-2] = val; - stack_pointer += -1; + (void)index_or_null; + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(receiver); @@ -10730,11 +10684,12 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef receiver; + _PyStackRef null_or_index; _PyStackRef v; _PyStackRef retval; // _SPECIALIZE_SEND { - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION @@ -10752,6 +10707,7 @@ // _SEND { v = stack_pointer[-1]; + null_or_index = stack_pointer[-2]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); @@ -10772,53 +10728,66 @@ gen_frame->previous = frame; DISPATCH_INLINED(gen_frame); } - if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { + if (!PyStackRef_IsNull(null_or_index)) { _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg); + stack_pointer[-2] = null_or_index; + DISPATCH(); + } + retval = item; } else { - _PyFrame_SetStackPointer(frame, stack_pointer); - retval_o = PyObject_CallMethodOneArg(receiver_o, - &_Py_ID(send), - PyStackRef_AsPyObjectBorrow(v)); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - if (retval_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (matches) { + if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_MonitorRaise(tstate, frame, this_instr); + retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); stack_pointer = _PyFrame_GetStackPointer(frame); } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = _PyGen_FetchStopIterationValue(&retval_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err == 0) { - assert(retval_o != NULL); - JUMPBY(oparg); - } else { - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(v); + retval_o = PyObject_CallMethodOneArg(receiver_o, + &_Py_ID(send), + PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); } + if (retval_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_MonitorRaise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyGen_FetchStopIterationValue(&retval_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err == 0) { + assert(retval_o != NULL); + JUMPBY(oparg); + } + else { + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + } + retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + stack_pointer[-2] = null_or_index; + stack_pointer[-1] = retval; _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); stack_pointer = _PyFrame_GetStackPointer(frame); - retval = PyStackRef_FromPyObjectSteal(retval_o); } - stack_pointer[0] = retval; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } @@ -10849,7 +10818,7 @@ // _SEND_GEN_FRAME { v = stack_pointer[-1]; - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { UPDATE_MISS_STATS(SEND); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index def462bacec176..48fe9c14f4e2dd 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -16,10 +16,8 @@ static void *opcode_targets_table[256] = { &&TARGET_FORMAT_WITH_SPEC, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, - &&TARGET_GET_ITER, - &&TARGET_RESERVED, &&TARGET_GET_LEN, - &&TARGET_GET_YIELD_FROM_ITER, + &&TARGET_RESERVED, &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, @@ -72,6 +70,7 @@ static void *opcode_targets_table[256] = { &&TARGET_EXTENDED_ARG, &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, + &&TARGET_GET_ITER, &&TARGET_IMPORT_FROM, &&TARGET_IMPORT_NAME, &&TARGET_IS_OP, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -379,7 +379,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -626,7 +626,6 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS); @@ -868,7 +867,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, [GET_LEN] = _TAIL_CALL_GET_LEN, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, [INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL, @@ -1002,6 +1000,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1126,7 +1125,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, - [GET_YIELD_FROM_ITER] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, [INSTRUMENTED_CALL] = _TAIL_CALL_TRACE_RECORD, @@ -1260,6 +1258,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 7ca33e9e77fb74..1674a0b414c89d 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1031,7 +1031,7 @@ dummy_func(void) { gen_frame = PyJitRef_WrapInvalid(new_frame); } - op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) { + op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) { _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0); if (new_frame == NULL) { ctx->done = true; @@ -1767,6 +1767,12 @@ dummy_func(void) { sym_set_recorded_gen_func(nos, func); } + op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) { + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(gen, func); + } + op(_GUARD_IP__PUSH_FRAME, (ip/4 --)) { (void)ip; stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index df6368ca8ce011..dc9b1435f50340 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -209,9 +209,9 @@ case _END_SEND: { JitOptRef val; val = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-2] = val; - stack_pointer += -1; + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = val; + stack_pointer += -2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -1385,7 +1385,7 @@ JitOptRef receiver; JitOptRef gen_frame; v = stack_pointer[-1]; - receiver = stack_pointer[-2]; + receiver = stack_pointer[-3]; _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0); if (new_frame == NULL) { ctx->done = true; @@ -2730,13 +2730,6 @@ break; } - case _GET_YIELD_FROM_ITER: { - JitOptRef iter; - iter = sym_new_not_null(ctx); - stack_pointer[-1] = iter; - break; - } - /* _FOR_ITER is not a viable micro-op for tier 2 */ case _FOR_ITER_TIER_TWO: { @@ -4383,6 +4376,15 @@ break; } + case _RECORD_3OS_GEN_FUNC: { + JitOptRef gen; + gen = stack_pointer[-3]; + PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; + assert(func == NULL || PyFunction_Check(func)); + sym_set_recorded_gen_func(gen, func); + break; + } + case _RECORD_4OS: { JitOptRef value; value = stack_pointer[-4]; diff --git a/Python/record_functions.c.h b/Python/record_functions.c.h index 64cafcb326e111..958cdab34c8ff4 100644 --- a/Python/record_functions.c.h +++ b/Python/record_functions.c.h @@ -41,6 +41,20 @@ void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackR } } +void _PyOpcode_RecordFunction_3OS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef gen; + gen = stack_pointer[-3]; + PyObject *obj = PyStackRef_AsPyObjectBorrow(gen); + if (PyGen_Check(obj)) { + PyGenObject *gen_obj = (PyGenObject *)obj; + _PyStackRef func = gen_obj->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); + } + } +} + void _PyOpcode_RecordFunction_4OS(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { _PyStackRef value; value = stack_pointer[-4]; @@ -73,14 +87,15 @@ void _PyOpcode_RecordFunction_CODE(_PyInterpreterFrame *frame, _PyStackRef *stac #define _RECORD_TOS_TYPE_INDEX 1 #define _RECORD_NOS_INDEX 2 -#define _RECORD_NOS_GEN_FUNC_INDEX 3 -#define _RECORD_CALLABLE_INDEX 4 -#define _RECORD_BOUND_METHOD_INDEX 5 -#define _RECORD_4OS_INDEX 6 +#define _RECORD_3OS_GEN_FUNC_INDEX 3 +#define _RECORD_NOS_GEN_FUNC_INDEX 4 +#define _RECORD_CALLABLE_INDEX 5 +#define _RECORD_BOUND_METHOD_INDEX 6 +#define _RECORD_4OS_INDEX 7 const uint8_t _PyOpcode_RecordFunctionIndices[256] = { [TO_BOOL_ALWAYS_TRUE] = _RECORD_TOS_TYPE_INDEX, [BINARY_OP_SUBSCR_GETITEM] = _RECORD_NOS_INDEX, - [SEND_GEN] = _RECORD_NOS_GEN_FUNC_INDEX, + [SEND_GEN] = _RECORD_3OS_GEN_FUNC_INDEX, [LOAD_ATTR_INSTANCE_VALUE] = _RECORD_TOS_TYPE_INDEX, [LOAD_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX, [LOAD_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX, @@ -110,10 +125,11 @@ const uint8_t _PyOpcode_RecordFunctionIndices[256] = { [CALL_EX_PY] = _RECORD_4OS_INDEX, }; -const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[7] = { +const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[8] = { [0] = NULL, [_RECORD_TOS_TYPE_INDEX] = _PyOpcode_RecordFunction_TOS_TYPE, [_RECORD_NOS_INDEX] = _PyOpcode_RecordFunction_NOS, + [_RECORD_3OS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_3OS_GEN_FUNC, [_RECORD_NOS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_NOS_GEN_FUNC, [_RECORD_CALLABLE_INDEX] = _PyOpcode_RecordFunction_CALLABLE, [_RECORD_BOUND_METHOD_INDEX] = _PyOpcode_RecordFunction_BOUND_METHOD, diff --git a/Python/specialize.c b/Python/specialize.c index 4ef8b27795650c..09ec25767a4c3f 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -41,9 +41,24 @@ do { \ # define SPECIALIZATION_FAIL(opcode, kind) ((void)0) #endif // Py_STATS +static void +fixup_getiter(_Py_CODEUNIT *instruction, int flags) +{ + // Compiler can't know if types.coroutine() will be called, + // so fix up here + if (instruction->op.arg) { + if (flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) { + instruction->op.arg = GET_ITER_YIELD_FROM_NO_CHECK; + } + else { + instruction->op.arg = GET_ITER_YIELD_FROM_CORO_CHECK; + } + } +} + // Initialize warmup counters and optimize instructions. This cannot fail. void -_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters) +_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters, int flags) { #if ENABLE_SPECIALIZATION _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter; @@ -66,6 +81,9 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters opcode = instructions[i].op.code; int caches = _PyOpcode_Caches[opcode]; oparg = (oparg << 8) | instructions[i].op.arg; + if (opcode == GET_ITER) { + fixup_getiter(&instructions[i], flags); + } if (caches) { // The initial value depends on the opcode switch (opcode) { @@ -91,6 +109,13 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters oparg = 0; } } + #else + for (Py_ssize_t i = 0; i < size-1; i++) { + if (instructions[i].op.code == GET_ITER) { + fixup_getiter(&instructions[i], flags); + } + i += _PyOpcode_Caches[opcode]; + } #endif /* ENABLE_SPECIALIZATION */ } diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 89f843644329ec..7bb4d725d51a4d 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -714,7 +714,7 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "trigger_backoff_counter", "_PyThreadState_PopCStackRefSteal", "doesnt_escape", - + "_Py_GatherStats_GetIter", )