]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44525: Split calls into PRECALL and CALL (GH-30011)
authorMark Shannon <mark@hotpy.org>
Tue, 14 Dec 2021 18:22:44 +0000 (18:22 +0000)
committerGitHub <noreply@github.com>
Tue, 14 Dec 2021 18:22:44 +0000 (18:22 +0000)
* 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.

15 files changed:
Doc/library/dis.rst
Include/internal/pycore_code.h
Include/opcode.h
Lib/importlib/_bootstrap_external.py
Lib/opcode.py
Lib/test/test_compile.py
Lib/test/test_dis.py
Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst [new file with mode: 0644]
Objects/exception_handling_notes.txt
Objects/lnotab_notes.txt
Programs/test_frozenmain.h
Python/ceval.c
Python/compile.c
Python/opcode_targets.h
Python/specialize.c

index 7ac5a9b1f54549d3dd393810aca392bc343ff290..35d9baadf6d16ce1a8c31ae9700259d1515f8b79 100644 (file)
@@ -36,7 +36,7 @@ the following command can be used to display the disassembly of
    >>> dis.dis(myfunc)
      2           0 LOAD_GLOBAL              0 (len)
                  2 LOAD_FAST                0 (alist)
-                 4 CALL_FUNCTION            1
+                 4 CALL_NO_KW               1
                  6 RETURN_VALUE
 
 (The "2" is a line number).
@@ -104,7 +104,7 @@ Example::
     ...
     LOAD_GLOBAL
     LOAD_FAST
-    CALL_FUNCTION
+    CALL_NO_KW
     RETURN_VALUE
 
 
@@ -616,7 +616,7 @@ iterations of the loop.
 .. opcode:: LOAD_BUILD_CLASS
 
    Pushes :func:`builtins.__build_class__` onto the stack.  It is later called
-   by :opcode:`CALL_FUNCTION` to construct a class.
+   by :opcode:`CALL_NO_KW` to construct a class.
 
 
 .. opcode:: BEFORE_WITH (delta)
@@ -1039,21 +1039,20 @@ All of the following opcodes use their arguments.
      with ``__cause__`` set to ``TOS``)
 
 
-.. opcode:: CALL_FUNCTION (argc)
+.. opcode:: CALL_NO_KW (argc)
 
    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_FUNCTION`` pops all arguments and the callable object off the stack,
+   ``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.
 
-   .. versionchanged:: 3.6
-      This opcode is used only for calls with positional arguments.
+   .. versionadded:: 3.11
 
 
-.. opcode:: CALL_FUNCTION_KW (argc)
+.. 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.
@@ -1063,13 +1062,11 @@ All of the following opcodes use their 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_FUNCTION_KW`` pops all arguments and the callable object off the stack,
+   ``CALL_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.
 
-   .. versionchanged:: 3.6
-      Keyword arguments are packed in a tuple instead of a dictionary,
-      *argc* indicates the total number of arguments.
+   .. versionadded:: 3.11
 
 
 .. opcode:: CALL_FUNCTION_EX (flags)
@@ -1099,30 +1096,16 @@ All of the following opcodes use their arguments.
    .. versionadded:: 3.7
 
 
-.. opcode:: CALL_METHOD (argc)
-
-   Calls a method.  *argc* is the number of positional arguments.
-   Keyword arguments are not supported.  This opcode is designed to be used
-   with :opcode:`LOAD_METHOD`.  Positional arguments are on top of the stack.
-   Below them, the two items described in :opcode:`LOAD_METHOD` are on the
-   stack (either ``self`` and an unbound method object or ``NULL`` and an
-   arbitrary callable). All of them are popped and the return value is pushed.
-
-   .. versionadded:: 3.7
-
-
-.. opcode:: CALL_METHOD_KW (argc)
+.. opcode:: PRECALL_METHOD (argc)
 
-   Calls a method in a similar fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments.
-   *argc* is the number of positional and keyword arguments.
-   This opcode is designed to be used with :opcode:`LOAD_METHOD`.  TOS is a
-   tuple of keyword argument names.  Argument values are below that.
-   Below them, the two items described in :opcode:`LOAD_METHOD` are on the
-   stack (either ``self`` and an unbound method object or ``NULL`` and an
-   arbitrary callable).  All of them are popped from the stack and the return value is pushed.
+   Prefixes either :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`.
+   This opcode is designed to be used with :opcode:`LOAD_METHOD`.
+   Sets internal variables, so that :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`
+   clean up after :opcode:`LOAD_METHOD` correctly.
 
    .. versionadded:: 3.11
 
+
 .. opcode:: MAKE_FUNCTION (flags)
 
    Pushes a new function object on the stack.  From bottom to top, the consumed
index 496d52f580f1f3cab413b5b09eefc4b0b8a023e2..b0463e361718a536dce83361f1b6e90da748c598 100644 (file)
@@ -271,7 +271,7 @@ 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_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins);
+int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, 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);
@@ -288,7 +288,7 @@ void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
 #define COLLECT_SPECIALIZATION_STATS_DETAILED PRINT_SPECIALIZATION_STATS_DETAILED
 #endif
 
-#define SPECIALIZATION_FAILURE_KINDS 20
+#define SPECIALIZATION_FAILURE_KINDS 30
 
 #if COLLECT_SPECIALIZATION_STATS
 
index 1341a8abad4d7b38222069369ad8012879705c9f..4d14081a6b6180cda38653a8acc0d00482785326 100644 (file)
@@ -87,7 +87,6 @@ extern "C" {
 #define JUMP_IF_NOT_EG_MATCH            127
 #define GEN_START                       129
 #define RAISE_VARARGS                   130
-#define CALL_FUNCTION                   131
 #define MAKE_FUNCTION                   132
 #define BUILD_SLICE                     133
 #define MAKE_CELL                       135
@@ -95,7 +94,6 @@ extern "C" {
 #define LOAD_DEREF                      137
 #define STORE_DEREF                     138
 #define DELETE_DEREF                    139
-#define CALL_FUNCTION_KW                141
 #define CALL_FUNCTION_EX                142
 #define EXTENDED_ARG                    144
 #define LIST_APPEND                     145
@@ -108,12 +106,13 @@ extern "C" {
 #define BUILD_CONST_KEY_MAP             156
 #define BUILD_STRING                    157
 #define LOAD_METHOD                     160
-#define CALL_METHOD                     161
 #define LIST_EXTEND                     162
 #define SET_UPDATE                      163
 #define DICT_MERGE                      164
 #define DICT_UPDATE                     165
-#define CALL_METHOD_KW                  166
+#define PRECALL_METHOD                  168
+#define CALL_NO_KW                      169
+#define CALL_KW                         170
 #define BINARY_OP_ADAPTIVE                7
 #define BINARY_OP_ADD_INT                 8
 #define BINARY_OP_ADD_FLOAT              13
@@ -135,35 +134,38 @@ extern "C" {
 #define STORE_SUBSCR_ADAPTIVE            36
 #define STORE_SUBSCR_LIST_INT            38
 #define STORE_SUBSCR_DICT                39
-#define CALL_FUNCTION_ADAPTIVE           40
-#define CALL_FUNCTION_BUILTIN_O          41
-#define CALL_FUNCTION_BUILTIN_FAST       42
-#define CALL_FUNCTION_LEN                43
-#define CALL_FUNCTION_ISINSTANCE         44
-#define CALL_FUNCTION_PY_SIMPLE          45
-#define JUMP_ABSOLUTE_QUICK              46
-#define LOAD_ATTR_ADAPTIVE               47
-#define LOAD_ATTR_INSTANCE_VALUE         48
-#define LOAD_ATTR_WITH_HINT              55
-#define LOAD_ATTR_SLOT                   56
-#define LOAD_ATTR_MODULE                 57
-#define LOAD_GLOBAL_ADAPTIVE             58
-#define LOAD_GLOBAL_MODULE               59
-#define LOAD_GLOBAL_BUILTIN              62
-#define LOAD_METHOD_ADAPTIVE             63
-#define LOAD_METHOD_CACHED               64
-#define LOAD_METHOD_CLASS                65
-#define LOAD_METHOD_MODULE               66
-#define LOAD_METHOD_NO_DICT              67
-#define STORE_ATTR_ADAPTIVE              75
-#define STORE_ATTR_INSTANCE_VALUE        76
-#define STORE_ATTR_SLOT                  77
-#define STORE_ATTR_WITH_HINT             78
-#define LOAD_FAST__LOAD_FAST             79
-#define STORE_FAST__LOAD_FAST            80
-#define LOAD_FAST__LOAD_CONST            81
-#define LOAD_CONST__LOAD_FAST            87
-#define STORE_FAST__STORE_FAST          123
+#define CALL_NO_KW_ADAPTIVE              40
+#define CALL_NO_KW_BUILTIN_O             41
+#define CALL_NO_KW_BUILTIN_FAST          42
+#define CALL_NO_KW_LEN                   43
+#define CALL_NO_KW_ISINSTANCE            44
+#define CALL_NO_KW_PY_SIMPLE             45
+#define CALL_NO_KW_LIST_APPEND           46
+#define CALL_NO_KW_METHOD_DESCRIPTOR_O   47
+#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST  48
+#define JUMP_ABSOLUTE_QUICK              55
+#define LOAD_ATTR_ADAPTIVE               56
+#define LOAD_ATTR_INSTANCE_VALUE         57
+#define LOAD_ATTR_WITH_HINT              58
+#define LOAD_ATTR_SLOT                   59
+#define LOAD_ATTR_MODULE                 62
+#define LOAD_GLOBAL_ADAPTIVE             63
+#define LOAD_GLOBAL_MODULE               64
+#define LOAD_GLOBAL_BUILTIN              65
+#define LOAD_METHOD_ADAPTIVE             66
+#define LOAD_METHOD_CACHED               67
+#define LOAD_METHOD_CLASS                75
+#define LOAD_METHOD_MODULE               76
+#define LOAD_METHOD_NO_DICT              77
+#define STORE_ATTR_ADAPTIVE              78
+#define STORE_ATTR_INSTANCE_VALUE        79
+#define STORE_ATTR_SLOT                  80
+#define STORE_ATTR_WITH_HINT             81
+#define LOAD_FAST__LOAD_FAST             87
+#define STORE_FAST__LOAD_FAST           123
+#define LOAD_FAST__LOAD_CONST           128
+#define LOAD_CONST__LOAD_FAST           131
+#define STORE_FAST__STORE_FAST          134
 #define DO_TRACING                      255
 #ifdef NEED_OPCODE_JUMP_TABLES
 static uint32_t _PyOpcode_RelativeJump[8] = {
index 6e7ea7b378143110e7e185ca93fc468e9dc7ce40..abd0170cac0701b6e89eb60d0776037ed0b8dd8a 100644 (file)
@@ -372,6 +372,7 @@ _code_type = type(_write_atomic.__code__)
 #                         BINARY_OP)
 #     Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
 #     Python 3.11a3 3466 (bpo-45292: PEP-654 except*)
+#     Python 3.11a4 3467 (Change CALL_xxx opcodes)
 
 #
 # MAGIC must change whenever the bytecode emitted by the compiler may no
@@ -381,7 +382,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 = (3466).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3467).to_bytes(2, 'little') + b'\r\n'
 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 
 _PYCACHE = '__pycache__'
index 299216d3c879918a1e8f4392e1e2a40f6d8f2070..0b64686d605f9d4b86b25a08883e49d657cd99f1 100644 (file)
@@ -155,7 +155,7 @@ jabs_op('JUMP_IF_NOT_EG_MATCH', 127)
 
 def_op('GEN_START', 129)        # Kind of generator/coroutine
 def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
-def_op('CALL_FUNCTION', 131)    # #args
+
 def_op('MAKE_FUNCTION', 132)    # Flags
 def_op('BUILD_SLICE', 133)      # Number of items
 
@@ -170,7 +170,6 @@ hasfree.append(138)
 def_op('DELETE_DEREF', 139)
 hasfree.append(139)
 
-def_op('CALL_FUNCTION_KW', 141)  # #args + #kwargs
 def_op('CALL_FUNCTION_EX', 142)  # Flags
 
 def_op('EXTENDED_ARG', 144)
@@ -189,12 +188,15 @@ def_op('BUILD_CONST_KEY_MAP', 156)
 def_op('BUILD_STRING', 157)
 
 name_op('LOAD_METHOD', 160)
-def_op('CALL_METHOD', 161)
+
 def_op('LIST_EXTEND', 162)
 def_op('SET_UPDATE', 163)
 def_op('DICT_MERGE', 164)
 def_op('DICT_UPDATE', 165)
-def_op('CALL_METHOD_KW', 166)
+
+def_op('PRECALL_METHOD', 168)
+def_op('CALL_NO_KW', 169)
+def_op('CALL_KW', 170)
 
 del def_op, name_op, jrel_op, jabs_op
 
@@ -249,12 +251,15 @@ _specialized_instructions = [
     "STORE_SUBSCR_ADAPTIVE",
     "STORE_SUBSCR_LIST_INT",
     "STORE_SUBSCR_DICT",
-    "CALL_FUNCTION_ADAPTIVE",
-    "CALL_FUNCTION_BUILTIN_O",
-    "CALL_FUNCTION_BUILTIN_FAST",
-    "CALL_FUNCTION_LEN",
-    "CALL_FUNCTION_ISINSTANCE",
-    "CALL_FUNCTION_PY_SIMPLE",
+    "CALL_NO_KW_ADAPTIVE",
+    "CALL_NO_KW_BUILTIN_O",
+    "CALL_NO_KW_BUILTIN_FAST",
+    "CALL_NO_KW_LEN",
+    "CALL_NO_KW_ISINSTANCE",
+    "CALL_NO_KW_PY_SIMPLE",
+    "CALL_NO_KW_LIST_APPEND",
+    "CALL_NO_KW_METHOD_DESCRIPTOR_O",
+    "CALL_NO_KW_METHOD_DESCRIPTOR_FAST",
     "JUMP_ABSOLUTE_QUICK",
     "LOAD_ATTR_ADAPTIVE",
     "LOAD_ATTR_INSTANCE_VALUE",
index 5bd7b065306912f063a7df6f501e6d357076eec5..11615b32232e84be07c35d3dcde41bbd0022b572 100644 (file)
@@ -839,7 +839,7 @@ if 1:
                 self.assertNotIn('LOAD_METHOD', instructions)
                 self.assertNotIn('CALL_METHOD', instructions)
                 self.assertIn('LOAD_ATTR', instructions)
-                self.assertIn('CALL_FUNCTION', instructions)
+                self.assertIn('CALL_NO_KW', instructions)
 
     def test_lineno_procedure_call(self):
         def call():
@@ -1095,7 +1095,7 @@ f(
 )
 """
         compiled_code, _ = self.check_positions_against_ast(snippet)
-        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION',
+        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
             line=1, end_line=3, column=0, end_column=1)
 
     def test_very_long_line_end_offset(self):
@@ -1105,7 +1105,7 @@ f(
         snippet = f"g('{long_string}')"
 
         compiled_code, _ = self.check_positions_against_ast(snippet)
-        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION',
+        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW',
             line=1, end_line=1, column=None, end_column=None)
 
     def test_complex_single_line_expression(self):
index e821e001ad88005453712a2cd4085a482b181711..c35f1d3ec8bd7d0c0b9887ff8cc59b1c80524873 100644 (file)
@@ -95,7 +95,7 @@ def _f(a):
 dis_f = """\
 %3d           0 LOAD_GLOBAL              0 (print)
               2 LOAD_FAST                0 (a)
-              4 CALL_FUNCTION            1
+              4 CALL_NO_KW               1
               6 POP_TOP
 
 %3d           8 LOAD_CONST               1 (1)
@@ -107,7 +107,7 @@ dis_f = """\
 dis_f_co_code = """\
           0 LOAD_GLOBAL              0
           2 LOAD_FAST                0
-          4 CALL_FUNCTION            1
+          4 CALL_NO_KW               1
           6 POP_TOP
           8 LOAD_CONST               1
          10 RETURN_VALUE
@@ -125,7 +125,7 @@ dis_bug708901 = """\
 
 %3d           4 LOAD_CONST               2 (10)
 
-%3d           6 CALL_FUNCTION            2
+%3d           6 CALL_NO_KW               2
               8 GET_ITER
         >>   10 FOR_ITER                 2 (to 16)
              12 STORE_FAST               0 (res)
@@ -152,12 +152,12 @@ dis_bug1333982 = """\
               4 MAKE_FUNCTION            0
               6 LOAD_FAST                0 (x)
               8 GET_ITER
-             10 CALL_FUNCTION            1
+             10 CALL_NO_KW               1
 
 %3d          12 LOAD_CONST               3 (1)
 
 %3d          14 BINARY_OP                0 (+)
-             16 CALL_FUNCTION            1
+             16 CALL_NO_KW               1
              18 RAISE_VARARGS            1
 """ % (bug1333982.__code__.co_firstlineno + 1,
        __file__,
@@ -260,7 +260,7 @@ dis_annot_stmt_str = """\
 
   3          14 LOAD_NAME                3 (fun)
              16 LOAD_CONST               0 (1)
-             18 CALL_FUNCTION            1
+             18 CALL_NO_KW               1
              20 LOAD_NAME                2 (__annotations__)
              22 LOAD_CONST               2 ('y')
              24 STORE_SUBSCR
@@ -269,7 +269,7 @@ dis_annot_stmt_str = """\
              28 LOAD_NAME                4 (lst)
              30 LOAD_NAME                3 (fun)
              32 LOAD_CONST               3 (0)
-             34 CALL_FUNCTION            1
+             34 CALL_NO_KW               1
              36 STORE_SUBSCR
              38 LOAD_NAME                1 (int)
              40 POP_TOP
@@ -384,12 +384,12 @@ dis_tryfinally = """\
 %3d           2 LOAD_FAST                0 (a)
 
 %3d           4 LOAD_FAST                1 (b)
-              6 CALL_FUNCTION            0
+              6 CALL_NO_KW               0
               8 POP_TOP
              10 RETURN_VALUE
         >>   12 PUSH_EXC_INFO
              14 LOAD_FAST                1 (b)
-             16 CALL_FUNCTION            0
+             16 CALL_NO_KW               0
              18 POP_TOP
              20 RERAISE                  0
         >>   22 POP_EXCEPT_AND_RERAISE
@@ -407,13 +407,13 @@ dis_tryfinallyconst = """\
 %3d           2 NOP
 
 %3d           4 LOAD_FAST                0 (b)
-              6 CALL_FUNCTION            0
+              6 CALL_NO_KW               0
               8 POP_TOP
              10 LOAD_CONST               1 (1)
              12 RETURN_VALUE
              14 PUSH_EXC_INFO
              16 LOAD_FAST                0 (b)
-             18 CALL_FUNCTION            0
+             18 CALL_NO_KW               0
              20 POP_TOP
              22 RERAISE                  0
         >>   24 POP_EXCEPT_AND_RERAISE
@@ -468,7 +468,7 @@ Disassembly of <code object foo at 0x..., file "%s", line %d>:
              10 MAKE_FUNCTION            8 (closure)
              12 LOAD_DEREF               1 (y)
              14 GET_ITER
-             16 CALL_FUNCTION            1
+             16 CALL_NO_KW               1
              18 RETURN_VALUE
 """ % (dis_nested_0,
        __file__,
@@ -1004,7 +1004,7 @@ expected_opinfo_outer = [
   Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=32, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=7, argval=7, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=38, starts_line=8, is_jump_target=False, positions=None),
   Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
@@ -1028,7 +1028,7 @@ expected_opinfo_f = [
   Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=28, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=30, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=32, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=4, argval=4, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=38, starts_line=6, is_jump_target=False, positions=None),
   Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
@@ -1043,7 +1043,7 @@ expected_opinfo_inner = [
   Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=10, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=12, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=14, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=6, argval=6, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=20, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
@@ -1052,13 +1052,13 @@ expected_opinfo_inner = [
 expected_opinfo_jumpy = [
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=0, starts_line=3, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=2, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='FOR_ITER', opcode=93, arg=17, argval=44, argrepr='to 44', offset=8, starts_line=None, is_jump_target=True, positions=None),
   Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=10, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=12, starts_line=4, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=20, starts_line=5, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=22, starts_line=None, is_jump_target=False, positions=None),
@@ -1074,13 +1074,13 @@ expected_opinfo_jumpy = [
   Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=4, argval=8, argrepr='to 8', offset=42, starts_line=7, is_jump_target=True, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, 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=46, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, starts_line=11, is_jump_target=True, positions=None),
   Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=48, argval=96, argrepr='to 96', offset=54, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, starts_line=12, is_jump_target=True, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=58, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False, positions=None),
@@ -1100,7 +1100,7 @@ expected_opinfo_jumpy = [
   Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=28, argval=56, argrepr='to 56', offset=94, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=96, 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=98, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=102, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=104, starts_line=20, is_jump_target=True, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False, positions=None),
@@ -1116,7 +1116,7 @@ expected_opinfo_jumpy = [
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, positions=None),
@@ -1127,12 +1127,12 @@ expected_opinfo_jumpy = [
   Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, 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=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None),
   Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None),
@@ -1148,21 +1148,21 @@ expected_opinfo_jumpy = [
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, 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=194, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, 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=208, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, 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=222, starts_line=None, is_jump_target=False, positions=None),
-  Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None),
+  Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
   Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None),
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst
new file mode 100644 (file)
index 0000000..d929666
--- /dev/null
@@ -0,0 +1,8 @@
+Replace the four call bytecode instructions which one pre-call instruction
+and two call instructions.
+
+Removes ``CALL_FUNCTION``, ``CALL_FUNCTION_KW``, ``CALL_METHOD`` and
+``CALL_METHOD_KW``.
+
+Adds ``CALL_NO_KW`` and ``CALL_KW`` call instructions, and
+``PRECALL_METHOD`` prefix for pairing with ``LOAD_METHOD``.
index e738c2781ad23fe1a9566b1c87ed33959d4b3292..a136358f90c888e735218577324892dd579a3f26 100644 (file)
@@ -23,7 +23,7 @@ compiles as follows in 3.10:
 
   3           2 LOAD_GLOBAL              0 (g)
               4 LOAD_CONST               1 (0)
-              6 CALL_FUNCTION            1
+              6 CALL_NO_KW               1
               8 POP_TOP
              10 POP_BLOCK
              12 LOAD_CONST               0 (None)
@@ -47,7 +47,7 @@ a table to determine where to jump to when an exception is raised.
 
   3           2 LOAD_GLOBAL              0 (g)
               4 LOAD_CONST               1 (0)
-              6 CALL_FUNCTION            1
+              6 CALL_NO_KW               1
               8 POP_TOP
              10 LOAD_CONST               0 (None)
              12 RETURN_VALUE
@@ -68,7 +68,7 @@ ExceptionTable:
 (Note this code is from an early 3.11 alpha, the NOP may well have be removed before release).
 
 If an instruction raises an exception then its offset is used to find the target to jump to.
-For example, the CALL_FUNCTION at offset 6, falls into the range 2 to 8.
+For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8.
 So, if g() raises an exception, then control jumps to offset 14.
 
 
index e52e437c65025eefb94006c9af5dae162c53986c..362b87a86a481f086328f76bbbe409a6608dd037 100644 (file)
@@ -188,7 +188,7 @@ which compiles to this:
 
   3           6 LOAD_GLOBAL              0 (print)
               8 LOAD_CONST               1 (1)
-             10 CALL_FUNCTION            1
+             10 CALL_NO_KW               1
              12 POP_TOP
 
   4          14 BREAK_LOOP
@@ -197,7 +197,7 @@ which compiles to this:
 
   6          20 LOAD_GLOBAL              0 (print)
              22 LOAD_CONST               2 (2)
-             24 CALL_FUNCTION            1
+             24 CALL_NO_KW               1
              26 POP_TOP
         >>   28 LOAD_CONST               0 (None)
              30 RETURN_VALUE
index 2c789915bf5035903846bee023f23265f18cab21..45ca31e1b5e95ec777248646a29d589be216f87e 100644 (file)
@@ -2,11 +2,11 @@
 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,86,0,0,0,100,0,100,1,108,0,
-    90,0,100,0,100,1,108,1,90,1,101,2,100,2,131,1,
-    1,0,101,2,100,3,101,0,106,3,131,2,1,0,101,1,
-    106,4,131,0,100,4,25,0,90,5,100,5,68,0,93,14,
+    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,131,1,1,0,113,26,100,1,83,0,
+    25,0,155,0,157,4,169,1,1,0,113,26,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,
index fb19f78ba14d460cae8e5fe9afbdc252a88226dc..6d2784894f74f97548b07aba5c0f3ddf0279defb 100644 (file)
@@ -1673,6 +1673,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
 
     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)
+
     /* WARNING: Because the CFrame lives on the C stack,
      * but can be accessed from a heap allocated object (tstate)
      * strict stack discipline must be maintained.
@@ -1815,11 +1831,6 @@ check_eval_breaker:
         switch (opcode) {
 #endif
 
-        /* Variables used for making calls */
-        PyObject *kwnames;
-        int nargs;
-        int postcall_shrink;
-
         /* BEWARE!
            It is essential that any operation that fails must goto error
            and that all operation that succeed call DISPATCH() ! */
@@ -4319,7 +4330,7 @@ check_eval_breaker:
             if (iter == NULL)
                 goto error;
             PREDICT(FOR_ITER);
-            PREDICT(CALL_FUNCTION);
+            PREDICT(CALL_NO_KW);
             DISPATCH();
         }
 
@@ -4661,7 +4672,7 @@ check_eval_breaker:
             DISPATCH();
         }
 
-        TARGET(CALL_METHOD) {
+        TARGET(PRECALL_METHOD) {
             /* Designed to work in tamdem with LOAD_METHOD. */
             /* `meth` is NULL when LOAD_METHOD thinks that it's not
                 a method call.
@@ -4689,38 +4700,26 @@ check_eval_breaker:
                make it accept the `self` as a first argument.
             */
             int is_method = (PEEK(oparg + 2) != NULL);
-            oparg += is_method;
-            nargs = oparg;
-            kwnames = NULL;
+            extra_args = is_method;
             postcall_shrink = 2-is_method;
-            goto call_function;
-        }
-
-        TARGET(CALL_METHOD_KW) {
-            /* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD
-            but pops TOS to get a tuple of keyword names. */
-            kwnames = POP();
-            int is_method = (PEEK(oparg + 2) != NULL);
-            oparg += is_method;
-            nargs = oparg - (int)PyTuple_GET_SIZE(kwnames);
-            postcall_shrink = 2-is_method;
-            goto call_function;
+            DISPATCH();
         }
 
-        TARGET(CALL_FUNCTION_KW) {
+        TARGET(CALL_KW) {
             kwnames = POP();
+            oparg += extra_args;
+            extra_args = 0;
             nargs = oparg - (int)PyTuple_GET_SIZE(kwnames);
-            postcall_shrink = 1;
             goto call_function;
         }
 
-        TARGET(CALL_FUNCTION) {
-            PREDICTED(CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, unquickened);
+        TARGET(CALL_NO_KW) {
             PyObject *function;
-            nargs = oparg;
+            PREDICTED(CALL_NO_KW);
+            STAT_INC(CALL_NO_KW, unquickened);
             kwnames = NULL;
-            postcall_shrink = 1;
+            oparg += extra_args;
+            nargs = oparg;
         call_function:
             function = PEEK(oparg + 1);
             if (Py_TYPE(function) == &PyMethod_Type) {
@@ -4748,6 +4747,7 @@ check_eval_breaker:
                         stack_pointer, nargs, kwnames
                     );
                     STACK_SHRINK(postcall_shrink);
+                    RESET_STACK_ADJUST_FOR_CALLS;
                     // The frame has stolen all the arguments from the stack,
                     // so there is no need to clean them up.
                     Py_XDECREF(kwnames);
@@ -4780,6 +4780,7 @@ check_eval_breaker:
                 Py_DECREF(stack_pointer[i]);
             }
             STACK_SHRINK(postcall_shrink);
+            RESET_STACK_ADJUST_FOR_CALLS;
             PUSH(res);
             if (res == NULL) {
                 goto error;
@@ -4788,43 +4789,46 @@ check_eval_breaker:
             DISPATCH();
         }
 
-        TARGET(CALL_FUNCTION_ADAPTIVE) {
+        TARGET(CALL_NO_KW_ADAPTIVE) {
             SpecializedCacheEntry *cache = GET_CACHE();
-            nargs = cache->adaptive.original_oparg;
+            oparg = cache->adaptive.original_oparg;
             if (cache->adaptive.counter == 0) {
                 next_instr--;
-                if (_Py_Specialize_CallFunction(
+                int nargs = oparg+extra_args;
+                if (_Py_Specialize_CallNoKw(
                     PEEK(nargs + 1), next_instr, nargs, cache, BUILTINS()) < 0) {
                     goto error;
                 }
                 DISPATCH();
             }
             else {
-                STAT_INC(CALL_FUNCTION, deferred);
+                STAT_INC(CALL_NO_KW, deferred);
                 cache->adaptive.counter--;
-                oparg = nargs;
                 kwnames = NULL;
-                postcall_shrink = 1;
+                oparg += extra_args;
+                nargs = oparg;
                 goto call_function;
             }
         }
 
-        TARGET(CALL_FUNCTION_PY_SIMPLE) {
+        TARGET(CALL_NO_KW_PY_SIMPLE) {
             SpecializedCacheEntry *caches = GET_CACHE();
             _PyAdaptiveEntry *cache0 = &caches[0].adaptive;
-            int argcount = cache0->original_oparg;
+            int argcount = cache0->original_oparg + extra_args;
+            DEOPT_IF(argcount != cache0->index, CALL_NO_KW);
             _PyCallCache *cache1 = &caches[-1].call;
             PyObject *callable = PEEK(argcount+1);
-            DEOPT_IF(!PyFunction_Check(callable), CALL_FUNCTION);
+            DEOPT_IF(!PyFunction_Check(callable), CALL_NO_KW);
             PyFunctionObject *func = (PyFunctionObject *)callable;
-            DEOPT_IF(func->func_version != cache1->func_version, CALL_FUNCTION);
+            DEOPT_IF(func->func_version != cache1->func_version, CALL_NO_KW);
             /* PEP 523 */
-            DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, hit);
+            DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_NO_KW);
+            STAT_INC(CALL_NO_KW, hit);
             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) {
+                RESET_STACK_ADJUST_FOR_CALLS;
                 goto error;
             }
             _PyFrame_InitializeSpecials(new_frame, func,
@@ -4842,7 +4846,8 @@ check_eval_breaker:
             for (int i = argcount+deflen; i < code->co_nlocalsplus; i++) {
                 new_frame->localsplus[i] = NULL;
             }
-            STACK_SHRINK(1);
+            STACK_SHRINK(postcall_shrink);
+            RESET_STACK_ADJUST_FOR_CALLS;
             Py_DECREF(func);
             _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
@@ -4851,14 +4856,15 @@ check_eval_breaker:
             goto start_frame;
         }
 
-        TARGET(CALL_FUNCTION_BUILTIN_O) {
+        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_FUNCTION);
-            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, hit);
+            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);
 
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
             // This is slower but CPython promises to check all non-vectorcall
@@ -4881,18 +4887,19 @@ check_eval_breaker:
             DISPATCH();
         }
 
-        TARGET(CALL_FUNCTION_BUILTIN_FAST) {
+        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_FUNCTION);
+            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_NO_KW);
             DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL,
-                CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, hit);
+                CALL_NO_KW);
+            STAT_INC(CALL_NO_KW, hit);
 
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
             /* res = func(self, args, nargs) */
@@ -4919,16 +4926,17 @@ check_eval_breaker:
             DISPATCH();
         }
 
-        TARGET(CALL_FUNCTION_LEN) {
+        TARGET(CALL_NO_KW_LEN) {
             assert(cframe.use_tracing == 0);
+            assert(STACK_ADJUST_IS_RESET);
             /* len(o) */
             SpecializedCacheEntry *caches = GET_CACHE();
             assert(caches[0].adaptive.original_oparg == 1);
             _PyObjectCache *cache1 = &caches[-1].obj;
 
             PyObject *callable = SECOND();
-            DEOPT_IF(callable != cache1->obj, CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, hit);
+            DEOPT_IF(callable != cache1->obj, CALL_NO_KW);
+            STAT_INC(CALL_NO_KW, hit);
 
             Py_ssize_t len_i = PyObject_Length(TOP());
             if (len_i < 0) {
@@ -4947,16 +4955,17 @@ check_eval_breaker:
             DISPATCH();
         }
 
-        TARGET(CALL_FUNCTION_ISINSTANCE) {
+        TARGET(CALL_NO_KW_ISINSTANCE) {
             assert(cframe.use_tracing == 0);
+            assert(STACK_ADJUST_IS_RESET);
             /* isinstance(o, o2) */
             SpecializedCacheEntry *caches = GET_CACHE();
             assert(caches[0].adaptive.original_oparg == 2);
             _PyObjectCache *cache1 = &caches[-1].obj;
 
             PyObject *callable = THIRD();
-            DEOPT_IF(callable != cache1->obj, CALL_FUNCTION);
-            STAT_INC(CALL_FUNCTION, hit);
+            DEOPT_IF(callable != cache1->obj, CALL_NO_KW);
+            STAT_INC(CALL_NO_KW, hit);
 
             int retval = PyObject_IsInstance(SECOND(), TOP());
             if (retval < 0) {
@@ -4976,6 +4985,97 @@ check_eval_breaker:
             DISPATCH();
         }
 
+        TARGET(CALL_NO_KW_LIST_APPEND) {
+            assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD);
+            assert(GET_CACHE()->adaptive.original_oparg == 1);
+            DEOPT_IF(extra_args == 0, CALL_NO_KW);
+            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);
+            PyObject *arg = TOP();
+            int err = PyList_Append(list, arg);
+            if (err) {
+                goto error;
+            }
+            PyObject *callable = THIRD();
+            Py_DECREF(arg);
+            Py_DECREF(list);
+            Py_INCREF(Py_None);
+            STACK_SHRINK(2);
+            SET_TOP(Py_None);
+            Py_DECREF(callable);
+            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;
+            // 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 *res = cfunc(self, arg);
+            _Py_LeaveRecursiveCall(tstate);
+            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+            Py_DECREF(self);
+            Py_DECREF(arg);
+            SET_TOP(res);
+            Py_DECREF(callable);
+            if (res == NULL) {
+                goto error;
+            }
+            DISPATCH();
+        }
+
+        TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) {
+            assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD);
+            /* 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);
+            _PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth;
+            PyObject *self = PEEK(nargs+1);
+            PyObject *res = cfunc(self, &PEEK(nargs), 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++) {
+                Py_DECREF(stack_pointer[i]);
+            }
+            SET_TOP(res);
+            Py_DECREF(callable);
+            if (res == NULL) {
+                goto error;
+            }
+            DISPATCH();
+        }
+
         TARGET(CALL_FUNCTION_EX) {
             PREDICTED(CALL_FUNCTION_EX);
             PyObject *func, *callargs, *kwargs = NULL, *result;
@@ -5289,7 +5389,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_FUNCTION)
+MISS_WITH_CACHE(CALL_NO_KW)
 MISS_WITH_CACHE(BINARY_OP)
 MISS_WITH_CACHE(COMPARE_OP)
 MISS_WITH_CACHE(BINARY_SUBSCR)
@@ -7509,7 +7609,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_FUNCTION && prevprevopcode == DUP_TOP)) {
+        else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_NO_KW && prevprevopcode == DUP_TOP)) {
             _PyErr_Format(tstate, PyExc_TypeError,
                           "'async with' received an object from __aexit__ "
                           "that does not implement __await__: %.100s",
index 00e1e016969ad2bba2b9b517e68b32bebff42825..afd9a629c0a9ef5dacac702e69af5991d838df8d 100644 (file)
@@ -1155,13 +1155,11 @@ stack_effect(int opcode, int oparg, int jump)
             return -oparg;
 
         /* Functions and calls */
-        case CALL_FUNCTION:
+        case PRECALL_METHOD:
+            return -1;
+        case CALL_NO_KW:
             return -oparg;
-        case CALL_METHOD:
-            return -oparg-1;
-        case CALL_METHOD_KW:
-            return -oparg-2;
-        case CALL_FUNCTION_KW:
+        case CALL_KW:
             return -oparg-1;
         case CALL_FUNCTION_EX:
             return -1 - ((oparg & 0x01) != 0);
@@ -1817,7 +1815,7 @@ compiler_call_exit_with_nones(struct compiler *c) {
     ADDOP_LOAD_CONST(c, Py_None);
     ADDOP(c, DUP_TOP);
     ADDOP(c, DUP_TOP);
-    ADDOP_I(c, CALL_FUNCTION, 3);
+    ADDOP_I(c, CALL_NO_KW, 3);
     return 1;
 }
 
@@ -2166,7 +2164,7 @@ 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_FUNCTION, 1);
+        ADDOP_I(c, CALL_NO_KW, 1);
     }
     c->u->u_lineno = old_lineno;
     c->u->u_end_lineno = old_end_lineno;
@@ -3885,7 +3883,7 @@ 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_FUNCTION, 1);
+        ADDOP_I(c, CALL_NO_KW, 1);
     }
     ADDOP_I(c, RAISE_VARARGS, 1);
     compiler_use_next_block(c, end);
@@ -4693,10 +4691,12 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
         if (!compiler_call_simple_kw_helper(c, kwds, kwdsl)) {
             return 0;
         };
-        ADDOP_I(c, CALL_METHOD_KW, argsl + kwdsl);
+        ADDOP_I(c, PRECALL_METHOD, argsl + kwdsl+1);
+        ADDOP_I(c, CALL_KW, argsl + kwdsl);
     }
     else {
-        ADDOP_I(c, CALL_METHOD, argsl);
+        ADDOP_I(c, PRECALL_METHOD, argsl);
+        ADDOP_I(c, CALL_NO_KW, argsl);
     }
     c->u->u_lineno = old_lineno;
     return 1;
@@ -4763,7 +4763,8 @@ compiler_joined_str(struct compiler *c, expr_ty e)
             VISIT(c, expr, asdl_seq_GET(e->v.JoinedStr.values, i));
             ADDOP_I(c, LIST_APPEND, 1);
         }
-        ADDOP_I(c, CALL_METHOD, 1);
+        ADDOP_I(c, PRECALL_METHOD, 1);
+        ADDOP_I(c, CALL_NO_KW, 1);
     }
     else {
         VISIT_SEQ(c, expr, e->v.JoinedStr.values);
@@ -4935,11 +4936,11 @@ compiler_call_helper(struct compiler *c,
         if (!compiler_call_simple_kw_helper(c, keywords, nkwelts)) {
             return 0;
         };
-        ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts);
+        ADDOP_I(c, CALL_KW, n + nelts + nkwelts);
         return 1;
     }
     else {
-        ADDOP_I(c, CALL_FUNCTION, n + nelts);
+        ADDOP_I(c, CALL_NO_KW, n + nelts);
         return 1;
     }
 
@@ -5336,7 +5337,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
         ADDOP(c, GET_ITER);
     }
 
-    ADDOP_I(c, CALL_FUNCTION, 1);
+    ADDOP_I(c, CALL_NO_KW, 1);
 
     if (is_async_generator && type != COMP_GENEXP) {
         ADDOP(c, GET_AWAITABLE);
index aeb9830cccc1577e550451973ea91f2c61e9d402..05bd9392d8ea9644d58463f43b06c4f5043549e7 100644 (file)
@@ -39,34 +39,34 @@ static void *opcode_targets[256] = {
     &&TARGET_POP_EXCEPT_AND_RERAISE,
     &&TARGET_STORE_SUBSCR_LIST_INT,
     &&TARGET_STORE_SUBSCR_DICT,
-    &&TARGET_CALL_FUNCTION_ADAPTIVE,
-    &&TARGET_CALL_FUNCTION_BUILTIN_O,
-    &&TARGET_CALL_FUNCTION_BUILTIN_FAST,
-    &&TARGET_CALL_FUNCTION_LEN,
-    &&TARGET_CALL_FUNCTION_ISINSTANCE,
-    &&TARGET_CALL_FUNCTION_PY_SIMPLE,
-    &&TARGET_JUMP_ABSOLUTE_QUICK,
-    &&TARGET_LOAD_ATTR_ADAPTIVE,
-    &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
+    &&TARGET_CALL_NO_KW_ADAPTIVE,
+    &&TARGET_CALL_NO_KW_BUILTIN_O,
+    &&TARGET_CALL_NO_KW_BUILTIN_FAST,
+    &&TARGET_CALL_NO_KW_LEN,
+    &&TARGET_CALL_NO_KW_ISINSTANCE,
+    &&TARGET_CALL_NO_KW_PY_SIMPLE,
+    &&TARGET_CALL_NO_KW_LIST_APPEND,
+    &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
+    &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
     &&TARGET_WITH_EXCEPT_START,
     &&TARGET_GET_AITER,
     &&TARGET_GET_ANEXT,
     &&TARGET_BEFORE_ASYNC_WITH,
     &&TARGET_BEFORE_WITH,
     &&TARGET_END_ASYNC_FOR,
+    &&TARGET_JUMP_ABSOLUTE_QUICK,
+    &&TARGET_LOAD_ATTR_ADAPTIVE,
+    &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
     &&TARGET_LOAD_ATTR_WITH_HINT,
     &&TARGET_LOAD_ATTR_SLOT,
+    &&TARGET_STORE_SUBSCR,
+    &&TARGET_DELETE_SUBSCR,
     &&TARGET_LOAD_ATTR_MODULE,
     &&TARGET_LOAD_GLOBAL_ADAPTIVE,
     &&TARGET_LOAD_GLOBAL_MODULE,
-    &&TARGET_STORE_SUBSCR,
-    &&TARGET_DELETE_SUBSCR,
     &&TARGET_LOAD_GLOBAL_BUILTIN,
     &&TARGET_LOAD_METHOD_ADAPTIVE,
     &&TARGET_LOAD_METHOD_CACHED,
-    &&TARGET_LOAD_METHOD_CLASS,
-    &&TARGET_LOAD_METHOD_MODULE,
-    &&TARGET_LOAD_METHOD_NO_DICT,
     &&TARGET_GET_ITER,
     &&TARGET_GET_YIELD_FROM_ITER,
     &&TARGET_PRINT_EXPR,
@@ -74,19 +74,19 @@ static void *opcode_targets[256] = {
     &&TARGET_YIELD_FROM,
     &&TARGET_GET_AWAITABLE,
     &&TARGET_LOAD_ASSERTION_ERROR,
+    &&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_LIST_TO_TUPLE,
     &&TARGET_RETURN_VALUE,
     &&TARGET_IMPORT_STAR,
     &&TARGET_SETUP_ANNOTATIONS,
     &&TARGET_YIELD_VALUE,
-    &&TARGET_LOAD_CONST__LOAD_FAST,
+    &&TARGET_LOAD_FAST__LOAD_FAST,
     &&TARGET_PREP_RERAISE_STAR,
     &&TARGET_POP_EXCEPT,
     &&TARGET_STORE_NAME,
@@ -122,25 +122,25 @@ static void *opcode_targets[256] = {
     &&TARGET_COPY,
     &&TARGET_JUMP_IF_NOT_EXC_MATCH,
     &&TARGET_BINARY_OP,
-    &&TARGET_STORE_FAST__STORE_FAST,
+    &&TARGET_STORE_FAST__LOAD_FAST,
     &&TARGET_LOAD_FAST,
     &&TARGET_STORE_FAST,
     &&TARGET_DELETE_FAST,
     &&TARGET_JUMP_IF_NOT_EG_MATCH,
-    &&_unknown_opcode,
+    &&TARGET_LOAD_FAST__LOAD_CONST,
     &&TARGET_GEN_START,
     &&TARGET_RAISE_VARARGS,
-    &&TARGET_CALL_FUNCTION,
+    &&TARGET_LOAD_CONST__LOAD_FAST,
     &&TARGET_MAKE_FUNCTION,
     &&TARGET_BUILD_SLICE,
-    &&_unknown_opcode,
+    &&TARGET_STORE_FAST__STORE_FAST,
     &&TARGET_MAKE_CELL,
     &&TARGET_LOAD_CLOSURE,
     &&TARGET_LOAD_DEREF,
     &&TARGET_STORE_DEREF,
     &&TARGET_DELETE_DEREF,
     &&_unknown_opcode,
-    &&TARGET_CALL_FUNCTION_KW,
+    &&_unknown_opcode,
     &&TARGET_CALL_FUNCTION_EX,
     &&_unknown_opcode,
     &&TARGET_EXTENDED_ARG,
@@ -160,16 +160,16 @@ static void *opcode_targets[256] = {
     &&_unknown_opcode,
     &&_unknown_opcode,
     &&TARGET_LOAD_METHOD,
-    &&TARGET_CALL_METHOD,
+    &&_unknown_opcode,
     &&TARGET_LIST_EXTEND,
     &&TARGET_SET_UPDATE,
     &&TARGET_DICT_MERGE,
     &&TARGET_DICT_UPDATE,
-    &&TARGET_CALL_METHOD_KW,
-    &&_unknown_opcode,
-    &&_unknown_opcode,
     &&_unknown_opcode,
     &&_unknown_opcode,
+    &&TARGET_PRECALL_METHOD,
+    &&TARGET_CALL_NO_KW,
+    &&TARGET_CALL_KW,
     &&_unknown_opcode,
     &&_unknown_opcode,
     &&_unknown_opcode,
index 5121845008100832e83a0e5efdefa184c746975a..bdcba46ed4d311e124b9ff1a7e39aa94eabf26a0 100644 (file)
@@ -127,7 +127,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_FUNCTION, "call_function");
+    err += add_stat_dict(stats, CALL_NO_KW, "call_no_kw");
     err += add_stat_dict(stats, BINARY_OP, "binary_op");
     err += add_stat_dict(stats, COMPARE_OP, "compare_op");
     if (err < 0) {
@@ -186,7 +186,7 @@ _Py_PrintSpecializationStats(void)
     print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr");
     print_stats(out, &_specialization_stats[STORE_SUBSCR], "store_subscr");
     print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr");
-    print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function");
+    print_stats(out, &_specialization_stats[CALL_NO_KW], "call_no_kw");
     print_stats(out, &_specialization_stats[BINARY_OP], "binary_op");
     print_stats(out, &_specialization_stats[COMPARE_OP], "compare_op");
     if (out != stderr) {
@@ -238,7 +238,7 @@ static uint8_t adaptive_opcodes[256] = {
     [LOAD_METHOD] = LOAD_METHOD_ADAPTIVE,
     [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
     [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE,
-    [CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE,
+    [CALL_NO_KW] = CALL_NO_KW_ADAPTIVE,
     [STORE_ATTR] = STORE_ATTR_ADAPTIVE,
     [BINARY_OP] = BINARY_OP_ADAPTIVE,
     [COMPARE_OP] = COMPARE_OP_ADAPTIVE,
@@ -251,7 +251,7 @@ static uint8_t cache_requirements[256] = {
     [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
     [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */
     [STORE_SUBSCR] = 0,
-    [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
+    [CALL_NO_KW] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
     [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
     [BINARY_OP] = 1,  // _PyAdaptiveEntry
     [COMPARE_OP] = 1, /* _PyAdaptiveEntry */
@@ -491,6 +491,8 @@ initial_counter_value(void) {
 #define SPEC_FAIL_PYCFUNCTION_NOARGS 16
 #define SPEC_FAIL_BAD_CALL_FLAGS 17
 #define SPEC_FAIL_CLASS 18
+#define SPEC_FAIL_C_METHOD_CALL 19
+#define SPEC_FAIL_METHDESCR_NON_METHOD 20
 
 /* COMPARE_OP */
 #define SPEC_FAIL_STRING_COMPARE 13
@@ -1261,7 +1263,51 @@ specialize_class_call(
     PyObject *callable, _Py_CODEUNIT *instr,
     int nargs, SpecializedCacheEntry *cache)
 {
-    SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_CLASS);
+    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;
+            }
+            *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_NO_KW, SPEC_FAIL_OTHER);
     return -1;
 }
 
@@ -1274,15 +1320,19 @@ specialize_py_call(
     PyCodeObject *code = (PyCodeObject *)func->func_code;
     int kind = function_kind(code);
     if (kind != SIMPLE_FUNCTION) {
-        SPECIALIZATION_FAIL(CALL_FUNCTION, kind);
+        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_FUNCTION, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
+        SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
         return -1;
     }
     assert(nargs <= argcount && nargs >= min_args);
@@ -1291,18 +1341,19 @@ specialize_py_call(
     assert(defstart >= 0 && deflen >= 0);
     assert(deflen == 0 || func->func_defaults != NULL);
     if (defstart > 0xffff || deflen > 0xffff) {
-        SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_RANGE);
+        SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
         return -1;
     }
     int version = _PyFunction_GetVersionForCurrentState(func);
     if (version == 0) {
-        SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_VERSIONS);
+        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_FUNCTION_PY_SIMPLE, _Py_OPARG(*instr));
+    *instr = _Py_MAKECODEUNIT(CALL_NO_KW_PY_SIMPLE, _Py_OPARG(*instr));
     return 0;
 }
 
@@ -1335,6 +1386,10 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
     SpecializedCacheEntry *cache, PyObject *builtins)
 {
     _PyObjectCache *cache1 = &cache[-1].obj;
+    if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) {
+        SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_C_METHOD_CALL);
+        return -1;
+    }
     if (PyCFunction_GET_FUNCTION(callable) == NULL) {
         return 1;
     }
@@ -1343,18 +1398,18 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
         METH_KEYWORDS | METH_METHOD)) {
         case METH_O: {
             if (nargs != 1) {
-                SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_RANGE);
+                SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE);
                 return 1;
             }
             /* len(o) */
             PyObject *builtin_len = PyDict_GetItemString(builtins, "len");
             if (callable == builtin_len) {
                 cache1->obj = builtin_len;  // borrowed
-                *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_LEN,
+                *instr = _Py_MAKECODEUNIT(CALL_NO_KW_LEN,
                     _Py_OPARG(*instr));
                 return 0;
             }
-            *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_BUILTIN_O,
+            *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_O,
                 _Py_OPARG(*instr));
             return 0;
         }
@@ -1365,17 +1420,17 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
                     builtins, "isinstance");
                 if (callable == builtin_isinstance) {
                     cache1->obj = builtin_isinstance;  // borrowed
-                    *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_ISINSTANCE,
+                    *instr = _Py_MAKECODEUNIT(CALL_NO_KW_ISINSTANCE,
                         _Py_OPARG(*instr));
                     return 0;
                 }
             }
-            *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_BUILTIN_FAST,
+            *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_FAST,
                 _Py_OPARG(*instr));
             return 0;
         }
         default:
-            SPECIALIZATION_FAIL(CALL_FUNCTION,
+            SPECIALIZATION_FAIL(CALL_NO_KW,
                 builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable)));
             return 1;
     }
@@ -1406,7 +1461,7 @@ call_fail_kind(PyObject *callable)
     - Specialize calling classes.
 */
 int
-_Py_Specialize_CallFunction(
+_Py_Specialize_CallNoKw(
     PyObject *callable, _Py_CODEUNIT *instr,
     int nargs, SpecializedCacheEntry *cache,
     PyObject *builtins)
@@ -1421,18 +1476,22 @@ _Py_Specialize_CallFunction(
     else if (PyType_Check(callable)) {
         fail = specialize_class_call(callable, instr, nargs, cache);
     }
+    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
+        fail = specialize_method_descriptor(
+            (PyMethodDescrObject *)callable, instr, nargs, cache);
+    }
     else {
-        SPECIALIZATION_FAIL(CALL_FUNCTION, call_fail_kind(callable));
+        SPECIALIZATION_FAIL(CALL_NO_KW, call_fail_kind(callable));
         fail = -1;
     }
     _PyAdaptiveEntry *cache0 = &cache->adaptive;
     if (fail) {
-        STAT_INC(CALL_FUNCTION, specialization_failure);
+        STAT_INC(CALL_NO_KW, specialization_failure);
         assert(!PyErr_Occurred());
         cache_backoff(cache0);
     }
     else {
-        STAT_INC(CALL_FUNCTION, specialization_success);
+        STAT_INC(CALL_NO_KW, specialization_success);
         assert(!PyErr_Occurred());
         cache0->counter = initial_counter_value();
     }