Skip to content

Commit 9f8f451

Browse files
authored
bpo-44525: Split calls into PRECALL and CALL (GH-30011)
* Add 3 new opcodes for calls: PRECALL_METHOD, CALL_NO_KW, CALL_KW. * Update specialization to handle new CALL opcodes. * Specialize call to method descriptors. * Remove old CALL opcodes: CALL_FUNCTION, CALL_METHOD, CALL_METHOD_KW, CALL_FUNCTION_KW.
1 parent d60457a commit 9f8f451

File tree

15 files changed

+395
-236
lines changed

15 files changed

+395
-236
lines changed

Doc/library/dis.rst

+15-32
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ the following command can be used to display the disassembly of
3636
>>> dis.dis(myfunc)
3737
2 0 LOAD_GLOBAL 0 (len)
3838
2 LOAD_FAST 0 (alist)
39-
4 CALL_FUNCTION 1
39+
4 CALL_NO_KW 1
4040
6 RETURN_VALUE
4141

4242
(The "2" is a line number).
@@ -104,7 +104,7 @@ Example::
104104
...
105105
LOAD_GLOBAL
106106
LOAD_FAST
107-
CALL_FUNCTION
107+
CALL_NO_KW
108108
RETURN_VALUE
109109

110110

@@ -616,7 +616,7 @@ iterations of the loop.
616616
.. opcode:: LOAD_BUILD_CLASS
617617

618618
Pushes :func:`builtins.__build_class__` onto the stack. It is later called
619-
by :opcode:`CALL_FUNCTION` to construct a class.
619+
by :opcode:`CALL_NO_KW` to construct a class.
620620

621621

622622
.. opcode:: BEFORE_WITH (delta)
@@ -1039,21 +1039,20 @@ All of the following opcodes use their arguments.
10391039
with ``__cause__`` set to ``TOS``)
10401040

10411041

1042-
.. opcode:: CALL_FUNCTION (argc)
1042+
.. opcode:: CALL_NO_KW (argc)
10431043

10441044
Calls a callable object with positional arguments.
10451045
*argc* indicates the number of positional arguments.
10461046
The top of the stack contains positional arguments, with the right-most
10471047
argument on top. Below the arguments is a callable object to call.
1048-
``CALL_FUNCTION`` pops all arguments and the callable object off the stack,
1048+
``CALL_NO_KW`` pops all arguments and the callable object off the stack,
10491049
calls the callable object with those arguments, and pushes the return value
10501050
returned by the callable object.
10511051

1052-
.. versionchanged:: 3.6
1053-
This opcode is used only for calls with positional arguments.
1052+
.. versionadded:: 3.11
10541053

10551054

1056-
.. opcode:: CALL_FUNCTION_KW (argc)
1055+
.. opcode:: CALL_KW (argc)
10571056

10581057
Calls a callable object with positional (if any) and keyword arguments.
10591058
*argc* indicates the total number of positional and keyword arguments.
@@ -1063,13 +1062,11 @@ All of the following opcodes use their arguments.
10631062
in the order corresponding to the tuple.
10641063
Below that are positional arguments, with the right-most parameter on
10651064
top. Below the arguments is a callable object to call.
1066-
``CALL_FUNCTION_KW`` pops all arguments and the callable object off the stack,
1065+
``CALL_KW`` pops all arguments and the callable object off the stack,
10671066
calls the callable object with those arguments, and pushes the return value
10681067
returned by the callable object.
10691068

1070-
.. versionchanged:: 3.6
1071-
Keyword arguments are packed in a tuple instead of a dictionary,
1072-
*argc* indicates the total number of arguments.
1069+
.. versionadded:: 3.11
10731070

10741071

10751072
.. opcode:: CALL_FUNCTION_EX (flags)
@@ -1099,30 +1096,16 @@ All of the following opcodes use their arguments.
10991096
.. versionadded:: 3.7
11001097

11011098

1102-
.. opcode:: CALL_METHOD (argc)
1103-
1104-
Calls a method. *argc* is the number of positional arguments.
1105-
Keyword arguments are not supported. This opcode is designed to be used
1106-
with :opcode:`LOAD_METHOD`. Positional arguments are on top of the stack.
1107-
Below them, the two items described in :opcode:`LOAD_METHOD` are on the
1108-
stack (either ``self`` and an unbound method object or ``NULL`` and an
1109-
arbitrary callable). All of them are popped and the return value is pushed.
1110-
1111-
.. versionadded:: 3.7
1112-
1113-
1114-
.. opcode:: CALL_METHOD_KW (argc)
1099+
.. opcode:: PRECALL_METHOD (argc)
11151100

1116-
Calls a method in a similar fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments.
1117-
*argc* is the number of positional and keyword arguments.
1118-
This opcode is designed to be used with :opcode:`LOAD_METHOD`. TOS is a
1119-
tuple of keyword argument names. Argument values are below that.
1120-
Below them, the two items described in :opcode:`LOAD_METHOD` are on the
1121-
stack (either ``self`` and an unbound method object or ``NULL`` and an
1122-
arbitrary callable). All of them are popped from the stack and the return value is pushed.
1101+
Prefixes either :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`.
1102+
This opcode is designed to be used with :opcode:`LOAD_METHOD`.
1103+
Sets internal variables, so that :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`
1104+
clean up after :opcode:`LOAD_METHOD` correctly.
11231105

11241106
.. versionadded:: 3.11
11251107

1108+
11261109
.. opcode:: MAKE_FUNCTION (flags)
11271110

11281111
Pushes a new function object on the stack. From bottom to top, the consumed

Include/internal/pycore_code.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNI
271271
int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
272272
int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
273273
int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
274-
int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
274+
int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
275275
void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
276276
SpecializedCacheEntry *cache);
277277
void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
@@ -288,7 +288,7 @@ void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
288288
#define COLLECT_SPECIALIZATION_STATS_DETAILED PRINT_SPECIALIZATION_STATS_DETAILED
289289
#endif
290290

291-
#define SPECIALIZATION_FAILURE_KINDS 20
291+
#define SPECIALIZATION_FAILURE_KINDS 30
292292

293293
#if COLLECT_SPECIALIZATION_STATS
294294

Include/opcode.h

+35-33
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ def _write_atomic(path, data, mode=0o666):
372372
# BINARY_OP)
373373
# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
374374
# Python 3.11a3 3466 (bpo-45292: PEP-654 except*)
375+
# Python 3.11a4 3467 (Change CALL_xxx opcodes)
375376

376377
#
377378
# MAGIC must change whenever the bytecode emitted by the compiler may no
@@ -381,7 +382,7 @@ def _write_atomic(path, data, mode=0o666):
381382
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
382383
# in PC/launcher.c must also be updated.
383384

384-
MAGIC_NUMBER = (3466).to_bytes(2, 'little') + b'\r\n'
385+
MAGIC_NUMBER = (3467).to_bytes(2, 'little') + b'\r\n'
385386
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
386387

387388
_PYCACHE = '__pycache__'

Lib/opcode.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def jabs_op(name, op):
155155

156156
def_op('GEN_START', 129) # Kind of generator/coroutine
157157
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
158-
def_op('CALL_FUNCTION', 131) # #args
158+
159159
def_op('MAKE_FUNCTION', 132) # Flags
160160
def_op('BUILD_SLICE', 133) # Number of items
161161

@@ -170,7 +170,6 @@ def jabs_op(name, op):
170170
def_op('DELETE_DEREF', 139)
171171
hasfree.append(139)
172172

173-
def_op('CALL_FUNCTION_KW', 141) # #args + #kwargs
174173
def_op('CALL_FUNCTION_EX', 142) # Flags
175174

176175
def_op('EXTENDED_ARG', 144)
@@ -189,12 +188,15 @@ def jabs_op(name, op):
189188
def_op('BUILD_STRING', 157)
190189

191190
name_op('LOAD_METHOD', 160)
192-
def_op('CALL_METHOD', 161)
191+
193192
def_op('LIST_EXTEND', 162)
194193
def_op('SET_UPDATE', 163)
195194
def_op('DICT_MERGE', 164)
196195
def_op('DICT_UPDATE', 165)
197-
def_op('CALL_METHOD_KW', 166)
196+
197+
def_op('PRECALL_METHOD', 168)
198+
def_op('CALL_NO_KW', 169)
199+
def_op('CALL_KW', 170)
198200

199201
del def_op, name_op, jrel_op, jabs_op
200202

@@ -249,12 +251,15 @@ def jabs_op(name, op):
249251
"STORE_SUBSCR_ADAPTIVE",
250252
"STORE_SUBSCR_LIST_INT",
251253
"STORE_SUBSCR_DICT",
252-
"CALL_FUNCTION_ADAPTIVE",
253-
"CALL_FUNCTION_BUILTIN_O",
254-
"CALL_FUNCTION_BUILTIN_FAST",
255-
"CALL_FUNCTION_LEN",
256-
"CALL_FUNCTION_ISINSTANCE",
257-
"CALL_FUNCTION_PY_SIMPLE",
254+
"CALL_NO_KW_ADAPTIVE",
255+
"CALL_NO_KW_BUILTIN_O",
256+
"CALL_NO_KW_BUILTIN_FAST",
257+
"CALL_NO_KW_LEN",
258+
"CALL_NO_KW_ISINSTANCE",
259+
"CALL_NO_KW_PY_SIMPLE",
260+
"CALL_NO_KW_LIST_APPEND",
261+
"CALL_NO_KW_METHOD_DESCRIPTOR_O",
262+
"CALL_NO_KW_METHOD_DESCRIPTOR_FAST",
258263
"JUMP_ABSOLUTE_QUICK",
259264
"LOAD_ATTR_ADAPTIVE",
260265
"LOAD_ATTR_INSTANCE_VALUE",

Lib/test/test_compile.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ def foo(x):
839839
self.assertNotIn('LOAD_METHOD', instructions)
840840
self.assertNotIn('CALL_METHOD', instructions)
841841
self.assertIn('LOAD_ATTR', instructions)
842-
self.assertIn('CALL_FUNCTION', instructions)
842+
self.assertIn('CALL_NO_KW', instructions)
843843

844844
def test_lineno_procedure_call(self):
845845
def call():
@@ -1095,7 +1095,7 @@ def test_multiline_expression(self):
10951095
)
10961096
"""
10971097
compiled_code, _ = self.check_positions_against_ast(snippet)
1098-
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION',
1098+
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
10991099
line=1, end_line=3, column=0, end_column=1)
11001100

11011101
def test_very_long_line_end_offset(self):
@@ -1105,7 +1105,7 @@ def test_very_long_line_end_offset(self):
11051105
snippet = f"g('{long_string}')"
11061106

11071107
compiled_code, _ = self.check_positions_against_ast(snippet)
1108-
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION',
1108+
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
11091109
line=1, end_line=1, column=None, end_column=None)
11101110

11111111
def test_complex_single_line_expression(self):

0 commit comments

Comments
 (0)