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

135
Include/opcode.h generated
View File

@ -18,18 +18,7 @@ extern "C" {
#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 INPLACE_MATRIX_MULTIPLY 17
#define BINARY_POWER 19
#define BINARY_MULTIPLY 20
#define BINARY_MODULO 22
#define BINARY_ADD 23
#define BINARY_SUBTRACT 24
#define BINARY_SUBSCR 25 #define BINARY_SUBSCR 25
#define BINARY_FLOOR_DIVIDE 26
#define BINARY_TRUE_DIVIDE 27
#define INPLACE_FLOOR_DIVIDE 28
#define INPLACE_TRUE_DIVIDE 29
#define GET_LEN 30 #define GET_LEN 30
#define MATCH_MAPPING 31 #define MATCH_MAPPING 31
#define MATCH_SEQUENCE 32 #define MATCH_SEQUENCE 32
@ -42,18 +31,8 @@ extern "C" {
#define BEFORE_ASYNC_WITH 52 #define BEFORE_ASYNC_WITH 52
#define BEFORE_WITH 53 #define BEFORE_WITH 53
#define END_ASYNC_FOR 54 #define END_ASYNC_FOR 54
#define INPLACE_ADD 55
#define INPLACE_SUBTRACT 56
#define INPLACE_MULTIPLY 57
#define INPLACE_MODULO 59
#define STORE_SUBSCR 60 #define STORE_SUBSCR 60
#define DELETE_SUBSCR 61 #define DELETE_SUBSCR 61
#define BINARY_LSHIFT 62
#define BINARY_RSHIFT 63
#define BINARY_AND 64
#define BINARY_XOR 65
#define BINARY_OR 66
#define INPLACE_POWER 67
#define GET_ITER 68 #define GET_ITER 68
#define GET_YIELD_FROM_ITER 69 #define GET_YIELD_FROM_ITER 69
#define PRINT_EXPR 70 #define PRINT_EXPR 70
@ -61,11 +40,6 @@ extern "C" {
#define YIELD_FROM 72 #define YIELD_FROM 72
#define GET_AWAITABLE 73 #define GET_AWAITABLE 73
#define LOAD_ASSERTION_ERROR 74 #define LOAD_ASSERTION_ERROR 74
#define INPLACE_LSHIFT 75
#define INPLACE_RSHIFT 76
#define INPLACE_AND 77
#define INPLACE_XOR 78
#define INPLACE_OR 79
#define LIST_TO_TUPLE 82 #define LIST_TO_TUPLE 82
#define RETURN_VALUE 83 #define RETURN_VALUE 83
#define IMPORT_STAR 84 #define IMPORT_STAR 84
@ -105,6 +79,7 @@ extern "C" {
#define RERAISE 119 #define RERAISE 119
#define COPY 120 #define COPY 120
#define JUMP_IF_NOT_EXC_MATCH 121 #define JUMP_IF_NOT_EXC_MATCH 121
#define BINARY_OP 122
#define LOAD_FAST 124 #define LOAD_FAST 124
#define STORE_FAST 125 #define STORE_FAST 125
#define DELETE_FAST 126 #define DELETE_FAST 126
@ -136,47 +111,46 @@ extern "C" {
#define DICT_MERGE 164 #define DICT_MERGE 164
#define DICT_UPDATE 165 #define DICT_UPDATE 165
#define CALL_METHOD_KW 166 #define CALL_METHOD_KW 166
#define BINARY_ADD_ADAPTIVE 7 #define BINARY_OP_ADAPTIVE 7
#define BINARY_ADD_INT 8 #define BINARY_OP_ADD_INT 8
#define BINARY_ADD_FLOAT 13 #define BINARY_OP_ADD_FLOAT 13
#define BINARY_ADD_UNICODE 14 #define BINARY_OP_ADD_UNICODE 14
#define BINARY_ADD_UNICODE_INPLACE_FAST 18 #define BINARY_OP_INPLACE_ADD_UNICODE 16
#define BINARY_MULTIPLY_ADAPTIVE 21 #define BINARY_OP_MULTIPLY_INT 17
#define BINARY_MULTIPLY_INT 34 #define BINARY_OP_MULTIPLY_FLOAT 18
#define BINARY_MULTIPLY_FLOAT 36 #define BINARY_SUBSCR_ADAPTIVE 19
#define BINARY_SUBSCR_ADAPTIVE 38 #define BINARY_SUBSCR_LIST_INT 20
#define BINARY_SUBSCR_LIST_INT 39 #define BINARY_SUBSCR_TUPLE_INT 21
#define BINARY_SUBSCR_TUPLE_INT 40 #define BINARY_SUBSCR_DICT 22
#define BINARY_SUBSCR_DICT 41 #define CALL_FUNCTION_ADAPTIVE 23
#define CALL_FUNCTION_ADAPTIVE 42 #define CALL_FUNCTION_BUILTIN_O 24
#define CALL_FUNCTION_BUILTIN_O 43 #define CALL_FUNCTION_BUILTIN_FAST 26
#define CALL_FUNCTION_BUILTIN_FAST 44 #define CALL_FUNCTION_LEN 27
#define CALL_FUNCTION_LEN 45 #define CALL_FUNCTION_ISINSTANCE 28
#define CALL_FUNCTION_ISINSTANCE 46 #define CALL_FUNCTION_PY_SIMPLE 29
#define CALL_FUNCTION_PY_SIMPLE 47 #define JUMP_ABSOLUTE_QUICK 34
#define JUMP_ABSOLUTE_QUICK 48 #define LOAD_ATTR_ADAPTIVE 36
#define LOAD_ATTR_ADAPTIVE 58 #define LOAD_ATTR_INSTANCE_VALUE 38
#define LOAD_ATTR_INSTANCE_VALUE 80 #define LOAD_ATTR_WITH_HINT 39
#define LOAD_ATTR_WITH_HINT 81 #define LOAD_ATTR_SLOT 40
#define LOAD_ATTR_SLOT 87 #define LOAD_ATTR_MODULE 41
#define LOAD_ATTR_MODULE 88 #define LOAD_GLOBAL_ADAPTIVE 42
#define LOAD_GLOBAL_ADAPTIVE 122 #define LOAD_GLOBAL_MODULE 43
#define LOAD_GLOBAL_MODULE 123 #define LOAD_GLOBAL_BUILTIN 44
#define LOAD_GLOBAL_BUILTIN 127 #define LOAD_METHOD_ADAPTIVE 45
#define LOAD_METHOD_ADAPTIVE 128 #define LOAD_METHOD_CACHED 46
#define LOAD_METHOD_CACHED 134 #define LOAD_METHOD_CLASS 47
#define LOAD_METHOD_CLASS 140 #define LOAD_METHOD_MODULE 48
#define LOAD_METHOD_MODULE 143 #define LOAD_METHOD_NO_DICT 55
#define LOAD_METHOD_NO_DICT 149 #define STORE_ATTR_ADAPTIVE 56
#define STORE_ATTR_ADAPTIVE 150 #define STORE_ATTR_INSTANCE_VALUE 57
#define STORE_ATTR_INSTANCE_VALUE 151 #define STORE_ATTR_SLOT 58
#define STORE_ATTR_SLOT 153 #define STORE_ATTR_WITH_HINT 59
#define STORE_ATTR_WITH_HINT 154 #define LOAD_FAST__LOAD_FAST 62
#define LOAD_FAST__LOAD_FAST 158 #define STORE_FAST__LOAD_FAST 63
#define STORE_FAST__LOAD_FAST 159 #define LOAD_FAST__LOAD_CONST 64
#define LOAD_FAST__LOAD_CONST 167 #define LOAD_CONST__LOAD_FAST 65
#define LOAD_CONST__LOAD_FAST 168 #define STORE_FAST__STORE_FAST 66
#define STORE_FAST__STORE_FAST 169
#define DO_TRACING 255 #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] = {
@ -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,10 +1048,12 @@ 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:
occurrence -= 1
if not occurrence:
self.assertEqual(position[0], line) self.assertEqual(position[0], line)
self.assertEqual(position[1], end_line) self.assertEqual(position[1], end_line)
self.assertEqual(position[2], column) self.assertEqual(position[2], column)
@ -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 *left = SECOND();
PyObject *right = TOP(); PyObject *right = TOP();
next_instr--; DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
if (_Py_Specialize_BinaryMultiply(left, right, next_instr) < 0) { DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
goto error; STAT_INC(BINARY_OP, hit);
}
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 *right = TOP();
DEOPT_IF(!PyLong_CheckExact(left), BINARY_MULTIPLY);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_MULTIPLY);
STAT_INC(BINARY_MULTIPLY, 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 *left = SECOND();
PyObject *right = TOP(); PyObject *right = TOP();
next_instr--; DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
if (_Py_Specialize_BinaryAdd(left, right, next_instr) < 0) { DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
goto error; STAT_INC(BINARY_OP, hit);
}
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 *right = TOP();
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD);
STAT_INC(BINARY_ADD, 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;
switch (binop) {
case Add: case Add:
return BINARY_ADD; oparg = inplace ? NB_INPLACE_ADD : NB_ADD;
break;
case Sub: case Sub:
return BINARY_SUBTRACT; oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT;
break;
case Mult: case Mult:
return BINARY_MULTIPLY; oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY;
break;
case MatMult: case MatMult:
return BINARY_MATRIX_MULTIPLY; oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY;
break;
case Div: case Div:
return BINARY_TRUE_DIVIDE; oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE;
break;
case Mod: case Mod:
return BINARY_MODULO; oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER;
break;
case Pow: case Pow:
return BINARY_POWER; oparg = inplace ? NB_INPLACE_POWER : NB_POWER;
break;
case LShift: case LShift:
return BINARY_LSHIFT; oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT;
break;
case RShift: case RShift:
return BINARY_RSHIFT; oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT;
break;
case BitOr: case BitOr:
return BINARY_OR; oparg = inplace ? NB_INPLACE_OR : NB_OR;
break;
case BitXor: case BitXor:
return BINARY_XOR; oparg = inplace ? NB_INPLACE_XOR : NB_XOR;
break;
case BitAnd: case BitAnd:
return BINARY_AND; oparg = inplace ? NB_INPLACE_AND : NB_AND;
break;
case FloorDiv: case FloorDiv:
return BINARY_FLOOR_DIVIDE; oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE;
break;
default: default:
PyErr_Format(PyExc_SystemError, PyErr_Format(PyExc_SystemError, "%s op %d should not be possible",
"binary op %d should not be possible", op); inplace ? "inplace" : "binary", binop);
return 0;
}
}
static int
inplace_binop(operator_ty op)
{
switch (op) {
case Add:
return INPLACE_ADD;
case Sub:
return INPLACE_SUBTRACT;
case Mult:
return INPLACE_MULTIPLY;
case MatMult:
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; 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

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