mirror of https://github.com/python/cpython
bpo-45636: Merge all numeric operators (GH-29482)
This commit is contained in:
parent
1cbaa505d0
commit
9178f533ff
|
@ -406,156 +406,29 @@ result back on the stack.
|
||||||
.. versionadded:: 3.5
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
|
||||||
**Binary operations**
|
**Binary and in-place operations**
|
||||||
|
|
||||||
Binary operations remove the top of the stack (TOS) and the second top-most
|
Binary operations remove the top of the stack (TOS) and the second top-most
|
||||||
stack item (TOS1) from the stack. They perform the operation, and put the
|
stack item (TOS1) from the stack. They perform the operation, and put the
|
||||||
result back on the stack.
|
result back on the stack.
|
||||||
|
|
||||||
.. opcode:: BINARY_POWER
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 ** TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_MULTIPLY
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 * TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_MATRIX_MULTIPLY
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 @ TOS``.
|
|
||||||
|
|
||||||
.. versionadded:: 3.5
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_FLOOR_DIVIDE
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 // TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_TRUE_DIVIDE
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 / TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_MODULO
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 % TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_ADD
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 + TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_SUBTRACT
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 - TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_SUBSCR
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1[TOS]``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_LSHIFT
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 << TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_RSHIFT
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 >> TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_AND
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 & TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_XOR
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 ^ TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BINARY_OR
|
|
||||||
|
|
||||||
Implements ``TOS = TOS1 | TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
**In-place operations**
|
|
||||||
|
|
||||||
In-place operations are like binary operations, in that they remove TOS and
|
In-place operations are like binary operations, in that they remove TOS and
|
||||||
TOS1, and push the result back on the stack, but the operation is done in-place
|
TOS1, and push the result back on the stack, but the operation is done in-place
|
||||||
when TOS1 supports it, and the resulting TOS may be (but does not have to be)
|
when TOS1 supports it, and the resulting TOS may be (but does not have to be)
|
||||||
the original TOS1.
|
the original TOS1.
|
||||||
|
|
||||||
.. opcode:: INPLACE_POWER
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 ** TOS``.
|
.. opcode:: BINARY_OP (op)
|
||||||
|
|
||||||
|
Implements the binary and in-place operators (depending on the value of
|
||||||
|
*op*).
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_MULTIPLY
|
.. opcode:: BINARY_SUBSCR
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 * TOS``.
|
Implements ``TOS = TOS1[TOS]``.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_MATRIX_MULTIPLY
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 @ TOS``.
|
|
||||||
|
|
||||||
.. versionadded:: 3.5
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_FLOOR_DIVIDE
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 // TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_TRUE_DIVIDE
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 / TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_MODULO
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 % TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_ADD
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 + TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_SUBTRACT
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 - TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_LSHIFT
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 << TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_RSHIFT
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 >> TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_AND
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 & TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_XOR
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 ^ TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: INPLACE_OR
|
|
||||||
|
|
||||||
Implements in-place ``TOS = TOS1 | TOS``.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: STORE_SUBSCR
|
.. opcode:: STORE_SUBSCR
|
||||||
|
|
|
@ -315,6 +315,9 @@ Optimizations
|
||||||
CPython bytecode changes
|
CPython bytecode changes
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
* Replaced all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single
|
||||||
|
:opcode:`BINARY_OP` implementation.
|
||||||
|
|
||||||
* Added a new :opcode:`CALL_METHOD_KW` opcode. Calls a method in a similar
|
* Added a new :opcode:`CALL_METHOD_KW` opcode. Calls a method in a similar
|
||||||
fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments. Works
|
fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments. Works
|
||||||
in tandem with :opcode:`LOAD_METHOD`.
|
in tandem with :opcode:`LOAD_METHOD`.
|
||||||
|
|
|
@ -267,9 +267,9 @@ int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *nam
|
||||||
int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
|
int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
|
||||||
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
|
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
|
||||||
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
|
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
|
||||||
int _Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr);
|
|
||||||
int _Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr);
|
|
||||||
int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
|
int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
|
||||||
|
void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||||
|
SpecializedCacheEntry *cache);
|
||||||
|
|
||||||
#define PRINT_SPECIALIZATION_STATS 0
|
#define PRINT_SPECIALIZATION_STATS 0
|
||||||
#define PRINT_SPECIALIZATION_STATS_DETAILED 0
|
#define PRINT_SPECIALIZATION_STATS_DETAILED 0
|
||||||
|
|
|
@ -6,178 +6,152 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Instruction opcodes for compiled code */
|
/* Instruction opcodes for compiled code */
|
||||||
#define POP_TOP 1
|
#define POP_TOP 1
|
||||||
#define ROT_TWO 2
|
#define ROT_TWO 2
|
||||||
#define ROT_THREE 3
|
#define ROT_THREE 3
|
||||||
#define DUP_TOP 4
|
#define DUP_TOP 4
|
||||||
#define DUP_TOP_TWO 5
|
#define DUP_TOP_TWO 5
|
||||||
#define ROT_FOUR 6
|
#define ROT_FOUR 6
|
||||||
#define NOP 9
|
#define NOP 9
|
||||||
#define UNARY_POSITIVE 10
|
#define UNARY_POSITIVE 10
|
||||||
#define UNARY_NEGATIVE 11
|
#define UNARY_NEGATIVE 11
|
||||||
#define UNARY_NOT 12
|
#define UNARY_NOT 12
|
||||||
#define UNARY_INVERT 15
|
#define UNARY_INVERT 15
|
||||||
#define BINARY_MATRIX_MULTIPLY 16
|
#define BINARY_SUBSCR 25
|
||||||
#define INPLACE_MATRIX_MULTIPLY 17
|
#define GET_LEN 30
|
||||||
#define BINARY_POWER 19
|
#define MATCH_MAPPING 31
|
||||||
#define BINARY_MULTIPLY 20
|
#define MATCH_SEQUENCE 32
|
||||||
#define BINARY_MODULO 22
|
#define MATCH_KEYS 33
|
||||||
#define BINARY_ADD 23
|
#define PUSH_EXC_INFO 35
|
||||||
#define BINARY_SUBTRACT 24
|
#define POP_EXCEPT_AND_RERAISE 37
|
||||||
#define BINARY_SUBSCR 25
|
#define WITH_EXCEPT_START 49
|
||||||
#define BINARY_FLOOR_DIVIDE 26
|
#define GET_AITER 50
|
||||||
#define BINARY_TRUE_DIVIDE 27
|
#define GET_ANEXT 51
|
||||||
#define INPLACE_FLOOR_DIVIDE 28
|
#define BEFORE_ASYNC_WITH 52
|
||||||
#define INPLACE_TRUE_DIVIDE 29
|
#define BEFORE_WITH 53
|
||||||
#define GET_LEN 30
|
#define END_ASYNC_FOR 54
|
||||||
#define MATCH_MAPPING 31
|
#define STORE_SUBSCR 60
|
||||||
#define MATCH_SEQUENCE 32
|
#define DELETE_SUBSCR 61
|
||||||
#define MATCH_KEYS 33
|
#define GET_ITER 68
|
||||||
#define PUSH_EXC_INFO 35
|
#define GET_YIELD_FROM_ITER 69
|
||||||
#define POP_EXCEPT_AND_RERAISE 37
|
#define PRINT_EXPR 70
|
||||||
#define WITH_EXCEPT_START 49
|
#define LOAD_BUILD_CLASS 71
|
||||||
#define GET_AITER 50
|
#define YIELD_FROM 72
|
||||||
#define GET_ANEXT 51
|
#define GET_AWAITABLE 73
|
||||||
#define BEFORE_ASYNC_WITH 52
|
#define LOAD_ASSERTION_ERROR 74
|
||||||
#define BEFORE_WITH 53
|
#define LIST_TO_TUPLE 82
|
||||||
#define END_ASYNC_FOR 54
|
#define RETURN_VALUE 83
|
||||||
#define INPLACE_ADD 55
|
#define IMPORT_STAR 84
|
||||||
#define INPLACE_SUBTRACT 56
|
#define SETUP_ANNOTATIONS 85
|
||||||
#define INPLACE_MULTIPLY 57
|
#define YIELD_VALUE 86
|
||||||
#define INPLACE_MODULO 59
|
#define POP_EXCEPT 89
|
||||||
#define STORE_SUBSCR 60
|
#define HAVE_ARGUMENT 90
|
||||||
#define DELETE_SUBSCR 61
|
#define STORE_NAME 90
|
||||||
#define BINARY_LSHIFT 62
|
#define DELETE_NAME 91
|
||||||
#define BINARY_RSHIFT 63
|
#define UNPACK_SEQUENCE 92
|
||||||
#define BINARY_AND 64
|
#define FOR_ITER 93
|
||||||
#define BINARY_XOR 65
|
#define UNPACK_EX 94
|
||||||
#define BINARY_OR 66
|
#define STORE_ATTR 95
|
||||||
#define INPLACE_POWER 67
|
#define DELETE_ATTR 96
|
||||||
#define GET_ITER 68
|
#define STORE_GLOBAL 97
|
||||||
#define GET_YIELD_FROM_ITER 69
|
#define DELETE_GLOBAL 98
|
||||||
#define PRINT_EXPR 70
|
#define ROT_N 99
|
||||||
#define LOAD_BUILD_CLASS 71
|
#define LOAD_CONST 100
|
||||||
#define YIELD_FROM 72
|
#define LOAD_NAME 101
|
||||||
#define GET_AWAITABLE 73
|
#define BUILD_TUPLE 102
|
||||||
#define LOAD_ASSERTION_ERROR 74
|
#define BUILD_LIST 103
|
||||||
#define INPLACE_LSHIFT 75
|
#define BUILD_SET 104
|
||||||
#define INPLACE_RSHIFT 76
|
#define BUILD_MAP 105
|
||||||
#define INPLACE_AND 77
|
#define LOAD_ATTR 106
|
||||||
#define INPLACE_XOR 78
|
#define COMPARE_OP 107
|
||||||
#define INPLACE_OR 79
|
#define IMPORT_NAME 108
|
||||||
#define LIST_TO_TUPLE 82
|
#define IMPORT_FROM 109
|
||||||
#define RETURN_VALUE 83
|
#define JUMP_FORWARD 110
|
||||||
#define IMPORT_STAR 84
|
#define JUMP_IF_FALSE_OR_POP 111
|
||||||
#define SETUP_ANNOTATIONS 85
|
#define JUMP_IF_TRUE_OR_POP 112
|
||||||
#define YIELD_VALUE 86
|
#define JUMP_ABSOLUTE 113
|
||||||
#define POP_EXCEPT 89
|
#define POP_JUMP_IF_FALSE 114
|
||||||
#define HAVE_ARGUMENT 90
|
#define POP_JUMP_IF_TRUE 115
|
||||||
#define STORE_NAME 90
|
#define LOAD_GLOBAL 116
|
||||||
#define DELETE_NAME 91
|
#define IS_OP 117
|
||||||
#define UNPACK_SEQUENCE 92
|
#define CONTAINS_OP 118
|
||||||
#define FOR_ITER 93
|
#define RERAISE 119
|
||||||
#define UNPACK_EX 94
|
#define COPY 120
|
||||||
#define STORE_ATTR 95
|
#define JUMP_IF_NOT_EXC_MATCH 121
|
||||||
#define DELETE_ATTR 96
|
#define BINARY_OP 122
|
||||||
#define STORE_GLOBAL 97
|
#define LOAD_FAST 124
|
||||||
#define DELETE_GLOBAL 98
|
#define STORE_FAST 125
|
||||||
#define ROT_N 99
|
#define DELETE_FAST 126
|
||||||
#define LOAD_CONST 100
|
#define GEN_START 129
|
||||||
#define LOAD_NAME 101
|
#define RAISE_VARARGS 130
|
||||||
#define BUILD_TUPLE 102
|
#define CALL_FUNCTION 131
|
||||||
#define BUILD_LIST 103
|
#define MAKE_FUNCTION 132
|
||||||
#define BUILD_SET 104
|
#define BUILD_SLICE 133
|
||||||
#define BUILD_MAP 105
|
#define MAKE_CELL 135
|
||||||
#define LOAD_ATTR 106
|
#define LOAD_CLOSURE 136
|
||||||
#define COMPARE_OP 107
|
#define LOAD_DEREF 137
|
||||||
#define IMPORT_NAME 108
|
#define STORE_DEREF 138
|
||||||
#define IMPORT_FROM 109
|
#define DELETE_DEREF 139
|
||||||
#define JUMP_FORWARD 110
|
#define CALL_FUNCTION_KW 141
|
||||||
#define JUMP_IF_FALSE_OR_POP 111
|
#define CALL_FUNCTION_EX 142
|
||||||
#define JUMP_IF_TRUE_OR_POP 112
|
#define EXTENDED_ARG 144
|
||||||
#define JUMP_ABSOLUTE 113
|
#define LIST_APPEND 145
|
||||||
#define POP_JUMP_IF_FALSE 114
|
#define SET_ADD 146
|
||||||
#define POP_JUMP_IF_TRUE 115
|
#define MAP_ADD 147
|
||||||
#define LOAD_GLOBAL 116
|
#define LOAD_CLASSDEREF 148
|
||||||
#define IS_OP 117
|
#define MATCH_CLASS 152
|
||||||
#define CONTAINS_OP 118
|
#define FORMAT_VALUE 155
|
||||||
#define RERAISE 119
|
#define BUILD_CONST_KEY_MAP 156
|
||||||
#define COPY 120
|
#define BUILD_STRING 157
|
||||||
#define JUMP_IF_NOT_EXC_MATCH 121
|
#define LOAD_METHOD 160
|
||||||
#define LOAD_FAST 124
|
#define CALL_METHOD 161
|
||||||
#define STORE_FAST 125
|
#define LIST_EXTEND 162
|
||||||
#define DELETE_FAST 126
|
#define SET_UPDATE 163
|
||||||
#define GEN_START 129
|
#define DICT_MERGE 164
|
||||||
#define RAISE_VARARGS 130
|
#define DICT_UPDATE 165
|
||||||
#define CALL_FUNCTION 131
|
#define CALL_METHOD_KW 166
|
||||||
#define MAKE_FUNCTION 132
|
#define BINARY_OP_ADAPTIVE 7
|
||||||
#define BUILD_SLICE 133
|
#define BINARY_OP_ADD_INT 8
|
||||||
#define MAKE_CELL 135
|
#define BINARY_OP_ADD_FLOAT 13
|
||||||
#define LOAD_CLOSURE 136
|
#define BINARY_OP_ADD_UNICODE 14
|
||||||
#define LOAD_DEREF 137
|
#define BINARY_OP_INPLACE_ADD_UNICODE 16
|
||||||
#define STORE_DEREF 138
|
#define BINARY_OP_MULTIPLY_INT 17
|
||||||
#define DELETE_DEREF 139
|
#define BINARY_OP_MULTIPLY_FLOAT 18
|
||||||
#define CALL_FUNCTION_KW 141
|
#define BINARY_SUBSCR_ADAPTIVE 19
|
||||||
#define CALL_FUNCTION_EX 142
|
#define BINARY_SUBSCR_LIST_INT 20
|
||||||
#define EXTENDED_ARG 144
|
#define BINARY_SUBSCR_TUPLE_INT 21
|
||||||
#define LIST_APPEND 145
|
#define BINARY_SUBSCR_DICT 22
|
||||||
#define SET_ADD 146
|
#define CALL_FUNCTION_ADAPTIVE 23
|
||||||
#define MAP_ADD 147
|
#define CALL_FUNCTION_BUILTIN_O 24
|
||||||
#define LOAD_CLASSDEREF 148
|
#define CALL_FUNCTION_BUILTIN_FAST 26
|
||||||
#define MATCH_CLASS 152
|
#define CALL_FUNCTION_LEN 27
|
||||||
#define FORMAT_VALUE 155
|
#define CALL_FUNCTION_ISINSTANCE 28
|
||||||
#define BUILD_CONST_KEY_MAP 156
|
#define CALL_FUNCTION_PY_SIMPLE 29
|
||||||
#define BUILD_STRING 157
|
#define JUMP_ABSOLUTE_QUICK 34
|
||||||
#define LOAD_METHOD 160
|
#define LOAD_ATTR_ADAPTIVE 36
|
||||||
#define CALL_METHOD 161
|
#define LOAD_ATTR_INSTANCE_VALUE 38
|
||||||
#define LIST_EXTEND 162
|
#define LOAD_ATTR_WITH_HINT 39
|
||||||
#define SET_UPDATE 163
|
#define LOAD_ATTR_SLOT 40
|
||||||
#define DICT_MERGE 164
|
#define LOAD_ATTR_MODULE 41
|
||||||
#define DICT_UPDATE 165
|
#define LOAD_GLOBAL_ADAPTIVE 42
|
||||||
#define CALL_METHOD_KW 166
|
#define LOAD_GLOBAL_MODULE 43
|
||||||
#define BINARY_ADD_ADAPTIVE 7
|
#define LOAD_GLOBAL_BUILTIN 44
|
||||||
#define BINARY_ADD_INT 8
|
#define LOAD_METHOD_ADAPTIVE 45
|
||||||
#define BINARY_ADD_FLOAT 13
|
#define LOAD_METHOD_CACHED 46
|
||||||
#define BINARY_ADD_UNICODE 14
|
#define LOAD_METHOD_CLASS 47
|
||||||
#define BINARY_ADD_UNICODE_INPLACE_FAST 18
|
#define LOAD_METHOD_MODULE 48
|
||||||
#define BINARY_MULTIPLY_ADAPTIVE 21
|
#define LOAD_METHOD_NO_DICT 55
|
||||||
#define BINARY_MULTIPLY_INT 34
|
#define STORE_ATTR_ADAPTIVE 56
|
||||||
#define BINARY_MULTIPLY_FLOAT 36
|
#define STORE_ATTR_INSTANCE_VALUE 57
|
||||||
#define BINARY_SUBSCR_ADAPTIVE 38
|
#define STORE_ATTR_SLOT 58
|
||||||
#define BINARY_SUBSCR_LIST_INT 39
|
#define STORE_ATTR_WITH_HINT 59
|
||||||
#define BINARY_SUBSCR_TUPLE_INT 40
|
#define LOAD_FAST__LOAD_FAST 62
|
||||||
#define BINARY_SUBSCR_DICT 41
|
#define STORE_FAST__LOAD_FAST 63
|
||||||
#define CALL_FUNCTION_ADAPTIVE 42
|
#define LOAD_FAST__LOAD_CONST 64
|
||||||
#define CALL_FUNCTION_BUILTIN_O 43
|
#define LOAD_CONST__LOAD_FAST 65
|
||||||
#define CALL_FUNCTION_BUILTIN_FAST 44
|
#define STORE_FAST__STORE_FAST 66
|
||||||
#define CALL_FUNCTION_LEN 45
|
#define DO_TRACING 255
|
||||||
#define CALL_FUNCTION_ISINSTANCE 46
|
|
||||||
#define CALL_FUNCTION_PY_SIMPLE 47
|
|
||||||
#define JUMP_ABSOLUTE_QUICK 48
|
|
||||||
#define LOAD_ATTR_ADAPTIVE 58
|
|
||||||
#define LOAD_ATTR_INSTANCE_VALUE 80
|
|
||||||
#define LOAD_ATTR_WITH_HINT 81
|
|
||||||
#define LOAD_ATTR_SLOT 87
|
|
||||||
#define LOAD_ATTR_MODULE 88
|
|
||||||
#define LOAD_GLOBAL_ADAPTIVE 122
|
|
||||||
#define LOAD_GLOBAL_MODULE 123
|
|
||||||
#define LOAD_GLOBAL_BUILTIN 127
|
|
||||||
#define LOAD_METHOD_ADAPTIVE 128
|
|
||||||
#define LOAD_METHOD_CACHED 134
|
|
||||||
#define LOAD_METHOD_CLASS 140
|
|
||||||
#define LOAD_METHOD_MODULE 143
|
|
||||||
#define LOAD_METHOD_NO_DICT 149
|
|
||||||
#define STORE_ATTR_ADAPTIVE 150
|
|
||||||
#define STORE_ATTR_INSTANCE_VALUE 151
|
|
||||||
#define STORE_ATTR_SLOT 153
|
|
||||||
#define STORE_ATTR_WITH_HINT 154
|
|
||||||
#define LOAD_FAST__LOAD_FAST 158
|
|
||||||
#define STORE_FAST__LOAD_FAST 159
|
|
||||||
#define LOAD_FAST__LOAD_CONST 167
|
|
||||||
#define LOAD_CONST__LOAD_FAST 168
|
|
||||||
#define STORE_FAST__STORE_FAST 169
|
|
||||||
#define DO_TRACING 255
|
|
||||||
#ifdef NEED_OPCODE_JUMP_TABLES
|
#ifdef NEED_OPCODE_JUMP_TABLES
|
||||||
static uint32_t _PyOpcode_RelativeJump[8] = {
|
static uint32_t _PyOpcode_RelativeJump[8] = {
|
||||||
0U,
|
0U,
|
||||||
|
@ -205,6 +179,33 @@ static uint32_t _PyOpcode_Jump[8] = {
|
||||||
|| ((op) == 100) \
|
|| ((op) == 100) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define NB_ADD 0
|
||||||
|
#define NB_AND 1
|
||||||
|
#define NB_FLOOR_DIVIDE 2
|
||||||
|
#define NB_LSHIFT 3
|
||||||
|
#define NB_MATRIX_MULTIPLY 4
|
||||||
|
#define NB_MULTIPLY 5
|
||||||
|
#define NB_REMAINDER 6
|
||||||
|
#define NB_OR 7
|
||||||
|
#define NB_POWER 8
|
||||||
|
#define NB_RSHIFT 9
|
||||||
|
#define NB_SUBTRACT 10
|
||||||
|
#define NB_TRUE_DIVIDE 11
|
||||||
|
#define NB_XOR 12
|
||||||
|
#define NB_INPLACE_ADD 13
|
||||||
|
#define NB_INPLACE_AND 14
|
||||||
|
#define NB_INPLACE_FLOOR_DIVIDE 15
|
||||||
|
#define NB_INPLACE_LSHIFT 16
|
||||||
|
#define NB_INPLACE_MATRIX_MULTIPLY 17
|
||||||
|
#define NB_INPLACE_MULTIPLY 18
|
||||||
|
#define NB_INPLACE_REMAINDER 19
|
||||||
|
#define NB_INPLACE_OR 20
|
||||||
|
#define NB_INPLACE_POWER 21
|
||||||
|
#define NB_INPLACE_RSHIFT 22
|
||||||
|
#define NB_INPLACE_SUBTRACT 23
|
||||||
|
#define NB_INPLACE_TRUE_DIVIDE 24
|
||||||
|
#define NB_INPLACE_XOR 25
|
||||||
|
|
||||||
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
|
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
|
||||||
|
|
||||||
/* Reserve some bytecodes for internal use in the compiler.
|
/* Reserve some bytecodes for internal use in the compiler.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import io
|
||||||
|
|
||||||
from opcode import *
|
from opcode import *
|
||||||
from opcode import __all__ as _opcodes_all
|
from opcode import __all__ as _opcodes_all
|
||||||
|
from opcode import _nb_ops
|
||||||
|
|
||||||
__all__ = ["code_info", "dis", "disassemble", "distb", "disco",
|
__all__ = ["code_info", "dis", "disassemble", "distb", "disco",
|
||||||
"findlinestarts", "findlabels", "show_code",
|
"findlinestarts", "findlabels", "show_code",
|
||||||
|
@ -27,6 +28,7 @@ MAKE_FUNCTION = opmap['MAKE_FUNCTION']
|
||||||
MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure')
|
MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure')
|
||||||
|
|
||||||
LOAD_CONST = opmap['LOAD_CONST']
|
LOAD_CONST = opmap['LOAD_CONST']
|
||||||
|
BINARY_OP = opmap['BINARY_OP']
|
||||||
|
|
||||||
def _try_compile(source, name):
|
def _try_compile(source, name):
|
||||||
"""Attempts to compile the given source, first as an expression and
|
"""Attempts to compile the given source, first as an expression and
|
||||||
|
@ -446,6 +448,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
|
||||||
elif op == MAKE_FUNCTION:
|
elif op == MAKE_FUNCTION:
|
||||||
argrepr = ', '.join(s for i, s in enumerate(MAKE_FUNCTION_FLAGS)
|
argrepr = ', '.join(s for i, s in enumerate(MAKE_FUNCTION_FLAGS)
|
||||||
if arg & (1<<i))
|
if arg & (1<<i))
|
||||||
|
elif op == BINARY_OP:
|
||||||
|
_, argrepr = _nb_ops[arg]
|
||||||
yield Instruction(opname[op], op,
|
yield Instruction(opname[op], op,
|
||||||
arg, argval, argrepr,
|
arg, argval, argrepr,
|
||||||
offset, starts_line, is_jump_target, positions)
|
offset, starts_line, is_jump_target, positions)
|
||||||
|
|
|
@ -366,6 +366,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Python 3.11a1 3461 (JUMP_ABSOLUTE must jump backwards)
|
# Python 3.11a1 3461 (JUMP_ABSOLUTE must jump backwards)
|
||||||
# Python 3.11a2 3462 (bpo-44511: remove COPY_DICT_WITHOUT_KEYS, change
|
# Python 3.11a2 3462 (bpo-44511: remove COPY_DICT_WITHOUT_KEYS, change
|
||||||
# MATCH_CLASS and MATCH_KEYS, and add COPY)
|
# MATCH_CLASS and MATCH_KEYS, and add COPY)
|
||||||
|
# Python 3.11a3 3463 (Merge numeric BINARY_*/INPLACE_* into BINARY_OP)
|
||||||
|
|
||||||
#
|
#
|
||||||
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||||
|
|
|
@ -67,20 +67,9 @@ def_op('UNARY_NEGATIVE', 11)
|
||||||
def_op('UNARY_NOT', 12)
|
def_op('UNARY_NOT', 12)
|
||||||
|
|
||||||
def_op('UNARY_INVERT', 15)
|
def_op('UNARY_INVERT', 15)
|
||||||
def_op('BINARY_MATRIX_MULTIPLY', 16)
|
|
||||||
def_op('INPLACE_MATRIX_MULTIPLY', 17)
|
|
||||||
|
|
||||||
def_op('BINARY_POWER', 19)
|
|
||||||
def_op('BINARY_MULTIPLY', 20)
|
|
||||||
|
|
||||||
def_op('BINARY_MODULO', 22)
|
|
||||||
def_op('BINARY_ADD', 23)
|
|
||||||
def_op('BINARY_SUBTRACT', 24)
|
|
||||||
def_op('BINARY_SUBSCR', 25)
|
def_op('BINARY_SUBSCR', 25)
|
||||||
def_op('BINARY_FLOOR_DIVIDE', 26)
|
|
||||||
def_op('BINARY_TRUE_DIVIDE', 27)
|
|
||||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
|
||||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
|
||||||
def_op('GET_LEN', 30)
|
def_op('GET_LEN', 30)
|
||||||
def_op('MATCH_MAPPING', 31)
|
def_op('MATCH_MAPPING', 31)
|
||||||
def_op('MATCH_SEQUENCE', 32)
|
def_op('MATCH_SEQUENCE', 32)
|
||||||
|
@ -95,21 +84,11 @@ def_op('GET_AITER', 50)
|
||||||
def_op('GET_ANEXT', 51)
|
def_op('GET_ANEXT', 51)
|
||||||
def_op('BEFORE_ASYNC_WITH', 52)
|
def_op('BEFORE_ASYNC_WITH', 52)
|
||||||
def_op('BEFORE_WITH', 53)
|
def_op('BEFORE_WITH', 53)
|
||||||
|
|
||||||
def_op('END_ASYNC_FOR', 54)
|
def_op('END_ASYNC_FOR', 54)
|
||||||
def_op('INPLACE_ADD', 55)
|
|
||||||
def_op('INPLACE_SUBTRACT', 56)
|
|
||||||
def_op('INPLACE_MULTIPLY', 57)
|
|
||||||
|
|
||||||
def_op('INPLACE_MODULO', 59)
|
|
||||||
def_op('STORE_SUBSCR', 60)
|
def_op('STORE_SUBSCR', 60)
|
||||||
def_op('DELETE_SUBSCR', 61)
|
def_op('DELETE_SUBSCR', 61)
|
||||||
def_op('BINARY_LSHIFT', 62)
|
|
||||||
def_op('BINARY_RSHIFT', 63)
|
|
||||||
def_op('BINARY_AND', 64)
|
|
||||||
def_op('BINARY_XOR', 65)
|
|
||||||
def_op('BINARY_OR', 66)
|
|
||||||
def_op('INPLACE_POWER', 67)
|
|
||||||
def_op('GET_ITER', 68)
|
def_op('GET_ITER', 68)
|
||||||
def_op('GET_YIELD_FROM_ITER', 69)
|
def_op('GET_YIELD_FROM_ITER', 69)
|
||||||
def_op('PRINT_EXPR', 70)
|
def_op('PRINT_EXPR', 70)
|
||||||
|
@ -117,11 +96,6 @@ def_op('LOAD_BUILD_CLASS', 71)
|
||||||
def_op('YIELD_FROM', 72)
|
def_op('YIELD_FROM', 72)
|
||||||
def_op('GET_AWAITABLE', 73)
|
def_op('GET_AWAITABLE', 73)
|
||||||
def_op('LOAD_ASSERTION_ERROR', 74)
|
def_op('LOAD_ASSERTION_ERROR', 74)
|
||||||
def_op('INPLACE_LSHIFT', 75)
|
|
||||||
def_op('INPLACE_RSHIFT', 76)
|
|
||||||
def_op('INPLACE_AND', 77)
|
|
||||||
def_op('INPLACE_XOR', 78)
|
|
||||||
def_op('INPLACE_OR', 79)
|
|
||||||
|
|
||||||
def_op('LIST_TO_TUPLE', 82)
|
def_op('LIST_TO_TUPLE', 82)
|
||||||
def_op('RETURN_VALUE', 83)
|
def_op('RETURN_VALUE', 83)
|
||||||
|
@ -167,6 +141,7 @@ def_op('CONTAINS_OP', 118)
|
||||||
def_op('RERAISE', 119)
|
def_op('RERAISE', 119)
|
||||||
def_op('COPY', 120)
|
def_op('COPY', 120)
|
||||||
jabs_op('JUMP_IF_NOT_EXC_MATCH', 121)
|
jabs_op('JUMP_IF_NOT_EXC_MATCH', 121)
|
||||||
|
def_op('BINARY_OP', 122)
|
||||||
|
|
||||||
def_op('LOAD_FAST', 124) # Local variable number
|
def_op('LOAD_FAST', 124) # Local variable number
|
||||||
haslocal.append(124)
|
haslocal.append(124)
|
||||||
|
@ -219,15 +194,43 @@ def_op('CALL_METHOD_KW', 166)
|
||||||
|
|
||||||
del def_op, name_op, jrel_op, jabs_op
|
del def_op, name_op, jrel_op, jabs_op
|
||||||
|
|
||||||
|
_nb_ops = [
|
||||||
|
("NB_ADD", "+"),
|
||||||
|
("NB_AND", "&"),
|
||||||
|
("NB_FLOOR_DIVIDE", "//"),
|
||||||
|
("NB_LSHIFT", "<<"),
|
||||||
|
("NB_MATRIX_MULTIPLY", "@"),
|
||||||
|
("NB_MULTIPLY", "*"),
|
||||||
|
("NB_REMAINDER", "%"),
|
||||||
|
("NB_OR", "|"),
|
||||||
|
("NB_POWER", "**"),
|
||||||
|
("NB_RSHIFT", ">>"),
|
||||||
|
("NB_SUBTRACT", "-"),
|
||||||
|
("NB_TRUE_DIVIDE", "/"),
|
||||||
|
("NB_XOR", "^"),
|
||||||
|
("NB_INPLACE_ADD", "+="),
|
||||||
|
("NB_INPLACE_AND", "&="),
|
||||||
|
("NB_INPLACE_FLOOR_DIVIDE", "//="),
|
||||||
|
("NB_INPLACE_LSHIFT", "<<="),
|
||||||
|
("NB_INPLACE_MATRIX_MULTIPLY", "@="),
|
||||||
|
("NB_INPLACE_MULTIPLY", "*="),
|
||||||
|
("NB_INPLACE_REMAINDER", "%="),
|
||||||
|
("NB_INPLACE_OR", "|="),
|
||||||
|
("NB_INPLACE_POWER", "**="),
|
||||||
|
("NB_INPLACE_RSHIFT", ">>="),
|
||||||
|
("NB_INPLACE_SUBTRACT", "-="),
|
||||||
|
("NB_INPLACE_TRUE_DIVIDE", "/="),
|
||||||
|
("NB_INPLACE_XOR", "^="),
|
||||||
|
]
|
||||||
|
|
||||||
_specialized_instructions = [
|
_specialized_instructions = [
|
||||||
"BINARY_ADD_ADAPTIVE",
|
"BINARY_OP_ADAPTIVE",
|
||||||
"BINARY_ADD_INT",
|
"BINARY_OP_ADD_INT",
|
||||||
"BINARY_ADD_FLOAT",
|
"BINARY_OP_ADD_FLOAT",
|
||||||
"BINARY_ADD_UNICODE",
|
"BINARY_OP_ADD_UNICODE",
|
||||||
"BINARY_ADD_UNICODE_INPLACE_FAST",
|
"BINARY_OP_INPLACE_ADD_UNICODE",
|
||||||
"BINARY_MULTIPLY_ADAPTIVE",
|
"BINARY_OP_MULTIPLY_INT",
|
||||||
"BINARY_MULTIPLY_INT",
|
"BINARY_OP_MULTIPLY_FLOAT",
|
||||||
"BINARY_MULTIPLY_FLOAT",
|
|
||||||
"BINARY_SUBSCR_ADAPTIVE",
|
"BINARY_SUBSCR_ADAPTIVE",
|
||||||
"BINARY_SUBSCR_LIST_INT",
|
"BINARY_SUBSCR_LIST_INT",
|
||||||
"BINARY_SUBSCR_TUPLE_INT",
|
"BINARY_SUBSCR_TUPLE_INT",
|
||||||
|
|
|
@ -1048,15 +1048,17 @@ class TestSourcePositions(unittest.TestCase):
|
||||||
return code, ast_tree
|
return code, ast_tree
|
||||||
|
|
||||||
def assertOpcodeSourcePositionIs(self, code, opcode,
|
def assertOpcodeSourcePositionIs(self, code, opcode,
|
||||||
line, end_line, column, end_column):
|
line, end_line, column, end_column, occurrence=1):
|
||||||
|
|
||||||
for instr, position in zip(dis.Bytecode(code), code.co_positions()):
|
for instr, position in zip(dis.Bytecode(code), code.co_positions()):
|
||||||
if instr.opname == opcode:
|
if instr.opname == opcode:
|
||||||
self.assertEqual(position[0], line)
|
occurrence -= 1
|
||||||
self.assertEqual(position[1], end_line)
|
if not occurrence:
|
||||||
self.assertEqual(position[2], column)
|
self.assertEqual(position[0], line)
|
||||||
self.assertEqual(position[3], end_column)
|
self.assertEqual(position[1], end_line)
|
||||||
return
|
self.assertEqual(position[2], column)
|
||||||
|
self.assertEqual(position[3], end_column)
|
||||||
|
return
|
||||||
|
|
||||||
self.fail(f"Opcode {opcode} not found in code")
|
self.fail(f"Opcode {opcode} not found in code")
|
||||||
|
|
||||||
|
@ -1077,12 +1079,12 @@ class TestSourcePositions(unittest.TestCase):
|
||||||
|
|
||||||
compiled_code, _ = self.check_positions_against_ast(snippet)
|
compiled_code, _ = self.check_positions_against_ast(snippet)
|
||||||
|
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'INPLACE_SUBTRACT',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=10_000 + 2, end_line=10_000 + 2,
|
line=10_000 + 2, end_line=10_000 + 2,
|
||||||
column=2, end_column=8)
|
column=2, end_column=8, occurrence=1)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'INPLACE_ADD',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=10_000 + 4, end_line=10_000 + 4,
|
line=10_000 + 4, end_line=10_000 + 4,
|
||||||
column=2, end_column=9)
|
column=2, end_column=9, occurrence=2)
|
||||||
|
|
||||||
def test_multiline_expression(self):
|
def test_multiline_expression(self):
|
||||||
snippet = """\
|
snippet = """\
|
||||||
|
@ -1110,14 +1112,14 @@ f(
|
||||||
compiled_code, _ = self.check_positions_against_ast(snippet)
|
compiled_code, _ = self.check_positions_against_ast(snippet)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBSCR',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBSCR',
|
||||||
line=1, end_line=1, column=13, end_column=21)
|
line=1, end_line=1, column=13, end_column=21)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_MULTIPLY',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=1, end_line=1, column=9, end_column=21)
|
line=1, end_line=1, column=9, end_column=21, occurrence=1)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_ADD',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=1, end_line=1, column=9, end_column=26)
|
line=1, end_line=1, column=9, end_column=26, occurrence=2)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_MATRIX_MULTIPLY',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=1, end_line=1, column=4, end_column=27)
|
line=1, end_line=1, column=4, end_column=27, occurrence=3)
|
||||||
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBTRACT',
|
self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
|
||||||
line=1, end_line=1, column=0, end_column=27)
|
line=1, end_line=1, column=0, end_column=27, occurrence=4)
|
||||||
|
|
||||||
|
|
||||||
class TestExpressionStackSize(unittest.TestCase):
|
class TestExpressionStackSize(unittest.TestCase):
|
||||||
|
|
|
@ -156,7 +156,7 @@ dis_bug1333982 = """\
|
||||||
|
|
||||||
%3d 12 LOAD_CONST 3 (1)
|
%3d 12 LOAD_CONST 3 (1)
|
||||||
|
|
||||||
%3d 14 BINARY_ADD
|
%3d 14 BINARY_OP 0 (+)
|
||||||
16 CALL_FUNCTION 1
|
16 CALL_FUNCTION 1
|
||||||
18 RAISE_VARARGS 1
|
18 RAISE_VARARGS 1
|
||||||
""" % (bug1333982.__code__.co_firstlineno + 1,
|
""" % (bug1333982.__code__.co_firstlineno + 1,
|
||||||
|
@ -226,7 +226,7 @@ expr_str = "x + 1"
|
||||||
dis_expr_str = """\
|
dis_expr_str = """\
|
||||||
1 0 LOAD_NAME 0 (x)
|
1 0 LOAD_NAME 0 (x)
|
||||||
2 LOAD_CONST 0 (1)
|
2 LOAD_CONST 0 (1)
|
||||||
4 BINARY_ADD
|
4 BINARY_OP 0 (+)
|
||||||
6 RETURN_VALUE
|
6 RETURN_VALUE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ simple_stmt_str = "x = x + 1"
|
||||||
dis_simple_stmt_str = """\
|
dis_simple_stmt_str = """\
|
||||||
1 0 LOAD_NAME 0 (x)
|
1 0 LOAD_NAME 0 (x)
|
||||||
2 LOAD_CONST 0 (1)
|
2 LOAD_CONST 0 (1)
|
||||||
4 BINARY_ADD
|
4 BINARY_OP 0 (+)
|
||||||
6 STORE_NAME 0 (x)
|
6 STORE_NAME 0 (x)
|
||||||
8 LOAD_CONST 1 (None)
|
8 LOAD_CONST 1 (None)
|
||||||
10 RETURN_VALUE
|
10 RETURN_VALUE
|
||||||
|
@ -291,7 +291,7 @@ dis_compound_stmt_str = """\
|
||||||
|
|
||||||
3 >> 6 LOAD_NAME 0 (x)
|
3 >> 6 LOAD_NAME 0 (x)
|
||||||
8 LOAD_CONST 1 (1)
|
8 LOAD_CONST 1 (1)
|
||||||
10 INPLACE_ADD
|
10 BINARY_OP 13 (+=)
|
||||||
12 STORE_NAME 0 (x)
|
12 STORE_NAME 0 (x)
|
||||||
|
|
||||||
2 14 JUMP_ABSOLUTE 3 (to 6)
|
2 14 JUMP_ABSOLUTE 3 (to 6)
|
||||||
|
@ -302,7 +302,7 @@ dis_traceback = """\
|
||||||
|
|
||||||
%3d 2 LOAD_CONST 1 (1)
|
%3d 2 LOAD_CONST 1 (1)
|
||||||
4 LOAD_CONST 2 (0)
|
4 LOAD_CONST 2 (0)
|
||||||
--> 6 BINARY_TRUE_DIVIDE
|
--> 6 BINARY_OP 11 (/)
|
||||||
8 POP_TOP
|
8 POP_TOP
|
||||||
|
|
||||||
%3d 10 LOAD_FAST 1 (tb)
|
%3d 10 LOAD_FAST 1 (tb)
|
||||||
|
@ -485,7 +485,7 @@ Disassembly of <code object <listcomp> at 0x..., file "%s", line %d>:
|
||||||
6 STORE_FAST 1 (z)
|
6 STORE_FAST 1 (z)
|
||||||
8 LOAD_DEREF 2 (x)
|
8 LOAD_DEREF 2 (x)
|
||||||
10 LOAD_FAST 1 (z)
|
10 LOAD_FAST 1 (z)
|
||||||
12 BINARY_ADD
|
12 BINARY_OP 0 (+)
|
||||||
14 LIST_APPEND 2
|
14 LIST_APPEND 2
|
||||||
16 JUMP_ABSOLUTE 2 (to 4)
|
16 JUMP_ABSOLUTE 2 (to 4)
|
||||||
>> 18 RETURN_VALUE
|
>> 18 RETURN_VALUE
|
||||||
|
@ -602,7 +602,7 @@ class DisTests(unittest.TestCase):
|
||||||
s = ['''\
|
s = ['''\
|
||||||
%*d LOAD_FAST 0 (x)
|
%*d LOAD_FAST 0 (x)
|
||||||
%*d LOAD_CONST 1 (1)
|
%*d LOAD_CONST 1 (1)
|
||||||
%*d BINARY_ADD
|
%*d BINARY_OP 0 (+)
|
||||||
%*d STORE_FAST 0 (x)
|
%*d STORE_FAST 0 (x)
|
||||||
''' % (w, 8*i, w, 8*i + 2, w, 8*i + 4, w, 8*i + 6)
|
''' % (w, 8*i, w, 8*i + 2, w, 8*i + 4, w, 8*i + 6)
|
||||||
for i in range(count)]
|
for i in range(count)]
|
||||||
|
@ -1080,7 +1080,7 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=68, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=68, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=70, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=70, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=14, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=14, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False, positions=None),
|
||||||
|
@ -1101,7 +1101,7 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=104, starts_line=20, is_jump_target=True, positions=None),
|
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=104, starts_line=20, is_jump_target=True, positions=None),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=110, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
|
||||||
|
|
|
@ -424,7 +424,7 @@ class TestTranforms(BytecodeTestCase):
|
||||||
def g()->1+1:
|
def g()->1+1:
|
||||||
pass
|
pass
|
||||||
return g
|
return g
|
||||||
self.assertNotInBytecode(f, 'BINARY_ADD')
|
self.assertNotInBytecode(f, 'BINARY_OP')
|
||||||
self.check_lnotab(f)
|
self.check_lnotab(f)
|
||||||
|
|
||||||
def test_constant_folding(self):
|
def test_constant_folding(self):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Replace all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single
|
||||||
|
:opcode:`BINARY_OP` implementation.
|
604
Python/ceval.c
604
Python/ceval.c
|
@ -92,8 +92,6 @@ static PyObject * import_from(PyThreadState *, PyObject *, PyObject *);
|
||||||
static int import_all_from(PyThreadState *, PyObject *, PyObject *);
|
static int import_all_from(PyThreadState *, PyObject *, PyObject *);
|
||||||
static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *);
|
static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *);
|
||||||
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
|
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
|
||||||
static PyObject * unicode_concatenate(PyThreadState *, PyObject *, PyObject *,
|
|
||||||
InterpreterFrame *, const _Py_CODEUNIT *);
|
|
||||||
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
|
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
|
||||||
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
|
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
|
||||||
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
|
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
|
||||||
|
@ -1921,57 +1919,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_POWER) {
|
TARGET(BINARY_OP_MULTIPLY_INT) {
|
||||||
PyObject *exp = POP();
|
|
||||||
PyObject *base = TOP();
|
|
||||||
PyObject *res = PyNumber_Power(base, exp, Py_None);
|
|
||||||
Py_DECREF(base);
|
|
||||||
Py_DECREF(exp);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_MULTIPLY) {
|
|
||||||
PREDICTED(BINARY_MULTIPLY);
|
|
||||||
STAT_INC(BINARY_MULTIPLY, unquickened);
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_Multiply(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_MULTIPLY_ADAPTIVE) {
|
|
||||||
if (oparg == 0) {
|
|
||||||
PyObject *left = SECOND();
|
|
||||||
PyObject *right = TOP();
|
|
||||||
next_instr--;
|
|
||||||
if (_Py_Specialize_BinaryMultiply(left, right, next_instr) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
STAT_INC(BINARY_MULTIPLY, deferred);
|
|
||||||
UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1);
|
|
||||||
STAT_DEC(BINARY_MULTIPLY, unquickened);
|
|
||||||
JUMP_TO_INSTRUCTION(BINARY_MULTIPLY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_MULTIPLY_INT) {
|
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyLong_CheckExact(left), BINARY_MULTIPLY);
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(!PyLong_CheckExact(right), BINARY_MULTIPLY);
|
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
|
||||||
STAT_INC(BINARY_MULTIPLY, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
|
PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
|
||||||
SET_SECOND(prod);
|
SET_SECOND(prod);
|
||||||
Py_DECREF(right);
|
Py_DECREF(right);
|
||||||
|
@ -1983,12 +1936,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_MULTIPLY_FLOAT) {
|
TARGET(BINARY_OP_MULTIPLY_FLOAT) {
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_MULTIPLY);
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_MULTIPLY);
|
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
|
||||||
STAT_INC(BINARY_MULTIPLY, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
double dprod = ((PyFloatObject *)left)->ob_fval *
|
double dprod = ((PyFloatObject *)left)->ob_fval *
|
||||||
((PyFloatObject *)right)->ob_fval;
|
((PyFloatObject *)right)->ob_fval;
|
||||||
PyObject *prod = PyFloat_FromDouble(dprod);
|
PyObject *prod = PyFloat_FromDouble(dprod);
|
||||||
|
@ -2002,101 +1955,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_MATRIX_MULTIPLY) {
|
TARGET(BINARY_OP_ADD_UNICODE) {
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_MatrixMultiply(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_TRUE_DIVIDE) {
|
|
||||||
PyObject *divisor = POP();
|
|
||||||
PyObject *dividend = TOP();
|
|
||||||
PyObject *quotient = PyNumber_TrueDivide(dividend, divisor);
|
|
||||||
Py_DECREF(dividend);
|
|
||||||
Py_DECREF(divisor);
|
|
||||||
SET_TOP(quotient);
|
|
||||||
if (quotient == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_FLOOR_DIVIDE) {
|
|
||||||
PyObject *divisor = POP();
|
|
||||||
PyObject *dividend = TOP();
|
|
||||||
PyObject *quotient = PyNumber_FloorDivide(dividend, divisor);
|
|
||||||
Py_DECREF(dividend);
|
|
||||||
Py_DECREF(divisor);
|
|
||||||
SET_TOP(quotient);
|
|
||||||
if (quotient == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_MODULO) {
|
|
||||||
PyObject *divisor = POP();
|
|
||||||
PyObject *dividend = TOP();
|
|
||||||
PyObject *res;
|
|
||||||
if (PyUnicode_CheckExact(dividend) && (
|
|
||||||
!PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) {
|
|
||||||
// fast path; string formatting, but not if the RHS is a str subclass
|
|
||||||
// (see issue28598)
|
|
||||||
res = PyUnicode_Format(dividend, divisor);
|
|
||||||
} else {
|
|
||||||
res = PyNumber_Remainder(dividend, divisor);
|
|
||||||
}
|
|
||||||
Py_DECREF(divisor);
|
|
||||||
Py_DECREF(dividend);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_ADD) {
|
|
||||||
PREDICTED(BINARY_ADD);
|
|
||||||
STAT_INC(BINARY_ADD, unquickened);
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *sum = PyNumber_Add(left, right);
|
|
||||||
SET_TOP(sum);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
if (sum == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_ADD_ADAPTIVE) {
|
|
||||||
if (oparg == 0) {
|
|
||||||
PyObject *left = SECOND();
|
|
||||||
PyObject *right = TOP();
|
|
||||||
next_instr--;
|
|
||||||
if (_Py_Specialize_BinaryAdd(left, right, next_instr) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
STAT_INC(BINARY_ADD, deferred);
|
|
||||||
UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1);
|
|
||||||
STAT_DEC(BINARY_ADD, unquickened);
|
|
||||||
JUMP_TO_INSTRUCTION(BINARY_ADD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_ADD_UNICODE) {
|
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD);
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
|
||||||
STAT_INC(BINARY_ADD, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
PyObject *res = PyUnicode_Concat(left, right);
|
PyObject *res = PyUnicode_Concat(left, right);
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
SET_TOP(res);
|
SET_TOP(res);
|
||||||
|
@ -2108,12 +1972,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_ADD_UNICODE_INPLACE_FAST) {
|
TARGET(BINARY_OP_INPLACE_ADD_UNICODE) {
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD);
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
|
||||||
DEOPT_IF(Py_REFCNT(left) != 2, BINARY_ADD);
|
DEOPT_IF(Py_REFCNT(left) != 2, BINARY_OP);
|
||||||
int next_oparg = _Py_OPARG(*next_instr);
|
int next_oparg = _Py_OPARG(*next_instr);
|
||||||
assert(_Py_OPCODE(*next_instr) == STORE_FAST);
|
assert(_Py_OPCODE(*next_instr) == STORE_FAST);
|
||||||
/* In the common case, there are 2 references to the value
|
/* In the common case, there are 2 references to the value
|
||||||
|
@ -2123,8 +1987,8 @@ check_eval_breaker:
|
||||||
* the refcnt to 1.
|
* the refcnt to 1.
|
||||||
*/
|
*/
|
||||||
PyObject *var = GETLOCAL(next_oparg);
|
PyObject *var = GETLOCAL(next_oparg);
|
||||||
DEOPT_IF(var != left, BINARY_ADD);
|
DEOPT_IF(var != left, BINARY_OP);
|
||||||
STAT_INC(BINARY_ADD, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
GETLOCAL(next_oparg) = NULL;
|
GETLOCAL(next_oparg) = NULL;
|
||||||
Py_DECREF(left);
|
Py_DECREF(left);
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
|
@ -2136,12 +2000,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_ADD_FLOAT) {
|
TARGET(BINARY_OP_ADD_FLOAT) {
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_ADD);
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
|
||||||
STAT_INC(BINARY_ADD, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
double dsum = ((PyFloatObject *)left)->ob_fval +
|
double dsum = ((PyFloatObject *)left)->ob_fval +
|
||||||
((PyFloatObject *)right)->ob_fval;
|
((PyFloatObject *)right)->ob_fval;
|
||||||
PyObject *sum = PyFloat_FromDouble(dsum);
|
PyObject *sum = PyFloat_FromDouble(dsum);
|
||||||
|
@ -2155,12 +2019,12 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_ADD_INT) {
|
TARGET(BINARY_OP_ADD_INT) {
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
DEOPT_IF(!PyLong_CheckExact(left), BINARY_ADD);
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||||
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
|
||||||
STAT_INC(BINARY_ADD, hit);
|
STAT_INC(BINARY_OP, hit);
|
||||||
PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
|
PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
|
||||||
SET_SECOND(sum);
|
SET_SECOND(sum);
|
||||||
Py_DECREF(right);
|
Py_DECREF(right);
|
||||||
|
@ -2172,18 +2036,6 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_SUBTRACT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *diff = PyNumber_Subtract(left, right);
|
|
||||||
Py_DECREF(right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
SET_TOP(diff);
|
|
||||||
if (diff == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_SUBSCR) {
|
TARGET(BINARY_SUBSCR) {
|
||||||
PREDICTED(BINARY_SUBSCR);
|
PREDICTED(BINARY_SUBSCR);
|
||||||
STAT_INC(BINARY_SUBSCR, unquickened);
|
STAT_INC(BINARY_SUBSCR, unquickened);
|
||||||
|
@ -2282,66 +2134,6 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_LSHIFT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_Lshift(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_RSHIFT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_Rshift(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_AND) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_And(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_XOR) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_Xor(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(BINARY_OR) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_Or(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(LIST_APPEND) {
|
TARGET(LIST_APPEND) {
|
||||||
PyObject *v = POP();
|
PyObject *v = POP();
|
||||||
PyObject *list = PEEK(oparg);
|
PyObject *list = PEEK(oparg);
|
||||||
|
@ -2366,169 +2158,6 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(INPLACE_POWER) {
|
|
||||||
PyObject *exp = POP();
|
|
||||||
PyObject *base = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
|
|
||||||
Py_DECREF(base);
|
|
||||||
Py_DECREF(exp);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_MULTIPLY) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceMultiply(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_MATRIX_MULTIPLY) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_TRUE_DIVIDE) {
|
|
||||||
PyObject *divisor = POP();
|
|
||||||
PyObject *dividend = TOP();
|
|
||||||
PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor);
|
|
||||||
Py_DECREF(dividend);
|
|
||||||
Py_DECREF(divisor);
|
|
||||||
SET_TOP(quotient);
|
|
||||||
if (quotient == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_FLOOR_DIVIDE) {
|
|
||||||
PyObject *divisor = POP();
|
|
||||||
PyObject *dividend = TOP();
|
|
||||||
PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor);
|
|
||||||
Py_DECREF(dividend);
|
|
||||||
Py_DECREF(divisor);
|
|
||||||
SET_TOP(quotient);
|
|
||||||
if (quotient == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_MODULO) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *mod = PyNumber_InPlaceRemainder(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(mod);
|
|
||||||
if (mod == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_ADD) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *sum;
|
|
||||||
if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
|
|
||||||
sum = unicode_concatenate(tstate, left, right, frame, next_instr);
|
|
||||||
/* unicode_concatenate consumed the ref to left */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sum = PyNumber_InPlaceAdd(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
}
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(sum);
|
|
||||||
if (sum == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_SUBTRACT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *diff = PyNumber_InPlaceSubtract(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(diff);
|
|
||||||
if (diff == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_LSHIFT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceLshift(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_RSHIFT) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceRshift(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_AND) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceAnd(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_XOR) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceXor(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(INPLACE_OR) {
|
|
||||||
PyObject *right = POP();
|
|
||||||
PyObject *left = TOP();
|
|
||||||
PyObject *res = PyNumber_InPlaceOr(left, right);
|
|
||||||
Py_DECREF(left);
|
|
||||||
Py_DECREF(right);
|
|
||||||
SET_TOP(res);
|
|
||||||
if (res == NULL)
|
|
||||||
goto error;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(STORE_SUBSCR) {
|
TARGET(STORE_SUBSCR) {
|
||||||
PyObject *sub = TOP();
|
PyObject *sub = TOP();
|
||||||
PyObject *container = SECOND();
|
PyObject *container = SECOND();
|
||||||
|
@ -5032,6 +4661,130 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET(BINARY_OP) {
|
||||||
|
PREDICTED(BINARY_OP);
|
||||||
|
STAT_INC(BINARY_OP, unquickened);
|
||||||
|
PyObject *rhs = POP();
|
||||||
|
PyObject *lhs = TOP();
|
||||||
|
PyObject *res;
|
||||||
|
switch (oparg) {
|
||||||
|
case NB_ADD:
|
||||||
|
res = PyNumber_Add(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_AND:
|
||||||
|
res = PyNumber_And(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_FLOOR_DIVIDE:
|
||||||
|
res = PyNumber_FloorDivide(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_LSHIFT:
|
||||||
|
res = PyNumber_Lshift(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_MATRIX_MULTIPLY:
|
||||||
|
res = PyNumber_MatrixMultiply(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_MULTIPLY:
|
||||||
|
res = PyNumber_Multiply(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_REMAINDER:
|
||||||
|
if (PyUnicode_CheckExact(lhs) &&
|
||||||
|
(!PyUnicode_Check(rhs) || PyUnicode_CheckExact(rhs)))
|
||||||
|
{
|
||||||
|
// bpo-28598: Fast path for string formatting (but not
|
||||||
|
// if the RHS is a str subclass).
|
||||||
|
res = PyUnicode_Format(lhs, rhs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = PyNumber_Remainder(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_OR:
|
||||||
|
res = PyNumber_Or(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_POWER:
|
||||||
|
res = PyNumber_Power(lhs, rhs, Py_None);
|
||||||
|
break;
|
||||||
|
case NB_RSHIFT:
|
||||||
|
res = PyNumber_Rshift(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_SUBTRACT:
|
||||||
|
res = PyNumber_Subtract(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_TRUE_DIVIDE:
|
||||||
|
res = PyNumber_TrueDivide(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_XOR:
|
||||||
|
res = PyNumber_Xor(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_ADD:
|
||||||
|
res = PyNumber_InPlaceAdd(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_AND:
|
||||||
|
res = PyNumber_InPlaceAnd(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_FLOOR_DIVIDE:
|
||||||
|
res = PyNumber_InPlaceFloorDivide(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_LSHIFT:
|
||||||
|
res = PyNumber_InPlaceLshift(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_MATRIX_MULTIPLY:
|
||||||
|
res = PyNumber_InPlaceMatrixMultiply(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_MULTIPLY:
|
||||||
|
res = PyNumber_InPlaceMultiply(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_REMAINDER:
|
||||||
|
res = PyNumber_InPlaceRemainder(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_OR:
|
||||||
|
res = PyNumber_InPlaceOr(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_POWER:
|
||||||
|
res = PyNumber_InPlacePower(lhs, rhs, Py_None);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_RSHIFT:
|
||||||
|
res = PyNumber_InPlaceRshift(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_SUBTRACT:
|
||||||
|
res = PyNumber_InPlaceSubtract(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_TRUE_DIVIDE:
|
||||||
|
res = PyNumber_InPlaceTrueDivide(lhs, rhs);
|
||||||
|
break;
|
||||||
|
case NB_INPLACE_XOR:
|
||||||
|
res = PyNumber_InPlaceXor(lhs, rhs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Py_UNREACHABLE();
|
||||||
|
}
|
||||||
|
Py_DECREF(lhs);
|
||||||
|
Py_DECREF(rhs);
|
||||||
|
SET_TOP(res);
|
||||||
|
if (res == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET(BINARY_OP_ADAPTIVE) {
|
||||||
|
assert(cframe.use_tracing == 0);
|
||||||
|
SpecializedCacheEntry *cache = GET_CACHE();
|
||||||
|
if (cache->adaptive.counter == 0) {
|
||||||
|
PyObject *lhs = SECOND();
|
||||||
|
PyObject *rhs = TOP();
|
||||||
|
next_instr--;
|
||||||
|
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, cache);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
STAT_INC(BINARY_OP, deferred);
|
||||||
|
cache->adaptive.counter--;
|
||||||
|
oparg = cache->adaptive.original_oparg;
|
||||||
|
STAT_DEC(BINARY_OP, unquickened);
|
||||||
|
JUMP_TO_INSTRUCTION(BINARY_OP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TARGET(EXTENDED_ARG) {
|
TARGET(EXTENDED_ARG) {
|
||||||
int oldoparg = oparg;
|
int oldoparg = oparg;
|
||||||
NEXTOPARG();
|
NEXTOPARG();
|
||||||
|
@ -5137,9 +4890,8 @@ MISS_WITH_CACHE(STORE_ATTR)
|
||||||
MISS_WITH_CACHE(LOAD_GLOBAL)
|
MISS_WITH_CACHE(LOAD_GLOBAL)
|
||||||
MISS_WITH_CACHE(LOAD_METHOD)
|
MISS_WITH_CACHE(LOAD_METHOD)
|
||||||
MISS_WITH_CACHE(CALL_FUNCTION)
|
MISS_WITH_CACHE(CALL_FUNCTION)
|
||||||
|
MISS_WITH_CACHE(BINARY_OP)
|
||||||
MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR)
|
MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR)
|
||||||
MISS_WITH_OPARG_COUNTER(BINARY_ADD)
|
|
||||||
MISS_WITH_OPARG_COUNTER(BINARY_MULTIPLY)
|
|
||||||
|
|
||||||
binary_subscr_dict_error:
|
binary_subscr_dict_error:
|
||||||
{
|
{
|
||||||
|
@ -7173,60 +6925,6 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w,
|
|
||||||
InterpreterFrame *frame, const _Py_CODEUNIT *next_instr)
|
|
||||||
{
|
|
||||||
PyObject *res;
|
|
||||||
if (Py_REFCNT(v) == 2) {
|
|
||||||
/* In the common case, there are 2 references to the value
|
|
||||||
* stored in 'variable' when the += is performed: one on the
|
|
||||||
* value stack (in 'v') and one still stored in the
|
|
||||||
* 'variable'. We try to delete the variable now to reduce
|
|
||||||
* the refcnt to 1.
|
|
||||||
*/
|
|
||||||
int opcode, oparg;
|
|
||||||
NEXTOPARG();
|
|
||||||
next_instr++;
|
|
||||||
switch (opcode) {
|
|
||||||
case STORE_FAST:
|
|
||||||
{
|
|
||||||
if (GETLOCAL(oparg) == v)
|
|
||||||
SETLOCAL(oparg, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STORE_DEREF:
|
|
||||||
{
|
|
||||||
PyObject *c = _PyFrame_GetLocalsArray(frame)[oparg];
|
|
||||||
if (PyCell_GET(c) == v) {
|
|
||||||
PyCell_SET(c, NULL);
|
|
||||||
Py_DECREF(v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STORE_NAME:
|
|
||||||
{
|
|
||||||
PyObject *names = frame->f_code->co_names;
|
|
||||||
PyObject *name = GETITEM(names, oparg);
|
|
||||||
PyObject *locals = frame->f_locals;
|
|
||||||
if (locals && PyDict_CheckExact(locals)) {
|
|
||||||
PyObject *w = PyDict_GetItemWithError(locals, name);
|
|
||||||
if ((w == v && PyDict_DelItem(locals, name) != 0) ||
|
|
||||||
(w == NULL && _PyErr_Occurred(tstate)))
|
|
||||||
{
|
|
||||||
Py_DECREF(v);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = v;
|
|
||||||
PyUnicode_Append(&res, w);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
165
Python/compile.c
165
Python/compile.c
|
@ -309,7 +309,6 @@ static int compiler_annassign(struct compiler *, stmt_ty);
|
||||||
static int compiler_subscript(struct compiler *, expr_ty);
|
static int compiler_subscript(struct compiler *, expr_ty);
|
||||||
static int compiler_slice(struct compiler *, expr_ty);
|
static int compiler_slice(struct compiler *, expr_ty);
|
||||||
|
|
||||||
static int inplace_binop(operator_ty);
|
|
||||||
static int are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);
|
static int are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1022,40 +1021,13 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
case MAP_ADD:
|
case MAP_ADD:
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
/* Binary operators */
|
|
||||||
case BINARY_POWER:
|
|
||||||
case BINARY_MULTIPLY:
|
|
||||||
case BINARY_MATRIX_MULTIPLY:
|
|
||||||
case BINARY_MODULO:
|
|
||||||
case BINARY_ADD:
|
|
||||||
case BINARY_SUBTRACT:
|
|
||||||
case BINARY_SUBSCR:
|
case BINARY_SUBSCR:
|
||||||
case BINARY_FLOOR_DIVIDE:
|
|
||||||
case BINARY_TRUE_DIVIDE:
|
|
||||||
return -1;
|
|
||||||
case INPLACE_FLOOR_DIVIDE:
|
|
||||||
case INPLACE_TRUE_DIVIDE:
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case INPLACE_ADD:
|
|
||||||
case INPLACE_SUBTRACT:
|
|
||||||
case INPLACE_MULTIPLY:
|
|
||||||
case INPLACE_MATRIX_MULTIPLY:
|
|
||||||
case INPLACE_MODULO:
|
|
||||||
return -1;
|
return -1;
|
||||||
case STORE_SUBSCR:
|
case STORE_SUBSCR:
|
||||||
return -3;
|
return -3;
|
||||||
case DELETE_SUBSCR:
|
case DELETE_SUBSCR:
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
case BINARY_LSHIFT:
|
|
||||||
case BINARY_RSHIFT:
|
|
||||||
case BINARY_AND:
|
|
||||||
case BINARY_XOR:
|
|
||||||
case BINARY_OR:
|
|
||||||
return -1;
|
|
||||||
case INPLACE_POWER:
|
|
||||||
return -1;
|
|
||||||
case GET_ITER:
|
case GET_ITER:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1063,12 +1035,6 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
return -1;
|
return -1;
|
||||||
case LOAD_BUILD_CLASS:
|
case LOAD_BUILD_CLASS:
|
||||||
return 1;
|
return 1;
|
||||||
case INPLACE_LSHIFT:
|
|
||||||
case INPLACE_RSHIFT:
|
|
||||||
case INPLACE_AND:
|
|
||||||
case INPLACE_XOR:
|
|
||||||
case INPLACE_OR:
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case RETURN_VALUE:
|
case RETURN_VALUE:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1259,6 +1225,8 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
return 0;
|
return 0;
|
||||||
case COPY:
|
case COPY:
|
||||||
return 1;
|
return 1;
|
||||||
|
case BINARY_OP:
|
||||||
|
return -1;
|
||||||
default:
|
default:
|
||||||
return PY_INVALID_STACK_EFFECT;
|
return PY_INVALID_STACK_EFFECT;
|
||||||
}
|
}
|
||||||
|
@ -1685,6 +1653,12 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b)
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ADDOP_BINARY(C, BINOP) \
|
||||||
|
RETURN_IF_FALSE(addop_binary((C), (BINOP), false))
|
||||||
|
|
||||||
|
#define ADDOP_INPLACE(C, BINOP) \
|
||||||
|
RETURN_IF_FALSE(addop_binary((C), (BINOP), true))
|
||||||
|
|
||||||
/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
|
/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
|
||||||
the ASDL name to synthesize the name of the C type and the visit function.
|
the ASDL name to synthesize the name of the C type and the visit function.
|
||||||
*/
|
*/
|
||||||
|
@ -3693,77 +3667,56 @@ unaryop(unaryop_ty op)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
binop(operator_ty op)
|
addop_binary(struct compiler *c, operator_ty binop, bool inplace)
|
||||||
{
|
{
|
||||||
switch (op) {
|
int oparg;
|
||||||
case Add:
|
switch (binop) {
|
||||||
return BINARY_ADD;
|
case Add:
|
||||||
case Sub:
|
oparg = inplace ? NB_INPLACE_ADD : NB_ADD;
|
||||||
return BINARY_SUBTRACT;
|
break;
|
||||||
case Mult:
|
case Sub:
|
||||||
return BINARY_MULTIPLY;
|
oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT;
|
||||||
case MatMult:
|
break;
|
||||||
return BINARY_MATRIX_MULTIPLY;
|
case Mult:
|
||||||
case Div:
|
oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY;
|
||||||
return BINARY_TRUE_DIVIDE;
|
break;
|
||||||
case Mod:
|
case MatMult:
|
||||||
return BINARY_MODULO;
|
oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY;
|
||||||
case Pow:
|
break;
|
||||||
return BINARY_POWER;
|
case Div:
|
||||||
case LShift:
|
oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE;
|
||||||
return BINARY_LSHIFT;
|
break;
|
||||||
case RShift:
|
case Mod:
|
||||||
return BINARY_RSHIFT;
|
oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER;
|
||||||
case BitOr:
|
break;
|
||||||
return BINARY_OR;
|
case Pow:
|
||||||
case BitXor:
|
oparg = inplace ? NB_INPLACE_POWER : NB_POWER;
|
||||||
return BINARY_XOR;
|
break;
|
||||||
case BitAnd:
|
case LShift:
|
||||||
return BINARY_AND;
|
oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT;
|
||||||
case FloorDiv:
|
break;
|
||||||
return BINARY_FLOOR_DIVIDE;
|
case RShift:
|
||||||
default:
|
oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT;
|
||||||
PyErr_Format(PyExc_SystemError,
|
break;
|
||||||
"binary op %d should not be possible", op);
|
case BitOr:
|
||||||
return 0;
|
oparg = inplace ? NB_INPLACE_OR : NB_OR;
|
||||||
}
|
break;
|
||||||
}
|
case BitXor:
|
||||||
|
oparg = inplace ? NB_INPLACE_XOR : NB_XOR;
|
||||||
static int
|
break;
|
||||||
inplace_binop(operator_ty op)
|
case BitAnd:
|
||||||
{
|
oparg = inplace ? NB_INPLACE_AND : NB_AND;
|
||||||
switch (op) {
|
break;
|
||||||
case Add:
|
case FloorDiv:
|
||||||
return INPLACE_ADD;
|
oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE;
|
||||||
case Sub:
|
break;
|
||||||
return INPLACE_SUBTRACT;
|
default:
|
||||||
case Mult:
|
PyErr_Format(PyExc_SystemError, "%s op %d should not be possible",
|
||||||
return INPLACE_MULTIPLY;
|
inplace ? "inplace" : "binary", binop);
|
||||||
case MatMult:
|
return 0;
|
||||||
return INPLACE_MATRIX_MULTIPLY;
|
|
||||||
case Div:
|
|
||||||
return INPLACE_TRUE_DIVIDE;
|
|
||||||
case Mod:
|
|
||||||
return INPLACE_MODULO;
|
|
||||||
case Pow:
|
|
||||||
return INPLACE_POWER;
|
|
||||||
case LShift:
|
|
||||||
return INPLACE_LSHIFT;
|
|
||||||
case RShift:
|
|
||||||
return INPLACE_RSHIFT;
|
|
||||||
case BitOr:
|
|
||||||
return INPLACE_OR;
|
|
||||||
case BitXor:
|
|
||||||
return INPLACE_XOR;
|
|
||||||
case BitAnd:
|
|
||||||
return INPLACE_AND;
|
|
||||||
case FloorDiv:
|
|
||||||
return INPLACE_FLOOR_DIVIDE;
|
|
||||||
default:
|
|
||||||
PyErr_Format(PyExc_SystemError,
|
|
||||||
"inplace binary op %d should not be possible", op);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
ADDOP_I(c, BINARY_OP, oparg);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -5354,7 +5307,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
||||||
case BinOp_kind:
|
case BinOp_kind:
|
||||||
VISIT(c, expr, e->v.BinOp.left);
|
VISIT(c, expr, e->v.BinOp.left);
|
||||||
VISIT(c, expr, e->v.BinOp.right);
|
VISIT(c, expr, e->v.BinOp.right);
|
||||||
ADDOP(c, binop(e->v.BinOp.op));
|
ADDOP_BINARY(c, e->v.BinOp.op);
|
||||||
break;
|
break;
|
||||||
case UnaryOp_kind:
|
case UnaryOp_kind:
|
||||||
VISIT(c, expr, e->v.UnaryOp.operand);
|
VISIT(c, expr, e->v.UnaryOp.operand);
|
||||||
|
@ -5540,7 +5493,7 @@ compiler_augassign(struct compiler *c, stmt_ty s)
|
||||||
c->u->u_end_col_offset = old_end_col_offset;
|
c->u->u_end_col_offset = old_end_col_offset;
|
||||||
|
|
||||||
VISIT(c, expr, s->v.AugAssign.value);
|
VISIT(c, expr, s->v.AugAssign.value);
|
||||||
ADDOP(c, inplace_binop(s->v.AugAssign.op));
|
ADDOP_INPLACE(c, s->v.AugAssign.op);
|
||||||
|
|
||||||
SET_LOC(c, e);
|
SET_LOC(c, e);
|
||||||
|
|
||||||
|
@ -6000,7 +5953,7 @@ pattern_helper_sequence_subscr(struct compiler *c, asdl_pattern_seq *patterns,
|
||||||
// nonnegative index:
|
// nonnegative index:
|
||||||
ADDOP(c, GET_LEN);
|
ADDOP(c, GET_LEN);
|
||||||
ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - i));
|
ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - i));
|
||||||
ADDOP(c, BINARY_SUBTRACT);
|
ADDOP_BINARY(c, Sub);
|
||||||
}
|
}
|
||||||
ADDOP(c, BINARY_SUBSCR);
|
ADDOP(c, BINARY_SUBSCR);
|
||||||
RETURN_IF_FALSE(compiler_pattern_subpattern(c, pattern, pc));
|
RETURN_IF_FALSE(compiler_pattern_subpattern(c, pattern, pc));
|
||||||
|
|
|
@ -6,67 +6,67 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_DUP_TOP,
|
&&TARGET_DUP_TOP,
|
||||||
&&TARGET_DUP_TOP_TWO,
|
&&TARGET_DUP_TOP_TWO,
|
||||||
&&TARGET_ROT_FOUR,
|
&&TARGET_ROT_FOUR,
|
||||||
&&TARGET_BINARY_ADD_ADAPTIVE,
|
&&TARGET_BINARY_OP_ADAPTIVE,
|
||||||
&&TARGET_BINARY_ADD_INT,
|
&&TARGET_BINARY_OP_ADD_INT,
|
||||||
&&TARGET_NOP,
|
&&TARGET_NOP,
|
||||||
&&TARGET_UNARY_POSITIVE,
|
&&TARGET_UNARY_POSITIVE,
|
||||||
&&TARGET_UNARY_NEGATIVE,
|
&&TARGET_UNARY_NEGATIVE,
|
||||||
&&TARGET_UNARY_NOT,
|
&&TARGET_UNARY_NOT,
|
||||||
&&TARGET_BINARY_ADD_FLOAT,
|
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||||
&&TARGET_BINARY_ADD_UNICODE,
|
&&TARGET_BINARY_OP_ADD_UNICODE,
|
||||||
&&TARGET_UNARY_INVERT,
|
&&TARGET_UNARY_INVERT,
|
||||||
&&TARGET_BINARY_MATRIX_MULTIPLY,
|
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||||
&&TARGET_INPLACE_MATRIX_MULTIPLY,
|
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||||
&&TARGET_BINARY_ADD_UNICODE_INPLACE_FAST,
|
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||||
&&TARGET_BINARY_POWER,
|
|
||||||
&&TARGET_BINARY_MULTIPLY,
|
|
||||||
&&TARGET_BINARY_MULTIPLY_ADAPTIVE,
|
|
||||||
&&TARGET_BINARY_MODULO,
|
|
||||||
&&TARGET_BINARY_ADD,
|
|
||||||
&&TARGET_BINARY_SUBTRACT,
|
|
||||||
&&TARGET_BINARY_SUBSCR,
|
|
||||||
&&TARGET_BINARY_FLOOR_DIVIDE,
|
|
||||||
&&TARGET_BINARY_TRUE_DIVIDE,
|
|
||||||
&&TARGET_INPLACE_FLOOR_DIVIDE,
|
|
||||||
&&TARGET_INPLACE_TRUE_DIVIDE,
|
|
||||||
&&TARGET_GET_LEN,
|
|
||||||
&&TARGET_MATCH_MAPPING,
|
|
||||||
&&TARGET_MATCH_SEQUENCE,
|
|
||||||
&&TARGET_MATCH_KEYS,
|
|
||||||
&&TARGET_BINARY_MULTIPLY_INT,
|
|
||||||
&&TARGET_PUSH_EXC_INFO,
|
|
||||||
&&TARGET_BINARY_MULTIPLY_FLOAT,
|
|
||||||
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
|
||||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||||
&&TARGET_BINARY_SUBSCR_DICT,
|
&&TARGET_BINARY_SUBSCR_DICT,
|
||||||
&&TARGET_CALL_FUNCTION_ADAPTIVE,
|
&&TARGET_CALL_FUNCTION_ADAPTIVE,
|
||||||
&&TARGET_CALL_FUNCTION_BUILTIN_O,
|
&&TARGET_CALL_FUNCTION_BUILTIN_O,
|
||||||
|
&&TARGET_BINARY_SUBSCR,
|
||||||
&&TARGET_CALL_FUNCTION_BUILTIN_FAST,
|
&&TARGET_CALL_FUNCTION_BUILTIN_FAST,
|
||||||
&&TARGET_CALL_FUNCTION_LEN,
|
&&TARGET_CALL_FUNCTION_LEN,
|
||||||
&&TARGET_CALL_FUNCTION_ISINSTANCE,
|
&&TARGET_CALL_FUNCTION_ISINSTANCE,
|
||||||
&&TARGET_CALL_FUNCTION_PY_SIMPLE,
|
&&TARGET_CALL_FUNCTION_PY_SIMPLE,
|
||||||
|
&&TARGET_GET_LEN,
|
||||||
|
&&TARGET_MATCH_MAPPING,
|
||||||
|
&&TARGET_MATCH_SEQUENCE,
|
||||||
|
&&TARGET_MATCH_KEYS,
|
||||||
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
||||||
|
&&TARGET_PUSH_EXC_INFO,
|
||||||
|
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||||
|
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
||||||
|
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||||
|
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||||
|
&&TARGET_LOAD_ATTR_SLOT,
|
||||||
|
&&TARGET_LOAD_ATTR_MODULE,
|
||||||
|
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
||||||
|
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||||
|
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||||
|
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||||
|
&&TARGET_LOAD_METHOD_CACHED,
|
||||||
|
&&TARGET_LOAD_METHOD_CLASS,
|
||||||
|
&&TARGET_LOAD_METHOD_MODULE,
|
||||||
&&TARGET_WITH_EXCEPT_START,
|
&&TARGET_WITH_EXCEPT_START,
|
||||||
&&TARGET_GET_AITER,
|
&&TARGET_GET_AITER,
|
||||||
&&TARGET_GET_ANEXT,
|
&&TARGET_GET_ANEXT,
|
||||||
&&TARGET_BEFORE_ASYNC_WITH,
|
&&TARGET_BEFORE_ASYNC_WITH,
|
||||||
&&TARGET_BEFORE_WITH,
|
&&TARGET_BEFORE_WITH,
|
||||||
&&TARGET_END_ASYNC_FOR,
|
&&TARGET_END_ASYNC_FOR,
|
||||||
&&TARGET_INPLACE_ADD,
|
&&TARGET_LOAD_METHOD_NO_DICT,
|
||||||
&&TARGET_INPLACE_SUBTRACT,
|
&&TARGET_STORE_ATTR_ADAPTIVE,
|
||||||
&&TARGET_INPLACE_MULTIPLY,
|
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
&&TARGET_STORE_ATTR_SLOT,
|
||||||
&&TARGET_INPLACE_MODULO,
|
&&TARGET_STORE_ATTR_WITH_HINT,
|
||||||
&&TARGET_STORE_SUBSCR,
|
&&TARGET_STORE_SUBSCR,
|
||||||
&&TARGET_DELETE_SUBSCR,
|
&&TARGET_DELETE_SUBSCR,
|
||||||
&&TARGET_BINARY_LSHIFT,
|
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||||
&&TARGET_BINARY_RSHIFT,
|
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||||
&&TARGET_BINARY_AND,
|
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||||
&&TARGET_BINARY_XOR,
|
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||||
&&TARGET_BINARY_OR,
|
&&TARGET_STORE_FAST__STORE_FAST,
|
||||||
&&TARGET_INPLACE_POWER,
|
&&_unknown_opcode,
|
||||||
&&TARGET_GET_ITER,
|
&&TARGET_GET_ITER,
|
||||||
&&TARGET_GET_YIELD_FROM_ITER,
|
&&TARGET_GET_YIELD_FROM_ITER,
|
||||||
&&TARGET_PRINT_EXPR,
|
&&TARGET_PRINT_EXPR,
|
||||||
|
@ -74,20 +74,20 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_YIELD_FROM,
|
&&TARGET_YIELD_FROM,
|
||||||
&&TARGET_GET_AWAITABLE,
|
&&TARGET_GET_AWAITABLE,
|
||||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||||
&&TARGET_INPLACE_LSHIFT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_INPLACE_RSHIFT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_INPLACE_AND,
|
&&_unknown_opcode,
|
||||||
&&TARGET_INPLACE_XOR,
|
&&_unknown_opcode,
|
||||||
&&TARGET_INPLACE_OR,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LIST_TO_TUPLE,
|
&&TARGET_LIST_TO_TUPLE,
|
||||||
&&TARGET_RETURN_VALUE,
|
&&TARGET_RETURN_VALUE,
|
||||||
&&TARGET_IMPORT_STAR,
|
&&TARGET_IMPORT_STAR,
|
||||||
&&TARGET_SETUP_ANNOTATIONS,
|
&&TARGET_SETUP_ANNOTATIONS,
|
||||||
&&TARGET_YIELD_VALUE,
|
&&TARGET_YIELD_VALUE,
|
||||||
&&TARGET_LOAD_ATTR_SLOT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_ATTR_MODULE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_POP_EXCEPT,
|
&&TARGET_POP_EXCEPT,
|
||||||
&&TARGET_STORE_NAME,
|
&&TARGET_STORE_NAME,
|
||||||
&&TARGET_DELETE_NAME,
|
&&TARGET_DELETE_NAME,
|
||||||
|
@ -121,44 +121,44 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_RERAISE,
|
&&TARGET_RERAISE,
|
||||||
&&TARGET_COPY,
|
&&TARGET_COPY,
|
||||||
&&TARGET_JUMP_IF_NOT_EXC_MATCH,
|
&&TARGET_JUMP_IF_NOT_EXC_MATCH,
|
||||||
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
&&TARGET_BINARY_OP,
|
||||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_FAST,
|
&&TARGET_LOAD_FAST,
|
||||||
&&TARGET_STORE_FAST,
|
&&TARGET_STORE_FAST,
|
||||||
&&TARGET_DELETE_FAST,
|
&&TARGET_DELETE_FAST,
|
||||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_GEN_START,
|
&&TARGET_GEN_START,
|
||||||
&&TARGET_RAISE_VARARGS,
|
&&TARGET_RAISE_VARARGS,
|
||||||
&&TARGET_CALL_FUNCTION,
|
&&TARGET_CALL_FUNCTION,
|
||||||
&&TARGET_MAKE_FUNCTION,
|
&&TARGET_MAKE_FUNCTION,
|
||||||
&&TARGET_BUILD_SLICE,
|
&&TARGET_BUILD_SLICE,
|
||||||
&&TARGET_LOAD_METHOD_CACHED,
|
&&_unknown_opcode,
|
||||||
&&TARGET_MAKE_CELL,
|
&&TARGET_MAKE_CELL,
|
||||||
&&TARGET_LOAD_CLOSURE,
|
&&TARGET_LOAD_CLOSURE,
|
||||||
&&TARGET_LOAD_DEREF,
|
&&TARGET_LOAD_DEREF,
|
||||||
&&TARGET_STORE_DEREF,
|
&&TARGET_STORE_DEREF,
|
||||||
&&TARGET_DELETE_DEREF,
|
&&TARGET_DELETE_DEREF,
|
||||||
&&TARGET_LOAD_METHOD_CLASS,
|
&&_unknown_opcode,
|
||||||
&&TARGET_CALL_FUNCTION_KW,
|
&&TARGET_CALL_FUNCTION_KW,
|
||||||
&&TARGET_CALL_FUNCTION_EX,
|
&&TARGET_CALL_FUNCTION_EX,
|
||||||
&&TARGET_LOAD_METHOD_MODULE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_EXTENDED_ARG,
|
&&TARGET_EXTENDED_ARG,
|
||||||
&&TARGET_LIST_APPEND,
|
&&TARGET_LIST_APPEND,
|
||||||
&&TARGET_SET_ADD,
|
&&TARGET_SET_ADD,
|
||||||
&&TARGET_MAP_ADD,
|
&&TARGET_MAP_ADD,
|
||||||
&&TARGET_LOAD_CLASSDEREF,
|
&&TARGET_LOAD_CLASSDEREF,
|
||||||
&&TARGET_LOAD_METHOD_NO_DICT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_ATTR_ADAPTIVE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
&&_unknown_opcode,
|
||||||
&&TARGET_MATCH_CLASS,
|
&&TARGET_MATCH_CLASS,
|
||||||
&&TARGET_STORE_ATTR_SLOT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_ATTR_WITH_HINT,
|
&&_unknown_opcode,
|
||||||
&&TARGET_FORMAT_VALUE,
|
&&TARGET_FORMAT_VALUE,
|
||||||
&&TARGET_BUILD_CONST_KEY_MAP,
|
&&TARGET_BUILD_CONST_KEY_MAP,
|
||||||
&&TARGET_BUILD_STRING,
|
&&TARGET_BUILD_STRING,
|
||||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_METHOD,
|
&&TARGET_LOAD_METHOD,
|
||||||
&&TARGET_CALL_METHOD,
|
&&TARGET_CALL_METHOD,
|
||||||
&&TARGET_LIST_EXTEND,
|
&&TARGET_LIST_EXTEND,
|
||||||
|
@ -166,9 +166,9 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_DICT_MERGE,
|
&&TARGET_DICT_MERGE,
|
||||||
&&TARGET_DICT_UPDATE,
|
&&TARGET_DICT_UPDATE,
|
||||||
&&TARGET_CALL_METHOD_KW,
|
&&TARGET_CALL_METHOD_KW,
|
||||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_FAST__STORE_FAST,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
|
|
|
@ -124,11 +124,10 @@ _Py_GetSpecializationStats(void) {
|
||||||
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
|
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
|
||||||
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
|
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
|
||||||
err += add_stat_dict(stats, LOAD_METHOD, "load_method");
|
err += add_stat_dict(stats, LOAD_METHOD, "load_method");
|
||||||
err += add_stat_dict(stats, BINARY_ADD, "binary_add");
|
|
||||||
err += add_stat_dict(stats, BINARY_MULTIPLY, "binary_multiply");
|
|
||||||
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
|
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
|
||||||
err += add_stat_dict(stats, STORE_ATTR, "store_attr");
|
err += add_stat_dict(stats, STORE_ATTR, "store_attr");
|
||||||
err += add_stat_dict(stats, CALL_FUNCTION, "call_function");
|
err += add_stat_dict(stats, CALL_FUNCTION, "call_function");
|
||||||
|
err += add_stat_dict(stats, BINARY_OP, "binary_op");
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
Py_DECREF(stats);
|
Py_DECREF(stats);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -182,11 +181,10 @@ _Py_PrintSpecializationStats(void)
|
||||||
print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr");
|
print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr");
|
||||||
print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global");
|
print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global");
|
||||||
print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method");
|
print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method");
|
||||||
print_stats(out, &_specialization_stats[BINARY_ADD], "binary_add");
|
|
||||||
print_stats(out, &_specialization_stats[BINARY_MULTIPLY], "binary_multiply");
|
|
||||||
print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr");
|
print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr");
|
||||||
print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr");
|
print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr");
|
||||||
print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function");
|
print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function");
|
||||||
|
print_stats(out, &_specialization_stats[BINARY_OP], "binary_op");
|
||||||
if (out != stderr) {
|
if (out != stderr) {
|
||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
|
@ -234,11 +232,10 @@ static uint8_t adaptive_opcodes[256] = {
|
||||||
[LOAD_ATTR] = LOAD_ATTR_ADAPTIVE,
|
[LOAD_ATTR] = LOAD_ATTR_ADAPTIVE,
|
||||||
[LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE,
|
[LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE,
|
||||||
[LOAD_METHOD] = LOAD_METHOD_ADAPTIVE,
|
[LOAD_METHOD] = LOAD_METHOD_ADAPTIVE,
|
||||||
[BINARY_ADD] = BINARY_ADD_ADAPTIVE,
|
|
||||||
[BINARY_MULTIPLY] = BINARY_MULTIPLY_ADAPTIVE,
|
|
||||||
[BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
|
[BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
|
||||||
[CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE,
|
[CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE,
|
||||||
[STORE_ATTR] = STORE_ATTR_ADAPTIVE,
|
[STORE_ATTR] = STORE_ATTR_ADAPTIVE,
|
||||||
|
[BINARY_OP] = BINARY_OP_ADAPTIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The number of cache entries required for a "family" of instructions. */
|
/* The number of cache entries required for a "family" of instructions. */
|
||||||
|
@ -246,11 +243,10 @@ static uint8_t cache_requirements[256] = {
|
||||||
[LOAD_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
[LOAD_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
||||||
[LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */
|
[LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */
|
||||||
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
|
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
|
||||||
[BINARY_ADD] = 0,
|
|
||||||
[BINARY_MULTIPLY] = 0,
|
|
||||||
[BINARY_SUBSCR] = 0,
|
[BINARY_SUBSCR] = 0,
|
||||||
[CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
|
[CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
|
||||||
[STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
[STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
||||||
|
[BINARY_OP] = 1, // _PyAdaptiveEntry
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return the oparg for the cache_offset and instruction index.
|
/* Return the oparg for the cache_offset and instruction index.
|
||||||
|
@ -1183,76 +1179,6 @@ success:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
_Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr)
|
|
||||||
{
|
|
||||||
PyTypeObject *left_type = Py_TYPE(left);
|
|
||||||
if (left_type != Py_TYPE(right)) {
|
|
||||||
SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_DIFFERENT_TYPES);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (left_type == &PyUnicode_Type) {
|
|
||||||
int next_opcode = _Py_OPCODE(instr[1]);
|
|
||||||
if (next_opcode == STORE_FAST) {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE_INPLACE_FAST, initial_counter_value());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE, initial_counter_value());
|
|
||||||
}
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
else if (left_type == &PyLong_Type) {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_INT, initial_counter_value());
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
else if (left_type == &PyFloat_Type) {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_FLOAT, initial_counter_value());
|
|
||||||
goto success;
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER);
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
STAT_INC(BINARY_ADD, specialization_failure);
|
|
||||||
assert(!PyErr_Occurred());
|
|
||||||
*instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
|
|
||||||
return 0;
|
|
||||||
success:
|
|
||||||
STAT_INC(BINARY_ADD, specialization_success);
|
|
||||||
assert(!PyErr_Occurred());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr)
|
|
||||||
{
|
|
||||||
if (!Py_IS_TYPE(left, Py_TYPE(right))) {
|
|
||||||
SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_DIFFERENT_TYPES);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (PyLong_CheckExact(left)) {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_INT, initial_counter_value());
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
else if (PyFloat_CheckExact(left)) {
|
|
||||||
*instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_FLOAT, initial_counter_value());
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_OTHER);
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
STAT_INC(BINARY_MULTIPLY, specialization_failure);
|
|
||||||
assert(!PyErr_Occurred());
|
|
||||||
*instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
|
|
||||||
return 0;
|
|
||||||
success:
|
|
||||||
STAT_INC(BINARY_MULTIPLY, specialization_success);
|
|
||||||
assert(!PyErr_Occurred());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
specialize_class_call(
|
specialize_class_call(
|
||||||
PyObject *callable, _Py_CODEUNIT *instr,
|
PyObject *callable, _Py_CODEUNIT *instr,
|
||||||
|
@ -1448,3 +1374,64 @@ _Py_Specialize_CallFunction(
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||||
|
SpecializedCacheEntry *cache)
|
||||||
|
{
|
||||||
|
_PyAdaptiveEntry *adaptive = &cache->adaptive;
|
||||||
|
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
|
||||||
|
SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES);
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
switch (adaptive->original_oparg) {
|
||||||
|
case NB_ADD:
|
||||||
|
case NB_INPLACE_ADD:
|
||||||
|
if (PyUnicode_CheckExact(lhs)) {
|
||||||
|
if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_INPLACE_ADD_UNICODE,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_UNICODE,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
if (PyLong_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_INT, _Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
if (PyFloat_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_FLOAT,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NB_MULTIPLY:
|
||||||
|
case NB_INPLACE_MULTIPLY:
|
||||||
|
if (PyLong_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
if (PyFloat_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_FLOAT,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// These operators don't have any available specializations. Rather
|
||||||
|
// than repeatedly attempting to specialize them, just convert them
|
||||||
|
// back to BINARY_OP (while still recording a failure, of course)!
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP, adaptive->original_oparg);
|
||||||
|
}
|
||||||
|
SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER);
|
||||||
|
failure:
|
||||||
|
STAT_INC(BINARY_OP, specialization_failure);
|
||||||
|
cache_backoff(adaptive);
|
||||||
|
return;
|
||||||
|
success:
|
||||||
|
STAT_INC(BINARY_OP, specialization_success);
|
||||||
|
adaptive->counter = initial_counter_value();
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Instruction opcodes for compiled code */
|
/* Instruction opcodes for compiled code */
|
||||||
""".lstrip()
|
""".lstrip()
|
||||||
|
|
||||||
footer = """
|
footer = """
|
||||||
|
@ -28,6 +28,8 @@ footer = """
|
||||||
#endif /* !Py_OPCODE_H */
|
#endif /* !Py_OPCODE_H */
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
DEFINE = "#define {:<31} {:>3}\n"
|
||||||
|
|
||||||
UINT32_MASK = (1<<32)-1
|
UINT32_MASK = (1<<32)-1
|
||||||
|
|
||||||
def write_int_array_from_ops(name, ops, out):
|
def write_int_array_from_ops(name, ops, out):
|
||||||
|
@ -62,17 +64,16 @@ def main(opcode_py, outfile='Include/opcode.h'):
|
||||||
fobj.write(header)
|
fobj.write(header)
|
||||||
for name in opcode['opname']:
|
for name in opcode['opname']:
|
||||||
if name in opmap:
|
if name in opmap:
|
||||||
fobj.write("#define %-23s %3s\n" % (name, opmap[name]))
|
fobj.write(DEFINE.format(name, opmap[name]))
|
||||||
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
|
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
|
||||||
fobj.write("#define %-23s %3d\n" %
|
fobj.write(DEFINE.format("HAVE_ARGUMENT", opcode["HAVE_ARGUMENT"]))
|
||||||
('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT']))
|
|
||||||
|
|
||||||
for name in opcode['_specialized_instructions']:
|
for name in opcode['_specialized_instructions']:
|
||||||
while used[next_op]:
|
while used[next_op]:
|
||||||
next_op += 1
|
next_op += 1
|
||||||
fobj.write("#define %-23s %3s\n" % (name, next_op))
|
fobj.write(DEFINE.format(name, next_op))
|
||||||
used[next_op] = True
|
used[next_op] = True
|
||||||
fobj.write("#define DO_TRACING 255\n")
|
fobj.write(DEFINE.format('DO_TRACING', 255))
|
||||||
fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
|
fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
|
||||||
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
|
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
|
||||||
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
|
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
|
||||||
|
@ -84,10 +85,14 @@ def main(opcode_py, outfile='Include/opcode.h'):
|
||||||
fobj.write(f"\n || ((op) == {op}) \\")
|
fobj.write(f"\n || ((op) == {op}) \\")
|
||||||
fobj.write("\n )\n")
|
fobj.write("\n )\n")
|
||||||
|
|
||||||
|
fobj.write("\n")
|
||||||
|
for i, (op, _) in enumerate(opcode["_nb_ops"]):
|
||||||
|
fobj.write(DEFINE.format(op, i))
|
||||||
|
|
||||||
fobj.write(footer)
|
fobj.write(footer)
|
||||||
|
|
||||||
|
|
||||||
print("%s regenerated from %s" % (outfile, opcode_py))
|
print(f"{outfile} regenerated from {opcode_py}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in New Issue