GH-120507: Lower the BEFORE_WITH and BEFORE_ASYNC_WITH instructions. (#120640)

* Remove BEFORE_WITH and BEFORE_ASYNC_WITH instructions.

* Add LOAD_SPECIAL instruction

* Reimplement `with` and `async with` statements using LOAD_SPECIAL
This commit is contained in:
Mark Shannon 2024-06-18 12:17:46 +01:00 committed by GitHub
parent 73dc1c678e
commit 9cefcc0ee7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 663 additions and 651 deletions

View file

@ -133,6 +133,13 @@ PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate);
#define FVS_MASK 0x4
#define FVS_HAVE_SPEC 0x4
/* Special methods used by LOAD_SPECIAL */
#define SPECIAL___ENTER__ 0
#define SPECIAL___EXIT__ 1
#define SPECIAL___AENTER__ 2
#define SPECIAL___AEXIT__ 3
#define SPECIAL_MAX 3
#ifndef Py_LIMITED_API
# define Py_CPYTHON_CEVAL_H
# include "cpython/ceval.h"

View file

@ -245,6 +245,13 @@ typedef PyObject *(*conversion_func)(PyObject *);
PyAPI_DATA(const binaryfunc) _PyEval_BinaryOps[];
PyAPI_DATA(const conversion_func) _PyEval_ConversionFuncs[];
typedef struct _special_method {
PyObject *name;
const char *error;
} _Py_SpecialMethod;
PyAPI_DATA(const _Py_SpecialMethod) _Py_SpecialMethods[];
PyAPI_FUNC(int) _PyEval_CheckExceptStarTypeValid(PyThreadState *tstate, PyObject* right);
PyAPI_FUNC(int) _PyEval_CheckExceptTypeValid(PyThreadState *tstate, PyObject* right);
PyAPI_FUNC(int) _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type, PyObject **match, PyObject **rest);

View file

@ -709,6 +709,7 @@ extern int _PyObject_IsInstanceDictEmpty(PyObject *);
// Export for 'math' shared extension
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecial(PyObject *, PyObject *);
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null);
extern int _PyObject_IsAbstract(PyObject *);

View file

@ -33,10 +33,6 @@ extern int _PyOpcode_num_popped(int opcode, int oparg);
#ifdef NEED_OPCODE_METADATA
int _PyOpcode_num_popped(int opcode, int oparg) {
switch(opcode) {
case BEFORE_ASYNC_WITH:
return 1;
case BEFORE_WITH:
return 1;
case BINARY_OP:
return 2;
case BINARY_OP_ADD_FLOAT:
@ -331,6 +327,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 0;
case LOAD_NAME:
return 0;
case LOAD_SPECIAL:
return 1;
case LOAD_SUPER_ATTR:
return 3;
case LOAD_SUPER_ATTR_ATTR:
@ -468,7 +466,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
case UNPACK_SEQUENCE_TWO_TUPLE:
return 1;
case WITH_EXCEPT_START:
return 4;
return 5;
case YIELD_VALUE:
return 1;
default:
@ -482,10 +480,6 @@ extern int _PyOpcode_num_pushed(int opcode, int oparg);
#ifdef NEED_OPCODE_METADATA
int _PyOpcode_num_pushed(int opcode, int oparg) {
switch(opcode) {
case BEFORE_ASYNC_WITH:
return 2;
case BEFORE_WITH:
return 2;
case BINARY_OP:
return 1;
case BINARY_OP_ADD_FLOAT:
@ -780,6 +774,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
return 1;
case LOAD_NAME:
return 1;
case LOAD_SPECIAL:
return 2;
case LOAD_SUPER_ATTR:
return 1 + (oparg & 1);
case LOAD_SUPER_ATTR_ATTR:
@ -917,7 +913,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case UNPACK_SEQUENCE_TWO_TUPLE:
return 2;
case WITH_EXCEPT_START:
return 5;
return 6;
case YIELD_VALUE:
return 1;
default:
@ -992,8 +988,6 @@ struct opcode_metadata {
extern const struct opcode_metadata _PyOpcode_opcode_metadata[264];
#ifdef NEED_OPCODE_METADATA
const struct opcode_metadata _PyOpcode_opcode_metadata[264] = {
[BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[BEFORE_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG },
[BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
@ -1138,6 +1132,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[264] = {
[LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
[LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@ -1327,6 +1322,7 @@ _PyOpcode_macro_expansion[256] = {
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } },
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } },
[LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, 0, 0 } } },
[LOAD_SPECIAL] = { .nuops = 1, .uops = { { _LOAD_SPECIAL, 0, 0 } } },
[LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, 0, 0 } } },
[LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_METHOD, 0, 0 } } },
[MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, 0, 0 } } },
@ -1391,8 +1387,6 @@ _PyOpcode_macro_expansion[256] = {
extern const char *_PyOpcode_OpName[264];
#ifdef NEED_OPCODE_METADATA
const char *_PyOpcode_OpName[264] = {
[BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH",
[BEFORE_WITH] = "BEFORE_WITH",
[BINARY_OP] = "BINARY_OP",
[BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT",
[BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT",
@ -1541,6 +1535,7 @@ const char *_PyOpcode_OpName[264] = {
[LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
[LOAD_LOCALS] = "LOAD_LOCALS",
[LOAD_NAME] = "LOAD_NAME",
[LOAD_SPECIAL] = "LOAD_SPECIAL",
[LOAD_SUPER_ATTR] = "LOAD_SUPER_ATTR",
[LOAD_SUPER_ATTR_ATTR] = "LOAD_SUPER_ATTR_ATTR",
[LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD",
@ -1642,8 +1637,6 @@ const uint8_t _PyOpcode_Caches[256] = {
extern const uint8_t _PyOpcode_Deopt[256];
#ifdef NEED_OPCODE_METADATA
const uint8_t _PyOpcode_Deopt[256] = {
[BEFORE_ASYNC_WITH] = BEFORE_ASYNC_WITH,
[BEFORE_WITH] = BEFORE_WITH,
[BINARY_OP] = BINARY_OP,
[BINARY_OP_ADD_FLOAT] = BINARY_OP,
[BINARY_OP_ADD_INT] = BINARY_OP,
@ -1789,6 +1782,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
[LOAD_GLOBAL_MODULE] = LOAD_GLOBAL,
[LOAD_LOCALS] = LOAD_LOCALS,
[LOAD_NAME] = LOAD_NAME,
[LOAD_SPECIAL] = LOAD_SPECIAL,
[LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,
[LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR,
[LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR,
@ -1859,6 +1853,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
#endif // NEED_OPCODE_METADATA
#define EXTRA_CASES \
case 118: \
case 119: \
case 120: \
case 121: \

View file

@ -11,8 +11,6 @@ extern "C" {
#define _EXIT_TRACE 300
#define _SET_IP 301
#define _BEFORE_ASYNC_WITH BEFORE_ASYNC_WITH
#define _BEFORE_WITH BEFORE_WITH
#define _BINARY_OP 302
#define _BINARY_OP_ADD_FLOAT 303
#define _BINARY_OP_ADD_INT 304
@ -215,6 +213,7 @@ extern "C" {
#define _LOAD_GLOBAL_MODULE 425
#define _LOAD_LOCALS LOAD_LOCALS
#define _LOAD_NAME LOAD_NAME
#define _LOAD_SPECIAL LOAD_SPECIAL
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
#define _MAKE_CELL MAKE_CELL

View file

@ -182,6 +182,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG,
[_ITER_NEXT_RANGE] = HAS_ERROR_FLAG,
[_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
[_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_PUSH_EXC_INFO] = 0,
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_DEOPT_FLAG,
@ -442,6 +443,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS",
[_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE",
[_LOAD_LOCALS] = "_LOAD_LOCALS",
[_LOAD_SPECIAL] = "_LOAD_SPECIAL",
[_LOAD_SUPER_ATTR_ATTR] = "_LOAD_SUPER_ATTR_ATTR",
[_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD",
[_MAKE_CELL] = "_MAKE_CELL",
@ -840,8 +842,10 @@ int _PyUop_num_popped(int opcode, int oparg)
return 1;
case _FOR_ITER_GEN_FRAME:
return 1;
case _LOAD_SPECIAL:
return 1;
case _WITH_EXCEPT_START:
return 4;
return 5;
case _PUSH_EXC_INFO:
return 1;
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT:

233
Include/opcode_ids.h generated
View file

@ -11,124 +11,123 @@ extern "C" {
/* Instruction opcodes for compiled code */
#define CACHE 0
#define BEFORE_ASYNC_WITH 1
#define BEFORE_WITH 2
#define BINARY_SLICE 1
#define BINARY_SUBSCR 2
#define BINARY_OP_INPLACE_ADD_UNICODE 3
#define BINARY_SLICE 4
#define BINARY_SUBSCR 5
#define CHECK_EG_MATCH 6
#define CHECK_EXC_MATCH 7
#define CLEANUP_THROW 8
#define DELETE_SUBSCR 9
#define END_ASYNC_FOR 10
#define END_FOR 11
#define END_SEND 12
#define EXIT_INIT_CHECK 13
#define FORMAT_SIMPLE 14
#define FORMAT_WITH_SPEC 15
#define GET_AITER 16
#define CHECK_EG_MATCH 4
#define CHECK_EXC_MATCH 5
#define CLEANUP_THROW 6
#define DELETE_SUBSCR 7
#define END_ASYNC_FOR 8
#define END_FOR 9
#define END_SEND 10
#define EXIT_INIT_CHECK 11
#define FORMAT_SIMPLE 12
#define FORMAT_WITH_SPEC 13
#define GET_AITER 14
#define GET_ANEXT 15
#define GET_ITER 16
#define RESERVED 17
#define GET_ANEXT 18
#define GET_ITER 19
#define GET_LEN 20
#define GET_YIELD_FROM_ITER 21
#define INTERPRETER_EXIT 22
#define LOAD_BUILD_CLASS 23
#define LOAD_LOCALS 24
#define MAKE_FUNCTION 25
#define MATCH_KEYS 26
#define MATCH_MAPPING 27
#define MATCH_SEQUENCE 28
#define NOP 29
#define POP_EXCEPT 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_CONST_KEY_MAP 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_FUNCTION_EX 53
#define CALL_INTRINSIC_1 54
#define CALL_INTRINSIC_2 55
#define CALL_KW 56
#define COMPARE_OP 57
#define CONTAINS_OP 58
#define CONVERT_VALUE 59
#define COPY 60
#define COPY_FREE_VARS 61
#define DELETE_ATTR 62
#define DELETE_DEREF 63
#define DELETE_FAST 64
#define DELETE_GLOBAL 65
#define DELETE_NAME 66
#define DICT_MERGE 67
#define DICT_UPDATE 68
#define ENTER_EXECUTOR 69
#define EXTENDED_ARG 70
#define FOR_ITER 71
#define GET_AWAITABLE 72
#define IMPORT_FROM 73
#define IMPORT_NAME 74
#define IS_OP 75
#define JUMP_BACKWARD 76
#define JUMP_BACKWARD_NO_INTERRUPT 77
#define JUMP_FORWARD 78
#define LIST_APPEND 79
#define LIST_EXTEND 80
#define LOAD_ATTR 81
#define LOAD_COMMON_CONSTANT 82
#define LOAD_CONST 83
#define LOAD_DEREF 84
#define LOAD_FAST 85
#define LOAD_FAST_AND_CLEAR 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_SUPER_ATTR 93
#define MAKE_CELL 94
#define MAP_ADD 95
#define MATCH_CLASS 96
#define POP_JUMP_IF_FALSE 97
#define POP_JUMP_IF_NONE 98
#define POP_JUMP_IF_NOT_NONE 99
#define POP_JUMP_IF_TRUE 100
#define RAISE_VARARGS 101
#define RERAISE 102
#define RETURN_CONST 103
#define SEND 104
#define SET_ADD 105
#define SET_FUNCTION_ATTRIBUTE 106
#define SET_UPDATE 107
#define STORE_ATTR 108
#define STORE_DEREF 109
#define STORE_FAST 110
#define STORE_FAST_LOAD_FAST 111
#define STORE_FAST_STORE_FAST 112
#define STORE_GLOBAL 113
#define STORE_NAME 114
#define SWAP 115
#define UNPACK_EX 116
#define UNPACK_SEQUENCE 117
#define YIELD_VALUE 118
#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 POP_EXCEPT 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_CONST_KEY_MAP 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_FUNCTION_EX 51
#define CALL_INTRINSIC_1 52
#define CALL_INTRINSIC_2 53
#define CALL_KW 54
#define COMPARE_OP 55
#define CONTAINS_OP 56
#define CONVERT_VALUE 57
#define COPY 58
#define COPY_FREE_VARS 59
#define DELETE_ATTR 60
#define DELETE_DEREF 61
#define DELETE_FAST 62
#define DELETE_GLOBAL 63
#define DELETE_NAME 64
#define DICT_MERGE 65
#define DICT_UPDATE 66
#define ENTER_EXECUTOR 67
#define EXTENDED_ARG 68
#define FOR_ITER 69
#define GET_AWAITABLE 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_CHECK 85
#define LOAD_FAST_LOAD_FAST 86
#define LOAD_FROM_DICT_OR_DEREF 87
#define LOAD_FROM_DICT_OR_GLOBALS 88
#define LOAD_GLOBAL 89
#define LOAD_NAME 90
#define LOAD_SPECIAL 91
#define LOAD_SUPER_ATTR 92
#define MAKE_CELL 93
#define MAP_ADD 94
#define MATCH_CLASS 95
#define POP_JUMP_IF_FALSE 96
#define POP_JUMP_IF_NONE 97
#define POP_JUMP_IF_NOT_NONE 98
#define POP_JUMP_IF_TRUE 99
#define RAISE_VARARGS 100
#define RERAISE 101
#define RETURN_CONST 102
#define SEND 103
#define SET_ADD 104
#define SET_FUNCTION_ATTRIBUTE 105
#define SET_UPDATE 106
#define STORE_ATTR 107
#define STORE_DEREF 108
#define STORE_FAST 109
#define STORE_FAST_LOAD_FAST 110
#define STORE_FAST_STORE_FAST 111
#define STORE_GLOBAL 112
#define STORE_NAME 113
#define SWAP 114
#define UNPACK_EX 115
#define UNPACK_SEQUENCE 116
#define YIELD_VALUE 117
#define RESUME 149
#define BINARY_OP_ADD_FLOAT 150
#define BINARY_OP_ADD_INT 151
@ -231,7 +230,7 @@ extern "C" {
#define SETUP_WITH 262
#define STORE_FAST_MAYBE_NULL 263
#define HAVE_ARGUMENT 43
#define HAVE_ARGUMENT 41
#define MIN_INSTRUMENTED_OPCODE 236
#ifdef __cplusplus