bpo-45636: Merge all numeric operators (GH-29482)

This commit is contained in:
Brandt Bucher 2021-11-10 22:56:22 -08:00 committed by GitHub
parent 1cbaa505d0
commit 9178f533ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 613 additions and 1081 deletions

View File

@ -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

View File

@ -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`.

View File

@ -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

345
Include/opcode.h generated
View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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",

View File

@ -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):

View File

@ -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),

View File

@ -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):

View File

@ -0,0 +1,2 @@
Replace all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single
:opcode:`BINARY_OP` implementation.

View File

@ -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 *

View File

@ -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));

126
Python/opcode_targets.h generated
View File

@ -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,

View File

@ -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();
}

View File

@ -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__':