mirror of https://github.com/python/cpython
bpo-46329: Streamline calling sequence a bit. (GH-31465)
* Move handling of bound-methods to PRECALL. * Remove call_shape.postcall_shrink * Remove call_shape.callable * Remove call_shape.callable. Change CALL oparg to match PRECALL oparg. * Move KW_NAMES before PRECALL. * Update opcode docs in dis.rst
This commit is contained in:
parent
0a222db2bc
commit
59585d6b2e
|
@ -36,11 +36,12 @@ the following command can be used to display the disassembly of
|
|||
>>> dis.dis(myfunc)
|
||||
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
|
||||
2 2 PUSH_NULL
|
||||
4 LOAD_GLOBAL 0 (len)
|
||||
6 LOAD_FAST 0 (alist)
|
||||
8 PRECALL 1
|
||||
10 CALL 1
|
||||
12 RETURN_VALUE
|
||||
|
||||
(The "2" is a line number).
|
||||
|
||||
|
@ -106,9 +107,10 @@ Example::
|
|||
... print(instr.opname)
|
||||
...
|
||||
RESUME
|
||||
PUSH_NULL
|
||||
LOAD_GLOBAL
|
||||
LOAD_FAST
|
||||
PRECALL_FUNCTION
|
||||
PRECALL
|
||||
CALL
|
||||
RETURN_VALUE
|
||||
|
||||
|
@ -1063,18 +1065,28 @@ iterations of the loop.
|
|||
with ``__cause__`` set to ``TOS``)
|
||||
|
||||
|
||||
.. opcode:: CALL (named)
|
||||
.. opcode:: CALL (argc)
|
||||
|
||||
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):
|
||||
Calls a callable object with the number of arguments specified by ``argc``,
|
||||
including the named arguments specified by the preceding
|
||||
:opcode:`KW_NAMES`, if any.
|
||||
On the stack are (in ascending order), either:
|
||||
|
||||
* NULL
|
||||
* The callable
|
||||
* The positional arguments
|
||||
* The named arguments
|
||||
|
||||
or:
|
||||
|
||||
* The callable
|
||||
* ``self``
|
||||
* The remaining positional arguments
|
||||
* The named arguments
|
||||
|
||||
``argc`` is the total of the positional and named arguments, excluding
|
||||
``self`` when a ``NULL`` is not present.
|
||||
|
||||
``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.
|
||||
|
@ -1102,33 +1114,34 @@ 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:`PRECALL_METHOD` when calling the
|
||||
the first argument (``self``) by :opcode:`CALL` when calling the
|
||||
unbound method. Otherwise, ``NULL`` and the object return by the attribute
|
||||
lookup are pushed.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
|
||||
.. opcode:: PRECALL_METHOD (argc)
|
||||
.. opcode:: PRECALL (argc)
|
||||
|
||||
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`
|
||||
clean up after :opcode:`LOAD_METHOD` correctly.
|
||||
Prefixes :opcode:`CALL`. Logically this is a no op.
|
||||
It exists to enable effective specialization of calls.
|
||||
``argc`` is the number of arguments as described in :opcode:`CALL`.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: PRECALL_FUNCTION (args)
|
||||
.. opcode:: PUSH_NULL
|
||||
|
||||
Prefixes :opcode:`CALL` (possibly with an intervening ``KW_NAMES``).
|
||||
Sets internal variables, so that :opcode:`CALL` can execute correctly.
|
||||
Pushes a ``NULL`` to the stack.
|
||||
Used in the call sequence to match the ``NULL`` pushed by
|
||||
:opcode:`LOAD_METHOD` for non-method calls.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: KW_NAMES (i)
|
||||
|
||||
Prefixes :opcode:`PRECALL`.
|
||||
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.
|
||||
|
||||
|
|
|
@ -386,6 +386,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# ROT_TWO/ROT_THREE/ROT_FOUR/ROT_N with SWAP)
|
||||
# Python 3.11a5 3478 (New CALL opcodes)
|
||||
# Python 3.11a5 3479 (Add PUSH_NULL opcode)
|
||||
# Python 3.11a5 3480 (New CALL opcodes, second iteration)
|
||||
|
||||
# Python 3.12 will start with magic number 3500
|
||||
|
||||
|
@ -403,7 +404,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 = (3479).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3480).to_bytes(2, 'little') + b'\r\n'
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
_PYCACHE = '__pycache__'
|
||||
|
|
|
@ -109,7 +109,7 @@ dis_f = """\
|
|||
LOAD_GLOBAL 0 (print)
|
||||
LOAD_FAST 0 (a)
|
||||
PRECALL 1
|
||||
CALL 0
|
||||
CALL 1
|
||||
POP_TOP
|
||||
|
||||
%3d LOAD_CONST 1 (1)
|
||||
|
@ -125,7 +125,7 @@ dis_f_co_code = """\
|
|||
LOAD_GLOBAL 0
|
||||
LOAD_FAST 0
|
||||
PRECALL 1
|
||||
CALL 0
|
||||
CALL 1
|
||||
POP_TOP
|
||||
LOAD_CONST 1
|
||||
RETURN_VALUE
|
||||
|
@ -147,7 +147,7 @@ dis_bug708901 = """\
|
|||
%3d LOAD_CONST 2 (10)
|
||||
|
||||
%3d PRECALL 2
|
||||
CALL 0
|
||||
CALL 2
|
||||
GET_ITER
|
||||
>> FOR_ITER 2 (to 22)
|
||||
STORE_FAST 0 (res)
|
||||
|
@ -319,7 +319,7 @@ dis_annot_stmt_str = """\
|
|||
LOAD_NAME 3 (fun)
|
||||
LOAD_CONST 0 (1)
|
||||
PRECALL 1
|
||||
CALL 0
|
||||
CALL 1
|
||||
LOAD_NAME 2 (__annotations__)
|
||||
LOAD_CONST 2 ('y')
|
||||
STORE_SUBSCR
|
||||
|
@ -330,7 +330,7 @@ dis_annot_stmt_str = """\
|
|||
LOAD_NAME 3 (fun)
|
||||
LOAD_CONST 3 (0)
|
||||
PRECALL 1
|
||||
CALL 0
|
||||
CALL 1
|
||||
STORE_SUBSCR
|
||||
LOAD_NAME 1 (int)
|
||||
POP_TOP
|
||||
|
@ -1164,7 +1164,7 @@ expected_opinfo_outer = [
|
|||
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=36, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=7, argval=7, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=44, starts_line=8, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1191,7 +1191,7 @@ expected_opinfo_f = [
|
|||
Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=34, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=36, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=4, argval=4, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=44, starts_line=6, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1209,7 +1209,7 @@ expected_opinfo_inner = [
|
|||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=16, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=6, argval=6, 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='CALL', opcode=171, arg=6, argval=6, 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_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=26, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1221,7 +1221,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=4, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=6, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=8, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=10, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=10, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=12, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='FOR_ITER', opcode=93, arg=19, argval=54, argrepr='to 54', offset=14, starts_line=None, is_jump_target=True, positions=None),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1229,7 +1229,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', 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=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=30, starts_line=5, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=32, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1247,7 +1247,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=58, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, 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=11, is_jump_target=True, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=57, argval=114, argrepr='to 114', offset=68, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1255,7 +1255,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', 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=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=76, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=78, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=78, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', 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=13, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=84, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1277,7 +1277,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=116, starts_line=None, is_jump_target=False, 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=118, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=120, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, 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='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=126, starts_line=20, is_jump_target=True, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=128, starts_line=21, is_jump_target=False, positions=None),
|
||||
|
@ -1291,13 +1291,13 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=144, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=146, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, 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='CALL', opcode=171, arg=1, argval=1, 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='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=154, starts_line=25, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=156, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=190, argrepr='to 190', offset=166, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1320,7 +1320,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=202, starts_line=None, 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=204, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=240, argrepr='to 240', offset=214, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1332,7 +1332,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=226, 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=228, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, 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='CALL', opcode=171, arg=1, argval=1, 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),
|
||||
|
@ -1341,7 +1341,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=244, 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=246, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=252, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=254, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1350,7 +1350,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=262, 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=264, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=266, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=0, argval=0, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=270, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=272, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=274, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Move ``KW_NAMES`` before ``PRECALL`` instruction in call sequence. Change
|
||||
``operand`` of ``CALL`` to match ``PRECALL`` for easier specialization.
|
|
@ -3,11 +3,11 @@ unsigned char M_test_frozenmain[] = {
|
|||
227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,
|
||||
0,0,0,0,0,115,104,0,0,0,151,0,100,0,100,1,
|
||||
108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2,
|
||||
100,2,166,1,171,0,1,0,2,0,101,2,100,3,101,0,
|
||||
106,3,166,2,171,0,1,0,2,0,101,1,106,4,166,0,
|
||||
100,2,166,1,171,1,1,0,2,0,101,2,100,3,101,0,
|
||||
106,3,166,2,171,2,1,0,2,0,101,1,106,4,166,0,
|
||||
171,0,100,4,25,0,90,5,100,5,68,0,93,16,90,6,
|
||||
2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6,
|
||||
25,0,155,0,157,4,166,1,171,0,1,0,113,33,100,1,
|
||||
25,0,155,0,157,4,166,1,171,1,1,0,113,33,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,
|
||||
|
|
269
Python/ceval.c
269
Python/ceval.c
|
@ -1585,15 +1585,19 @@ pop_frame(PyThreadState *tstate, InterpreterFrame *frame)
|
|||
}
|
||||
|
||||
/* It is only between the PRECALL instruction and the following CALL,
|
||||
* that these values have any meaning.
|
||||
* that this has any meaning.
|
||||
*/
|
||||
typedef struct {
|
||||
PyObject *callable;
|
||||
PyObject *kwnames;
|
||||
int total_args;
|
||||
int postcall_shrink;
|
||||
} CallShape;
|
||||
|
||||
static inline bool
|
||||
is_method(PyObject **stack_pointer, int args) {
|
||||
return PEEK(args+2) != NULL;
|
||||
}
|
||||
|
||||
#define KWNAMES_LEN() \
|
||||
(call_shape.kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(call_shape.kwnames)))
|
||||
|
||||
PyObject* _Py_HOT_FUNCTION
|
||||
_PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int throwflag)
|
||||
|
@ -1616,11 +1620,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
|
|||
CFrame cframe;
|
||||
CallShape call_shape;
|
||||
call_shape.kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
|
||||
/* The following three values are always set by the PRECALL instructions.
|
||||
They are set here to keep the compiler happy. */
|
||||
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)
|
||||
|
@ -4513,23 +4512,31 @@ handle_eval_breaker:
|
|||
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;
|
||||
assert(call_shape.kwnames == NULL);
|
||||
PyObject *function = PEEK(nargs + 1);
|
||||
#ifdef Py_STATS
|
||||
extern int _PySpecialization_ClassifyCallable(PyObject *);
|
||||
SpecializationStats *stats =
|
||||
&_py_stats.opcode_stats[PRECALL].specialization;
|
||||
stats->failure++;
|
||||
int kind = _PySpecialization_ClassifyCallable(call_shape.callable);
|
||||
int kind = _PySpecialization_ClassifyCallable(function);
|
||||
stats->failure_kinds[kind]++;
|
||||
#endif
|
||||
if (!is_method && 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(oparg+2) = meth;
|
||||
Py_DECREF(function);
|
||||
function = meth;
|
||||
}
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(KW_NAMES) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
assert(oparg < PyTuple_GET_SIZE(consts));
|
||||
call_shape.kwnames = GETITEM(consts, oparg);
|
||||
DISPATCH();
|
||||
|
@ -4537,25 +4544,12 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(CALL) {
|
||||
PREDICTED(CALL);
|
||||
PyObject *function;
|
||||
assert((oparg == 0 && call_shape.kwnames == NULL)
|
||||
|| (oparg != 0 && oparg == PyTuple_GET_SIZE(call_shape.kwnames)));
|
||||
int is_meth;
|
||||
call_function:
|
||||
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(call_shape.total_args + 1) = self;
|
||||
Py_DECREF(function);
|
||||
function = meth;
|
||||
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;
|
||||
is_meth = is_method(stack_pointer, oparg);
|
||||
int total_args = oparg + is_meth;
|
||||
PyObject *function = PEEK(total_args + 1);
|
||||
int positional_args = total_args - KWNAMES_LEN();
|
||||
// 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;
|
||||
|
@ -4566,7 +4560,7 @@ handle_eval_breaker:
|
|||
stack_pointer, positional_args, call_shape.kwnames
|
||||
);
|
||||
call_shape.kwnames = NULL;
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
// The frame has stolen all the arguments from the stack,
|
||||
// so there is no need to clean them up.
|
||||
if (new_frame == NULL) {
|
||||
|
@ -4599,7 +4593,7 @@ handle_eval_breaker:
|
|||
for (int i = 0; i < total_args; i++) {
|
||||
Py_DECREF(stack_pointer[i]);
|
||||
}
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
PUSH(res);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
|
@ -4610,14 +4604,14 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(CALL_ADAPTIVE) {
|
||||
SpecializedCacheEntry *cache = GET_CACHE();
|
||||
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)));
|
||||
int original_oparg = cache->adaptive.original_oparg;
|
||||
if (cache->adaptive.counter == 0) {
|
||||
next_instr--;
|
||||
int nargs = call_shape.total_args;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int nargs = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(nargs + 1);
|
||||
int err = _Py_Specialize_CallNoKw(
|
||||
call_shape.callable, next_instr, nargs,
|
||||
callable, next_instr, nargs,
|
||||
call_shape.kwnames, cache, BUILTINS());
|
||||
if (err < 0) {
|
||||
goto error;
|
||||
|
@ -4627,7 +4621,7 @@ handle_eval_breaker:
|
|||
else {
|
||||
STAT_INC(CALL, deferred);
|
||||
cache->adaptive.counter--;
|
||||
oparg = named_args;
|
||||
oparg = original_oparg;
|
||||
goto call_function;
|
||||
}
|
||||
}
|
||||
|
@ -4635,10 +4629,13 @@ handle_eval_breaker:
|
|||
TARGET(CALL_PY_EXACT_ARGS) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int argcount = call_shape.total_args;
|
||||
DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL);
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int argcount = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(argcount + 1);
|
||||
DEOPT_IF(!PyFunction_Check(callable), CALL);
|
||||
_PyCallCache *cache1 = &caches[-1].call;
|
||||
PyFunctionObject *func = (PyFunctionObject *)call_shape.callable;
|
||||
PyFunctionObject *func = (PyFunctionObject *)callable;
|
||||
DEOPT_IF(func->func_version != cache1->func_version, CALL);
|
||||
PyCodeObject *code = (PyCodeObject *)func->func_code;
|
||||
DEOPT_IF(code->co_argcount != argcount, CALL);
|
||||
|
@ -4654,7 +4651,7 @@ handle_eval_breaker:
|
|||
for (int i = argcount; i < code->co_nlocalsplus; i++) {
|
||||
new_frame->localsplus[i] = NULL;
|
||||
}
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
new_frame->previous = frame;
|
||||
frame = cframe.current_frame = new_frame;
|
||||
|
@ -4664,10 +4661,13 @@ handle_eval_breaker:
|
|||
TARGET(CALL_PY_WITH_DEFAULTS) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int argcount = call_shape.total_args;
|
||||
DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL);
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int argcount = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(argcount + 1);
|
||||
DEOPT_IF(!PyFunction_Check(callable), CALL);
|
||||
_PyCallCache *cache1 = &caches[-1].call;
|
||||
PyFunctionObject *func = (PyFunctionObject *)call_shape.callable;
|
||||
PyFunctionObject *func = (PyFunctionObject *)callable;
|
||||
DEOPT_IF(func->func_version != cache1->func_version, CALL);
|
||||
PyCodeObject *code = (PyCodeObject *)func->func_code;
|
||||
DEOPT_IF(argcount > code->co_argcount, CALL);
|
||||
|
@ -4691,7 +4691,7 @@ handle_eval_breaker:
|
|||
for (int i = code->co_argcount; i < code->co_nlocalsplus; i++) {
|
||||
new_frame->localsplus[i] = NULL;
|
||||
}
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
new_frame->previous = frame;
|
||||
frame = cframe.current_frame = new_frame;
|
||||
|
@ -4701,14 +4701,15 @@ handle_eval_breaker:
|
|||
TARGET(CALL_NO_KW_TYPE_1) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
assert(cframe.use_tracing == 0);
|
||||
DEOPT_IF(call_shape.total_args != 1, CALL);
|
||||
assert(GET_CACHE()->adaptive.original_oparg == 1);
|
||||
DEOPT_IF(is_method(stack_pointer, 1), CALL);
|
||||
PyObject *obj = TOP();
|
||||
PyObject *callable = SECOND();
|
||||
DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL);
|
||||
PyObject *res = Py_NewRef(Py_TYPE(obj));
|
||||
Py_DECREF(callable);
|
||||
Py_DECREF(obj);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2);
|
||||
SET_TOP(res);
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
|
@ -4716,16 +4717,18 @@ handle_eval_breaker:
|
|||
TARGET(CALL_NO_KW_STR_1) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
assert(cframe.use_tracing == 0);
|
||||
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
|
||||
DEOPT_IF(call_shape.total_args != 1, CALL);
|
||||
assert(GET_CACHE()->adaptive.original_oparg == 1);
|
||||
PyObject *callable = PEEK(2);
|
||||
DEOPT_IF(!PyType_Check(callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)callable;
|
||||
DEOPT_IF(is_method(stack_pointer, 1), CALL);
|
||||
DEOPT_IF(tp != &PyUnicode_Type, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
PyObject *arg = TOP();
|
||||
PyObject *res = PyObject_Str(arg);
|
||||
Py_DECREF(arg);
|
||||
Py_DECREF(&PyUnicode_Type);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2);
|
||||
SET_TOP(res);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
|
@ -4736,16 +4739,19 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(CALL_NO_KW_TUPLE_1) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
|
||||
DEOPT_IF(call_shape.total_args != 1, CALL);
|
||||
assert(GET_CACHE()->adaptive.original_oparg == 1);
|
||||
int is_meth = is_method(stack_pointer, 1);
|
||||
PyObject *callable = PEEK(2);
|
||||
DEOPT_IF(!PyType_Check(callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)callable;
|
||||
DEOPT_IF(is_meth, CALL);
|
||||
DEOPT_IF(tp != &PyTuple_Type, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
PyObject *arg = TOP();
|
||||
PyObject *res = PySequence_Tuple(arg);
|
||||
Py_DECREF(arg);
|
||||
Py_DECREF(&PyTuple_Type);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2);
|
||||
SET_TOP(res);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
|
@ -4755,22 +4761,25 @@ handle_eval_breaker:
|
|||
}
|
||||
|
||||
TARGET(CALL_BUILTIN_CLASS) {
|
||||
DEOPT_IF(!PyType_Check(call_shape.callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)call_shape.callable;
|
||||
int original_oparg = GET_CACHE()->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
int kwnames_len = KWNAMES_LEN();
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(!PyType_Check(callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)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);
|
||||
STACK_SHRINK(total_args);
|
||||
PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer,
|
||||
total_args-kwnames_len, call_shape.kwnames);
|
||||
call_shape.kwnames = NULL;
|
||||
/* Free the arguments. */
|
||||
for (int i = 0; i < call_shape.total_args; i++) {
|
||||
for (int i = 0; i < total_args; i++) {
|
||||
Py_DECREF(stack_pointer[i]);
|
||||
}
|
||||
Py_DECREF(tp);
|
||||
STACK_SHRINK(call_shape.postcall_shrink-1);
|
||||
STACK_SHRINK(1-is_meth);
|
||||
SET_TOP(res);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
|
@ -4783,8 +4792,12 @@ handle_eval_breaker:
|
|||
assert(cframe.use_tracing == 0);
|
||||
/* Builtin METH_O functions */
|
||||
assert(call_shape.kwnames == NULL);
|
||||
DEOPT_IF(call_shape.total_args != 1, CALL);
|
||||
PyObject *callable = call_shape.callable;
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
DEOPT_IF(total_args != 1, CALL);
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
|
||||
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
|
@ -4802,7 +4815,7 @@ handle_eval_breaker:
|
|||
|
||||
Py_DECREF(arg);
|
||||
Py_DECREF(callable);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
SET_TOP(res);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
|
@ -4815,27 +4828,30 @@ handle_eval_breaker:
|
|||
assert(cframe.use_tracing == 0);
|
||||
/* Builtin METH_FASTCALL functions, without keywords */
|
||||
assert(call_shape.kwnames == NULL);
|
||||
PyObject *callable = call_shape.callable;
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
|
||||
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL,
|
||||
CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
|
||||
int nargs = call_shape.total_args;
|
||||
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
|
||||
STACK_SHRINK(nargs);
|
||||
STACK_SHRINK(total_args);
|
||||
/* res = func(self, args, nargs) */
|
||||
PyObject *res = ((_PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyCFunction_GET_SELF(callable),
|
||||
stack_pointer,
|
||||
nargs);
|
||||
total_args);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
||||
/* Free the arguments. */
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
for (int i = 0; i < total_args; i++) {
|
||||
Py_DECREF(stack_pointer[i]);
|
||||
}
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
PUSH(res);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
|
@ -4853,19 +4869,16 @@ handle_eval_breaker:
|
|||
TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
|
||||
PyObject *callable = call_shape.callable;
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
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);
|
||||
STACK_SHRINK(total_args);
|
||||
/* res = func(self, args, nargs, kwnames) */
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
|
@ -4873,17 +4886,17 @@ handle_eval_breaker:
|
|||
PyObject *res = cfunc(
|
||||
PyCFunction_GET_SELF(callable),
|
||||
stack_pointer,
|
||||
nargs,
|
||||
total_args - KWNAMES_LEN(),
|
||||
call_shape.kwnames
|
||||
);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
call_shape.kwnames = NULL;
|
||||
|
||||
/* Free the arguments. */
|
||||
for (int i = 0; i < call_shape.total_args; i++) {
|
||||
for (int i = 0; i < total_args; i++) {
|
||||
Py_DECREF(stack_pointer[i]);
|
||||
}
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
PUSH(res);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
|
@ -4898,11 +4911,12 @@ handle_eval_breaker:
|
|||
assert(call_shape.kwnames == NULL);
|
||||
/* len(o) */
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
DEOPT_IF(call_shape.total_args != 1, CALL);
|
||||
assert(caches[0].adaptive.original_oparg == 0);
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
DEOPT_IF(total_args != 1, CALL);
|
||||
_PyObjectCache *cache1 = &caches[-1].obj;
|
||||
|
||||
PyObject *callable = call_shape.callable;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(callable != cache1->obj, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
|
||||
|
@ -4914,7 +4928,7 @@ handle_eval_breaker:
|
|||
PyObject *res = PyLong_FromSsize_t(len_i);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
SET_TOP(res);
|
||||
Py_DECREF(callable);
|
||||
Py_DECREF(arg);
|
||||
|
@ -4929,11 +4943,14 @@ handle_eval_breaker:
|
|||
assert(call_shape.kwnames == NULL);
|
||||
/* isinstance(o, o2) */
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
assert(caches[0].adaptive.original_oparg == 0);
|
||||
DEOPT_IF(call_shape.total_args != 2, CALL);
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(total_args != 2, CALL);
|
||||
_PyObjectCache *cache1 = &caches[-1].obj;
|
||||
|
||||
DEOPT_IF(call_shape.callable != cache1->obj, CALL);
|
||||
DEOPT_IF(callable != cache1->obj, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
|
||||
PyObject *cls = POP();
|
||||
|
@ -4946,11 +4963,11 @@ handle_eval_breaker:
|
|||
PyObject *res = PyBool_FromLong(retval);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
SET_TOP(res);
|
||||
Py_DECREF(inst);
|
||||
Py_DECREF(cls);
|
||||
Py_DECREF(call_shape.callable);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -4961,9 +4978,13 @@ handle_eval_breaker:
|
|||
assert(cframe.use_tracing == 0);
|
||||
assert(call_shape.kwnames == NULL);
|
||||
SpecializedCacheEntry *caches = GET_CACHE();
|
||||
int original_oparg = caches->adaptive.original_oparg;
|
||||
_PyObjectCache *cache1 = &caches[-1].obj;
|
||||
DEOPT_IF(call_shape.total_args != 2, CALL);
|
||||
DEOPT_IF(call_shape.callable != cache1->obj, CALL);
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(total_args != 2, CALL);
|
||||
DEOPT_IF(callable != cache1->obj, CALL);
|
||||
PyObject *list = SECOND();
|
||||
DEOPT_IF(!PyList_Check(list), CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
|
@ -4974,18 +4995,22 @@ handle_eval_breaker:
|
|||
}
|
||||
Py_DECREF(arg);
|
||||
Py_DECREF(list);
|
||||
STACK_SHRINK(call_shape.postcall_shrink+1);
|
||||
STACK_SHRINK(3-is_meth);
|
||||
Py_INCREF(Py_None);
|
||||
SET_TOP(Py_None);
|
||||
Py_DECREF(call_shape.callable);
|
||||
Py_DECREF(callable);
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {
|
||||
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;
|
||||
int original_oparg = GET_CACHE()->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(total_args != 2, CALL);
|
||||
DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);
|
||||
PyMethodDef *meth = ((PyMethodDescrObject *)callable)->d_method;
|
||||
DEOPT_IF(meth->ml_flags != METH_O, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
PyCFunction cfunc = meth->ml_meth;
|
||||
|
@ -5001,9 +5026,9 @@ handle_eval_breaker:
|
|||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
Py_DECREF(self);
|
||||
Py_DECREF(arg);
|
||||
STACK_SHRINK(call_shape.postcall_shrink+1);
|
||||
STACK_SHRINK(3-is_meth);
|
||||
SET_TOP(res);
|
||||
Py_DECREF(call_shape.callable);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -5013,9 +5038,13 @@ handle_eval_breaker:
|
|||
|
||||
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;
|
||||
int original_oparg = GET_CACHE()->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
DEOPT_IF(total_args != 1, CALL);
|
||||
DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);
|
||||
PyMethodDef *meth = ((PyMethodDescrObject *)callable)->d_method;
|
||||
DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
PyCFunction cfunc = meth->ml_meth;
|
||||
|
@ -5029,9 +5058,9 @@ handle_eval_breaker:
|
|||
_Py_LeaveRecursiveCall(tstate);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
Py_DECREF(self);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
SET_TOP(res);
|
||||
Py_DECREF(call_shape.callable);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -5041,13 +5070,17 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) {
|
||||
assert(call_shape.kwnames == NULL);
|
||||
int original_oparg = GET_CACHE()->adaptive.original_oparg;
|
||||
int is_meth = is_method(stack_pointer, original_oparg);
|
||||
int total_args = original_oparg + is_meth;
|
||||
PyObject *callable = PEEK(total_args + 1);
|
||||
/* Builtin METH_FASTCALL methods, without keywords */
|
||||
DEOPT_IF(!Py_IS_TYPE(call_shape.callable, &PyMethodDescr_Type), CALL);
|
||||
PyMethodDef *meth = ((PyMethodDescrObject *)call_shape.callable)->d_method;
|
||||
DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);
|
||||
PyMethodDef *meth = ((PyMethodDescrObject *)callable)->d_method;
|
||||
DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
_PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
int nargs = call_shape.total_args-1;
|
||||
int nargs = total_args-1;
|
||||
STACK_SHRINK(nargs);
|
||||
PyObject *self = TOP();
|
||||
PyObject *res = cfunc(self, stack_pointer, nargs);
|
||||
|
@ -5057,9 +5090,9 @@ handle_eval_breaker:
|
|||
Py_DECREF(stack_pointer[i]);
|
||||
}
|
||||
Py_DECREF(self);
|
||||
STACK_SHRINK(call_shape.postcall_shrink);
|
||||
STACK_SHRINK(2-is_meth);
|
||||
SET_TOP(res);
|
||||
Py_DECREF(call_shape.callable);
|
||||
Py_DECREF(callable);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -1800,7 +1800,7 @@ compiler_call_exit_with_nones(struct compiler *c) {
|
|||
ADDOP_LOAD_CONST(c, Py_None);
|
||||
ADDOP_LOAD_CONST(c, Py_None);
|
||||
ADDOP_I(c, PRECALL, 2);
|
||||
ADDOP_I(c, CALL, 0);
|
||||
ADDOP_I(c, CALL, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4679,16 +4679,12 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
|
|||
|
||||
if (kwdsl) {
|
||||
VISIT_SEQ(c, keyword, kwds);
|
||||
ADDOP_I(c, PRECALL, argsl + kwdsl);
|
||||
if (!compiler_call_simple_kw_helper(c, kwds, kwdsl)) {
|
||||
return 0;
|
||||
};
|
||||
ADDOP_I(c, CALL, kwdsl);
|
||||
}
|
||||
else {
|
||||
ADDOP_I(c, PRECALL, argsl);
|
||||
ADDOP_I(c, CALL, 0);
|
||||
}
|
||||
ADDOP_I(c, PRECALL, argsl + kwdsl);
|
||||
ADDOP_I(c, CALL, argsl + kwdsl);
|
||||
c->u->u_lineno = old_lineno;
|
||||
return 1;
|
||||
}
|
||||
|
@ -4758,7 +4754,7 @@ compiler_joined_str(struct compiler *c, expr_ty e)
|
|||
ADDOP_I(c, LIST_APPEND, 1);
|
||||
}
|
||||
ADDOP_I(c, PRECALL, 1);
|
||||
ADDOP_I(c, CALL, 0);
|
||||
ADDOP_I(c, CALL, 1);
|
||||
}
|
||||
else {
|
||||
VISIT_SEQ(c, expr, e->v.JoinedStr.values);
|
||||
|
@ -4927,18 +4923,13 @@ compiler_call_helper(struct compiler *c,
|
|||
}
|
||||
if (nkwelts) {
|
||||
VISIT_SEQ(c, keyword, keywords);
|
||||
ADDOP_I(c, PRECALL, n + nelts + nkwelts);
|
||||
if (!compiler_call_simple_kw_helper(c, keywords, nkwelts)) {
|
||||
return 0;
|
||||
};
|
||||
ADDOP_I(c, CALL, nkwelts);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
ADDOP_I(c, PRECALL, n + nelts);
|
||||
ADDOP_I(c, CALL, 0);
|
||||
return 1;
|
||||
}
|
||||
ADDOP_I(c, PRECALL, n + nelts + nkwelts);
|
||||
ADDOP_I(c, CALL, n + nelts + nkwelts);
|
||||
return 1;
|
||||
|
||||
ex_call:
|
||||
|
||||
|
|
Loading…
Reference in New Issue