mirror of https://github.com/python/cpython
bpo-46528: Simplify the VM's stack manipulations (GH-30902)
This commit is contained in:
parent
d4a85f104b
commit
8548366864
|
@ -348,7 +348,8 @@ The Python compiler currently generates the following bytecode instructions.
|
||||||
|
|
||||||
.. opcode:: NOP
|
.. opcode:: NOP
|
||||||
|
|
||||||
Do nothing code. Used as a placeholder by the bytecode optimizer.
|
Do nothing code. Used as a placeholder by the bytecode optimizer, and to
|
||||||
|
generate line tracing events.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: POP_TOP
|
.. opcode:: POP_TOP
|
||||||
|
@ -356,38 +357,19 @@ The Python compiler currently generates the following bytecode instructions.
|
||||||
Removes the top-of-stack (TOS) item.
|
Removes the top-of-stack (TOS) item.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: ROT_TWO
|
.. opcode:: COPY (i)
|
||||||
|
|
||||||
Swaps the two top-most stack items.
|
Push the *i*-th item to the top of the stack. The item is not removed from its
|
||||||
|
original location.
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: ROT_THREE
|
.. opcode:: SWAP (i)
|
||||||
|
|
||||||
Lifts second and third stack item one position up, moves top down to position
|
Swap TOS with the item at position *i*.
|
||||||
three.
|
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
.. opcode:: ROT_FOUR
|
|
||||||
|
|
||||||
Lifts second, third and fourth stack items one position up, moves top down
|
|
||||||
to position four.
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: DUP_TOP
|
|
||||||
|
|
||||||
Duplicates the reference on top of the stack.
|
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: DUP_TOP_TWO
|
|
||||||
|
|
||||||
Duplicates the two references on top of the stack, leaving them in the
|
|
||||||
same order.
|
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
|
||||||
|
|
||||||
|
|
||||||
**Unary operations**
|
**Unary operations**
|
||||||
|
@ -689,8 +671,6 @@ iterations of the loop.
|
||||||
success (``True``) or failure (``False``).
|
success (``True``) or failure (``False``).
|
||||||
|
|
||||||
|
|
||||||
All of the following opcodes use their arguments.
|
|
||||||
|
|
||||||
.. opcode:: STORE_NAME (namei)
|
.. opcode:: STORE_NAME (namei)
|
||||||
|
|
||||||
Implements ``name = TOS``. *namei* is the index of *name* in the attribute
|
Implements ``name = TOS``. *namei* is the index of *name* in the attribute
|
||||||
|
@ -1217,22 +1197,6 @@ All of the following opcodes use their arguments.
|
||||||
success (``True``) or failure (``False``).
|
success (``True``) or failure (``False``).
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: ROT_N (count)
|
|
||||||
|
|
||||||
Lift the top *count* stack items one position up, and move TOS down to
|
|
||||||
position *count*.
|
|
||||||
|
|
||||||
.. versionadded:: 3.10
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: COPY (i)
|
|
||||||
|
|
||||||
Push the *i*-th item to the top of the stack. The item is not removed from its
|
|
||||||
original location.
|
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: RESUME (where)
|
.. opcode:: RESUME (where)
|
||||||
|
|
||||||
A no-op. Performs internal tracing, debugging and optimization checks.
|
A no-op. Performs internal tracing, debugging and optimization checks.
|
||||||
|
|
|
@ -411,8 +411,9 @@ CPython bytecode changes
|
||||||
indicate failure with :const:`None` (where a tuple of extracted values would
|
indicate failure with :const:`None` (where a tuple of extracted values would
|
||||||
otherwise be).
|
otherwise be).
|
||||||
|
|
||||||
* Added :opcode:`COPY`, which pushes the *i*-th item to the top of the stack.
|
* Replace several stack manipulation instructions (``DUP_TOP``, ``DUP_TOP_TWO``,
|
||||||
The item is not removed from its original location.
|
``ROT_TWO``, ``ROT_THREE``, ``ROT_FOUR``, and ``ROT_N``) with new
|
||||||
|
:opcode:`COPY` and :opcode:`SWAP` instructions.
|
||||||
|
|
||||||
* Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to
|
* Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to
|
||||||
speed up conditional jumps.
|
speed up conditional jumps.
|
||||||
|
|
|
@ -8,11 +8,6 @@ extern "C" {
|
||||||
|
|
||||||
/* Instruction opcodes for compiled code */
|
/* Instruction opcodes for compiled code */
|
||||||
#define POP_TOP 1
|
#define POP_TOP 1
|
||||||
#define ROT_TWO 2
|
|
||||||
#define ROT_THREE 3
|
|
||||||
#define DUP_TOP 4
|
|
||||||
#define DUP_TOP_TWO 5
|
|
||||||
#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
|
||||||
|
@ -57,7 +52,7 @@ extern "C" {
|
||||||
#define DELETE_ATTR 96
|
#define DELETE_ATTR 96
|
||||||
#define STORE_GLOBAL 97
|
#define STORE_GLOBAL 97
|
||||||
#define DELETE_GLOBAL 98
|
#define DELETE_GLOBAL 98
|
||||||
#define ROT_N 99
|
#define SWAP 99
|
||||||
#define LOAD_CONST 100
|
#define LOAD_CONST 100
|
||||||
#define LOAD_NAME 101
|
#define LOAD_NAME 101
|
||||||
#define BUILD_TUPLE 102
|
#define BUILD_TUPLE 102
|
||||||
|
@ -117,61 +112,61 @@ extern "C" {
|
||||||
#define PRECALL_METHOD 168
|
#define PRECALL_METHOD 168
|
||||||
#define CALL_NO_KW 169
|
#define CALL_NO_KW 169
|
||||||
#define CALL_KW 170
|
#define CALL_KW 170
|
||||||
#define BINARY_OP_ADAPTIVE 7
|
#define BINARY_OP_ADAPTIVE 2
|
||||||
#define BINARY_OP_ADD_INT 8
|
#define BINARY_OP_ADD_INT 3
|
||||||
#define BINARY_OP_ADD_FLOAT 13
|
#define BINARY_OP_ADD_FLOAT 4
|
||||||
#define BINARY_OP_ADD_UNICODE 14
|
#define BINARY_OP_ADD_UNICODE 5
|
||||||
#define BINARY_OP_INPLACE_ADD_UNICODE 16
|
#define BINARY_OP_INPLACE_ADD_UNICODE 6
|
||||||
#define BINARY_OP_MULTIPLY_INT 17
|
#define BINARY_OP_MULTIPLY_INT 7
|
||||||
#define BINARY_OP_MULTIPLY_FLOAT 18
|
#define BINARY_OP_MULTIPLY_FLOAT 8
|
||||||
#define BINARY_OP_SUBTRACT_INT 19
|
#define BINARY_OP_SUBTRACT_INT 13
|
||||||
#define BINARY_OP_SUBTRACT_FLOAT 20
|
#define BINARY_OP_SUBTRACT_FLOAT 14
|
||||||
#define COMPARE_OP_ADAPTIVE 21
|
#define COMPARE_OP_ADAPTIVE 16
|
||||||
#define COMPARE_OP_FLOAT_JUMP 22
|
#define COMPARE_OP_FLOAT_JUMP 17
|
||||||
#define COMPARE_OP_INT_JUMP 23
|
#define COMPARE_OP_INT_JUMP 18
|
||||||
#define COMPARE_OP_STR_JUMP 24
|
#define COMPARE_OP_STR_JUMP 19
|
||||||
#define BINARY_SUBSCR_ADAPTIVE 26
|
#define BINARY_SUBSCR_ADAPTIVE 20
|
||||||
#define BINARY_SUBSCR_GETITEM 27
|
#define BINARY_SUBSCR_GETITEM 21
|
||||||
#define BINARY_SUBSCR_LIST_INT 28
|
#define BINARY_SUBSCR_LIST_INT 22
|
||||||
#define BINARY_SUBSCR_TUPLE_INT 29
|
#define BINARY_SUBSCR_TUPLE_INT 23
|
||||||
#define BINARY_SUBSCR_DICT 34
|
#define BINARY_SUBSCR_DICT 24
|
||||||
#define STORE_SUBSCR_ADAPTIVE 36
|
#define STORE_SUBSCR_ADAPTIVE 26
|
||||||
#define STORE_SUBSCR_LIST_INT 37
|
#define STORE_SUBSCR_LIST_INT 27
|
||||||
#define STORE_SUBSCR_DICT 38
|
#define STORE_SUBSCR_DICT 28
|
||||||
#define CALL_NO_KW_ADAPTIVE 39
|
#define CALL_NO_KW_ADAPTIVE 29
|
||||||
#define CALL_NO_KW_BUILTIN_O 40
|
#define CALL_NO_KW_BUILTIN_O 34
|
||||||
#define CALL_NO_KW_BUILTIN_FAST 41
|
#define CALL_NO_KW_BUILTIN_FAST 36
|
||||||
#define CALL_NO_KW_LEN 42
|
#define CALL_NO_KW_LEN 37
|
||||||
#define CALL_NO_KW_ISINSTANCE 43
|
#define CALL_NO_KW_ISINSTANCE 38
|
||||||
#define CALL_NO_KW_PY_SIMPLE 44
|
#define CALL_NO_KW_PY_SIMPLE 39
|
||||||
#define CALL_NO_KW_LIST_APPEND 45
|
#define CALL_NO_KW_LIST_APPEND 40
|
||||||
#define CALL_NO_KW_METHOD_DESCRIPTOR_O 46
|
#define CALL_NO_KW_METHOD_DESCRIPTOR_O 41
|
||||||
#define CALL_NO_KW_TYPE_1 47
|
#define CALL_NO_KW_TYPE_1 42
|
||||||
#define CALL_NO_KW_BUILTIN_CLASS_1 48
|
#define CALL_NO_KW_BUILTIN_CLASS_1 43
|
||||||
#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 55
|
#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 44
|
||||||
#define JUMP_ABSOLUTE_QUICK 56
|
#define JUMP_ABSOLUTE_QUICK 45
|
||||||
#define LOAD_ATTR_ADAPTIVE 57
|
#define LOAD_ATTR_ADAPTIVE 46
|
||||||
#define LOAD_ATTR_INSTANCE_VALUE 58
|
#define LOAD_ATTR_INSTANCE_VALUE 47
|
||||||
#define LOAD_ATTR_WITH_HINT 59
|
#define LOAD_ATTR_WITH_HINT 48
|
||||||
#define LOAD_ATTR_SLOT 62
|
#define LOAD_ATTR_SLOT 55
|
||||||
#define LOAD_ATTR_MODULE 63
|
#define LOAD_ATTR_MODULE 56
|
||||||
#define LOAD_GLOBAL_ADAPTIVE 64
|
#define LOAD_GLOBAL_ADAPTIVE 57
|
||||||
#define LOAD_GLOBAL_MODULE 65
|
#define LOAD_GLOBAL_MODULE 58
|
||||||
#define LOAD_GLOBAL_BUILTIN 66
|
#define LOAD_GLOBAL_BUILTIN 59
|
||||||
#define LOAD_METHOD_ADAPTIVE 67
|
#define LOAD_METHOD_ADAPTIVE 62
|
||||||
#define LOAD_METHOD_CACHED 72
|
#define LOAD_METHOD_CACHED 63
|
||||||
#define LOAD_METHOD_CLASS 76
|
#define LOAD_METHOD_CLASS 64
|
||||||
#define LOAD_METHOD_MODULE 77
|
#define LOAD_METHOD_MODULE 65
|
||||||
#define LOAD_METHOD_NO_DICT 78
|
#define LOAD_METHOD_NO_DICT 66
|
||||||
#define STORE_ATTR_ADAPTIVE 79
|
#define STORE_ATTR_ADAPTIVE 67
|
||||||
#define STORE_ATTR_INSTANCE_VALUE 80
|
#define STORE_ATTR_INSTANCE_VALUE 72
|
||||||
#define STORE_ATTR_SLOT 81
|
#define STORE_ATTR_SLOT 76
|
||||||
#define STORE_ATTR_WITH_HINT 131
|
#define STORE_ATTR_WITH_HINT 77
|
||||||
#define LOAD_FAST__LOAD_FAST 140
|
#define LOAD_FAST__LOAD_FAST 78
|
||||||
#define STORE_FAST__LOAD_FAST 141
|
#define STORE_FAST__LOAD_FAST 79
|
||||||
#define LOAD_FAST__LOAD_CONST 143
|
#define LOAD_FAST__LOAD_CONST 80
|
||||||
#define LOAD_CONST__LOAD_FAST 150
|
#define LOAD_CONST__LOAD_FAST 81
|
||||||
#define STORE_FAST__STORE_FAST 153
|
#define STORE_FAST__STORE_FAST 131
|
||||||
#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] = {
|
||||||
|
|
|
@ -382,6 +382,8 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Python 3.11a4 3474 (Add RESUME opcode)
|
# Python 3.11a4 3474 (Add RESUME opcode)
|
||||||
# Python 3.11a5 3475 (Add RETURN_GENERATOR opcode)
|
# Python 3.11a5 3475 (Add RETURN_GENERATOR opcode)
|
||||||
# Python 3.11a5 3476 (Add ASYNC_GEN_WRAP opcode)
|
# Python 3.11a5 3476 (Add ASYNC_GEN_WRAP opcode)
|
||||||
|
# Python 3.11a5 3477 (Replace DUP_TOP/DUP_TOP_TWO with COPY and
|
||||||
|
# ROT_TWO/ROT_THREE/ROT_FOUR/ROT_N with SWAP)
|
||||||
|
|
||||||
# Python 3.12 will start with magic number 3500
|
# Python 3.12 will start with magic number 3500
|
||||||
|
|
||||||
|
@ -395,7 +397,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||||
# in PC/launcher.c must also be updated.
|
# in PC/launcher.c must also be updated.
|
||||||
|
|
||||||
MAGIC_NUMBER = (3476).to_bytes(2, 'little') + b'\r\n'
|
MAGIC_NUMBER = (3477).to_bytes(2, 'little') + b'\r\n'
|
||||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||||
|
|
||||||
_PYCACHE = '__pycache__'
|
_PYCACHE = '__pycache__'
|
||||||
|
|
|
@ -55,11 +55,6 @@ def jabs_op(name, op):
|
||||||
# Blank lines correspond to available opcodes
|
# Blank lines correspond to available opcodes
|
||||||
|
|
||||||
def_op('POP_TOP', 1)
|
def_op('POP_TOP', 1)
|
||||||
def_op('ROT_TWO', 2)
|
|
||||||
def_op('ROT_THREE', 3)
|
|
||||||
def_op('DUP_TOP', 4)
|
|
||||||
def_op('DUP_TOP_TWO', 5)
|
|
||||||
def_op('ROT_FOUR', 6)
|
|
||||||
|
|
||||||
def_op('NOP', 9)
|
def_op('NOP', 9)
|
||||||
def_op('UNARY_POSITIVE', 10)
|
def_op('UNARY_POSITIVE', 10)
|
||||||
|
@ -116,7 +111,7 @@ name_op('STORE_ATTR', 95) # Index in name list
|
||||||
name_op('DELETE_ATTR', 96) # ""
|
name_op('DELETE_ATTR', 96) # ""
|
||||||
name_op('STORE_GLOBAL', 97) # ""
|
name_op('STORE_GLOBAL', 97) # ""
|
||||||
name_op('DELETE_GLOBAL', 98) # ""
|
name_op('DELETE_GLOBAL', 98) # ""
|
||||||
def_op('ROT_N', 99)
|
def_op('SWAP', 99)
|
||||||
def_op('LOAD_CONST', 100) # Index in const list
|
def_op('LOAD_CONST', 100) # Index in const list
|
||||||
hasconst.append(100)
|
hasconst.append(100)
|
||||||
name_op('LOAD_NAME', 101) # Index in name list
|
name_op('LOAD_NAME', 101) # Index in name list
|
||||||
|
|
|
@ -11,7 +11,6 @@ class OpcodeTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_stack_effect(self):
|
def test_stack_effect(self):
|
||||||
self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1)
|
self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1)
|
||||||
self.assertEqual(stack_effect(dis.opmap['DUP_TOP_TWO']), 2)
|
|
||||||
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
|
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
|
||||||
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
|
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
|
||||||
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
|
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
|
||||||
|
|
|
@ -1195,8 +1195,8 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=25, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=25, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=162, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=164, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=25, argval=222, argrepr='to 222', offset=170, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=25, argval=222, argrepr='to 222', offset=170, starts_line=None, is_jump_target=False, positions=None),
|
||||||
|
|
|
@ -119,8 +119,8 @@ class TestTranforms(BytecodeTestCase):
|
||||||
def test_pack_unpack(self):
|
def test_pack_unpack(self):
|
||||||
for line, elem in (
|
for line, elem in (
|
||||||
('a, = a,', 'LOAD_CONST',),
|
('a, = a,', 'LOAD_CONST',),
|
||||||
('a, b = a, b', 'ROT_TWO',),
|
('a, b = a, b', 'SWAP',),
|
||||||
('a, b, c = a, b, c', 'ROT_THREE',),
|
('a, b, c = a, b, c', 'SWAP',),
|
||||||
):
|
):
|
||||||
with self.subTest(line=line):
|
with self.subTest(line=line):
|
||||||
code = compile(line,'','single')
|
code = compile(line,'','single')
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Replace several stack manipulation instructions (``DUP_TOP``,
|
||||||
|
``DUP_TOP_TWO``, ``ROT_TWO``, ``ROT_THREE``, ``ROT_FOUR``, and ``ROT_N``)
|
||||||
|
with new :opcode:`COPY` and :opcode:`SWAP` instructions.
|
|
@ -1434,8 +1434,6 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
||||||
#define PEEK(n) (stack_pointer[-(n)])
|
#define PEEK(n) (stack_pointer[-(n)])
|
||||||
#define SET_TOP(v) (stack_pointer[-1] = (v))
|
#define SET_TOP(v) (stack_pointer[-1] = (v))
|
||||||
#define SET_SECOND(v) (stack_pointer[-2] = (v))
|
#define SET_SECOND(v) (stack_pointer[-2] = (v))
|
||||||
#define SET_THIRD(v) (stack_pointer[-3] = (v))
|
|
||||||
#define SET_FOURTH(v) (stack_pointer[-4] = (v))
|
|
||||||
#define BASIC_STACKADJ(n) (stack_pointer += n)
|
#define BASIC_STACKADJ(n) (stack_pointer += n)
|
||||||
#define BASIC_PUSH(v) (*stack_pointer++ = (v))
|
#define BASIC_PUSH(v) (*stack_pointer++ = (v))
|
||||||
#define BASIC_POP() (*--stack_pointer)
|
#define BASIC_POP() (*--stack_pointer)
|
||||||
|
@ -1920,54 +1918,6 @@ handle_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(ROT_TWO) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
PyObject *second = SECOND();
|
|
||||||
SET_TOP(second);
|
|
||||||
SET_SECOND(top);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(ROT_THREE) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
PyObject *second = SECOND();
|
|
||||||
PyObject *third = THIRD();
|
|
||||||
SET_TOP(second);
|
|
||||||
SET_SECOND(third);
|
|
||||||
SET_THIRD(top);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(ROT_FOUR) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
PyObject *second = SECOND();
|
|
||||||
PyObject *third = THIRD();
|
|
||||||
PyObject *fourth = FOURTH();
|
|
||||||
SET_TOP(second);
|
|
||||||
SET_SECOND(third);
|
|
||||||
SET_THIRD(fourth);
|
|
||||||
SET_FOURTH(top);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(DUP_TOP) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
Py_INCREF(top);
|
|
||||||
PUSH(top);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(DUP_TOP_TWO) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
PyObject *second = SECOND();
|
|
||||||
Py_INCREF(top);
|
|
||||||
Py_INCREF(second);
|
|
||||||
STACK_GROW(2);
|
|
||||||
SET_TOP(top);
|
|
||||||
SET_SECOND(second);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(UNARY_POSITIVE) {
|
TARGET(UNARY_POSITIVE) {
|
||||||
PyObject *value = TOP();
|
PyObject *value = TOP();
|
||||||
PyObject *res = PyNumber_Positive(value);
|
PyObject *res = PyNumber_Positive(value);
|
||||||
|
@ -5170,14 +5120,6 @@ handle_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(ROT_N) {
|
|
||||||
PyObject *top = TOP();
|
|
||||||
memmove(&PEEK(oparg - 1), &PEEK(oparg),
|
|
||||||
sizeof(PyObject*) * (oparg - 1));
|
|
||||||
PEEK(oparg) = top;
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(COPY) {
|
TARGET(COPY) {
|
||||||
assert(oparg != 0);
|
assert(oparg != 0);
|
||||||
PyObject *peek = PEEK(oparg);
|
PyObject *peek = PEEK(oparg);
|
||||||
|
@ -5221,6 +5163,14 @@ handle_eval_breaker:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET(SWAP) {
|
||||||
|
assert(oparg != 0);
|
||||||
|
PyObject *top = TOP();
|
||||||
|
SET_TOP(PEEK(oparg));
|
||||||
|
PEEK(oparg) = top;
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
TARGET(EXTENDED_ARG) {
|
TARGET(EXTENDED_ARG) {
|
||||||
int oldoparg = oparg;
|
int oldoparg = oparg;
|
||||||
NEXTOPARG();
|
NEXTOPARG();
|
||||||
|
@ -7380,7 +7330,7 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop
|
||||||
"that does not implement __await__: %.100s",
|
"that does not implement __await__: %.100s",
|
||||||
type->tp_name);
|
type->tp_name);
|
||||||
}
|
}
|
||||||
else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_NO_KW && prevprevopcode == DUP_TOP)) {
|
else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_NO_KW && prevprevopcode == LOAD_CONST)) {
|
||||||
_PyErr_Format(tstate, PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"'async with' received an object from __aexit__ "
|
"'async with' received an object from __aexit__ "
|
||||||
"that does not implement __await__: %.100s",
|
"that does not implement __await__: %.100s",
|
||||||
|
|
266
Python/compile.c
266
Python/compile.c
|
@ -867,14 +867,8 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
/* Stack manipulation */
|
/* Stack manipulation */
|
||||||
case POP_TOP:
|
case POP_TOP:
|
||||||
return -1;
|
return -1;
|
||||||
case ROT_TWO:
|
case SWAP:
|
||||||
case ROT_THREE:
|
|
||||||
case ROT_FOUR:
|
|
||||||
return 0;
|
return 0;
|
||||||
case DUP_TOP:
|
|
||||||
return 1;
|
|
||||||
case DUP_TOP_TWO:
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
/* Unary operators */
|
/* Unary operators */
|
||||||
case UNARY_POSITIVE:
|
case UNARY_POSITIVE:
|
||||||
|
@ -1094,8 +1088,6 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
case MATCH_SEQUENCE:
|
case MATCH_SEQUENCE:
|
||||||
case MATCH_KEYS:
|
case MATCH_KEYS:
|
||||||
return 1;
|
return 1;
|
||||||
case ROT_N:
|
|
||||||
return 0;
|
|
||||||
case COPY:
|
case COPY:
|
||||||
return 1;
|
return 1;
|
||||||
case BINARY_OP:
|
case BINARY_OP:
|
||||||
|
@ -1829,8 +1821,8 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
|
||||||
static int
|
static int
|
||||||
compiler_call_exit_with_nones(struct compiler *c) {
|
compiler_call_exit_with_nones(struct compiler *c) {
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP_I(c, CALL_NO_KW, 3);
|
ADDOP_I(c, CALL_NO_KW, 3);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1890,7 +1882,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
case FOR_LOOP:
|
case FOR_LOOP:
|
||||||
/* Pop the iterator */
|
/* Pop the iterator */
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1920,11 +1912,11 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
|
|
||||||
case FINALLY_END:
|
case FINALLY_END:
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP); /* exc_value */
|
ADDOP(c, POP_TOP); /* exc_value */
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
|
@ -1935,7 +1927,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
SET_LOC(c, (stmt_ty)info->fb_datum);
|
SET_LOC(c, (stmt_ty)info->fb_datum);
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
if(!compiler_call_exit_with_nones(c)) {
|
if(!compiler_call_exit_with_nones(c)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1957,7 +1949,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
}
|
}
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
|
@ -1970,7 +1962,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
|
|
||||||
case POP_VALUE:
|
case POP_VALUE:
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2647,7 +2639,7 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
|
|
||||||
ADDOP_I(c, LOAD_CLOSURE, i);
|
ADDOP_I(c, LOAD_CLOSURE, i);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
str = PyUnicode_InternFromString("__classcell__");
|
str = PyUnicode_InternFromString("__classcell__");
|
||||||
if (!str || !compiler_nameop(c, str, Store)) {
|
if (!str || !compiler_nameop(c, str, Store)) {
|
||||||
Py_XDECREF(str);
|
Py_XDECREF(str);
|
||||||
|
@ -2843,8 +2835,8 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
VISIT(c, expr,
|
VISIT(c, expr,
|
||||||
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
|
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, ROT_THREE);
|
ADDOP_I(c, COPY, 2);
|
||||||
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
||||||
ADDOP_JUMP(c, POP_JUMP_IF_FALSE, cleanup);
|
ADDOP_JUMP(c, POP_JUMP_IF_FALSE, cleanup);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
|
@ -3500,9 +3492,9 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
[] POP_BLOCK
|
[] POP_BLOCK
|
||||||
[] JUMP_FORWARD L0
|
[] JUMP_FORWARD L0
|
||||||
|
|
||||||
[exc] L1: DUP_TOP ) save copy of the original exception
|
[exc] L1: COPY 1 ) save copy of the original exception
|
||||||
[orig, exc] BUILD_LIST ) list for raised/reraised excs ("result")
|
[orig, exc] BUILD_LIST ) list for raised/reraised excs ("result")
|
||||||
[orig, exc, res] ROT_TWO
|
[orig, exc, res] SWAP 2
|
||||||
|
|
||||||
[orig, res, exc] <evaluate E1>
|
[orig, res, exc] <evaluate E1>
|
||||||
[orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2
|
[orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2
|
||||||
|
@ -3522,12 +3514,12 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
[orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
|
[orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
|
||||||
|
|
||||||
[orig, res] PREP_RERAISE_STAR
|
[orig, res] PREP_RERAISE_STAR
|
||||||
[exc] DUP_TOP
|
[exc] COPY 1
|
||||||
[exc, exc] POP_JUMP_IF_NOT_NONE RER
|
[exc, exc] POP_JUMP_IF_NOT_NONE RER
|
||||||
[exc] POP_TOP
|
[exc] POP_TOP
|
||||||
[] JUMP_FORWARD L0
|
[] JUMP_FORWARD L0
|
||||||
|
|
||||||
[exc] RER: ROT_TWO
|
[exc] RER: SWAP 2
|
||||||
[exc, prev_exc_info] POP_EXCEPT
|
[exc, prev_exc_info] POP_EXCEPT
|
||||||
[exc] RERAISE 0
|
[exc] RERAISE 0
|
||||||
|
|
||||||
|
@ -3592,19 +3584,19 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* Push the original EG into the stack */
|
/* Push the original EG into the stack */
|
||||||
/*
|
/*
|
||||||
[exc] DUP_TOP
|
[exc] COPY 1
|
||||||
[orig, exc]
|
[orig, exc]
|
||||||
*/
|
*/
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
|
|
||||||
/* create empty list for exceptions raised/reraise in the except* blocks */
|
/* create empty list for exceptions raised/reraise in the except* blocks */
|
||||||
/*
|
/*
|
||||||
[orig, exc] BUILD_LIST
|
[orig, exc] BUILD_LIST
|
||||||
[orig, exc, []] ROT_TWO
|
[orig, exc, []] SWAP 2
|
||||||
[orig, [], exc]
|
[orig, [], exc]
|
||||||
*/
|
*/
|
||||||
ADDOP_I(c, BUILD_LIST, 0);
|
ADDOP_I(c, BUILD_LIST, 0);
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
}
|
}
|
||||||
if (handler->v.ExceptHandler.type) {
|
if (handler->v.ExceptHandler.type) {
|
||||||
VISIT(c, expr, handler->v.ExceptHandler.type);
|
VISIT(c, expr, handler->v.ExceptHandler.type);
|
||||||
|
@ -3692,7 +3684,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
|
|
||||||
compiler_use_next_block(c, reraise_star);
|
compiler_use_next_block(c, reraise_star);
|
||||||
ADDOP(c, PREP_RERAISE_STAR);
|
ADDOP(c, PREP_RERAISE_STAR);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, reraise);
|
ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, reraise);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
|
|
||||||
|
@ -3703,7 +3695,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, reraise);
|
compiler_use_next_block(c, reraise);
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
ADDOP_I(c, RERAISE, 0);
|
ADDOP_I(c, RERAISE, 0);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
|
@ -3761,7 +3753,7 @@ compiler_import_as(struct compiler *c, identifier name, identifier asname)
|
||||||
if (dot == -1) {
|
if (dot == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
}
|
}
|
||||||
if (!compiler_nameop(c, asname, Store)) {
|
if (!compiler_nameop(c, asname, Store)) {
|
||||||
|
@ -3961,8 +3953,9 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
||||||
n = asdl_seq_LEN(s->v.Assign.targets);
|
n = asdl_seq_LEN(s->v.Assign.targets);
|
||||||
VISIT(c, expr, s->v.Assign.value);
|
VISIT(c, expr, s->v.Assign.value);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
if (i < n - 1)
|
if (i < n - 1) {
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
|
}
|
||||||
VISIT(c, expr,
|
VISIT(c, expr,
|
||||||
(expr_ty)asdl_seq_GET(s->v.Assign.targets, i));
|
(expr_ty)asdl_seq_GET(s->v.Assign.targets, i));
|
||||||
}
|
}
|
||||||
|
@ -4532,8 +4525,8 @@ compiler_compare(struct compiler *c, expr_ty e)
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
VISIT(c, expr,
|
VISIT(c, expr,
|
||||||
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
|
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, ROT_THREE);
|
ADDOP_I(c, COPY, 2);
|
||||||
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
||||||
ADDOP_JUMP(c, JUMP_IF_FALSE_OR_POP, cleanup);
|
ADDOP_JUMP(c, JUMP_IF_FALSE_OR_POP, cleanup);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
|
@ -4545,7 +4538,7 @@ compiler_compare(struct compiler *c, expr_ty e)
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end);
|
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
compiler_use_next_block(c, end);
|
compiler_use_next_block(c, end);
|
||||||
}
|
}
|
||||||
|
@ -5689,7 +5682,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case NamedExpr_kind:
|
case NamedExpr_kind:
|
||||||
VISIT(c, expr, e->v.NamedExpr.value);
|
VISIT(c, expr, e->v.NamedExpr.value);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
VISIT(c, expr, e->v.NamedExpr.target);
|
VISIT(c, expr, e->v.NamedExpr.target);
|
||||||
break;
|
break;
|
||||||
case BoolOp_kind:
|
case BoolOp_kind:
|
||||||
|
@ -5854,7 +5847,7 @@ compiler_augassign(struct compiler *c, stmt_ty s)
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case Attribute_kind:
|
case Attribute_kind:
|
||||||
VISIT(c, expr, e->v.Attribute.value);
|
VISIT(c, expr, e->v.Attribute.value);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
int old_lineno = c->u->u_lineno;
|
int old_lineno = c->u->u_lineno;
|
||||||
c->u->u_lineno = e->end_lineno;
|
c->u->u_lineno = e->end_lineno;
|
||||||
ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names);
|
ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names);
|
||||||
|
@ -5863,7 +5856,8 @@ compiler_augassign(struct compiler *c, stmt_ty s)
|
||||||
case Subscript_kind:
|
case Subscript_kind:
|
||||||
VISIT(c, expr, e->v.Subscript.value);
|
VISIT(c, expr, e->v.Subscript.value);
|
||||||
VISIT(c, expr, e->v.Subscript.slice);
|
VISIT(c, expr, e->v.Subscript.slice);
|
||||||
ADDOP(c, DUP_TOP_TWO);
|
ADDOP_I(c, COPY, 2);
|
||||||
|
ADDOP_I(c, COPY, 2);
|
||||||
ADDOP(c, BINARY_SUBSCR);
|
ADDOP(c, BINARY_SUBSCR);
|
||||||
break;
|
break;
|
||||||
case Name_kind:
|
case Name_kind:
|
||||||
|
@ -5890,11 +5884,12 @@ compiler_augassign(struct compiler *c, stmt_ty s)
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case Attribute_kind:
|
case Attribute_kind:
|
||||||
c->u->u_lineno = e->end_lineno;
|
c->u->u_lineno = e->end_lineno;
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names);
|
ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names);
|
||||||
break;
|
break;
|
||||||
case Subscript_kind:
|
case Subscript_kind:
|
||||||
ADDOP(c, ROT_THREE);
|
ADDOP_I(c, SWAP, 3);
|
||||||
|
ADDOP_I(c, SWAP, 2);
|
||||||
ADDOP(c, STORE_SUBSCR);
|
ADDOP(c, STORE_SUBSCR);
|
||||||
break;
|
break;
|
||||||
case Name_kind:
|
case Name_kind:
|
||||||
|
@ -6246,6 +6241,16 @@ compiler_error_duplicate_store(struct compiler *c, identifier n)
|
||||||
return compiler_error(c, "multiple assignments to name %R in pattern", n);
|
return compiler_error(c, "multiple assignments to name %R in pattern", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicate the effect of 3.10's ROT_* instructions using SWAPs.
|
||||||
|
static int
|
||||||
|
pattern_helper_rotate(struct compiler *c, Py_ssize_t count)
|
||||||
|
{
|
||||||
|
while (1 < count) {
|
||||||
|
ADDOP_I(c, SWAP, count--);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pattern_helper_store_name(struct compiler *c, identifier n, pattern_context *pc)
|
pattern_helper_store_name(struct compiler *c, identifier n, pattern_context *pc)
|
||||||
{
|
{
|
||||||
|
@ -6265,7 +6270,8 @@ pattern_helper_store_name(struct compiler *c, identifier n, pattern_context *pc)
|
||||||
return compiler_error_duplicate_store(c, n);
|
return compiler_error_duplicate_store(c, n);
|
||||||
}
|
}
|
||||||
// Rotate this object underneath any items we need to preserve:
|
// Rotate this object underneath any items we need to preserve:
|
||||||
ADDOP_I(c, ROT_N, pc->on_top + PyList_GET_SIZE(pc->stores) + 1);
|
Py_ssize_t rotations = pc->on_top + PyList_GET_SIZE(pc->stores) + 1;
|
||||||
|
RETURN_IF_FALSE(pattern_helper_rotate(c, rotations));
|
||||||
return !PyList_Append(pc->stores, n);
|
return !PyList_Append(pc->stores, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6334,7 +6340,7 @@ pattern_helper_sequence_subscr(struct compiler *c, asdl_pattern_seq *patterns,
|
||||||
assert(WILDCARD_STAR_CHECK(pattern));
|
assert(WILDCARD_STAR_CHECK(pattern));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
if (i < star) {
|
if (i < star) {
|
||||||
ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(i));
|
ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(i));
|
||||||
}
|
}
|
||||||
|
@ -6383,7 +6389,7 @@ compiler_pattern_as(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
}
|
}
|
||||||
// Need to make a copy for (possibly) storing later:
|
// Need to make a copy for (possibly) storing later:
|
||||||
pc->on_top++;
|
pc->on_top++;
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
RETURN_IF_FALSE(compiler_pattern(c, p->v.MatchAs.pattern, pc));
|
RETURN_IF_FALSE(compiler_pattern(c, p->v.MatchAs.pattern, pc));
|
||||||
// Success! Store it:
|
// Success! Store it:
|
||||||
pc->on_top--;
|
pc->on_top--;
|
||||||
|
@ -6458,7 +6464,7 @@ compiler_pattern_class(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
}
|
}
|
||||||
ADDOP_LOAD_CONST_NEW(c, attr_names);
|
ADDOP_LOAD_CONST_NEW(c, attr_names);
|
||||||
ADDOP_I(c, MATCH_CLASS, nargs);
|
ADDOP_I(c, MATCH_CLASS, nargs);
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP_I(c, IS_OP, 1);
|
ADDOP_I(c, IS_OP, 1);
|
||||||
// TOS is now a tuple of (nargs + nattrs) attributes (or None):
|
// TOS is now a tuple of (nargs + nattrs) attributes (or None):
|
||||||
|
@ -6576,7 +6582,7 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
ADDOP(c, MATCH_KEYS);
|
ADDOP(c, MATCH_KEYS);
|
||||||
// There's now a tuple of keys and a tuple of values on top of the subject:
|
// There's now a tuple of keys and a tuple of values on top of the subject:
|
||||||
pc->on_top += 2;
|
pc->on_top += 2;
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP_I(c, IS_OP, 1);
|
ADDOP_I(c, IS_OP, 1);
|
||||||
RETURN_IF_FALSE(jump_to_fail_pop(c, pc, POP_JUMP_IF_FALSE));
|
RETURN_IF_FALSE(jump_to_fail_pop(c, pc, POP_JUMP_IF_FALSE));
|
||||||
|
@ -6600,13 +6606,12 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
// for key in TOS:
|
// for key in TOS:
|
||||||
// del rest[key]
|
// del rest[key]
|
||||||
ADDOP_I(c, BUILD_MAP, 0); // [subject, keys, empty]
|
ADDOP_I(c, BUILD_MAP, 0); // [subject, keys, empty]
|
||||||
ADDOP(c, ROT_THREE); // [empty, subject, keys]
|
ADDOP_I(c, SWAP, 3); // [empty, keys, subject]
|
||||||
ADDOP(c, ROT_TWO); // [empty, keys, subject]
|
|
||||||
ADDOP_I(c, DICT_UPDATE, 2); // [copy, keys]
|
ADDOP_I(c, DICT_UPDATE, 2); // [copy, keys]
|
||||||
ADDOP_I(c, UNPACK_SEQUENCE, size); // [copy, keys...]
|
ADDOP_I(c, UNPACK_SEQUENCE, size); // [copy, keys...]
|
||||||
while (size) {
|
while (size) {
|
||||||
ADDOP_I(c, COPY, 1 + size--); // [copy, keys..., copy]
|
ADDOP_I(c, COPY, 1 + size--); // [copy, keys..., copy]
|
||||||
ADDOP(c, ROT_TWO); // [copy, keys..., copy, key]
|
ADDOP_I(c, SWAP, 2); // [copy, keys..., copy, key]
|
||||||
ADDOP(c, DELETE_SUBSCR); // [copy, keys...]
|
ADDOP(c, DELETE_SUBSCR); // [copy, keys...]
|
||||||
}
|
}
|
||||||
RETURN_IF_FALSE(pattern_helper_store_name(c, star_target, pc));
|
RETURN_IF_FALSE(pattern_helper_store_name(c, star_target, pc));
|
||||||
|
@ -6651,7 +6656,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
pc->fail_pop = NULL;
|
pc->fail_pop = NULL;
|
||||||
pc->fail_pop_size = 0;
|
pc->fail_pop_size = 0;
|
||||||
pc->on_top = 0;
|
pc->on_top = 0;
|
||||||
if (!compiler_addop(c, DUP_TOP) || !compiler_pattern(c, alt, pc)) {
|
if (!compiler_addop_i(c, COPY, 1) || !compiler_pattern(c, alt, pc)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
|
@ -6683,7 +6688,8 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
// this; the current solution is potentially very
|
// this; the current solution is potentially very
|
||||||
// inefficient when each alternative subpattern binds lots
|
// inefficient when each alternative subpattern binds lots
|
||||||
// of names in different orders. It's fine for reasonable
|
// of names in different orders. It's fine for reasonable
|
||||||
// cases, though.
|
// cases, though, and the peephole optimizer will ensure
|
||||||
|
// that the final code is as efficient as possible.
|
||||||
assert(istores < icontrol);
|
assert(istores < icontrol);
|
||||||
Py_ssize_t rotations = istores + 1;
|
Py_ssize_t rotations = istores + 1;
|
||||||
// Perform the same rotation on pc->stores:
|
// Perform the same rotation on pc->stores:
|
||||||
|
@ -6702,9 +6708,10 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
// rotated = pc_stores[:rotations]
|
// rotated = pc_stores[:rotations]
|
||||||
// del pc_stores[:rotations]
|
// del pc_stores[:rotations]
|
||||||
// pc_stores[icontrol-istores:icontrol-istores] = rotated
|
// pc_stores[icontrol-istores:icontrol-istores] = rotated
|
||||||
// Do the same thing to the stack, using several ROT_Ns:
|
// Do the same thing to the stack, using several
|
||||||
|
// rotations:
|
||||||
while (rotations--) {
|
while (rotations--) {
|
||||||
if (!compiler_addop_i(c, ROT_N, icontrol + 1)) {
|
if (!pattern_helper_rotate(c, icontrol + 1)){
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6730,7 +6737,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
}
|
}
|
||||||
compiler_use_next_block(c, end);
|
compiler_use_next_block(c, end);
|
||||||
Py_ssize_t nstores = PyList_GET_SIZE(control);
|
Py_ssize_t nstores = PyList_GET_SIZE(control);
|
||||||
// There's a bunch of stuff on the stack between any where the new stores
|
// There's a bunch of stuff on the stack between where the new stores
|
||||||
// are and where they need to be:
|
// are and where they need to be:
|
||||||
// - The other stores.
|
// - The other stores.
|
||||||
// - A copy of the subject.
|
// - A copy of the subject.
|
||||||
|
@ -6739,7 +6746,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
|
||||||
Py_ssize_t nrots = nstores + 1 + pc->on_top + PyList_GET_SIZE(pc->stores);
|
Py_ssize_t nrots = nstores + 1 + pc->on_top + PyList_GET_SIZE(pc->stores);
|
||||||
for (Py_ssize_t i = 0; i < nstores; i++) {
|
for (Py_ssize_t i = 0; i < nstores; i++) {
|
||||||
// Rotate this capture to its proper place on the stack:
|
// Rotate this capture to its proper place on the stack:
|
||||||
if (!compiler_addop_i(c, ROT_N, nrots)) {
|
if (!pattern_helper_rotate(c, nrots)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
// Update the list of previous stores with this new name, checking for
|
// Update the list of previous stores with this new name, checking for
|
||||||
|
@ -6898,7 +6905,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc)
|
||||||
SET_LOC(c, m->pattern);
|
SET_LOC(c, m->pattern);
|
||||||
// Only copy the subject if we're *not* on the last case:
|
// Only copy the subject if we're *not* on the last case:
|
||||||
if (i != cases - has_default - 1) {
|
if (i != cases - has_default - 1) {
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP_I(c, COPY, 1);
|
||||||
}
|
}
|
||||||
RETURN_IF_FALSE(pc->stores = PyList_New(0));
|
RETURN_IF_FALSE(pc->stores = PyList_New(0));
|
||||||
// Irrefutable cases must be either guarded, last, or both:
|
// Irrefutable cases must be either guarded, last, or both:
|
||||||
|
@ -8433,36 +8440,99 @@ fold_tuple_on_constants(struct compiler *c,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISITED (-1)
|
||||||
|
|
||||||
// Eliminate n * ROT_N(n).
|
// Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the
|
||||||
static void
|
// same effect. Return the number of instructions that were optimized.
|
||||||
fold_rotations(struct instr *inst, int n)
|
static int
|
||||||
|
swaptimize(basicblock *block, int ix)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < n; i++) {
|
// NOTE: "./python -m test test_patma" serves as a good, quick stress test
|
||||||
int rot;
|
// for this function. Make sure to blow away cached *.pyc files first!
|
||||||
switch (inst[i].i_opcode) {
|
assert(ix < block->b_iused);
|
||||||
case ROT_N:
|
struct instr *instructions = &block->b_instr[ix];
|
||||||
rot = inst[i].i_oparg;
|
// Find the length of the current sequence of SWAPs and NOPs, and record the
|
||||||
break;
|
// maximum depth of the stack manipulations:
|
||||||
case ROT_FOUR:
|
assert(instructions[0].i_opcode == SWAP);
|
||||||
rot = 4;
|
int depth = instructions[0].i_oparg;
|
||||||
break;
|
int len = 0;
|
||||||
case ROT_THREE:
|
int more = false;
|
||||||
rot = 3;
|
while (++len < block->b_iused - ix) {
|
||||||
break;
|
int opcode = instructions[len].i_opcode;
|
||||||
case ROT_TWO:
|
if (opcode == SWAP) {
|
||||||
rot = 2;
|
depth = Py_MAX(depth, instructions[len].i_oparg);
|
||||||
break;
|
more = true;
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (rot != n) {
|
else if (opcode != NOP) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < n; i++) {
|
// It's already optimal if there's only one SWAP:
|
||||||
inst[i].i_opcode = NOP;
|
if (!more) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
// Create an array with elements {0, 1, 2, ..., depth - 1}:
|
||||||
|
int *stack = PyMem_Malloc(depth * sizeof(int));
|
||||||
|
for (int i = 0; i < depth; i++) {
|
||||||
|
stack[i] = i;
|
||||||
|
}
|
||||||
|
// Simulate the combined effect of these instructions by "running" them on
|
||||||
|
// our "stack":
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (instructions[i].i_opcode == SWAP) {
|
||||||
|
int oparg = instructions[i].i_oparg;
|
||||||
|
int top = stack[0];
|
||||||
|
// SWAPs are 1-indexed:
|
||||||
|
stack[0] = stack[oparg - 1];
|
||||||
|
stack[oparg - 1] = top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now we can begin! Our approach here is based on a solution to a closely
|
||||||
|
// related problem (https://cs.stackexchange.com/a/13938). It's easiest to
|
||||||
|
// think of this algorithm as determining the steps needed to efficiently
|
||||||
|
// "un-shuffle" our stack. By performing the moves in *reverse* order,
|
||||||
|
// though, we can efficiently *shuffle* it! For this reason, we will be
|
||||||
|
// replacing instructions starting from the *end* of the run. Since the
|
||||||
|
// solution is optimal, we don't need to worry about running out of space:
|
||||||
|
int current = len - 1;
|
||||||
|
for (int i = 0; i < depth; i++) {
|
||||||
|
// Skip items that have already been visited, or just happen to be in
|
||||||
|
// the correct location:
|
||||||
|
if (stack[i] == VISITED || stack[i] == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Okay, we've found an item that hasn't been visited. It forms a cycle
|
||||||
|
// with other items; traversing the cycle and swapping each item with
|
||||||
|
// the next will put them all in the correct place. The weird
|
||||||
|
// loop-and-a-half is necessary to insert 0 into every cycle, since we
|
||||||
|
// can only swap from that position:
|
||||||
|
int j = i;
|
||||||
|
while (true) {
|
||||||
|
// Skip the actual swap if our item is zero, since swapping the top
|
||||||
|
// item with itself is pointless:
|
||||||
|
if (j) {
|
||||||
|
assert(0 <= current);
|
||||||
|
// SWAPs are 1-indexed:
|
||||||
|
instructions[current].i_opcode = SWAP;
|
||||||
|
instructions[current--].i_oparg = j + 1;
|
||||||
|
}
|
||||||
|
if (stack[j] == VISITED) {
|
||||||
|
// Completed the cycle:
|
||||||
|
assert(j == i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int next_j = stack[j];
|
||||||
|
stack[j] = VISITED;
|
||||||
|
j = next_j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// NOP out any unused instructions:
|
||||||
|
while (0 <= current) {
|
||||||
|
instructions[current--].i_opcode = NOP;
|
||||||
|
}
|
||||||
|
// Done! Return the number of optimized instructions:
|
||||||
|
PyMem_Free(stack);
|
||||||
|
return len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to eliminate jumps to jumps by updating inst to jump to
|
// Attempt to eliminate jumps to jumps by updating inst to jump to
|
||||||
|
@ -8591,12 +8661,16 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
||||||
bb->b_instr[i+1].i_opcode = NOP;
|
bb->b_instr[i+1].i_opcode = NOP;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
inst->i_opcode = ROT_TWO;
|
inst->i_opcode = SWAP;
|
||||||
|
inst->i_oparg = 2;
|
||||||
bb->b_instr[i+1].i_opcode = NOP;
|
bb->b_instr[i+1].i_opcode = NOP;
|
||||||
|
i--;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
inst->i_opcode = ROT_THREE;
|
inst->i_opcode = SWAP;
|
||||||
bb->b_instr[i+1].i_opcode = ROT_TWO;
|
inst->i_oparg = 3;
|
||||||
|
bb->b_instr[i+1].i_opcode = NOP;
|
||||||
|
i--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -8704,30 +8778,12 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
||||||
i -= jump_thread(inst, target, FOR_ITER);
|
i -= jump_thread(inst, target, FOR_ITER);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROT_N:
|
case SWAP:
|
||||||
switch (oparg) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
inst->i_opcode = NOP;
|
|
||||||
continue;
|
|
||||||
case 2:
|
|
||||||
inst->i_opcode = ROT_TWO;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
inst->i_opcode = ROT_THREE;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
inst->i_opcode = ROT_FOUR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i >= oparg - 1) {
|
|
||||||
fold_rotations(inst - oparg + 1, oparg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COPY:
|
|
||||||
if (oparg == 1) {
|
if (oparg == 1) {
|
||||||
inst->i_opcode = DUP_TOP;
|
inst->i_opcode = NOP;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
i += swaptimize(bb, i);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* All HAS_CONST opcodes should be handled with LOAD_CONST */
|
/* All HAS_CONST opcodes should be handled with LOAD_CONST */
|
||||||
|
|
|
@ -1,45 +1,40 @@
|
||||||
static void *opcode_targets[256] = {
|
static void *opcode_targets[256] = {
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&TARGET_POP_TOP,
|
&&TARGET_POP_TOP,
|
||||||
&&TARGET_ROT_TWO,
|
|
||||||
&&TARGET_ROT_THREE,
|
|
||||||
&&TARGET_DUP_TOP,
|
|
||||||
&&TARGET_DUP_TOP_TWO,
|
|
||||||
&&TARGET_ROT_FOUR,
|
|
||||||
&&TARGET_BINARY_OP_ADAPTIVE,
|
&&TARGET_BINARY_OP_ADAPTIVE,
|
||||||
&&TARGET_BINARY_OP_ADD_INT,
|
&&TARGET_BINARY_OP_ADD_INT,
|
||||||
|
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||||
|
&&TARGET_BINARY_OP_ADD_UNICODE,
|
||||||
|
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||||
|
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||||
|
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||||
&&TARGET_NOP,
|
&&TARGET_NOP,
|
||||||
&&TARGET_UNARY_POSITIVE,
|
&&TARGET_UNARY_POSITIVE,
|
||||||
&&TARGET_UNARY_NEGATIVE,
|
&&TARGET_UNARY_NEGATIVE,
|
||||||
&&TARGET_UNARY_NOT,
|
&&TARGET_UNARY_NOT,
|
||||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
|
||||||
&&TARGET_BINARY_OP_ADD_UNICODE,
|
|
||||||
&&TARGET_UNARY_INVERT,
|
|
||||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
|
||||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
|
||||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
|
||||||
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
||||||
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
|
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
|
||||||
|
&&TARGET_UNARY_INVERT,
|
||||||
&&TARGET_COMPARE_OP_ADAPTIVE,
|
&&TARGET_COMPARE_OP_ADAPTIVE,
|
||||||
&&TARGET_COMPARE_OP_FLOAT_JUMP,
|
&&TARGET_COMPARE_OP_FLOAT_JUMP,
|
||||||
&&TARGET_COMPARE_OP_INT_JUMP,
|
&&TARGET_COMPARE_OP_INT_JUMP,
|
||||||
&&TARGET_COMPARE_OP_STR_JUMP,
|
&&TARGET_COMPARE_OP_STR_JUMP,
|
||||||
&&TARGET_BINARY_SUBSCR,
|
|
||||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||||
&&TARGET_BINARY_SUBSCR_GETITEM,
|
&&TARGET_BINARY_SUBSCR_GETITEM,
|
||||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||||
&&TARGET_GET_LEN,
|
|
||||||
&&TARGET_MATCH_MAPPING,
|
|
||||||
&&TARGET_MATCH_SEQUENCE,
|
|
||||||
&&TARGET_MATCH_KEYS,
|
|
||||||
&&TARGET_BINARY_SUBSCR_DICT,
|
&&TARGET_BINARY_SUBSCR_DICT,
|
||||||
&&TARGET_PUSH_EXC_INFO,
|
&&TARGET_BINARY_SUBSCR,
|
||||||
&&TARGET_STORE_SUBSCR_ADAPTIVE,
|
&&TARGET_STORE_SUBSCR_ADAPTIVE,
|
||||||
&&TARGET_STORE_SUBSCR_LIST_INT,
|
&&TARGET_STORE_SUBSCR_LIST_INT,
|
||||||
&&TARGET_STORE_SUBSCR_DICT,
|
&&TARGET_STORE_SUBSCR_DICT,
|
||||||
&&TARGET_CALL_NO_KW_ADAPTIVE,
|
&&TARGET_CALL_NO_KW_ADAPTIVE,
|
||||||
|
&&TARGET_GET_LEN,
|
||||||
|
&&TARGET_MATCH_MAPPING,
|
||||||
|
&&TARGET_MATCH_SEQUENCE,
|
||||||
|
&&TARGET_MATCH_KEYS,
|
||||||
&&TARGET_CALL_NO_KW_BUILTIN_O,
|
&&TARGET_CALL_NO_KW_BUILTIN_O,
|
||||||
|
&&TARGET_PUSH_EXC_INFO,
|
||||||
&&TARGET_CALL_NO_KW_BUILTIN_FAST,
|
&&TARGET_CALL_NO_KW_BUILTIN_FAST,
|
||||||
&&TARGET_CALL_NO_KW_LEN,
|
&&TARGET_CALL_NO_KW_LEN,
|
||||||
&&TARGET_CALL_NO_KW_ISINSTANCE,
|
&&TARGET_CALL_NO_KW_ISINSTANCE,
|
||||||
|
@ -48,39 +43,44 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
|
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
|
||||||
&&TARGET_CALL_NO_KW_TYPE_1,
|
&&TARGET_CALL_NO_KW_TYPE_1,
|
||||||
&&TARGET_CALL_NO_KW_BUILTIN_CLASS_1,
|
&&TARGET_CALL_NO_KW_BUILTIN_CLASS_1,
|
||||||
|
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
||||||
|
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
||||||
|
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||||
|
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||||
|
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||||
&&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_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
|
||||||
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
|
||||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
|
||||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
|
||||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
|
||||||
&&TARGET_STORE_SUBSCR,
|
|
||||||
&&TARGET_DELETE_SUBSCR,
|
|
||||||
&&TARGET_LOAD_ATTR_SLOT,
|
&&TARGET_LOAD_ATTR_SLOT,
|
||||||
&&TARGET_LOAD_ATTR_MODULE,
|
&&TARGET_LOAD_ATTR_MODULE,
|
||||||
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
||||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||||
|
&&TARGET_STORE_SUBSCR,
|
||||||
|
&&TARGET_DELETE_SUBSCR,
|
||||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||||
&&TARGET_GET_ITER,
|
|
||||||
&&TARGET_GET_YIELD_FROM_ITER,
|
|
||||||
&&TARGET_PRINT_EXPR,
|
|
||||||
&&TARGET_LOAD_BUILD_CLASS,
|
|
||||||
&&TARGET_LOAD_METHOD_CACHED,
|
&&TARGET_LOAD_METHOD_CACHED,
|
||||||
&&TARGET_GET_AWAITABLE,
|
|
||||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
|
||||||
&&TARGET_RETURN_GENERATOR,
|
|
||||||
&&TARGET_LOAD_METHOD_CLASS,
|
&&TARGET_LOAD_METHOD_CLASS,
|
||||||
&&TARGET_LOAD_METHOD_MODULE,
|
&&TARGET_LOAD_METHOD_MODULE,
|
||||||
&&TARGET_LOAD_METHOD_NO_DICT,
|
&&TARGET_LOAD_METHOD_NO_DICT,
|
||||||
&&TARGET_STORE_ATTR_ADAPTIVE,
|
&&TARGET_STORE_ATTR_ADAPTIVE,
|
||||||
|
&&TARGET_GET_ITER,
|
||||||
|
&&TARGET_GET_YIELD_FROM_ITER,
|
||||||
|
&&TARGET_PRINT_EXPR,
|
||||||
|
&&TARGET_LOAD_BUILD_CLASS,
|
||||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||||
|
&&TARGET_GET_AWAITABLE,
|
||||||
|
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||||
|
&&TARGET_RETURN_GENERATOR,
|
||||||
&&TARGET_STORE_ATTR_SLOT,
|
&&TARGET_STORE_ATTR_SLOT,
|
||||||
|
&&TARGET_STORE_ATTR_WITH_HINT,
|
||||||
|
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||||
|
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||||
|
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||||
|
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||||
&&TARGET_LIST_TO_TUPLE,
|
&&TARGET_LIST_TO_TUPLE,
|
||||||
&&TARGET_RETURN_VALUE,
|
&&TARGET_RETURN_VALUE,
|
||||||
&&TARGET_IMPORT_STAR,
|
&&TARGET_IMPORT_STAR,
|
||||||
|
@ -98,7 +98,7 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_DELETE_ATTR,
|
&&TARGET_DELETE_ATTR,
|
||||||
&&TARGET_STORE_GLOBAL,
|
&&TARGET_STORE_GLOBAL,
|
||||||
&&TARGET_DELETE_GLOBAL,
|
&&TARGET_DELETE_GLOBAL,
|
||||||
&&TARGET_ROT_N,
|
&&TARGET_SWAP,
|
||||||
&&TARGET_LOAD_CONST,
|
&&TARGET_LOAD_CONST,
|
||||||
&&TARGET_LOAD_NAME,
|
&&TARGET_LOAD_NAME,
|
||||||
&&TARGET_BUILD_TUPLE,
|
&&TARGET_BUILD_TUPLE,
|
||||||
|
@ -130,7 +130,7 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_POP_JUMP_IF_NOT_NONE,
|
&&TARGET_POP_JUMP_IF_NOT_NONE,
|
||||||
&&TARGET_POP_JUMP_IF_NONE,
|
&&TARGET_POP_JUMP_IF_NONE,
|
||||||
&&TARGET_RAISE_VARARGS,
|
&&TARGET_RAISE_VARARGS,
|
||||||
&&TARGET_STORE_ATTR_WITH_HINT,
|
&&TARGET_STORE_FAST__STORE_FAST,
|
||||||
&&TARGET_MAKE_FUNCTION,
|
&&TARGET_MAKE_FUNCTION,
|
||||||
&&TARGET_BUILD_SLICE,
|
&&TARGET_BUILD_SLICE,
|
||||||
&&TARGET_JUMP_NO_INTERRUPT,
|
&&TARGET_JUMP_NO_INTERRUPT,
|
||||||
|
@ -139,20 +139,20 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_LOAD_DEREF,
|
&&TARGET_LOAD_DEREF,
|
||||||
&&TARGET_STORE_DEREF,
|
&&TARGET_STORE_DEREF,
|
||||||
&&TARGET_DELETE_DEREF,
|
&&TARGET_DELETE_DEREF,
|
||||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_CALL_FUNCTION_EX,
|
&&TARGET_CALL_FUNCTION_EX,
|
||||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
&&_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_COPY_FREE_VARS,
|
&&TARGET_COPY_FREE_VARS,
|
||||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
&&_unknown_opcode,
|
||||||
&&TARGET_RESUME,
|
&&TARGET_RESUME,
|
||||||
&&TARGET_MATCH_CLASS,
|
&&TARGET_MATCH_CLASS,
|
||||||
&&TARGET_STORE_FAST__STORE_FAST,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&TARGET_FORMAT_VALUE,
|
&&TARGET_FORMAT_VALUE,
|
||||||
&&TARGET_BUILD_CONST_KEY_MAP,
|
&&TARGET_BUILD_CONST_KEY_MAP,
|
||||||
|
|
Loading…
Reference in New Issue