bpo-46329: Split calls into precall and call instructions. (GH-30855)

* Add PRECALL_FUNCTION opcode.

* Move 'call shape' varaibles into struct.

* Replace CALL_NO_KW and CALL_KW with KW_NAMES and CALL instructions.

* Specialize for builtin methods taking using the METH_FASTCALL | METH_KEYWORDS protocol.

* Allow kwnames for specialized calls to builtin types.

* Specialize calls to tuple(arg) and str(arg).
This commit is contained in:
Mark Shannon 2022-01-28 12:42:30 +00:00 committed by GitHub
parent 5a9e423473
commit 89fd7c3452
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 957 additions and 674 deletions

View File

@ -34,10 +34,13 @@ the following command can be used to display the disassembly of
:func:`myfunc`::
>>> dis.dis(myfunc)
2 0 LOAD_GLOBAL 0 (len)
2 LOAD_FAST 0 (alist)
4 CALL_NO_KW 1
6 RETURN_VALUE
1 0 RESUME 0
2 2 LOAD_GLOBAL 0 (len)
4 LOAD_FAST 0 (alist)
6 PRECALL_FUNCTION 1
8 CALL 0
10 RETURN_VALUE
(The "2" is a line number).
@ -102,9 +105,11 @@ Example::
>>> for instr in bytecode:
... print(instr.opname)
...
RESUME
LOAD_GLOBAL
LOAD_FAST
CALL_NO_KW
PRECALL_FUNCTION
CALL
RETURN_VALUE
@ -617,7 +622,7 @@ iterations of the loop.
.. opcode:: LOAD_BUILD_CLASS
Pushes :func:`builtins.__build_class__` onto the stack. It is later called
by :opcode:`CALL_NO_KW` to construct a class.
to construct a class.
.. opcode:: BEFORE_WITH (delta)
@ -1058,30 +1063,19 @@ iterations of the loop.
with ``__cause__`` set to ``TOS``)
.. opcode:: CALL_NO_KW (argc)
.. opcode:: CALL (named)
Calls a callable object with positional arguments.
*argc* indicates the number of positional arguments.
The top of the stack contains positional arguments, with the right-most
argument on top. Below the arguments is a callable object to call.
``CALL_NO_KW`` pops all arguments and the callable object off the stack,
calls the callable object with those arguments, and pushes the return value
returned by the callable object.
Calls a callable object with the number of positional arguments specified by
the preceding :opcode:`PRECALL_FUNCTION` or :opcode:`PRECALL_METHOD` and
the named arguments specified by the preceding :opcode:`KW_NAMES`, if any.
*named* indicates the number of named arguments.
On the stack are (in ascending order):
.. versionadded:: 3.11
* The callable
* The positional arguments
* The named arguments
.. opcode:: CALL_KW (argc)
Calls a callable object with positional (if any) and keyword arguments.
*argc* indicates the total number of positional and keyword arguments.
The top element on the stack contains a tuple with the names of the
keyword arguments, which must be strings.
Below that are the values for the keyword arguments,
in the order corresponding to the tuple.
Below that are positional arguments, with the right-most parameter on
top. Below the arguments is a callable object to call.
``CALL_KW`` pops all arguments and the callable object off the stack,
``CALL`` pops all arguments and the callable object off the stack,
calls the callable object with those arguments, and pushes the return value
returned by the callable object.
@ -1108,7 +1102,7 @@ iterations of the loop.
Loads a method named ``co_names[namei]`` from the TOS object. TOS is popped.
This bytecode distinguishes two cases: if TOS has a method with the correct
name, the bytecode pushes the unbound method and TOS. TOS will be used as
the first argument (``self``) by :opcode:`CALL_METHOD` when calling the
the first argument (``self``) by :opcode:`PRECALL_METHOD` when calling the
unbound method. Otherwise, ``NULL`` and the object return by the attribute
lookup are pushed.
@ -1117,14 +1111,30 @@ iterations of the loop.
.. opcode:: PRECALL_METHOD (argc)
Prefixes either :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`.
Prefixes :opcode:`CALL` (possibly with an intervening ``KW_NAMES``).
This opcode is designed to be used with :opcode:`LOAD_METHOD`.
Sets internal variables, so that :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`
Sets internal variables, so that :opcode:`CALL`
clean up after :opcode:`LOAD_METHOD` correctly.
.. versionadded:: 3.11
.. opcode:: PRECALL_FUNCTION (args)
Prefixes :opcode:`CALL` (possibly with an intervening ``KW_NAMES``).
Sets internal variables, so that :opcode:`CALL` can execute correctly.
.. versionadded:: 3.11
.. opcode:: KW_NAMES (i)
Stores a reference to ``co_consts[consti]`` into an internal variable
for use by :opcode:`CALL`. ``co_consts[consti]`` must be a tuple of strings.
.. versionadded:: 3.11
.. opcode:: MAKE_FUNCTION (flags)
Pushes a new function object on the stack. From bottom to top, the consumed

View File

@ -400,7 +400,8 @@ CPython bytecode changes
* Replaced the three call instructions: :opcode:`CALL_FUNCTION`,
:opcode:`CALL_FUNCTION_KW` and :opcode:`CALL_METHOD` with
:opcode:`CALL_NO_KW`, :opcode:`CALL_KW` and :opcode:`PRECALL_METHOD`.
:opcode:`PRECALL_FUNCTION`, :opcode:`PRECALL_METHOD`, :opcode:`CALL`,
and :opcode:`KW_NAMES`.
This decouples the argument shifting for methods from the handling of
keyword arguments and allows better specialization of calls.

View File

@ -38,7 +38,7 @@ typedef struct {
typedef struct {
uint32_t func_version;
uint16_t defaults_start;
uint16_t min_args;
uint16_t defaults_len;
} _PyCallCache;
@ -271,7 +271,8 @@ int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNI
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
PyObject *kwnames, SpecializedCacheEntry *cache, PyObject *builtins);
void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
SpecializedCacheEntry *cache);
void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);

View File

@ -189,6 +189,9 @@ _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size)
void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame *frame);
InterpreterFrame *
_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func);
#ifdef __cplusplus
}
#endif

79
Include/opcode.h generated
View File

@ -109,9 +109,10 @@ extern "C" {
#define SET_UPDATE 163
#define DICT_MERGE 164
#define DICT_UPDATE 165
#define PRECALL_FUNCTION 167
#define PRECALL_METHOD 168
#define CALL_NO_KW 169
#define CALL_KW 170
#define CALL 171
#define KW_NAMES 172
#define BINARY_OP_ADAPTIVE 2
#define BINARY_OP_ADD_INT 3
#define BINARY_OP_ADD_FLOAT 4
@ -133,40 +134,45 @@ extern "C" {
#define STORE_SUBSCR_ADAPTIVE 26
#define STORE_SUBSCR_LIST_INT 27
#define STORE_SUBSCR_DICT 28
#define CALL_NO_KW_ADAPTIVE 29
#define CALL_NO_KW_BUILTIN_O 34
#define CALL_NO_KW_BUILTIN_FAST 36
#define CALL_NO_KW_LEN 37
#define CALL_NO_KW_ISINSTANCE 38
#define CALL_NO_KW_PY_SIMPLE 39
#define CALL_NO_KW_LIST_APPEND 40
#define CALL_NO_KW_METHOD_DESCRIPTOR_O 41
#define CALL_NO_KW_TYPE_1 42
#define CALL_NO_KW_BUILTIN_CLASS_1 43
#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 44
#define JUMP_ABSOLUTE_QUICK 45
#define LOAD_ATTR_ADAPTIVE 46
#define LOAD_ATTR_INSTANCE_VALUE 47
#define LOAD_ATTR_WITH_HINT 48
#define LOAD_ATTR_SLOT 55
#define LOAD_ATTR_MODULE 56
#define LOAD_GLOBAL_ADAPTIVE 57
#define LOAD_GLOBAL_MODULE 58
#define LOAD_GLOBAL_BUILTIN 59
#define LOAD_METHOD_ADAPTIVE 62
#define LOAD_METHOD_CACHED 63
#define LOAD_METHOD_CLASS 64
#define LOAD_METHOD_MODULE 65
#define LOAD_METHOD_NO_DICT 66
#define STORE_ATTR_ADAPTIVE 67
#define STORE_ATTR_INSTANCE_VALUE 72
#define STORE_ATTR_SLOT 76
#define STORE_ATTR_WITH_HINT 77
#define LOAD_FAST__LOAD_FAST 78
#define STORE_FAST__LOAD_FAST 79
#define LOAD_FAST__LOAD_CONST 80
#define LOAD_CONST__LOAD_FAST 81
#define STORE_FAST__STORE_FAST 131
#define CALL_ADAPTIVE 29
#define CALL_BUILTIN_CLASS 34
#define CALL_NO_KW_BUILTIN_O 36
#define CALL_NO_KW_BUILTIN_FAST 37
#define CALL_BUILTIN_FAST_WITH_KEYWORDS 38
#define CALL_NO_KW_LEN 39
#define CALL_NO_KW_ISINSTANCE 40
#define CALL_PY_EXACT_ARGS 41
#define CALL_PY_WITH_DEFAULTS 42
#define CALL_NO_KW_LIST_APPEND 43
#define CALL_NO_KW_METHOD_DESCRIPTOR_O 44
#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 45
#define CALL_NO_KW_STR_1 46
#define CALL_NO_KW_TUPLE_1 47
#define CALL_NO_KW_TYPE_1 48
#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 55
#define JUMP_ABSOLUTE_QUICK 56
#define LOAD_ATTR_ADAPTIVE 57
#define LOAD_ATTR_INSTANCE_VALUE 58
#define LOAD_ATTR_WITH_HINT 59
#define LOAD_ATTR_SLOT 62
#define LOAD_ATTR_MODULE 63
#define LOAD_GLOBAL_ADAPTIVE 64
#define LOAD_GLOBAL_MODULE 65
#define LOAD_GLOBAL_BUILTIN 66
#define LOAD_METHOD_ADAPTIVE 67
#define LOAD_METHOD_CACHED 72
#define LOAD_METHOD_CLASS 76
#define LOAD_METHOD_MODULE 77
#define LOAD_METHOD_NO_DICT 78
#define STORE_ATTR_ADAPTIVE 79
#define STORE_ATTR_INSTANCE_VALUE 80
#define STORE_ATTR_SLOT 81
#define STORE_ATTR_WITH_HINT 131
#define LOAD_FAST__LOAD_FAST 140
#define STORE_FAST__LOAD_FAST 141
#define LOAD_FAST__LOAD_CONST 143
#define LOAD_CONST__LOAD_FAST 150
#define STORE_FAST__STORE_FAST 153
#define DO_TRACING 255
#ifdef NEED_OPCODE_JUMP_TABLES
static uint32_t _PyOpcode_RelativeJump[8] = {
@ -193,6 +199,7 @@ static uint32_t _PyOpcode_Jump[8] = {
#define HAS_CONST(op) (false\
|| ((op) == 100) \
|| ((op) == 172) \
)
#define NB_ADD 0

View File

@ -384,9 +384,14 @@ _code_type = type(_write_atomic.__code__)
# 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.11a5 3478 (New CALL opcodes)
# Python 3.12 will start with magic number 3500
# Python 3.12 will start with magic number 3500
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
@ -397,7 +402,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3477).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3478).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'

View File

@ -188,9 +188,12 @@ def_op('SET_UPDATE', 163)
def_op('DICT_MERGE', 164)
def_op('DICT_UPDATE', 165)
def_op('PRECALL_FUNCTION', 167)
def_op('PRECALL_METHOD', 168)
def_op('CALL_NO_KW', 169)
def_op('CALL_KW', 170)
def_op('CALL', 171)
def_op('KW_NAMES', 172)
hasconst.append(172)
del def_op, name_op, jrel_op, jabs_op
@ -245,16 +248,21 @@ _specialized_instructions = [
"STORE_SUBSCR_ADAPTIVE",
"STORE_SUBSCR_LIST_INT",
"STORE_SUBSCR_DICT",
"CALL_NO_KW_ADAPTIVE",
"CALL_ADAPTIVE",
"CALL_BUILTIN_CLASS",
"CALL_NO_KW_BUILTIN_O",
"CALL_NO_KW_BUILTIN_FAST",
"CALL_BUILTIN_FAST_WITH_KEYWORDS",
"CALL_NO_KW_LEN",
"CALL_NO_KW_ISINSTANCE",
"CALL_NO_KW_PY_SIMPLE",
"CALL_PY_EXACT_ARGS",
"CALL_PY_WITH_DEFAULTS",
"CALL_NO_KW_LIST_APPEND",
"CALL_NO_KW_METHOD_DESCRIPTOR_O",
"CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS",
"CALL_NO_KW_STR_1",
"CALL_NO_KW_TUPLE_1",
"CALL_NO_KW_TYPE_1",
"CALL_NO_KW_BUILTIN_CLASS_1",
"CALL_NO_KW_METHOD_DESCRIPTOR_FAST",
"JUMP_ABSOLUTE_QUICK",
"LOAD_ATTR_ADAPTIVE",

View File

@ -837,9 +837,8 @@ if 1:
opcodes = list(dis.get_instructions(func))
instructions = [opcode.opname for opcode in opcodes]
self.assertNotIn('LOAD_METHOD', instructions)
self.assertNotIn('CALL_METHOD', instructions)
self.assertIn('LOAD_ATTR', instructions)
self.assertIn('CALL_NO_KW', instructions)
self.assertIn('PRECALL_FUNCTION', instructions)
def test_lineno_procedure_call(self):
def call():
@ -1096,7 +1095,7 @@ f(
)
"""
compiled_code, _ = self.check_positions_against_ast(snippet)
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
line=1, end_line=3, column=0, end_column=1)
def test_very_long_line_end_offset(self):
@ -1106,7 +1105,7 @@ f(
snippet = f"g('{long_string}')"
compiled_code, _ = self.check_positions_against_ast(snippet)
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
line=1, end_line=1, column=None, end_column=None)
def test_complex_single_line_expression(self):

View File

@ -104,11 +104,12 @@ dis_f = """\
%3d 2 LOAD_GLOBAL 0 (print)
4 LOAD_FAST 0 (a)
6 CALL_NO_KW 1
8 POP_TOP
6 PRECALL_FUNCTION 1
8 CALL 0
10 POP_TOP
%3d 10 LOAD_CONST 1 (1)
12 RETURN_VALUE
%3d 12 LOAD_CONST 1 (1)
14 RETURN_VALUE
""" % (_f.__code__.co_firstlineno,
_f.__code__.co_firstlineno + 1,
_f.__code__.co_firstlineno + 2)
@ -118,10 +119,11 @@ dis_f_co_code = """\
0 RESUME 0
2 LOAD_GLOBAL 0
4 LOAD_FAST 0
6 CALL_NO_KW 1
8 POP_TOP
10 LOAD_CONST 1
12 RETURN_VALUE
6 PRECALL_FUNCTION 1
8 CALL 0
10 POP_TOP
12 LOAD_CONST 1
14 RETURN_VALUE
"""
@ -138,15 +140,16 @@ dis_bug708901 = """\
%3d 6 LOAD_CONST 2 (10)
%3d 8 CALL_NO_KW 2
10 GET_ITER
>> 12 FOR_ITER 2 (to 18)
14 STORE_FAST 0 (res)
%3d 8 PRECALL_FUNCTION 2
10 CALL 0
12 GET_ITER
>> 14 FOR_ITER 2 (to 20)
16 STORE_FAST 0 (res)
%3d 16 JUMP_ABSOLUTE 6 (to 12)
%3d 18 JUMP_ABSOLUTE 7 (to 14)
%3d >> 18 LOAD_CONST 0 (None)
20 RETURN_VALUE
%3d >> 20 LOAD_CONST 0 (None)
22 RETURN_VALUE
""" % (bug708901.__code__.co_firstlineno,
bug708901.__code__.co_firstlineno + 1,
bug708901.__code__.co_firstlineno + 2,
@ -168,13 +171,15 @@ dis_bug1333982 = """\
6 MAKE_FUNCTION 0
8 LOAD_FAST 0 (x)
10 GET_ITER
12 CALL_NO_KW 1
12 PRECALL_FUNCTION 1
14 CALL 0
%3d 14 LOAD_CONST 3 (1)
%3d 16 LOAD_CONST 3 (1)
%3d 16 BINARY_OP 0 (+)
18 CALL_NO_KW 1
20 RAISE_VARARGS 1
%3d 18 BINARY_OP 0 (+)
20 PRECALL_FUNCTION 1
22 CALL 0
24 RAISE_VARARGS 1
""" % (bug1333982.__code__.co_firstlineno,
bug1333982.__code__.co_firstlineno + 1,
__file__,
@ -290,21 +295,23 @@ dis_annot_stmt_str = """\
3 16 LOAD_NAME 3 (fun)
18 LOAD_CONST 0 (1)
20 CALL_NO_KW 1
22 LOAD_NAME 2 (__annotations__)
24 LOAD_CONST 2 ('y')
26 STORE_SUBSCR
20 PRECALL_FUNCTION 1
22 CALL 0
24 LOAD_NAME 2 (__annotations__)
26 LOAD_CONST 2 ('y')
28 STORE_SUBSCR
4 28 LOAD_CONST 0 (1)
30 LOAD_NAME 4 (lst)
32 LOAD_NAME 3 (fun)
34 LOAD_CONST 3 (0)
36 CALL_NO_KW 1
38 STORE_SUBSCR
40 LOAD_NAME 1 (int)
42 POP_TOP
44 LOAD_CONST 4 (None)
46 RETURN_VALUE
4 30 LOAD_CONST 0 (1)
32 LOAD_NAME 4 (lst)
34 LOAD_NAME 3 (fun)
36 LOAD_CONST 3 (0)
38 PRECALL_FUNCTION 1
40 CALL 0
42 STORE_SUBSCR
44 LOAD_NAME 1 (int)
46 POP_TOP
48 LOAD_CONST 4 (None)
50 RETURN_VALUE
"""
compound_stmt_str = """\
@ -423,20 +430,22 @@ dis_tryfinally = """\
%3d 4 LOAD_FAST 0 (a)
%3d 6 LOAD_FAST 1 (b)
8 CALL_NO_KW 0
10 POP_TOP
12 RETURN_VALUE
>> 14 PUSH_EXC_INFO
16 LOAD_FAST 1 (b)
18 CALL_NO_KW 0
20 POP_TOP
22 RERAISE 0
>> 24 COPY 3
26 POP_EXCEPT
28 RERAISE 1
8 PRECALL_FUNCTION 0
10 CALL 0
12 POP_TOP
14 RETURN_VALUE
>> 16 PUSH_EXC_INFO
18 LOAD_FAST 1 (b)
20 PRECALL_FUNCTION 0
22 CALL 0
24 POP_TOP
26 RERAISE 0
>> 28 COPY 3
30 POP_EXCEPT
32 RERAISE 1
ExceptionTable:
4 to 4 -> 14 [0]
14 to 22 -> 24 [1] lasti
4 to 4 -> 16 [0]
16 to 26 -> 28 [1] lasti
""" % (_tryfinally.__code__.co_firstlineno,
_tryfinally.__code__.co_firstlineno + 1,
_tryfinally.__code__.co_firstlineno + 2,
@ -451,20 +460,22 @@ dis_tryfinallyconst = """\
%3d 4 NOP
%3d 6 LOAD_FAST 0 (b)
8 CALL_NO_KW 0
10 POP_TOP
12 LOAD_CONST 1 (1)
14 RETURN_VALUE
16 PUSH_EXC_INFO
18 LOAD_FAST 0 (b)
20 CALL_NO_KW 0
22 POP_TOP
24 RERAISE 0
>> 26 COPY 3
28 POP_EXCEPT
30 RERAISE 1
8 PRECALL_FUNCTION 0
10 CALL 0
12 POP_TOP
14 LOAD_CONST 1 (1)
16 RETURN_VALUE
18 PUSH_EXC_INFO
20 LOAD_FAST 0 (b)
22 PRECALL_FUNCTION 0
24 CALL 0
26 POP_TOP
28 RERAISE 0
>> 30 COPY 3
32 POP_EXCEPT
34 RERAISE 1
ExceptionTable:
16 to 24 -> 26 [1] lasti
18 to 28 -> 30 [1] lasti
""" % (_tryfinallyconst.__code__.co_firstlineno,
_tryfinallyconst.__code__.co_firstlineno + 1,
_tryfinallyconst.__code__.co_firstlineno + 2,
@ -520,8 +531,9 @@ Disassembly of <code object foo at 0x..., file "%s", line %d>:
12 MAKE_FUNCTION 8 (closure)
14 LOAD_DEREF 1 (y)
16 GET_ITER
18 CALL_NO_KW 1
20 RETURN_VALUE
18 PRECALL_FUNCTION 1
20 CALL 0
22 RETURN_VALUE
""" % (dis_nested_0,
__file__,
_h.__code__.co_firstlineno + 1,
@ -1066,10 +1078,11 @@ expected_opinfo_outer = [
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=34, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=7, argval=7, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=40, starts_line=8, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=7, argval=7, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=42, starts_line=8, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_f = [
@ -1091,10 +1104,11 @@ expected_opinfo_f = [
Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=30, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=32, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=34, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=4, argval=4, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=40, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=4, argval=4, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=42, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_inner = [
@ -1107,132 +1121,144 @@ expected_opinfo_inner = [
Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=12, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=14, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=16, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=6, argval=6, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=22, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=6, argval=6, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=24, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_jumpy = [
Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=1, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=3, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='FOR_ITER', opcode=93, arg=17, argval=46, argrepr='to 46', offset=10, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=26, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=16, argval=32, argrepr='to 32', offset=28, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=5, argval=10, argrepr='to 10', offset=30, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=32, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=34, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=36, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=22, argval=44, argrepr='to 44', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=40, starts_line=8, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=5, argval=54, argrepr='to 54', offset=42, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=5, argval=10, argrepr='to 10', offset=44, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=54, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=49, argval=98, argrepr='to 98', offset=56, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=58, starts_line=12, is_jump_target=True, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=13, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=68, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=70, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=72, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=14, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=76, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=78, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=42, argval=84, argrepr='to 84', offset=80, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=27, argval=54, argrepr='to 54', offset=82, starts_line=15, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=84, starts_line=16, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=86, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=88, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=47, argval=94, argrepr='to 94', offset=90, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=6, argval=106, argrepr='to 106', offset=92, starts_line=17, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=94, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=29, argval=58, argrepr='to 58', offset=96, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=98, starts_line=19, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=100, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=102, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=104, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=106, starts_line=20, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=108, starts_line=21, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=110, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=112, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=8, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=10, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='FOR_ITER', opcode=93, arg=18, argval=50, argrepr='to 50', offset=12, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=16, starts_line=4, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=26, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=28, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=30, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=18, argval=36, argrepr='to 36', offset=32, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=6, argval=12, argrepr='to 12', offset=34, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=36, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=38, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=40, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=24, argval=48, argrepr='to 48', offset=42, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=44, starts_line=8, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=6, argval=60, argrepr='to 60', offset=46, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=6, argval=12, argrepr='to 12', offset=48, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=50, starts_line=10, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=52, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=54, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=58, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=53, argval=106, argrepr='to 106', offset=62, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=64, starts_line=12, is_jump_target=True, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=68, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=70, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=72, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=13, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=76, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=78, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=80, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=82, starts_line=14, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=84, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=86, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=46, argval=92, argrepr='to 92', offset=88, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=30, argval=60, argrepr='to 60', offset=90, starts_line=15, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=92, starts_line=16, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=94, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=96, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=51, argval=102, argrepr='to 102', offset=98, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=7, argval=116, argrepr='to 116', offset=100, starts_line=17, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=102, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=32, argval=64, argrepr='to 64', offset=104, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=106, starts_line=19, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=108, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=110, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=116, starts_line=25, is_jump_target=False, positions=None),
Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=120, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=122, starts_line=26, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=124, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=130, starts_line=25, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=132, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=134, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=164, argrepr='to 164', offset=140, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=78, argval=156, argrepr='to 156', offset=146, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=148, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, 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=160, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=194, argrepr='to 194', offset=164, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=168, starts_line=22, is_jump_target=False, positions=None),
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=93, argval=186, argrepr='to 186', offset=170, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=23, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=176, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=10, argval=206, argrepr='to 206', offset=184, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=186, starts_line=22, is_jump_target=True, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=194, starts_line=28, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=196, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=202, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=206, starts_line=23, is_jump_target=True, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=208, starts_line=28, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=210, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=216, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=222, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=224, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=116, starts_line=20, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=118, starts_line=21, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=120, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=122, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=126, starts_line=25, is_jump_target=False, positions=None),
Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=130, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=26, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=134, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=142, starts_line=25, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=144, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=146, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=3, argval=3, argrepr='', offset=148, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=178, argrepr='to 178', offset=154, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=85, argval=170, argrepr='to 170', offset=160, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=210, argrepr='to 210', offset=178, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=182, starts_line=22, is_jump_target=False, positions=None),
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=101, argval=202, argrepr='to 202', offset=184, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=188, starts_line=23, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=190, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=224, argrepr='to 224', offset=200, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=202, starts_line=22, is_jump_target=True, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=210, starts_line=28, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=212, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=220, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=224, starts_line=23, is_jump_target=True, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=226, starts_line=28, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=228, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=236, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=242, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=244, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL_FUNCTION', opcode=167, arg=1, argval=1, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=252, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=254, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=258, starts_line=None, is_jump_target=False, positions=None),
]
# One last piece of inspect fodder to check the default line number handling
@ -1301,6 +1327,7 @@ class InstructionTests(InstructionTestCase):
(1, 3, 0, 1),
(1, 3, 0, 1),
(1, 3, 0, 1),
(1, 3, 0, 1),
(1, 3, 0, 1)
]
self.assertEqual(positions, expected)

View File

@ -0,0 +1,12 @@
Use two or three bytecodes to implement most calls.
Calls without named arguments are implemented as a sequence of two
instructions: ``PRECALL; CALL``. Calls with named arguments are implemented
as a sequence of three instructions: ``PRECALL; KW_NAMES; CALL``. There are
two different ``PRECALL`` instructions: ``PRECALL_FUNTION`` and
``PRECALL_METHOD``. The latter pairs with ``LOAD_METHOD``.
This partition into pre-call and call allows better specialization, and thus
better performance ultimately.
There is no change in semantics.

View File

@ -1,35 +1,36 @@
// Auto-generated by Programs/freeze_test_frozenmain.py
unsigned char M_test_frozenmain[] = {
227,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,
0,0,0,0,0,115,88,0,0,0,151,0,100,0,100,1,
0,0,0,0,0,115,96,0,0,0,151,0,100,0,100,1,
108,0,90,0,100,0,100,1,108,1,90,1,101,2,100,2,
169,1,1,0,101,2,100,3,101,0,106,3,169,2,1,0,
101,1,106,4,169,0,100,4,25,0,90,5,100,5,68,0,
93,14,90,6,101,2,100,6,101,6,155,0,100,7,101,5,
101,6,25,0,155,0,157,4,169,1,1,0,113,27,100,1,
83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122,
101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8,
115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103,
41,5,90,12,112,114,111,103,114,97,109,95,110,97,109,101,
218,10,101,120,101,99,117,116,97,98,108,101,90,15,117,115,
101,95,101,110,118,105,114,111,110,109,101,110,116,90,17,99,
111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111,
90,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111,
122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218,
3,115,121,115,90,17,95,116,101,115,116,105,110,116,101,114,
110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4,
97,114,103,118,90,11,103,101,116,95,99,111,110,102,105,103,
115,114,2,0,0,0,218,3,107,101,121,169,0,243,0,0,
0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109,
97,105,110,46,112,121,218,8,60,109,111,100,117,108,101,62,
114,11,0,0,0,1,0,0,0,115,18,0,0,0,2,128,
8,3,8,1,8,2,12,1,12,1,8,1,26,7,4,249,
115,20,0,0,0,2,128,8,3,8,1,8,2,12,1,12,
1,2,7,4,1,2,249,30,7,115,88,0,0,0,0,0,
1,11,1,11,1,11,1,11,1,25,1,25,1,25,1,25,
1,6,7,27,1,28,1,28,1,6,7,17,19,22,19,27,
1,28,1,28,10,27,10,39,10,41,42,50,10,51,1,7,
12,2,1,42,1,42,5,8,5,10,11,41,21,24,11,41,
11,41,28,34,35,38,28,39,11,41,11,41,5,42,5,42,
167,1,171,0,1,0,101,2,100,3,101,0,106,3,167,2,
171,0,1,0,101,1,106,4,167,0,171,0,100,4,25,0,
90,5,100,5,68,0,93,15,90,6,101,2,100,6,101,6,
155,0,100,7,101,5,101,6,25,0,155,0,157,4,167,1,
171,0,1,0,113,30,100,1,83,0,41,8,233,0,0,0,
0,78,122,18,70,114,111,122,101,110,32,72,101,108,108,111,
32,87,111,114,108,100,122,8,115,121,115,46,97,114,103,118,
218,6,99,111,110,102,105,103,41,5,90,12,112,114,111,103,
114,97,109,95,110,97,109,101,218,10,101,120,101,99,117,116,
97,98,108,101,90,15,117,115,101,95,101,110,118,105,114,111,
110,109,101,110,116,90,17,99,111,110,102,105,103,117,114,101,
95,99,95,115,116,100,105,111,90,14,98,117,102,102,101,114,
101,100,95,115,116,100,105,111,122,7,99,111,110,102,105,103,
32,122,2,58,32,41,7,218,3,115,121,115,90,17,95,116,
101,115,116,105,110,116,101,114,110,97,108,99,97,112,105,218,
5,112,114,105,110,116,218,4,97,114,103,118,90,11,103,101,
116,95,99,111,110,102,105,103,115,114,2,0,0,0,218,3,
107,101,121,169,0,243,0,0,0,0,250,18,116,101,115,116,
95,102,114,111,122,101,110,109,97,105,110,46,112,121,218,8,
60,109,111,100,117,108,101,62,114,11,0,0,0,1,0,0,
0,115,18,0,0,0,2,128,8,3,8,1,10,2,14,1,
14,1,8,1,28,7,4,249,115,20,0,0,0,2,128,8,
3,8,1,10,2,14,1,14,1,2,7,4,1,2,249,32,
7,115,96,0,0,0,0,0,1,11,1,11,1,11,1,11,
1,25,1,25,1,25,1,25,1,6,7,27,1,28,1,28,
1,28,1,6,7,17,19,22,19,27,1,28,1,28,1,28,
10,27,10,39,10,41,10,41,42,50,10,51,1,7,12,2,
1,42,1,42,5,8,5,10,11,41,21,24,11,41,11,41,
28,34,35,38,28,39,11,41,11,41,5,42,5,42,5,42,
5,42,1,42,1,42,114,9,0,0,0,
};

View File

@ -1636,6 +1636,17 @@ pop_frame(PyThreadState *tstate, InterpreterFrame *frame)
return prev_frame;
}
/* It is only between a PRECALL_METHOD/FUNCTION instruction and the following CALL,
* that these values have any meaning.
*/
typedef struct {
PyObject *callable;
PyObject *kwnames;
int total_args;
int postcall_shrink;
} CallShape;
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int throwflag)
{
@ -1654,22 +1665,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
_Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker;
CFrame cframe;
/* Variables used for making calls */
PyObject *kwnames;
int nargs;
/*
* It is only between a PRECALL_METHOD instruction and the following instruction,
* that these two values can be anything other than their defaults. */
int postcall_shrink = 1;
int extra_args = 0;
#define RESET_STACK_ADJUST_FOR_CALLS \
do { \
postcall_shrink = 1; \
extra_args = 0; \
} while (0)
#define STACK_ADJUST_IS_RESET \
(postcall_shrink == 1 && extra_args == 0)
CallShape call_shape;
call_shape.kwnames = NULL; // Borrowed reference
call_shape.postcall_shrink = 0;
call_shape.total_args = 0;
call_shape.callable = NULL; // Strong reference
/* WARNING: Because the CFrame lives on the C stack,
* but can be accessed from a heap allocated object (tstate)
@ -2532,12 +2532,12 @@ handle_eval_breaker:
PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
if (iter == NULL) {
int opcode_at_minus_3 = 0;
if ((next_instr - first_instr) > 2) {
opcode_at_minus_3 = _Py_OPCODE(next_instr[-3]);
int opcode_at_minus_4 = 0;
if ((next_instr - first_instr) > 4) {
opcode_at_minus_4 = _Py_OPCODE(next_instr[-4]);
}
format_awaitable_error(tstate, Py_TYPE(iterable),
opcode_at_minus_3,
opcode_at_minus_4,
_Py_OPCODE(next_instr[-2]));
}
@ -4173,7 +4173,6 @@ handle_eval_breaker:
if (iter == NULL)
goto error;
PREDICT(FOR_ITER);
PREDICT(CALL_NO_KW);
DISPATCH();
}
@ -4494,6 +4493,16 @@ handle_eval_breaker:
NOTRACE_DISPATCH();
}
TARGET(PRECALL_FUNCTION) {
/* Move ownership of reference from stack to call_shape */
call_shape.callable = PEEK(oparg + 1);
call_shape.postcall_shrink = 1;
call_shape.total_args = oparg;
call_shape.kwnames = NULL;
DISPATCH();
}
TARGET(PRECALL_METHOD) {
/* Designed to work in tamdem with LOAD_METHOD. */
/* `meth` is NULL when LOAD_METHOD thinks that it's not
@ -4522,54 +4531,57 @@ handle_eval_breaker:
make it accept the `self` as a first argument.
*/
int is_method = (PEEK(oparg + 2) != NULL);
extra_args = is_method;
postcall_shrink = 2-is_method;
int nargs = oparg + is_method;
/* Move ownership of reference from stack to call_shape
* and make sure that NULL is cleared from stack */
call_shape.callable = PEEK(nargs + 1);
call_shape.postcall_shrink = 2-is_method;
call_shape.total_args = nargs;
call_shape.kwnames = NULL;
DISPATCH();
}
TARGET(CALL_KW) {
kwnames = POP();
oparg += extra_args;
extra_args = 0;
nargs = oparg - (int)PyTuple_GET_SIZE(kwnames);
goto call_function;
TARGET(KW_NAMES) {
assert(call_shape.kwnames == NULL);
assert(oparg < PyTuple_GET_SIZE(consts));
call_shape.kwnames = GETITEM(consts, oparg);
DISPATCH();
}
TARGET(CALL_NO_KW) {
TARGET(CALL) {
PREDICTED(CALL);
PyObject *function;
PREDICTED(CALL_NO_KW);
kwnames = NULL;
oparg += extra_args;
nargs = oparg;
assert((oparg == 0 && call_shape.kwnames == NULL)
|| (oparg != 0 && oparg == PyTuple_GET_SIZE(call_shape.kwnames)));
call_function:
function = PEEK(oparg + 1);
function = call_shape.callable;
if (Py_TYPE(function) == &PyMethod_Type) {
PyObject *meth = ((PyMethodObject *)function)->im_func;
PyObject *self = ((PyMethodObject *)function)->im_self;
Py_INCREF(meth);
Py_INCREF(self);
PEEK(oparg + 1) = self;
PEEK(call_shape.total_args + 1) = self;
Py_DECREF(function);
function = meth;
oparg++;
nargs++;
assert(postcall_shrink >= 1);
postcall_shrink--;
call_shape.total_args++;
assert(call_shape.postcall_shrink >= 1);
call_shape.postcall_shrink--;
}
int total_args = call_shape.total_args;
int positional_args = total_args - oparg;
// Check if the call can be inlined or not
if (Py_TYPE(function) == &PyFunction_Type && tstate->interp->eval_frame == NULL) {
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS(function);
STACK_SHRINK(oparg);
STACK_SHRINK(total_args);
InterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, (PyFunctionObject *)function, locals,
stack_pointer, nargs, kwnames
stack_pointer, positional_args, call_shape.kwnames
);
STACK_SHRINK(postcall_shrink);
RESET_STACK_ADJUST_FOR_CALLS;
STACK_SHRINK(call_shape.postcall_shrink);
// The frame has stolen all the arguments from the stack,
// so there is no need to clean them up.
Py_XDECREF(kwnames);
Py_DECREF(function);
if (new_frame == NULL) {
goto error;
@ -4582,22 +4594,24 @@ handle_eval_breaker:
/* Callable is not a normal Python function */
PyObject *res;
if (cframe.use_tracing) {
res = trace_call_function(tstate, function, stack_pointer-oparg, nargs, kwnames);
res = trace_call_function(
tstate, function, stack_pointer-total_args,
positional_args, call_shape.kwnames);
}
else {
res = PyObject_Vectorcall(function, stack_pointer-oparg,
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
res = PyObject_Vectorcall(
function, stack_pointer-total_args,
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
call_shape.kwnames);
}
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(function);
Py_XDECREF(kwnames);
/* Clear the stack */
STACK_SHRINK(oparg);
for (int i = 0; i < oparg; i++) {
STACK_SHRINK(total_args);
for (int i = 0; i < total_args; i++) {
Py_DECREF(stack_pointer[i]);
}
STACK_SHRINK(postcall_shrink);
RESET_STACK_ADJUST_FOR_CALLS;
STACK_SHRINK(call_shape.postcall_shrink);
PUSH(res);
if (res == NULL) {
goto error;
@ -4606,65 +4620,87 @@ handle_eval_breaker:
DISPATCH();
}
TARGET(CALL_NO_KW_ADAPTIVE) {
TARGET(CALL_ADAPTIVE) {
SpecializedCacheEntry *cache = GET_CACHE();
oparg = cache->adaptive.original_oparg;
int named_args = cache->adaptive.original_oparg;
assert((named_args == 0 && call_shape.kwnames == NULL)
|| (named_args != 0 && named_args == PyTuple_GET_SIZE(call_shape.kwnames)));
if (cache->adaptive.counter == 0) {
next_instr--;
int nargs = oparg+extra_args;
if (_Py_Specialize_CallNoKw(
PEEK(nargs + 1), next_instr, nargs, cache, BUILTINS()) < 0) {
int nargs = call_shape.total_args;
int err = _Py_Specialize_CallNoKw(
call_shape.callable, next_instr, nargs,
call_shape.kwnames, cache, BUILTINS());
if (err < 0) {
goto error;
}
DISPATCH();
}
else {
STAT_INC(CALL_NO_KW, deferred);
STAT_INC(CALL, deferred);
cache->adaptive.counter--;
kwnames = NULL;
oparg += extra_args;
nargs = oparg;
oparg = named_args;
goto call_function;
}
}
TARGET(CALL_NO_KW_PY_SIMPLE) {
TARGET(CALL_PY_EXACT_ARGS) {
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
int argcount = cache0->original_oparg + extra_args;
DEOPT_IF(argcount != cache0->index, CALL_NO_KW);
int argcount = call_shape.total_args;
DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL);
_PyCallCache *cache1 = &caches[-1].call;
PyObject *callable = PEEK(argcount+1);
DEOPT_IF(!PyFunction_Check(callable), CALL_NO_KW);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != cache1->func_version, CALL_NO_KW);
/* PEP 523 */
DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
PyFunctionObject *func = (PyFunctionObject *)call_shape.callable;
DEOPT_IF(func->func_version != cache1->func_version, CALL);
PyCodeObject *code = (PyCodeObject *)func->func_code;
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
DEOPT_IF(code->co_argcount != argcount, CALL);
InterpreterFrame *new_frame = _PyFrame_Push(tstate, func);
if (new_frame == NULL) {
RESET_STACK_ADJUST_FOR_CALLS;
goto error;
}
_PyFrame_InitializeSpecials(new_frame, func,
NULL, code->co_nlocalsplus);
STACK_SHRINK(argcount);
for (int i = 0; i < argcount; i++) {
new_frame->localsplus[i] = stack_pointer[i];
}
int deflen = cache1->defaults_len;
for (int i = 0; i < deflen; i++) {
PyObject *def = PyTuple_GET_ITEM(func->func_defaults, cache1->defaults_start+i);
Py_INCREF(def);
new_frame->localsplus[argcount+i] = def;
}
for (int i = argcount+deflen; i < code->co_nlocalsplus; i++) {
for (int i = argcount; i < code->co_nlocalsplus; i++) {
new_frame->localsplus[i] = NULL;
}
STACK_SHRINK(postcall_shrink);
RESET_STACK_ADJUST_FOR_CALLS;
STACK_SHRINK(call_shape.postcall_shrink);
Py_DECREF(func);
_PyFrame_SetStackPointer(frame, stack_pointer);
new_frame->previous = frame;
frame = cframe.current_frame = new_frame;
goto start_frame;
}
TARGET(CALL_PY_WITH_DEFAULTS) {
SpecializedCacheEntry *caches = GET_CACHE();
int argcount = call_shape.total_args;
DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL);
_PyCallCache *cache1 = &caches[-1].call;
PyFunctionObject *func = (PyFunctionObject *)call_shape.callable;
DEOPT_IF(func->func_version != cache1->func_version, CALL);
PyCodeObject *code = (PyCodeObject *)func->func_code;
DEOPT_IF(argcount > code->co_argcount, CALL);
int minargs = cache1->min_args;
DEOPT_IF(argcount < minargs, CALL);
InterpreterFrame *new_frame = _PyFrame_Push(tstate, func);
if (new_frame == NULL) {
goto error;
}
STACK_SHRINK(argcount);
for (int i = 0; i < argcount; i++) {
new_frame->localsplus[i] = stack_pointer[i];
}
int def_offset = cache1->defaults_len - code->co_argcount;
for (int i = argcount; i < code->co_argcount; i++) {
PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i + def_offset);
Py_INCREF(def);
new_frame->localsplus[i] = def;
}
for (int i = code->co_argcount; i < code->co_nlocalsplus; i++) {
new_frame->localsplus[i] = NULL;
}
STACK_SHRINK(call_shape.postcall_shrink);
Py_DECREF(func);
_PyFrame_SetStackPointer(frame, stack_pointer);
new_frame->previous = frame;
@ -4674,35 +4710,75 @@ handle_eval_breaker:
TARGET(CALL_NO_KW_TYPE_1) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
assert(GET_CACHE()->adaptive.original_oparg == 1);
DEOPT_IF(call_shape.total_args != 1, CALL);
assert(call_shape.kwnames == NULL);
PyObject *obj = TOP();
PyObject *callable = SECOND();
DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL_NO_KW);
DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL);
PyObject *res = Py_NewRef(Py_TYPE(obj));
STACK_SHRINK(1);
Py_DECREF(callable);
Py_DECREF(obj);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
NOTRACE_DISPATCH();
}
TARGET(CALL_NO_KW_BUILTIN_CLASS_1) {
TARGET(CALL_NO_KW_STR_1) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
assert(cache0->original_oparg == 1);
PyObject *callable = SECOND();
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
DEOPT_IF(call_shape.total_args != 1, CALL);
DEOPT_IF(tp != &PyUnicode_Type, CALL);
STAT_INC(CALL, hit);
assert(call_shape.kwnames == NULL);
PyObject *arg = TOP();
DEOPT_IF(!PyType_Check(callable), CALL_NO_KW);
PyTypeObject *tp = (PyTypeObject *)callable;
DEOPT_IF(tp->tp_version_tag != cache0->version, CALL_NO_KW);
STACK_SHRINK(1);
PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, 1, NULL);
SET_TOP(res);
Py_DECREF(tp);
PyObject *res = PyObject_Str(arg);
Py_DECREF(arg);
Py_DECREF(&PyUnicode_Type);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
if (res == NULL) {
goto error;
}
DISPATCH();
}
TARGET(CALL_NO_KW_TUPLE_1) {
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
DEOPT_IF(call_shape.total_args != 1, CALL);
DEOPT_IF(tp != &PyTuple_Type, CALL);
STAT_INC(CALL, hit);
assert(call_shape.kwnames == NULL);
PyObject *arg = TOP();
PyObject *res = PySequence_Tuple(arg);
Py_DECREF(arg);
Py_DECREF(&PyTuple_Type);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
if (res == NULL) {
goto error;
}
DISPATCH();
}
TARGET(CALL_BUILTIN_CLASS) {
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
DEOPT_IF(tp->tp_vectorcall == NULL, CALL);
STAT_INC(CALL, hit);
int kwnames_len = GET_CACHE()->adaptive.original_oparg;
int nargs = call_shape.total_args - kwnames_len;
STACK_SHRINK(call_shape.total_args);
PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, nargs, call_shape.kwnames);
/* Free the arguments. */
for (int i = 0; i < call_shape.total_args; i++) {
Py_DECREF(stack_pointer[i]);
}
Py_DECREF(tp);
STACK_SHRINK(call_shape.postcall_shrink-1);
SET_TOP(res);
if (res == NULL) {
goto error;
}
@ -4711,13 +4787,13 @@ handle_eval_breaker:
TARGET(CALL_NO_KW_BUILTIN_O) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
/* Builtin METH_O functions */
PyObject *callable = SECOND();
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_NO_KW);
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
assert(call_shape.kwnames == NULL);
DEOPT_IF(call_shape.total_args != 1, CALL);
PyObject *callable = call_shape.callable;
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL);
STAT_INC(CALL, hit);
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
// This is slower but CPython promises to check all non-vectorcall
@ -4725,14 +4801,14 @@ handle_eval_breaker:
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
goto error;
}
PyObject *arg = POP();
PyObject *arg = TOP();
PyObject *res = cfunc(PyCFunction_GET_SELF(callable), arg);
_Py_LeaveRecursiveCall(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Clear the stack of the function object. */
Py_DECREF(arg);
Py_DECREF(callable);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
if (res == NULL) {
goto error;
@ -4742,32 +4818,31 @@ handle_eval_breaker:
TARGET(CALL_NO_KW_BUILTIN_FAST) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
/* Builtin METH_FASTCALL functions, without keywords */
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
int nargs = cache0->original_oparg;
PyObject **pfunc = &PEEK(nargs + 1);
PyObject *callable = *pfunc;
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_NO_KW);
assert(call_shape.kwnames == NULL);
PyObject *callable = call_shape.callable;
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL,
CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
CALL);
STAT_INC(CALL, hit);
int nargs = call_shape.total_args;
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
STACK_SHRINK(nargs);
/* res = func(self, args, nargs) */
PyObject *res = ((_PyCFunctionFast)(void(*)(void))cfunc)(
PyCFunction_GET_SELF(callable),
&PEEK(nargs),
stack_pointer,
nargs);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Clear the stack of the function object. */
while (stack_pointer > pfunc) {
PyObject *x = POP();
Py_DECREF(x);
/* Free the arguments. */
for (int i = 0; i < nargs; i++) {
Py_DECREF(stack_pointer[i]);
}
STACK_SHRINK(call_shape.postcall_shrink);
PUSH(res);
Py_DECREF(callable);
if (res == NULL) {
/* Not deopting because this doesn't mean our optimization was
wrong. `res` can be NULL for valid reasons. Eg. getattr(x,
@ -4779,29 +4854,72 @@ handle_eval_breaker:
DISPATCH();
}
TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) {
assert(cframe.use_tracing == 0);
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
PyObject *callable = call_shape.callable;
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
DEOPT_IF(PyCFunction_GET_FLAGS(callable) !=
(METH_FASTCALL | METH_KEYWORDS), CALL);
STAT_INC(CALL, hit);
int kwnames_len = GET_CACHE()->adaptive.original_oparg;
assert(
(call_shape.kwnames == NULL && kwnames_len == 0) ||
(call_shape.kwnames != NULL &&
PyTuple_GET_SIZE(call_shape.kwnames) == kwnames_len)
);
int nargs = call_shape.total_args - kwnames_len;
STACK_SHRINK(call_shape.total_args);
/* res = func(self, args, nargs, kwnames) */
_PyCFunctionFastWithKeywords cfunc =
(_PyCFunctionFastWithKeywords)(void(*)(void))
PyCFunction_GET_FUNCTION(callable);
PyObject *res = cfunc(
PyCFunction_GET_SELF(callable),
stack_pointer,
nargs,
call_shape.kwnames
);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Free the arguments. */
for (int i = 0; i < call_shape.total_args; i++) {
Py_DECREF(stack_pointer[i]);
}
STACK_SHRINK(call_shape.postcall_shrink);
PUSH(res);
Py_DECREF(callable);
if (res == NULL) {
goto error;
}
DISPATCH();
}
TARGET(CALL_NO_KW_LEN) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
assert(call_shape.kwnames == NULL);
/* len(o) */
SpecializedCacheEntry *caches = GET_CACHE();
assert(caches[0].adaptive.original_oparg == 1);
DEOPT_IF(call_shape.total_args != 1, CALL);
assert(caches[0].adaptive.original_oparg == 0);
_PyObjectCache *cache1 = &caches[-1].obj;
PyObject *callable = SECOND();
DEOPT_IF(callable != cache1->obj, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
PyObject *callable = call_shape.callable;
DEOPT_IF(callable != cache1->obj, CALL);
STAT_INC(CALL, hit);
Py_ssize_t len_i = PyObject_Length(TOP());
PyObject *arg = TOP();
Py_ssize_t len_i = PyObject_Length(arg);
if (len_i < 0) {
goto error;
}
PyObject *res = PyLong_FromSsize_t(len_i);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Clear the stack of the function object. */
Py_DECREF(POP());
Py_DECREF(callable);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
Py_DECREF(callable);
Py_DECREF(arg);
if (res == NULL) {
goto error;
}
@ -4810,28 +4928,30 @@ handle_eval_breaker:
TARGET(CALL_NO_KW_ISINSTANCE) {
assert(cframe.use_tracing == 0);
assert(STACK_ADJUST_IS_RESET);
assert(call_shape.kwnames == NULL);
/* isinstance(o, o2) */
SpecializedCacheEntry *caches = GET_CACHE();
assert(caches[0].adaptive.original_oparg == 2);
assert(caches[0].adaptive.original_oparg == 0);
DEOPT_IF(call_shape.total_args != 2, CALL);
_PyObjectCache *cache1 = &caches[-1].obj;
PyObject *callable = THIRD();
DEOPT_IF(callable != cache1->obj, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
DEOPT_IF(call_shape.callable != cache1->obj, CALL);
STAT_INC(CALL, hit);
int retval = PyObject_IsInstance(SECOND(), TOP());
PyObject *cls = POP();
PyObject *inst = TOP();
int retval = PyObject_IsInstance(inst, cls);
if (retval < 0) {
goto error;
}
PyObject *res = PyBool_FromLong(retval);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Clear the stack of the function object. */
Py_DECREF(POP());
Py_DECREF(POP());
Py_DECREF(callable);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
Py_DECREF(inst);
Py_DECREF(cls);
Py_DECREF(call_shape.callable);
if (res == NULL) {
goto error;
}
@ -4840,57 +4960,78 @@ handle_eval_breaker:
TARGET(CALL_NO_KW_LIST_APPEND) {
assert(cframe.use_tracing == 0);
assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD);
assert(GET_CACHE()->adaptive.original_oparg == 1);
DEOPT_IF(extra_args == 0, CALL_NO_KW);
assert(call_shape.kwnames == NULL);
SpecializedCacheEntry *caches = GET_CACHE();
_PyObjectCache *cache1 = &caches[-1].obj;
DEOPT_IF(call_shape.total_args != 2, CALL);
DEOPT_IF(call_shape.callable != cache1->obj, CALL);
PyObject *list = SECOND();
DEOPT_IF(!PyList_CheckExact(list), CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
assert(extra_args == 1);
extra_args = 0;
assert(STACK_ADJUST_IS_RESET);
DEOPT_IF(!PyList_Check(list), CALL);
STAT_INC(CALL, hit);
PyObject *arg = TOP();
int err = PyList_Append(list, arg);
if (err) {
goto error;
}
PyObject *callable = THIRD();
Py_DECREF(arg);
Py_DECREF(list);
STACK_SHRINK(call_shape.postcall_shrink+1);
Py_INCREF(Py_None);
STACK_SHRINK(2);
SET_TOP(Py_None);
Py_DECREF(callable);
Py_DECREF(call_shape.callable);
NOTRACE_DISPATCH();
}
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {
assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD);
assert(GET_CACHE()->adaptive.original_oparg == 1);
DEOPT_IF(extra_args == 0, CALL_NO_KW);
assert(extra_args == 1);
PyObject *callable = THIRD();
DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL_NO_KW);
DEOPT_IF(((PyMethodDescrObject *)callable)->d_method->ml_flags != METH_O, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
assert(extra_args == 1);
extra_args = 0;
assert(STACK_ADJUST_IS_RESET);
PyCFunction cfunc = ((PyMethodDescrObject *)callable)->d_method->ml_meth;
assert(call_shape.kwnames == NULL);
DEOPT_IF(call_shape.total_args != 2, CALL);
DEOPT_IF(!Py_IS_TYPE(call_shape.callable, &PyMethodDescr_Type), CALL);
PyMethodDef *meth = ((PyMethodDescrObject *)call_shape.callable)->d_method;
DEOPT_IF(meth->ml_flags != METH_O, CALL);
STAT_INC(CALL, hit);
PyCFunction cfunc = meth->ml_meth;
// This is slower but CPython promises to check all non-vectorcall
// function calls.
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
goto error;
}
PyObject *arg = POP();
PyObject *self = POP();
PyObject *arg = TOP();
PyObject *self = SECOND();
PyObject *res = cfunc(self, arg);
_Py_LeaveRecursiveCall(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(self);
Py_DECREF(arg);
STACK_SHRINK(call_shape.postcall_shrink+1);
SET_TOP(res);
Py_DECREF(callable);
Py_DECREF(call_shape.callable);
if (res == NULL) {
goto error;
}
DISPATCH();
}
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) {
assert(call_shape.kwnames == NULL);
DEOPT_IF(call_shape.total_args != 1, CALL);
DEOPT_IF(!Py_IS_TYPE(call_shape.callable, &PyMethodDescr_Type), CALL);
PyMethodDef *meth = ((PyMethodDescrObject *)call_shape.callable)->d_method;
DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL);
STAT_INC(CALL, hit);
PyCFunction cfunc = meth->ml_meth;
// This is slower but CPython promises to check all non-vectorcall
// function calls.
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
goto error;
}
PyObject *self = TOP();
PyObject *res = cfunc(self, NULL);
_Py_LeaveRecursiveCall(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(self);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
Py_DECREF(call_shape.callable);
if (res == NULL) {
goto error;
}
@ -4898,32 +5039,26 @@ handle_eval_breaker:
}
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) {
assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD);
assert(call_shape.kwnames == NULL);
/* Builtin METH_FASTCALL methods, without keywords */
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
DEOPT_IF(extra_args == 0, CALL_NO_KW);
assert(extra_args == 1);
int nargs = cache0->original_oparg;
PyObject *callable = PEEK(nargs + 2);
DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL_NO_KW);
PyMethodDef *meth = ((PyMethodDescrObject *)callable)->d_method;
DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL_NO_KW);
STAT_INC(CALL_NO_KW, hit);
assert(extra_args == 1);
extra_args = 0;
assert(STACK_ADJUST_IS_RESET);
DEOPT_IF(!Py_IS_TYPE(call_shape.callable, &PyMethodDescr_Type), CALL);
PyMethodDef *meth = ((PyMethodDescrObject *)call_shape.callable)->d_method;
DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL);
STAT_INC(CALL, hit);
_PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth;
PyObject *self = PEEK(nargs+1);
PyObject *res = cfunc(self, &PEEK(nargs), nargs);
int nargs = call_shape.total_args-1;
STACK_SHRINK(nargs);
PyObject *self = TOP();
PyObject *res = cfunc(self, stack_pointer, nargs);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
/* Clear the stack of the arguments. */
STACK_SHRINK(nargs+1);
for (int i = 0; i <= nargs; i++) {
for (int i = 0; i < nargs; i++) {
Py_DECREF(stack_pointer[i]);
}
Py_DECREF(self);
STACK_SHRINK(call_shape.postcall_shrink);
SET_TOP(res);
Py_DECREF(callable);
Py_DECREF(call_shape.callable);
if (res == NULL) {
goto error;
}
@ -5283,7 +5418,7 @@ MISS_WITH_CACHE(LOAD_ATTR)
MISS_WITH_CACHE(STORE_ATTR)
MISS_WITH_CACHE(LOAD_GLOBAL)
MISS_WITH_CACHE(LOAD_METHOD)
MISS_WITH_CACHE(CALL_NO_KW)
MISS_WITH_CACHE(CALL)
MISS_WITH_CACHE(BINARY_OP)
MISS_WITH_CACHE(COMPARE_OP)
MISS_WITH_CACHE(BINARY_SUBSCR)
@ -7321,7 +7456,7 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
}
static void
format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevopcode, int prevopcode)
format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevprevopcode, int prevopcode)
{
if (type->tp_as_async == NULL || type->tp_as_async->am_await == NULL) {
if (prevopcode == BEFORE_ASYNC_WITH) {
@ -7330,7 +7465,7 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop
"that does not implement __await__: %.100s",
type->tp_name);
}
else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_NO_KW && prevprevopcode == LOAD_CONST)) {
else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL && prevprevprevopcode == LOAD_CONST)) {
_PyErr_Format(tstate, PyExc_TypeError,
"'async with' received an object from __aexit__ "
"that does not implement __await__: %.100s",

View File

@ -1021,11 +1021,14 @@ stack_effect(int opcode, int oparg, int jump)
/* Functions and calls */
case PRECALL_METHOD:
return -1;
case CALL_NO_KW:
return -oparg;
case CALL_KW:
return -oparg-1;
case PRECALL_FUNCTION:
return -oparg;
case KW_NAMES:
return 0;
case CALL:
return 0;
case CALL_FUNCTION_EX:
return -1 - ((oparg & 0x01) != 0);
case MAKE_FUNCTION:
@ -1823,7 +1826,8 @@ compiler_call_exit_with_nones(struct compiler *c) {
ADDOP_LOAD_CONST(c, Py_None);
ADDOP_LOAD_CONST(c, Py_None);
ADDOP_LOAD_CONST(c, Py_None);
ADDOP_I(c, CALL_NO_KW, 3);
ADDOP_I(c, PRECALL_FUNCTION, 3);
ADDOP_I(c, CALL, 0);
return 1;
}
@ -2208,7 +2212,8 @@ compiler_apply_decorators(struct compiler *c, asdl_expr_seq* decos)
int old_end_col_offset = c->u->u_end_col_offset;
for (Py_ssize_t i = asdl_seq_LEN(decos) - 1; i > -1; i--) {
SET_LOC(c, (expr_ty)asdl_seq_GET(decos, i));
ADDOP_I(c, CALL_NO_KW, 1);
ADDOP_I(c, PRECALL_FUNCTION, 1);
ADDOP_I(c, CALL, 0);
}
c->u->u_lineno = old_lineno;
c->u->u_end_lineno = old_end_lineno;
@ -3903,7 +3908,8 @@ compiler_assert(struct compiler *c, stmt_ty s)
ADDOP(c, LOAD_ASSERTION_ERROR);
if (s->v.Assert.msg) {
VISIT(c, expr, s->v.Assert.msg);
ADDOP_I(c, CALL_NO_KW, 1);
ADDOP_I(c, PRECALL_FUNCTION, 1);
ADDOP_I(c, CALL, 0);
}
ADDOP_I(c, RAISE_VARARGS, 1);
compiler_use_next_block(c, end);
@ -4723,15 +4729,16 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
VISIT_SEQ(c, expr, e->v.Call.args);
if (kwdsl) {
VISIT_SEQ(c, keyword, kwds);
ADDOP_I(c, PRECALL_METHOD, argsl + kwdsl);
if (!compiler_call_simple_kw_helper(c, kwds, kwdsl)) {
return 0;
};
ADDOP_I(c, PRECALL_METHOD, argsl + kwdsl+1);
ADDOP_I(c, CALL_KW, argsl + kwdsl);
ADDOP_I(c, CALL, kwdsl);
}
else {
ADDOP_I(c, PRECALL_METHOD, argsl);
ADDOP_I(c, CALL_NO_KW, argsl);
ADDOP_I(c, CALL, 0);
}
c->u->u_lineno = old_lineno;
return 1;
@ -4799,7 +4806,7 @@ compiler_joined_str(struct compiler *c, expr_ty e)
ADDOP_I(c, LIST_APPEND, 1);
}
ADDOP_I(c, PRECALL_METHOD, 1);
ADDOP_I(c, CALL_NO_KW, 1);
ADDOP_I(c, CALL, 0);
}
else {
VISIT_SEQ(c, expr, e->v.JoinedStr.values);
@ -4900,21 +4907,15 @@ compiler_subkwargs(struct compiler *c, asdl_keyword_seq *keywords, Py_ssize_t be
}
/* Used by compiler_call_helper and maybe_optimize_method_call to emit
LOAD_CONST kw1
LOAD_CONST kw2
...
LOAD_CONST <tuple of kwnames>
before a CALL_(FUNCTION|METHOD)_KW.
Returns 1 on success, 0 on error.
*/
* KW_NAMES before CALL.
* Returns 1 on success, 0 on error.
*/
static int
compiler_call_simple_kw_helper(struct compiler *c,
asdl_keyword_seq *keywords,
Py_ssize_t nkwelts)
{
PyObject *names;
VISIT_SEQ(c, keyword, keywords);
names = PyTuple_New(nkwelts);
if (names == NULL) {
return 0;
@ -4924,7 +4925,12 @@ compiler_call_simple_kw_helper(struct compiler *c,
Py_INCREF(kw->arg);
PyTuple_SET_ITEM(names, i, kw->arg);
}
ADDOP_LOAD_CONST_NEW(c, names);
Py_ssize_t arg = compiler_add_const(c, names);
if (arg < 0) {
return 0;
}
Py_DECREF(names);
ADDOP_I(c, KW_NAMES, arg);
return 1;
}
@ -4968,14 +4974,17 @@ compiler_call_helper(struct compiler *c,
VISIT(c, expr, elt);
}
if (nkwelts) {
VISIT_SEQ(c, keyword, keywords);
ADDOP_I(c, PRECALL_FUNCTION, n + nelts + nkwelts);
if (!compiler_call_simple_kw_helper(c, keywords, nkwelts)) {
return 0;
};
ADDOP_I(c, CALL_KW, n + nelts + nkwelts);
ADDOP_I(c, CALL, nkwelts);
return 1;
}
else {
ADDOP_I(c, CALL_NO_KW, n + nelts);
ADDOP_I(c, PRECALL_FUNCTION, n + nelts);
ADDOP_I(c, CALL, 0);
return 1;
}
@ -5372,7 +5381,8 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
ADDOP(c, GET_ITER);
}
ADDOP_I(c, CALL_NO_KW, 1);
ADDOP_I(c, PRECALL_FUNCTION, 1);
ADDOP_I(c, CALL, 0);
if (is_async_generator && type != COMP_GENEXP) {
ADDOP(c, GET_AWAITABLE);
@ -8786,6 +8796,8 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
}
i += swaptimize(bb, i);
break;
case KW_NAMES:
break;
default:
/* All HAS_CONST opcodes should be handled with LOAD_CONST */
assert (!HAS_CONST(inst->i_opcode));
@ -9097,7 +9109,8 @@ trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts)
int max_const_index = 0;
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
if (b->b_instr[i].i_opcode == LOAD_CONST &&
if ((b->b_instr[i].i_opcode == LOAD_CONST ||
b->b_instr[i].i_opcode == KW_NAMES) &&
b->b_instr[i].i_oparg > max_const_index) {
max_const_index = b->b_instr[i].i_oparg;
}

View File

@ -83,7 +83,7 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame)
}
void
_PyFrame_Clear(InterpreterFrame * frame)
_PyFrame_Clear(InterpreterFrame *frame)
{
/* It is the responsibility of the owning generator/coroutine
* to have cleared the enclosing generator, if any. */
@ -107,3 +107,16 @@ _PyFrame_Clear(InterpreterFrame * frame)
Py_DECREF(frame->f_func);
Py_DECREF(frame->f_code);
}
InterpreterFrame *
_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
{
PyCodeObject *code = (PyCodeObject *)func->func_code;
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
if (new_frame == NULL) {
return NULL;
}
_PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus);
return new_frame;
}

View File

@ -28,59 +28,59 @@ static void *opcode_targets[256] = {
&&TARGET_STORE_SUBSCR_ADAPTIVE,
&&TARGET_STORE_SUBSCR_LIST_INT,
&&TARGET_STORE_SUBSCR_DICT,
&&TARGET_CALL_NO_KW_ADAPTIVE,
&&TARGET_CALL_ADAPTIVE,
&&TARGET_GET_LEN,
&&TARGET_MATCH_MAPPING,
&&TARGET_MATCH_SEQUENCE,
&&TARGET_MATCH_KEYS,
&&TARGET_CALL_NO_KW_BUILTIN_O,
&&TARGET_CALL_BUILTIN_CLASS,
&&TARGET_PUSH_EXC_INFO,
&&TARGET_CALL_NO_KW_BUILTIN_O,
&&TARGET_CALL_NO_KW_BUILTIN_FAST,
&&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
&&TARGET_CALL_NO_KW_LEN,
&&TARGET_CALL_NO_KW_ISINSTANCE,
&&TARGET_CALL_NO_KW_PY_SIMPLE,
&&TARGET_CALL_PY_EXACT_ARGS,
&&TARGET_CALL_PY_WITH_DEFAULTS,
&&TARGET_CALL_NO_KW_LIST_APPEND,
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
&&TARGET_CALL_NO_KW_STR_1,
&&TARGET_CALL_NO_KW_TUPLE_1,
&&TARGET_CALL_NO_KW_TYPE_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_GET_AITER,
&&TARGET_GET_ANEXT,
&&TARGET_BEFORE_ASYNC_WITH,
&&TARGET_BEFORE_WITH,
&&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_MODULE,
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
&&TARGET_LOAD_GLOBAL_MODULE,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_STORE_SUBSCR,
&&TARGET_DELETE_SUBSCR,
&&TARGET_LOAD_METHOD_ADAPTIVE,
&&TARGET_LOAD_METHOD_CACHED,
&&TARGET_LOAD_METHOD_CLASS,
&&TARGET_LOAD_METHOD_MODULE,
&&TARGET_LOAD_METHOD_NO_DICT,
&&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_LOAD_METHOD_CACHED,
&&TARGET_GET_AWAITABLE,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_RETURN_GENERATOR,
&&TARGET_LOAD_METHOD_CLASS,
&&TARGET_LOAD_METHOD_MODULE,
&&TARGET_LOAD_METHOD_NO_DICT,
&&TARGET_STORE_ATTR_ADAPTIVE,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
&&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_RETURN_VALUE,
&&TARGET_IMPORT_STAR,
@ -130,7 +130,7 @@ static void *opcode_targets[256] = {
&&TARGET_POP_JUMP_IF_NOT_NONE,
&&TARGET_POP_JUMP_IF_NONE,
&&TARGET_RAISE_VARARGS,
&&TARGET_STORE_FAST__STORE_FAST,
&&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_MAKE_FUNCTION,
&&TARGET_BUILD_SLICE,
&&TARGET_JUMP_NO_INTERRUPT,
@ -139,20 +139,20 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_LOAD_FAST__LOAD_FAST,
&&TARGET_STORE_FAST__LOAD_FAST,
&&TARGET_CALL_FUNCTION_EX,
&&_unknown_opcode,
&&TARGET_LOAD_FAST__LOAD_CONST,
&&TARGET_EXTENDED_ARG,
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
&&TARGET_MAP_ADD,
&&TARGET_LOAD_CLASSDEREF,
&&TARGET_COPY_FREE_VARS,
&&_unknown_opcode,
&&TARGET_LOAD_CONST__LOAD_FAST,
&&TARGET_RESUME,
&&TARGET_MATCH_CLASS,
&&_unknown_opcode,
&&TARGET_STORE_FAST__STORE_FAST,
&&_unknown_opcode,
&&TARGET_FORMAT_VALUE,
&&TARGET_BUILD_CONST_KEY_MAP,
@ -166,12 +166,12 @@ static void *opcode_targets[256] = {
&&TARGET_DICT_MERGE,
&&TARGET_DICT_UPDATE,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_PRECALL_FUNCTION,
&&TARGET_PRECALL_METHOD,
&&TARGET_CALL_NO_KW,
&&TARGET_CALL_KW,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_CALL,
&&TARGET_KW_NAMES,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,

View File

@ -124,7 +124,7 @@ _Py_GetSpecializationStats(void) {
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr");
err += add_stat_dict(stats, STORE_ATTR, "store_attr");
err += add_stat_dict(stats, CALL_NO_KW, "call_no_kw");
err += add_stat_dict(stats, CALL, "call");
err += add_stat_dict(stats, BINARY_OP, "binary_op");
err += add_stat_dict(stats, COMPARE_OP, "compare_op");
if (err < 0) {
@ -251,7 +251,7 @@ static uint8_t adaptive_opcodes[256] = {
[LOAD_METHOD] = LOAD_METHOD_ADAPTIVE,
[BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
[STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE,
[CALL_NO_KW] = CALL_NO_KW_ADAPTIVE,
[CALL] = CALL_ADAPTIVE,
[STORE_ATTR] = STORE_ATTR_ADAPTIVE,
[BINARY_OP] = BINARY_OP_ADAPTIVE,
[COMPARE_OP] = COMPARE_OP_ADAPTIVE,
@ -264,7 +264,7 @@ static uint8_t cache_requirements[256] = {
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
[BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */
[STORE_SUBSCR] = 0,
[CALL_NO_KW] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[CALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
[BINARY_OP] = 1, // _PyAdaptiveEntry
[COMPARE_OP] = 1, /* _PyAdaptiveEntry */
@ -512,8 +512,13 @@ initial_counter_value(void) {
#define SPEC_FAIL_CLASS 18
#define SPEC_FAIL_PYTHON_CLASS 19
#define SPEC_FAIL_C_METHOD_CALL 20
#define SPEC_FAIL_METHDESCR_NON_METHOD 21
#define SPEC_FAIL_METHOD_CALL_CLASS 22
#define SPEC_FAIL_BOUND_METHOD 21
#define SPEC_FAIL_CALL_STR 22
#define SPEC_FAIL_CLASS_NO_VECTORCALL 23
#define SPEC_FAIL_CLASS_MUTABLE 24
#define SPEC_FAIL_KWNAMES 25
#define SPEC_FAIL_METHOD_WRAPPER 26
#define SPEC_FAIL_OPERATOR_WRAPPER 27
/* COMPARE_OP */
#define SPEC_FAIL_STRING_COMPARE 13
@ -1337,122 +1342,40 @@ success:
static int
specialize_class_call(
PyObject *callable, _Py_CODEUNIT *instr,
int nargs, SpecializedCacheEntry *cache)
int nargs, PyObject *kwnames, SpecializedCacheEntry *cache)
{
PyTypeObject *tp = _PyType_CAST(callable);
if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_METHOD_CALL_CLASS);
return -1;
}
if (tp->tp_new == PyBaseObject_Type.tp_new) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_PYTHON_CLASS);
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_PYTHON_CLASS);
return -1;
}
if (nargs == 1) {
if (tp == &PyType_Type) {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_TYPE_1, _Py_OPARG(*instr));
return 0;
}
if ((tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) && tp->tp_vectorcall != NULL) {
cache->adaptive.version = tp->tp_version_tag;
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_CLASS_1, _Py_OPARG(*instr));
return 0;
}
}
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_CLASS);
return -1;
}
static PyMethodDescrObject *_list_append = NULL;
_Py_IDENTIFIER(append);
static int
specialize_method_descriptor(
PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
int nargs, SpecializedCacheEntry *cache)
{
int oparg = cache->adaptive.original_oparg;
if (nargs - oparg != 1) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_METHDESCR_NON_METHOD);
return -1;
}
if (_list_append == NULL) {
_list_append = (PyMethodDescrObject *)_PyType_LookupId(&PyList_Type, &PyId_append);
}
if (oparg == 1 && descr == _list_append) {
assert(_Py_OPCODE(instr[-1]) == PRECALL_METHOD);
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_LIST_APPEND, _Py_OPARG(*instr));
return 0;
}
switch (descr->d_method->ml_flags &
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
METH_KEYWORDS | METH_METHOD)) {
case METH_O: {
if (oparg != 1) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
return 1;
if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
if (nargs == 1 && kwnames == NULL) {
if (tp == &PyUnicode_Type) {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_STR_1, _Py_OPARG(*instr));
return 0;
}
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_O,
_Py_OPARG(*instr));
return 0;
}
case METH_FASTCALL: {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
_Py_OPARG(*instr));
else if (tp == &PyType_Type) {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_TYPE_1, _Py_OPARG(*instr));
return 0;
}
else if (tp == &PyTuple_Type) {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_TUPLE_1, _Py_OPARG(*instr));
return 0;
}
}
if (tp->tp_vectorcall != NULL) {
*instr = _Py_MAKECODEUNIT(CALL_BUILTIN_CLASS, _Py_OPARG(*instr));
return 0;
}
SPECIALIZATION_FAIL(CALL, tp == &PyUnicode_Type ?
SPEC_FAIL_CALL_STR : SPEC_FAIL_CLASS_NO_VECTORCALL);
return -1;
}
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OTHER);
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CLASS_MUTABLE);
return -1;
}
static int
specialize_py_call(
PyFunctionObject *func, _Py_CODEUNIT *instr,
int nargs, SpecializedCacheEntry *cache)
{
_PyCallCache *cache1 = &cache[-1].call;
PyCodeObject *code = (PyCodeObject *)func->func_code;
int kind = function_kind(code);
if (kind != SIMPLE_FUNCTION) {
SPECIALIZATION_FAIL(CALL_NO_KW, kind);
return -1;
}
int argcount = code->co_argcount;
if (argcount > 0xffff) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults);
assert(defcount <= argcount);
int min_args = argcount-defcount;
if (nargs > argcount || nargs < min_args) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return -1;
}
assert(nargs <= argcount && nargs >= min_args);
int defstart = nargs - min_args;
int deflen = argcount - nargs;
assert(defstart >= 0 && deflen >= 0);
assert(deflen == 0 || func->func_defaults != NULL);
if (defstart > 0xffff || deflen > 0xffff) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
int version = _PyFunction_GetVersionForCurrentState(func);
if (version == 0) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
}
cache[0].adaptive.index = nargs;
cache1->func_version = version;
cache1->defaults_start = defstart;
cache1->defaults_len = deflen;
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_PY_SIMPLE, _Py_OPARG(*instr));
return 0;
}
#ifdef Py_STATS
static int
builtin_call_fail_kind(int ml_flags)
@ -1477,15 +1400,118 @@ builtin_call_fail_kind(int ml_flags)
}
#endif
static PyMethodDescrObject *_list_append = NULL;
_Py_IDENTIFIER(append);
static int
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
SpecializedCacheEntry *cache, PyObject *builtins)
specialize_method_descriptor(
PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
int nargs, PyObject *kwnames, SpecializedCacheEntry *cache)
{
_PyObjectCache *cache1 = &cache[-1].obj;
if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_C_METHOD_CALL);
if (kwnames) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_KWNAMES);
return -1;
}
if (_list_append == NULL) {
_list_append = (PyMethodDescrObject *)_PyType_LookupId(&PyList_Type, &PyId_append);
}
assert(_list_append != NULL);
if (nargs == 2 && descr == _list_append) {
assert(_Py_OPCODE(instr[-1]) == PRECALL_METHOD);
cache[-1].obj.obj = (PyObject *)_list_append;
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_LIST_APPEND, _Py_OPARG(*instr));
return 0;
}
switch (descr->d_method->ml_flags &
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
METH_KEYWORDS | METH_METHOD)) {
case METH_NOARGS: {
if (nargs != 1) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return -1;
}
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
_Py_OPARG(*instr));
return 0;
}
case METH_O: {
if (nargs != 2) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_O,
_Py_OPARG(*instr));
return 0;
}
case METH_FASTCALL: {
*instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
_Py_OPARG(*instr));
return 0;
}
}
SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(descr->d_method->ml_flags));
return -1;
}
static int
specialize_py_call(
PyFunctionObject *func, _Py_CODEUNIT *instr,
int nargs, PyObject *kwnames, SpecializedCacheEntry *cache)
{
_PyCallCache *cache1 = &cache[-1].call;
PyCodeObject *code = (PyCodeObject *)func->func_code;
int kind = function_kind(code);
if (kwnames) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_KWNAMES);
return -1;
}
if (kind != SIMPLE_FUNCTION) {
SPECIALIZATION_FAIL(CALL, kind);
return -1;
}
int argcount = code->co_argcount;
if (argcount > 0xffff) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults);
assert(defcount <= argcount);
int min_args = argcount-defcount;
if (nargs > argcount || nargs < min_args) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return -1;
}
assert(nargs <= argcount && nargs >= min_args);
assert(min_args >= 0 && defcount >= 0);
assert(defcount == 0 || func->func_defaults != NULL);
if (min_args > 0xffff || defcount > 0xffff) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
int version = _PyFunction_GetVersionForCurrentState(func);
if (version == 0) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
}
cache[0].adaptive.index = nargs;
cache1->func_version = version;
cache1->min_args = min_args;
cache1->defaults_len = defcount;
if (argcount == nargs) {
*instr = _Py_MAKECODEUNIT(CALL_PY_EXACT_ARGS, _Py_OPARG(*instr));
}
else {
*instr = _Py_MAKECODEUNIT(CALL_PY_WITH_DEFAULTS, _Py_OPARG(*instr));
}
return 0;
}
static int
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
PyObject *kwnames, SpecializedCacheEntry *cache, PyObject *builtins)
{
_PyObjectCache *cache1 = &cache[-1].obj;
if (PyCFunction_GET_FUNCTION(callable) == NULL) {
return 1;
}
@ -1493,8 +1519,12 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
METH_KEYWORDS | METH_METHOD)) {
case METH_O: {
if (kwnames) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_KWNAMES);
return -1;
}
if (nargs != 1) {
SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return 1;
}
/* len(o) */
@ -1510,6 +1540,10 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
return 0;
}
case METH_FASTCALL: {
if (kwnames) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_KWNAMES);
return -1;
}
if (nargs == 2) {
/* isinstance(o1, o2) */
PyObject *builtin_isinstance = PyDict_GetItemString(
@ -1525,8 +1559,13 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
_Py_OPARG(*instr));
return 0;
}
case METH_FASTCALL | METH_KEYWORDS: {
*instr = _Py_MAKECODEUNIT(CALL_BUILTIN_FAST_WITH_KEYWORDS,
_Py_OPARG(*instr));
return 0;
}
default:
SPECIALIZATION_FAIL(CALL_NO_KW,
SPECIALIZATION_FAIL(CALL,
builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable)));
return 1;
}
@ -1549,6 +1588,15 @@ call_fail_kind(PyObject *callable)
else if (PyType_Check(callable)) {
return SPEC_FAIL_CLASS;
}
else if (Py_TYPE(callable) == &PyWrapperDescr_Type) {
return SPEC_FAIL_OPERATOR_WRAPPER;
}
else if (Py_TYPE(callable) == &_PyMethodWrapper_Type) {
return SPEC_FAIL_METHOD_WRAPPER;
}
else if (Py_TYPE(callable) == &PyMethod_Type) {
return SPEC_FAIL_BOUND_METHOD;
}
return SPEC_FAIL_OTHER;
}
#endif
@ -1559,35 +1607,35 @@ call_fail_kind(PyObject *callable)
int
_Py_Specialize_CallNoKw(
PyObject *callable, _Py_CODEUNIT *instr,
int nargs, SpecializedCacheEntry *cache,
PyObject *builtins)
int nargs, PyObject *kwnames,
SpecializedCacheEntry *cache, PyObject *builtins)
{
_PyAdaptiveEntry *cache0 = &cache->adaptive;
int fail;
if (PyCFunction_CheckExact(callable)) {
fail = specialize_c_call(callable, instr, nargs, cache, builtins);
fail = specialize_c_call(callable, instr, nargs, kwnames, cache, builtins);
}
else if (PyFunction_Check(callable)) {
fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, cache);
fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, kwnames, cache);
}
else if (PyType_Check(callable)) {
fail = specialize_class_call(callable, instr, nargs, cache);
fail = specialize_class_call(callable, instr, nargs, kwnames, cache);
}
else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
fail = specialize_method_descriptor(
(PyMethodDescrObject *)callable, instr, nargs, cache);
(PyMethodDescrObject *)callable, instr, nargs, kwnames, cache);
}
else {
SPECIALIZATION_FAIL(CALL_NO_KW, call_fail_kind(callable));
SPECIALIZATION_FAIL(CALL, call_fail_kind(callable));
fail = -1;
}
_PyAdaptiveEntry *cache0 = &cache->adaptive;
if (fail) {
STAT_INC(CALL_NO_KW, failure);
STAT_INC(CALL, failure);
assert(!PyErr_Occurred());
cache_backoff(cache0);
}
else {
STAT_INC(CALL_NO_KW, success);
STAT_INC(CALL, success);
assert(!PyErr_Occurred());
cache0->counter = initial_counter_value();
}