From 96f65835f8f66d058b444e0b4e436af45e2902f7 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 19 May 2022 11:42:43 +0900 Subject: [PATCH 01/19] gh-87901: Remove the encoding argument from os.popen (GH-92836) --- Doc/library/os.rst | 13 +++++++++---- Lib/os.py | 5 ++--- .../2022-05-18-21-04-09.gh-issue-87901.lnf041.rst | 2 ++ 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-05-18-21-04-09.gh-issue-87901.lnf041.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 3c189bb40e234c..dc0f2e4158ac0e 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3916,13 +3916,13 @@ written in Python, such as a mail server's external command delivery program. .. availability:: Unix. -.. function:: popen(cmd, mode='r', buffering=-1, encoding=None) +.. function:: popen(cmd, mode='r', buffering=-1) Open a pipe to or from command *cmd*. The return value is an open file object connected to the pipe, which can be read or written depending on whether *mode* is ``'r'`` (default) or ``'w'``. - The *buffering* and *encoding* arguments have the same meaning as + The *buffering* argument have the same meaning as the corresponding argument to the built-in :func:`open` function. The returned file object reads or writes text strings rather than bytes. @@ -3945,8 +3945,13 @@ written in Python, such as a mail server's external command delivery program. documentation for more powerful ways to manage and communicate with subprocesses. - .. versionchanged:: 3.11 - Added the *encoding* parameter. + .. note:: + The :ref:`Python UTF-8 Mode ` affects encodings used + for *cmd* and pipe contents. + + :func:`popen` is a simple wrapper around :class:`subprocess.Popen`. + Use :class:`subprocess.Popen` or :func:`subprocess.run` to + control options like encodings. .. function:: posix_spawn(path, argv, env, *, file_actions=None, \ diff --git a/Lib/os.py b/Lib/os.py index 67662ca7ad8588..648188e0f13490 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -974,15 +974,14 @@ def spawnlpe(mode, file, *args): # command in a shell can't be supported. if sys.platform != 'vxworks': # Supply os.popen() - def popen(cmd, mode="r", buffering=-1, encoding=None): + def popen(cmd, mode="r", buffering=-1): if not isinstance(cmd, str): raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) if mode not in ("r", "w"): raise ValueError("invalid mode %r" % mode) if buffering == 0 or buffering is None: raise ValueError("popen() does not support unbuffered streams") - import subprocess, io - encoding = io.text_encoding(encoding) + import subprocess if mode == "r": proc = subprocess.Popen(cmd, shell=True, text=True, diff --git a/Misc/NEWS.d/next/Library/2022-05-18-21-04-09.gh-issue-87901.lnf041.rst b/Misc/NEWS.d/next/Library/2022-05-18-21-04-09.gh-issue-87901.lnf041.rst new file mode 100644 index 00000000000000..3488541eb3d77c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-18-21-04-09.gh-issue-87901.lnf041.rst @@ -0,0 +1,2 @@ +Removed the ``encoding`` argument from :func:`os.popen` that was added in +3.11b1. From 8a6af5a34642f5564220eb50d72caada8f17fc78 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 19 May 2022 08:43:50 +0300 Subject: [PATCH 02/19] gh-92914: Round the allocated size for lists up to the even number (GH-92915) --- Lib/test/test_sys.py | 7 ++++--- .../2022-05-18-08-32-33.gh-issue-92914.tJUeTD.rst | 1 + Objects/listobject.c | 6 ++++++ 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-18-08-32-33.gh-issue-92914.tJUeTD.rst diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 9c0f4a69289d2e..94a09ff549331a 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1432,9 +1432,10 @@ def get_gen(): yield 1 import re check(re.finditer('',''), size('2P')) # list - samples = [[], [1,2,3], ['1', '2', '3']] - for sample in samples: - check(list(sample), vsize('Pn') + len(sample)*self.P) + check(list([]), vsize('Pn')) + check(list([1]), vsize('Pn') + 2*self.P) + check(list([1, 2]), vsize('Pn') + 2*self.P) + check(list([1, 2, 3]), vsize('Pn') + 4*self.P) # sortwrapper (list) # XXX # cmpwrapper (list) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-18-08-32-33.gh-issue-92914.tJUeTD.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-18-08-32-33.gh-issue-92914.tJUeTD.rst new file mode 100644 index 00000000000000..1242a15c029dc1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-18-08-32-33.gh-issue-92914.tJUeTD.rst @@ -0,0 +1 @@ +Always round the allocated size for lists up to the nearest even number. diff --git a/Objects/listobject.c b/Objects/listobject.c index b50623ed73d940..0a99ec919b8c87 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -94,6 +94,12 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size) assert(self->ob_item == NULL); assert(size > 0); + /* Since the Python memory allocator has granularity of 16 bytes on 64-bit + * platforms (8 on 32-bit), there is no benefit of allocating space for + * the odd number of items, and there is no drawback of rounding the + * allocated size up to the nearest even number. + */ + size = (size + 1) & ~(size_t)1; PyObject **items = PyMem_New(PyObject*, size); if (items == NULL) { PyErr_NoMemory(); From 60ee61571a60bcf4e40a4074e8db356b5af793c1 Mon Sep 17 00:00:00 2001 From: Duprat Date: Thu, 19 May 2022 09:12:33 +0200 Subject: [PATCH 03/19] Include ``asyncio.Barrier`` in 3.11 Whats New (GH-92927) --- Doc/whatsnew/3.11.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 97dd096731f0c3..0cbb0ba77217f6 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -431,6 +431,10 @@ asyncio existing stream-based connections to TLS. (Contributed by Ian Good in :issue:`34975`.) +* Add :class:`~asyncio.Barrier` class to the synchronization primitives of + the asyncio library. (Contributed by Yves Duprat and Andrew Svetlov in + :gh:`87518`.) + datetime -------- From 654032ac5f6982b36d45e024037f37fb65166aed Mon Sep 17 00:00:00 2001 From: Ayappan Perumal Date: Thu, 19 May 2022 14:47:44 +0530 Subject: [PATCH 04/19] gh-92670: Skip test_shutil.TestCopy.test_copyfile_nonexistent_dir on AIX (#92718) --- Lib/test/test_shutil.py | 4 ++++ .../next/Tests/2022-05-12-05-51-06.gh-issue-92670.7L43Z_.rst | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Tests/2022-05-12-05-51-06.gh-issue-92670.7L43Z_.rst diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 70033863452805..a61bb126e4e73f 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1294,6 +1294,10 @@ def test_copyfile_same_file(self): self.assertEqual(read_file(src_file), 'foo') @unittest.skipIf(MACOS or SOLARIS or _winapi, 'On MACOS, Solaris and Windows the errors are not confusing (though different)') + # gh-92670: The test uses a trailing slash to force the OS consider + # the path as a directory, but on AIX the trailing slash has no effect + # and is considered as a file. + @unittest.skipIf(AIX, 'Not valid on AIX, see gh-92670') def test_copyfile_nonexistent_dir(self): # Issue 43219 src_dir = self.mkdtemp() diff --git a/Misc/NEWS.d/next/Tests/2022-05-12-05-51-06.gh-issue-92670.7L43Z_.rst b/Misc/NEWS.d/next/Tests/2022-05-12-05-51-06.gh-issue-92670.7L43Z_.rst new file mode 100644 index 00000000000000..c1349519e7c37c --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-05-12-05-51-06.gh-issue-92670.7L43Z_.rst @@ -0,0 +1,3 @@ +Skip ``test_shutil.TestCopy.test_copyfile_nonexistent_dir`` test on AIX as the test uses a trailing +slash to force the OS consider the path as a directory, but on AIX the +trailing slash has no effect and is considered as a file. From 41638967a0e0bf1114c9bba9454d081605b49009 Mon Sep 17 00:00:00 2001 From: Jan Brasna <1784648+janbrasna@users.noreply.github.com> Date: Thu, 19 May 2022 11:22:16 +0200 Subject: [PATCH 05/19] Doc: amend ssl.PROTOCOL_SSLv2 and ssl.PROTOCOL_SSLv3 wording (#92634) --- Doc/library/ssl.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 54bd335282699c..c7ca4395ed96c9 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -714,7 +714,7 @@ Constants Selects SSL version 2 as the channel encryption protocol. This protocol is not available if OpenSSL is compiled with the - ``OPENSSL_NO_SSL2`` flag. + ``no-ssl2`` option. .. warning:: @@ -728,8 +728,8 @@ Constants Selects SSL version 3 as the channel encryption protocol. - This protocol is not be available if OpenSSL is compiled with the - ``OPENSSL_NO_SSLv3`` flag. + This protocol is not available if OpenSSL is compiled with the + ``no-ssl3`` option. .. warning:: From e48ac9c1003c3816198cbfb6132a995150f9b048 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 19 May 2022 11:05:26 +0100 Subject: [PATCH 06/19] GH-90690: Remove `PRECALL` instruction (GH-92925) --- Doc/library/dis.rst | 17 +- Include/internal/pycore_code.h | 8 - Include/internal/pycore_opcode.h | 172 +++++---- Include/opcode.h | 107 +++--- Lib/importlib/_bootstrap_external.py | 8 +- Lib/opcode.py | 38 +- Lib/test/test_compile.py | 2 +- Lib/test/test_dis.py | 331 ++++++++---------- ...2-05-18-12-55-35.gh-issue-90690.TKuoTa.rst | 2 + Programs/test_frozenmain.h | 40 +-- Python/ceval.c | 271 ++++++-------- Python/compile.c | 11 +- Python/opcode_targets.h | 102 +++--- Python/specialize.c | 136 +++---- 14 files changed, 544 insertions(+), 701 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-18-12-55-35.gh-issue-90690.TKuoTa.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 08e6c736d3e3c9..027db0153bea40 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -45,9 +45,8 @@ the following command can be used to display the disassembly of 2 2 PUSH_NULL 4 LOAD_GLOBAL 1 (NULL + len) 6 LOAD_FAST 0 (alist) - 8 PRECALL 1 - 10 CALL 1 - 12 RETURN_VALUE + 8 CALL 1 + 18 RETURN_VALUE (The "2" is a line number). @@ -119,7 +118,6 @@ Example:: PUSH_NULL LOAD_GLOBAL LOAD_FAST - PRECALL CALL RETURN_VALUE @@ -1182,15 +1180,6 @@ iterations of the loop. .. versionadded:: 3.7 -.. opcode:: PRECALL (argc) - - 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:: PUSH_NULL Pushes a ``NULL`` to the stack. @@ -1202,7 +1191,7 @@ iterations of the loop. .. opcode:: KW_NAMES (i) - Prefixes :opcode:`PRECALL`. + Prefixes :opcode:`CALL`. 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. diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 96cc9dcae11a71..3d198432741129 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -80,12 +80,6 @@ typedef struct { #define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache) -typedef struct { - _Py_CODEUNIT counter; -} _PyPrecallCache; - -#define INLINE_CACHE_ENTRIES_PRECALL CACHE_ENTRIES(_PyPrecallCache) - typedef struct { _Py_CODEUNIT counter; } _PyStoreSubscrCache; @@ -249,8 +243,6 @@ extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_C extern int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr); extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames); -extern int _Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, - int nargs, PyObject *kwnames, int oparg); extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg, PyObject **locals); extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 09f65014671338..17a68f030b0842 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -50,7 +50,6 @@ const uint8_t _PyOpcode_Caches[256] = { [LOAD_GLOBAL] = 5, [BINARY_OP] = 1, [LOAD_METHOD] = 10, - [PRECALL] = 1, [CALL] = 4, }; @@ -84,7 +83,22 @@ const uint8_t _PyOpcode_Deopt[256] = { [CACHE] = CACHE, [CALL] = CALL, [CALL_ADAPTIVE] = CALL, + [CALL_BOUND_METHOD_EXACT_ARGS] = CALL, + [CALL_BUILTIN_CLASS] = CALL, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL, [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL, + [CALL_NO_KW_BUILTIN_FAST] = CALL, + [CALL_NO_KW_BUILTIN_O] = CALL, + [CALL_NO_KW_ISINSTANCE] = CALL, + [CALL_NO_KW_LEN] = CALL, + [CALL_NO_KW_LIST_APPEND] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_O] = CALL, + [CALL_NO_KW_STR_1] = CALL, + [CALL_NO_KW_TUPLE_1] = CALL, + [CALL_NO_KW_TYPE_1] = CALL, [CALL_PY_EXACT_ARGS] = CALL, [CALL_PY_WITH_DEFAULTS] = CALL, [CHECK_EG_MATCH] = CHECK_EG_MATCH, @@ -176,24 +190,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE, [POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE, [POP_TOP] = POP_TOP, - [PRECALL] = PRECALL, - [PRECALL_ADAPTIVE] = PRECALL, - [PRECALL_BOUND_METHOD] = PRECALL, - [PRECALL_BUILTIN_CLASS] = PRECALL, - [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = PRECALL, - [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = PRECALL, - [PRECALL_NO_KW_BUILTIN_FAST] = PRECALL, - [PRECALL_NO_KW_BUILTIN_O] = PRECALL, - [PRECALL_NO_KW_ISINSTANCE] = PRECALL, - [PRECALL_NO_KW_LEN] = PRECALL, - [PRECALL_NO_KW_LIST_APPEND] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = PRECALL, - [PRECALL_NO_KW_STR_1] = PRECALL, - [PRECALL_NO_KW_TUPLE_1] = PRECALL, - [PRECALL_NO_KW_TYPE_1] = PRECALL, - [PRECALL_PYFUNC] = PRECALL, [PREP_RERAISE_STAR] = PREP_RERAISE_STAR, [PRINT_EXPR] = PRINT_EXPR, [PUSH_EXC_INFO] = PUSH_EXC_INFO, @@ -268,7 +264,22 @@ const uint8_t _PyOpcode_Original[256] = { [CACHE] = CACHE, [CALL] = CALL, [CALL_ADAPTIVE] = CALL, + [CALL_BOUND_METHOD_EXACT_ARGS] = CALL, + [CALL_BUILTIN_CLASS] = CALL, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL, [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL, + [CALL_NO_KW_BUILTIN_FAST] = CALL, + [CALL_NO_KW_BUILTIN_O] = CALL, + [CALL_NO_KW_ISINSTANCE] = CALL, + [CALL_NO_KW_LEN] = CALL, + [CALL_NO_KW_LIST_APPEND] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = CALL, + [CALL_NO_KW_METHOD_DESCRIPTOR_O] = CALL, + [CALL_NO_KW_STR_1] = CALL, + [CALL_NO_KW_TUPLE_1] = CALL, + [CALL_NO_KW_TYPE_1] = CALL, [CALL_PY_EXACT_ARGS] = CALL, [CALL_PY_WITH_DEFAULTS] = CALL, [CHECK_EG_MATCH] = CHECK_EG_MATCH, @@ -360,24 +371,6 @@ const uint8_t _PyOpcode_Original[256] = { [POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE, [POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE, [POP_TOP] = POP_TOP, - [PRECALL] = PRECALL, - [PRECALL_ADAPTIVE] = PRECALL, - [PRECALL_BOUND_METHOD] = PRECALL, - [PRECALL_BUILTIN_CLASS] = PRECALL, - [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = PRECALL, - [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = PRECALL, - [PRECALL_NO_KW_BUILTIN_FAST] = PRECALL, - [PRECALL_NO_KW_BUILTIN_O] = PRECALL, - [PRECALL_NO_KW_ISINSTANCE] = PRECALL, - [PRECALL_NO_KW_LEN] = PRECALL, - [PRECALL_NO_KW_LIST_APPEND] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = PRECALL, - [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = PRECALL, - [PRECALL_NO_KW_STR_1] = PRECALL, - [PRECALL_NO_KW_TUPLE_1] = PRECALL, - [PRECALL_NO_KW_TYPE_1] = PRECALL, - [PRECALL_PYFUNC] = PRECALL, [PREP_RERAISE_STAR] = PREP_RERAISE_STAR, [PRINT_EXPR] = PRINT_EXPR, [PUSH_EXC_INFO] = PUSH_EXC_INFO, @@ -451,62 +444,62 @@ static const char *const _PyOpcode_OpName[256] = { [CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS", [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS", [BINARY_SUBSCR] = "BINARY_SUBSCR", - [COMPARE_OP_ADAPTIVE] = "COMPARE_OP_ADAPTIVE", - [COMPARE_OP_FLOAT_JUMP] = "COMPARE_OP_FLOAT_JUMP", - [COMPARE_OP_INT_JUMP] = "COMPARE_OP_INT_JUMP", - [COMPARE_OP_STR_JUMP] = "COMPARE_OP_STR_JUMP", + [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS", + [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS", + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS", + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", [GET_LEN] = "GET_LEN", [MATCH_MAPPING] = "MATCH_MAPPING", [MATCH_SEQUENCE] = "MATCH_SEQUENCE", [MATCH_KEYS] = "MATCH_KEYS", - [EXTENDED_ARG_QUICK] = "EXTENDED_ARG_QUICK", + [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST", [PUSH_EXC_INFO] = "PUSH_EXC_INFO", [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH", [CHECK_EG_MATCH] = "CHECK_EG_MATCH", + [CALL_NO_KW_BUILTIN_O] = "CALL_NO_KW_BUILTIN_O", + [CALL_NO_KW_ISINSTANCE] = "CALL_NO_KW_ISINSTANCE", + [CALL_NO_KW_LEN] = "CALL_NO_KW_LEN", + [CALL_NO_KW_LIST_APPEND] = "CALL_NO_KW_LIST_APPEND", + [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", + [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", + [CALL_NO_KW_METHOD_DESCRIPTOR_O] = "CALL_NO_KW_METHOD_DESCRIPTOR_O", + [CALL_NO_KW_STR_1] = "CALL_NO_KW_STR_1", + [CALL_NO_KW_TUPLE_1] = "CALL_NO_KW_TUPLE_1", + [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1", + [COMPARE_OP_ADAPTIVE] = "COMPARE_OP_ADAPTIVE", + [WITH_EXCEPT_START] = "WITH_EXCEPT_START", + [GET_AITER] = "GET_AITER", + [GET_ANEXT] = "GET_ANEXT", + [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", + [BEFORE_WITH] = "BEFORE_WITH", + [END_ASYNC_FOR] = "END_ASYNC_FOR", + [COMPARE_OP_FLOAT_JUMP] = "COMPARE_OP_FLOAT_JUMP", + [COMPARE_OP_INT_JUMP] = "COMPARE_OP_INT_JUMP", + [COMPARE_OP_STR_JUMP] = "COMPARE_OP_STR_JUMP", + [EXTENDED_ARG_QUICK] = "EXTENDED_ARG_QUICK", [JUMP_BACKWARD_QUICK] = "JUMP_BACKWARD_QUICK", + [STORE_SUBSCR] = "STORE_SUBSCR", + [DELETE_SUBSCR] = "DELETE_SUBSCR", [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", + [GET_ITER] = "GET_ITER", + [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", + [PRINT_EXPR] = "PRINT_EXPR", + [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", + [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", + [RETURN_GENERATOR] = "RETURN_GENERATOR", [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", - [WITH_EXCEPT_START] = "WITH_EXCEPT_START", - [GET_AITER] = "GET_AITER", - [GET_ANEXT] = "GET_ANEXT", - [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", - [BEFORE_WITH] = "BEFORE_WITH", - [END_ASYNC_FOR] = "END_ASYNC_FOR", [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [LOAD_METHOD_ADAPTIVE] = "LOAD_METHOD_ADAPTIVE", [LOAD_METHOD_CLASS] = "LOAD_METHOD_CLASS", [LOAD_METHOD_MODULE] = "LOAD_METHOD_MODULE", - [LOAD_METHOD_NO_DICT] = "LOAD_METHOD_NO_DICT", - [STORE_SUBSCR] = "STORE_SUBSCR", - [DELETE_SUBSCR] = "DELETE_SUBSCR", - [LOAD_METHOD_WITH_DICT] = "LOAD_METHOD_WITH_DICT", - [LOAD_METHOD_WITH_VALUES] = "LOAD_METHOD_WITH_VALUES", - [PRECALL_ADAPTIVE] = "PRECALL_ADAPTIVE", - [PRECALL_BOUND_METHOD] = "PRECALL_BOUND_METHOD", - [PRECALL_BUILTIN_CLASS] = "PRECALL_BUILTIN_CLASS", - [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = "PRECALL_BUILTIN_FAST_WITH_KEYWORDS", - [GET_ITER] = "GET_ITER", - [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", - [PRINT_EXPR] = "PRINT_EXPR", - [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", - [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - [PRECALL_NO_KW_BUILTIN_FAST] = "PRECALL_NO_KW_BUILTIN_FAST", - [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", - [RETURN_GENERATOR] = "RETURN_GENERATOR", - [PRECALL_NO_KW_BUILTIN_O] = "PRECALL_NO_KW_BUILTIN_O", - [PRECALL_NO_KW_ISINSTANCE] = "PRECALL_NO_KW_ISINSTANCE", - [PRECALL_NO_KW_LEN] = "PRECALL_NO_KW_LEN", - [PRECALL_NO_KW_LIST_APPEND] = "PRECALL_NO_KW_LIST_APPEND", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", [LIST_TO_TUPLE] = "LIST_TO_TUPLE", [RETURN_VALUE] = "RETURN_VALUE", [IMPORT_STAR] = "IMPORT_STAR", @@ -538,7 +531,7 @@ static const char *const _PyOpcode_OpName[256] = { [JUMP_FORWARD] = "JUMP_FORWARD", [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_O", + [LOAD_METHOD_NO_DICT] = "LOAD_METHOD_NO_DICT", [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", @@ -546,13 +539,13 @@ static const char *const _PyOpcode_OpName[256] = { [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [PRECALL_NO_KW_STR_1] = "PRECALL_NO_KW_STR_1", + [LOAD_METHOD_WITH_DICT] = "LOAD_METHOD_WITH_DICT", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", [STORE_FAST] = "STORE_FAST", [DELETE_FAST] = "DELETE_FAST", - [PRECALL_NO_KW_TUPLE_1] = "PRECALL_NO_KW_TUPLE_1", + [LOAD_METHOD_WITH_VALUES] = "LOAD_METHOD_WITH_VALUES", [POP_JUMP_FORWARD_IF_NOT_NONE] = "POP_JUMP_FORWARD_IF_NOT_NONE", [POP_JUMP_FORWARD_IF_NONE] = "POP_JUMP_FORWARD_IF_NONE", [RAISE_VARARGS] = "RAISE_VARARGS", @@ -566,46 +559,46 @@ static const char *const _PyOpcode_OpName[256] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [PRECALL_NO_KW_TYPE_1] = "PRECALL_NO_KW_TYPE_1", + [RESUME_QUICK] = "RESUME_QUICK", [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [PRECALL_PYFUNC] = "PRECALL_PYFUNC", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", [MAP_ADD] = "MAP_ADD", [LOAD_CLASSDEREF] = "LOAD_CLASSDEREF", [COPY_FREE_VARS] = "COPY_FREE_VARS", - [RESUME_QUICK] = "RESUME_QUICK", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", + [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", - [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", - [LOAD_METHOD] = "LOAD_METHOD", [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [LOAD_METHOD] = "LOAD_METHOD", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", - [PRECALL] = "PRECALL", - [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", - [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", + [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", + [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", + [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", - [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", - [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", - [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", + [178] = "<178>", + [179] = "<179>", + [180] = "<180>", [181] = "<181>", [182] = "<182>", [183] = "<183>", @@ -685,6 +678,9 @@ static const char *const _PyOpcode_OpName[256] = { #endif #define EXTRA_CASES \ + case 178: \ + case 179: \ + case 180: \ case 181: \ case 182: \ case 183: \ diff --git a/Include/opcode.h b/Include/opcode.h index 084d34b8c73cd5..9a076e01c6530b 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -112,7 +112,6 @@ extern "C" { #define SET_UPDATE 163 #define DICT_MERGE 164 #define DICT_UPDATE 165 -#define PRECALL 166 #define CALL 171 #define KW_NAMES 172 #define POP_JUMP_BACKWARD_IF_NOT_NONE 173 @@ -136,60 +135,58 @@ extern "C" { #define CALL_ADAPTIVE 22 #define CALL_PY_EXACT_ARGS 23 #define CALL_PY_WITH_DEFAULTS 24 -#define COMPARE_OP_ADAPTIVE 26 -#define COMPARE_OP_FLOAT_JUMP 27 -#define COMPARE_OP_INT_JUMP 28 -#define COMPARE_OP_STR_JUMP 29 -#define EXTENDED_ARG_QUICK 34 -#define JUMP_BACKWARD_QUICK 38 -#define LOAD_ATTR_ADAPTIVE 39 -#define LOAD_ATTR_INSTANCE_VALUE 40 -#define LOAD_ATTR_MODULE 41 -#define LOAD_ATTR_SLOT 42 -#define LOAD_ATTR_WITH_HINT 43 -#define LOAD_CONST__LOAD_FAST 44 -#define LOAD_FAST__LOAD_CONST 45 -#define LOAD_FAST__LOAD_FAST 46 -#define LOAD_GLOBAL_ADAPTIVE 47 -#define LOAD_GLOBAL_BUILTIN 48 -#define LOAD_GLOBAL_MODULE 55 -#define LOAD_METHOD_ADAPTIVE 56 -#define LOAD_METHOD_CLASS 57 -#define LOAD_METHOD_MODULE 58 -#define LOAD_METHOD_NO_DICT 59 -#define LOAD_METHOD_WITH_DICT 62 -#define LOAD_METHOD_WITH_VALUES 63 -#define PRECALL_ADAPTIVE 64 -#define PRECALL_BOUND_METHOD 65 -#define PRECALL_BUILTIN_CLASS 66 -#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 67 -#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 72 -#define PRECALL_NO_KW_BUILTIN_FAST 73 -#define PRECALL_NO_KW_BUILTIN_O 76 -#define PRECALL_NO_KW_ISINSTANCE 77 -#define PRECALL_NO_KW_LEN 78 -#define PRECALL_NO_KW_LIST_APPEND 79 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 80 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 81 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 113 -#define PRECALL_NO_KW_STR_1 121 -#define PRECALL_NO_KW_TUPLE_1 127 -#define PRECALL_NO_KW_TYPE_1 141 -#define PRECALL_PYFUNC 143 -#define RESUME_QUICK 150 -#define STORE_ATTR_ADAPTIVE 153 -#define STORE_ATTR_INSTANCE_VALUE 154 -#define STORE_ATTR_SLOT 158 -#define STORE_ATTR_WITH_HINT 159 -#define STORE_FAST__LOAD_FAST 161 -#define STORE_FAST__STORE_FAST 167 -#define STORE_SUBSCR_ADAPTIVE 168 -#define STORE_SUBSCR_DICT 169 -#define STORE_SUBSCR_LIST_INT 170 -#define UNPACK_SEQUENCE_ADAPTIVE 177 -#define UNPACK_SEQUENCE_LIST 178 -#define UNPACK_SEQUENCE_TUPLE 179 -#define UNPACK_SEQUENCE_TWO_TUPLE 180 +#define CALL_BOUND_METHOD_EXACT_ARGS 26 +#define CALL_BUILTIN_CLASS 27 +#define CALL_BUILTIN_FAST_WITH_KEYWORDS 28 +#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 29 +#define CALL_NO_KW_BUILTIN_FAST 34 +#define CALL_NO_KW_BUILTIN_O 38 +#define CALL_NO_KW_ISINSTANCE 39 +#define CALL_NO_KW_LEN 40 +#define CALL_NO_KW_LIST_APPEND 41 +#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 42 +#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 43 +#define CALL_NO_KW_METHOD_DESCRIPTOR_O 44 +#define CALL_NO_KW_STR_1 45 +#define CALL_NO_KW_TUPLE_1 46 +#define CALL_NO_KW_TYPE_1 47 +#define COMPARE_OP_ADAPTIVE 48 +#define COMPARE_OP_FLOAT_JUMP 55 +#define COMPARE_OP_INT_JUMP 56 +#define COMPARE_OP_STR_JUMP 57 +#define EXTENDED_ARG_QUICK 58 +#define JUMP_BACKWARD_QUICK 59 +#define LOAD_ATTR_ADAPTIVE 62 +#define LOAD_ATTR_INSTANCE_VALUE 63 +#define LOAD_ATTR_MODULE 64 +#define LOAD_ATTR_SLOT 65 +#define LOAD_ATTR_WITH_HINT 66 +#define LOAD_CONST__LOAD_FAST 67 +#define LOAD_FAST__LOAD_CONST 72 +#define LOAD_FAST__LOAD_FAST 73 +#define LOAD_GLOBAL_ADAPTIVE 76 +#define LOAD_GLOBAL_BUILTIN 77 +#define LOAD_GLOBAL_MODULE 78 +#define LOAD_METHOD_ADAPTIVE 79 +#define LOAD_METHOD_CLASS 80 +#define LOAD_METHOD_MODULE 81 +#define LOAD_METHOD_NO_DICT 113 +#define LOAD_METHOD_WITH_DICT 121 +#define LOAD_METHOD_WITH_VALUES 127 +#define RESUME_QUICK 141 +#define STORE_ATTR_ADAPTIVE 143 +#define STORE_ATTR_INSTANCE_VALUE 150 +#define STORE_ATTR_SLOT 153 +#define STORE_ATTR_WITH_HINT 154 +#define STORE_FAST__LOAD_FAST 158 +#define STORE_FAST__STORE_FAST 159 +#define STORE_SUBSCR_ADAPTIVE 161 +#define STORE_SUBSCR_DICT 166 +#define STORE_SUBSCR_LIST_INT 167 +#define UNPACK_SEQUENCE_ADAPTIVE 168 +#define UNPACK_SEQUENCE_LIST 169 +#define UNPACK_SEQUENCE_TUPLE 170 +#define UNPACK_SEQUENCE_TWO_TUPLE 177 #define DO_TRACING 255 #define HAS_CONST(op) (false\ diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 5f67226adfc522..e7941aeae059de 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -402,9 +402,11 @@ def _write_atomic(path, data, mode=0o666): # add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual) # Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative) # Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative) -# Python 3.11a7 3494 (New location info table) -# Python 3.12 will start with magic number 3500 +# Python 3.11a7 3494 (New location info table) +# Python 3.12a1 3500 (Remove PRECALL opcode) + +# Python 3.13 will start with 3550 # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -416,7 +418,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3494).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3500).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/opcode.py b/Lib/opcode.py index 310582874dc8f0..27e9ab17969bad 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -188,7 +188,6 @@ def jabs_op(name, op): def_op('SET_UPDATE', 163) def_op('DICT_MERGE', 164) def_op('DICT_UPDATE', 165) -def_op('PRECALL', 166) def_op('CALL', 171) def_op('KW_NAMES', 172) @@ -254,6 +253,21 @@ def jabs_op(name, op): "CALL_ADAPTIVE", "CALL_PY_EXACT_ARGS", "CALL_PY_WITH_DEFAULTS", + "CALL_BOUND_METHOD_EXACT_ARGS", + "CALL_BUILTIN_CLASS", + "CALL_BUILTIN_FAST_WITH_KEYWORDS", + "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + "CALL_NO_KW_BUILTIN_FAST", + "CALL_NO_KW_BUILTIN_O", + "CALL_NO_KW_ISINSTANCE", + "CALL_NO_KW_LEN", + "CALL_NO_KW_LIST_APPEND", + "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", + "CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", + "CALL_NO_KW_METHOD_DESCRIPTOR_O", + "CALL_NO_KW_STR_1", + "CALL_NO_KW_TUPLE_1", + "CALL_NO_KW_TYPE_1", ], "COMPARE_OP": [ "COMPARE_OP_ADAPTIVE", @@ -294,25 +308,6 @@ def jabs_op(name, op): "LOAD_METHOD_WITH_DICT", "LOAD_METHOD_WITH_VALUES", ], - "PRECALL": [ - "PRECALL_ADAPTIVE", - "PRECALL_BOUND_METHOD", - "PRECALL_BUILTIN_CLASS", - "PRECALL_BUILTIN_FAST_WITH_KEYWORDS", - "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - "PRECALL_NO_KW_BUILTIN_FAST", - "PRECALL_NO_KW_BUILTIN_O", - "PRECALL_NO_KW_ISINSTANCE", - "PRECALL_NO_KW_LEN", - "PRECALL_NO_KW_LIST_APPEND", - "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST", - "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", - "PRECALL_NO_KW_METHOD_DESCRIPTOR_O", - "PRECALL_NO_KW_STR_1", - "PRECALL_NO_KW_TUPLE_1", - "PRECALL_NO_KW_TYPE_1", - "PRECALL_PYFUNC", - ], "RESUME": [ "RESUME_QUICK", ], @@ -394,9 +389,6 @@ def jabs_op(name, op): "func_version": 2, "min_args": 1, }, - "PRECALL": { - "counter": 1, - }, "STORE_SUBSCR": { "counter": 1, }, diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 5a9c618786f4e2..487a4fa2a9540d 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -839,7 +839,7 @@ def foo(x): instructions = [opcode.opname for opcode in opcodes] self.assertNotIn('LOAD_METHOD', instructions) self.assertIn('LOAD_ATTR', instructions) - self.assertIn('PRECALL', instructions) + self.assertIn('CALL', instructions) def test_lineno_procedure_call(self): def call(): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index af736d6fe96141..a19cf49e658ec5 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -107,7 +107,6 @@ def _f(a): %3d LOAD_GLOBAL 1 (NULL + print) LOAD_FAST 0 (a) - PRECALL 1 CALL 1 POP_TOP @@ -122,7 +121,6 @@ def _f(a): RESUME 0 LOAD_GLOBAL 1 LOAD_FAST 0 - PRECALL 1 CALL 1 POP_TOP LOAD_CONST 1 @@ -143,13 +141,12 @@ def bug708901(): %3d LOAD_CONST 2 (10) -%3d PRECALL 2 - CALL 2 +%3d CALL 2 GET_ITER - >> FOR_ITER 2 (to 40) + >> FOR_ITER 2 (to 36) STORE_FAST 0 (res) -%3d JUMP_BACKWARD 3 (to 34) +%3d JUMP_BACKWARD 3 (to 30) %3d >> LOAD_CONST 0 (None) RETURN_VALUE @@ -174,13 +171,11 @@ def bug1333982(x=[]): MAKE_FUNCTION 0 LOAD_FAST 0 (x) GET_ITER - PRECALL 0 CALL 0 %3d LOAD_CONST 3 (1) %3d BINARY_OP 0 (+) - PRECALL 0 CALL 0 RAISE_VARARGS 1 """ % (bug1333982.__code__.co_firstlineno, @@ -315,7 +310,6 @@ def bug42562(): 3 PUSH_NULL LOAD_NAME 3 (fun) LOAD_CONST 0 (1) - PRECALL 1 CALL 1 LOAD_NAME 2 (__annotations__) LOAD_CONST 2 ('y') @@ -326,7 +320,6 @@ def bug42562(): PUSH_NULL LOAD_NAME 3 (fun) LOAD_CONST 3 (0) - PRECALL 1 CALL 1 STORE_SUBSCR LOAD_NAME 1 (int) @@ -449,14 +442,12 @@ def _tryfinallyconst(b): %3d PUSH_NULL LOAD_FAST 1 (b) - PRECALL 0 CALL 0 POP_TOP RETURN_VALUE >> PUSH_EXC_INFO PUSH_NULL LOAD_FAST 1 (b) - PRECALL 0 CALL 0 POP_TOP RERAISE 0 @@ -479,7 +470,6 @@ def _tryfinallyconst(b): %3d PUSH_NULL LOAD_FAST 0 (b) - PRECALL 0 CALL 0 POP_TOP LOAD_CONST 1 (1) @@ -487,7 +477,6 @@ def _tryfinallyconst(b): PUSH_EXC_INFO PUSH_NULL LOAD_FAST 0 (b) - PRECALL 0 CALL 0 POP_TOP RERAISE 0 @@ -550,7 +539,6 @@ def foo(x): MAKE_FUNCTION 8 (closure) LOAD_DEREF 1 (y) GET_ITER - PRECALL 0 CALL 0 RETURN_VALUE """ % (dis_nested_0, @@ -608,26 +596,25 @@ def loop_test(): load_test(i) dis_loop_test_quickened_code = """\ -%3d 0 RESUME_QUICK 0 +%3d RESUME_QUICK 0 + +%3d BUILD_LIST 0 + LOAD_CONST 1 ((1, 2, 3)) + LIST_EXTEND 1 + LOAD_CONST 2 (3) + BINARY_OP_ADAPTIVE 5 (*) + GET_ITER + FOR_ITER 15 (to 48) + STORE_FAST 0 (i) -%3d 2 BUILD_LIST 0 - 4 LOAD_CONST 1 ((1, 2, 3)) - 6 LIST_EXTEND 1 - 8 LOAD_CONST 2 (3) - 10 BINARY_OP_ADAPTIVE 5 (*) - 14 GET_ITER - 16 FOR_ITER 17 (to 52) - 18 STORE_FAST 0 (i) - -%3d 20 LOAD_GLOBAL_MODULE 1 (NULL + load_test) - 32 LOAD_FAST 0 (i) - 34 PRECALL_PYFUNC 1 - 38 CALL_PY_WITH_DEFAULTS 1 - 48 POP_TOP - 50 JUMP_BACKWARD_QUICK 18 (to 16) - -%3d >> 52 LOAD_CONST 0 (None) - 54 RETURN_VALUE +%3d LOAD_GLOBAL_MODULE 1 (NULL + load_test) + LOAD_FAST 0 (i) + CALL_PY_WITH_DEFAULTS 1 + POP_TOP + JUMP_BACKWARD_QUICK 16 (to 16) + +%3d >> LOAD_CONST 0 (None) + RETURN_VALUE """ % (loop_test.__code__.co_firstlineno, loop_test.__code__.co_firstlineno + 1, loop_test.__code__.co_firstlineno + 2, @@ -990,26 +977,25 @@ def test_load_attr_specialize(self): @cpython_only def test_call_specialize(self): call_quicken = """\ - 0 RESUME_QUICK 0 + RESUME_QUICK 0 - 1 2 PUSH_NULL - 4 LOAD_NAME 0 (str) - 6 LOAD_CONST 0 (1) - 8 PRECALL_NO_KW_STR_1 1 - 12 CALL_ADAPTIVE 1 - 22 RETURN_VALUE + 1 PUSH_NULL + LOAD_NAME 0 (str) + LOAD_CONST 0 (1) + CALL_NO_KW_STR_1 1 + RETURN_VALUE """ co = compile("str(1)", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) got = self.get_disassembly(co, adaptive=True) - self.do_disassembly_compare(got, call_quicken, True) + self.do_disassembly_compare(got, call_quicken) @cpython_only def test_loop_quicken(self): # Loop can trigger a quicken where the loop is located self.code_quicken(loop_test, 1) got = self.get_disassembly(loop_test, adaptive=True) - self.do_disassembly_compare(got, dis_loop_test_quickened_code, True) + self.do_disassembly_compare(got, dis_loop_test_quickened_code) def get_cached_values(self, quickened, adaptive): def f(): @@ -1040,7 +1026,7 @@ def test_show_caches(self): for cache in caches: self.assertRegex(cache, pattern) self.assertEqual(caches.count(""), 8) - self.assertEqual(len(caches), 25) + self.assertEqual(len(caches), 23) class DisWithFileTests(DisTests): @@ -1319,6 +1305,7 @@ def _prepare_test_cases(): #_prepare_test_cases() Instruction = dis.Instruction + expected_opinfo_outer = [ Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='a', argrepr='a', offset=0, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='b', argrepr='b', offset=2, starts_line=None, is_jump_target=False, positions=None), @@ -1338,11 +1325,10 @@ def _prepare_test_cases(): Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=44, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=7, argval=7, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=62, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=58, starts_line=8, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), ] expected_opinfo_f = [ @@ -1364,11 +1350,10 @@ def _prepare_test_cases(): Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=40, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=42, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=44, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=4, argval=4, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=62, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=58, starts_line=6, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), ] expected_opinfo_inner = [ @@ -1381,137 +1366,126 @@ def _prepare_test_cases(): Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=22, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=24, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=26, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=6, argval=6, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=32, 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_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=44, starts_line=None, 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), + Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=40, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None), ] expected_opinfo_jumpy = [ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=1, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='range', argrepr='NULL + range', offset=2, starts_line=3, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=98, argrepr='to 98', offset=32, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=34, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=36, starts_line=4, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=48, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=54, 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=5, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=68, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=70, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=32, argrepr='to 32', offset=78, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=7, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=82, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=84, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=92, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=128, argrepr='to 128', offset=94, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=98, 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=110, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), - 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_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=128, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=132, starts_line=12, is_jump_target=True, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=146, 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=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=162, starts_line=13, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=14, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=128, argrepr='to 128', offset=184, starts_line=15, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=16, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=234, argrepr='to 234', offset=198, starts_line=17, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=200, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=204, 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=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=234, starts_line=20, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=236, starts_line=21, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=246, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=250, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=252, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=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=1, argval=1, argrepr='', offset=270, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=280, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=282, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=284, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=286, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=292, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=328, argrepr='to 328', offset=304, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=392, argrepr='to 392', offset=328, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=4, argval=392, argrepr='to 392', offset=382, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=392, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='FOR_ITER', opcode=93, arg=30, argval=90, argrepr='to 90', offset=28, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=30, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=32, starts_line=4, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=44, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=58, starts_line=5, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=60, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=62, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=72, argrepr='to 72', offset=68, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=22, argval=28, argrepr='to 28', offset=70, starts_line=6, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=7, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=76, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=88, argrepr='to 88', offset=82, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=84, starts_line=8, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=116, argrepr='to 116', offset=86, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=31, argval=28, argrepr='to 28', offset=88, starts_line=7, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=90, 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=102, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=116, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=34, argval=188, argrepr='to 188', offset=118, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=120, starts_line=12, is_jump_target=True, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=13, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=148, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=150, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=154, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=156, starts_line=14, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=158, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=160, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=170, argrepr='to 170', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=116, argrepr='to 116', offset=168, starts_line=15, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=170, starts_line=16, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=184, argrepr='to 184', offset=180, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=214, argrepr='to 214', offset=182, starts_line=17, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=184, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=34, argval=120, argrepr='to 120', offset=186, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=188, 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=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=202, 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='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=214, starts_line=20, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=216, starts_line=21, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=226, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=230, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=232, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=244, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=260, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=262, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=264, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=274, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=300, argrepr='to 300', offset=276, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=278, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=280, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=292, argrepr='to 292', offset=282, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=284, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=286, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=292, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=296, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=298, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=29, argval=360, argrepr='to 360', offset=300, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=304, starts_line=22, is_jump_target=False, positions=None), + Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=16, argval=352, argrepr='to 352', offset=318, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=322, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=334, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=336, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=346, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=4, argval=360, argrepr='to 360', offset=350, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=352, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=354, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=356, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=358, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=360, 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=372, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=374, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=386, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=392, 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=404, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=406, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=410, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=422, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=426, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=428, 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=440, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=442, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=446, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=456, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=458, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=460, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=462, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=464, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=406, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=416, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling @@ -1581,7 +1555,6 @@ def test_co_positions(self): (1, 3, 0, 1), (1, 3, 0, 1), (1, 3, 0, 1), - (1, 3, 0, 1), (1, 3, 0, 1) ] self.assertEqual(positions, expected) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-18-12-55-35.gh-issue-90690.TKuoTa.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-18-12-55-35.gh-issue-90690.TKuoTa.rst new file mode 100644 index 00000000000000..6c5aa91dfb9d3d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-18-12-55-35.gh-issue-90690.TKuoTa.rst @@ -0,0 +1,2 @@ +The PRECALL instruction has been removed. It offered only a small advantage +for specialization and is not needed in the vast majority of cases. diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 1c279134e94dc9..e6e2ef26b1c373 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,18 +1,17 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,115,176,0,0,0,151,0,100,0,100,1, + 0,0,0,0,0,115,160,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,0,0,171,1,0,0,0,0,0,0,0,0, - 1,0,2,0,101,2,100,3,101,0,106,3,0,0,0,0, - 0,0,0,0,166,2,0,0,171,2,0,0,0,0,0,0, - 0,0,1,0,2,0,101,1,106,4,0,0,0,0,0,0, - 0,0,166,0,0,0,171,0,0,0,0,0,0,0,0,0, - 100,4,25,0,0,0,0,0,0,0,0,0,90,5,100,5, - 68,0,93,25,90,6,2,0,101,2,100,6,101,6,155,0, - 100,7,101,5,101,6,25,0,0,0,0,0,0,0,0,0, - 155,0,157,4,166,1,0,0,171,1,0,0,0,0,0,0, - 0,0,1,0,140,26,100,1,83,0,41,8,233,0,0,0, + 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, + 101,2,100,3,101,0,106,3,0,0,0,0,0,0,0,0, + 171,2,0,0,0,0,0,0,0,0,1,0,2,0,101,1, + 106,4,0,0,0,0,0,0,0,0,171,0,0,0,0,0, + 0,0,0,0,100,4,25,0,0,0,0,0,0,0,0,0, + 90,5,100,5,68,0,93,23,90,6,2,0,101,2,100,6, + 101,6,155,0,100,7,101,5,101,6,25,0,0,0,0,0, + 0,0,0,0,155,0,157,4,171,1,0,0,0,0,0,0, + 0,0,1,0,140,24,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,218,12,112,114,111,103, @@ -28,15 +27,14 @@ unsigned char M_test_frozenmain[] = { 107,101,121,169,0,243,0,0,0,0,250,18,116,101,115,116, 95,102,114,111,122,101,110,109,97,105,110,46,112,121,250,8, 60,109,111,100,117,108,101,62,114,17,0,0,0,1,0,0, - 0,115,152,0,0,0,248,240,6,0,1,11,128,10,128,10, + 0,115,140,0,0,0,248,240,6,0,1,11,128,10,128,10, 128,10,216,0,24,208,0,24,208,0,24,208,0,24,224,0, - 5,128,5,208,6,26,209,0,27,212,0,27,208,0,27,216, - 0,5,128,5,128,106,144,35,148,40,209,0,27,212,0,27, - 208,0,27,216,9,38,208,9,26,212,9,38,209,9,40,212, - 9,40,168,24,212,9,50,128,6,240,2,6,12,2,240,0, - 7,1,42,240,0,7,1,42,128,67,240,14,0,5,10,128, - 69,208,10,40,144,67,208,10,40,208,10,40,152,54,160,35, - 156,59,208,10,40,208,10,40,209,4,41,212,4,41,208,4, - 41,208,4,41,240,15,7,1,42,240,0,7,1,42,114,15, - 0,0,0, + 5,128,5,208,6,26,212,0,27,208,0,27,216,0,5,128, + 5,128,106,144,35,148,40,212,0,27,208,0,27,216,9,38, + 208,9,26,212,9,38,212,9,40,168,24,212,9,50,128,6, + 240,2,6,12,2,240,0,7,1,42,240,0,7,1,42,128, + 67,240,14,0,5,10,128,69,208,10,40,144,67,208,10,40, + 208,10,40,152,54,160,35,156,59,208,10,40,208,10,40,212, + 4,41,208,4,41,208,4,41,240,15,7,1,42,240,0,7, + 1,42,114,15,0,0,0, }; diff --git a/Python/ceval.c b/Python/ceval.c index e4c47498c0cba4..deb131813eb11d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1439,10 +1439,6 @@ eval_frame_handle_pending(PyThreadState *tstate) #define JUMPTO(x) (next_instr = first_instr + (x)) #define JUMPBY(x) (next_instr += (x)) -// Skip from a PRECALL over a CALL to the next instruction: -#define SKIP_CALL() \ - JUMPBY(INLINE_CACHE_ENTRIES_PRECALL + 1 + INLINE_CACHE_ENTRIES_CALL) - /* Get opcode and oparg from original instructions, not quickened form. */ #define TRACING_NEXTOPARG() do { \ NEXTOPARG(); \ @@ -1687,7 +1683,7 @@ pop_frame(PyThreadState *tstate, _PyInterpreterFrame *frame) return prev_frame; } -/* It is only between the PRECALL instruction and the following CALL, +/* It is only between the KW_NAMES instruction and the following CALL, * that this has any meaning. */ typedef struct { @@ -4541,7 +4537,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(LOAD_METHOD) { PREDICTED(LOAD_METHOD); - /* Designed to work in tandem with PRECALL. */ + /* Designed to work in tandem with CALL. */ PyObject *name = GETITEM(names, oparg); PyObject *obj = TOP(); PyObject *meth = NULL; @@ -4566,7 +4562,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int /* meth is not an unbound method (but a regular attr, or something was returned by a descriptor protocol). Set the second element of the stack to NULL, to signal - PRECALL that it's not a method call. + CALL that it's not a method call. NULL | meth | arg1 | ... | argN */ @@ -4710,57 +4706,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } - TARGET(PRECALL) { - PREDICTED(PRECALL); - /* Designed to work in tamdem with LOAD_METHOD. */ - /* `meth` is NULL when LOAD_METHOD thinks that it's not - a method call. - - Stack layout: - - ... | NULL | callable | arg1 | ... | argN - ^- TOP() - ^- (-oparg) - ^- (-oparg-1) - ^- (-oparg-2) - - `callable` will be POPed by call_function. - NULL will will be POPed manually later. - If `meth` isn't NULL, it's a method call. Stack layout: - - ... | method | self | arg1 | ... | argN - ^- TOP() - ^- (-oparg) - ^- (-oparg-1) - ^- (-oparg-2) - - `self` and `method` will be POPed by call_function. - We'll be passing `oparg + 1` to call_function, to - make it accept the `self` as a first argument. - */ - int is_meth = is_method(stack_pointer, oparg); - int nargs = oparg + is_meth; - /* Move ownership of reference from stack to call_shape - * and make sure that NULL is cleared from stack */ - PyObject *function = PEEK(nargs + 1); - if (!is_meth && 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); - } - JUMPBY(INLINE_CACHE_ENTRIES_PRECALL); - DISPATCH(); - } - - TARGET(PRECALL_BOUND_METHOD) { - DEOPT_IF(is_method(stack_pointer, oparg), PRECALL); + TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { + DEOPT_IF(is_method(stack_pointer, oparg), CALL); PyObject *function = PEEK(oparg + 1); - DEOPT_IF(Py_TYPE(function) != &PyMethod_Type, PRECALL); - STAT_INC(PRECALL, hit); + DEOPT_IF(Py_TYPE(function) != &PyMethod_Type, CALL); + STAT_INC(CALL, hit); PyObject *meth = ((PyMethodObject *)function)->im_func; PyObject *self = ((PyMethodObject *)function)->im_self; Py_INCREF(meth); @@ -4768,17 +4718,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PEEK(oparg + 1) = self; PEEK(oparg + 2) = meth; Py_DECREF(function); - JUMPBY(INLINE_CACHE_ENTRIES_PRECALL); - DISPATCH(); - } - - TARGET(PRECALL_PYFUNC) { - int nargs = oparg + is_method(stack_pointer, oparg); - PyObject *function = PEEK(nargs + 1); - DEOPT_IF(Py_TYPE(function) != &PyFunction_Type, PRECALL); - STAT_INC(PRECALL, hit); - JUMPBY(INLINE_CACHE_ENTRIES_PRECALL); - DISPATCH(); + goto call_exact_args; } TARGET(KW_NAMES) { @@ -4789,11 +4729,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(CALL) { - int is_meth; + int total_args, is_meth; call_function: is_meth = is_method(stack_pointer, oparg); - int total_args = oparg + is_meth; - PyObject *function = PEEK(total_args + 1); + PyObject *function = PEEK(oparg + 1); + if (!is_meth && 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); + is_meth = 1; + } + total_args = oparg + is_meth; + 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) { @@ -4850,27 +4801,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_ADAPTIVE) { - _PyPrecallCache *cache = (_PyPrecallCache *)next_instr; - if (cache->counter == 0) { - next_instr--; - int is_meth = is_method(stack_pointer, oparg); - int nargs = oparg + is_meth; - PyObject *callable = PEEK(nargs + 1); - int err = _Py_Specialize_Precall(callable, next_instr, nargs, - call_shape.kwnames, oparg); - if (err < 0) { - goto error; - } - NOTRACE_DISPATCH_SAME_OPARG(); - } - else { - STAT_INC(PRECALL, deferred); - cache->counter--; - JUMP_TO_INSTRUCTION(PRECALL); - } - } - TARGET(CALL_ADAPTIVE) { _PyCallCache *cache = (_PyCallCache *)next_instr; if (cache->counter == 0) { @@ -4893,6 +4823,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(CALL_PY_EXACT_ARGS) { + call_exact_args: assert(call_shape.kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); _PyCallCache *cache = (_PyCallCache *)next_instr; @@ -4968,16 +4899,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto start_frame; } - TARGET(PRECALL_NO_KW_TYPE_1) { + TARGET(CALL_NO_KW_TYPE_1) { assert(call_shape.kwnames == NULL); assert(cframe.use_tracing == 0); assert(oparg == 1); - DEOPT_IF(is_method(stack_pointer, 1), PRECALL); + DEOPT_IF(is_method(stack_pointer, 1), CALL); PyObject *obj = TOP(); PyObject *callable = SECOND(); - DEOPT_IF(callable != (PyObject *)&PyType_Type, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyObject *res = Py_NewRef(Py_TYPE(obj)); Py_DECREF(callable); Py_DECREF(obj); @@ -4986,15 +4917,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } - TARGET(PRECALL_NO_KW_STR_1) { + TARGET(CALL_NO_KW_STR_1) { assert(call_shape.kwnames == NULL); assert(cframe.use_tracing == 0); assert(oparg == 1); - DEOPT_IF(is_method(stack_pointer, 1), PRECALL); + DEOPT_IF(is_method(stack_pointer, 1), CALL); PyObject *callable = PEEK(2); - DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyObject *arg = TOP(); PyObject *res = PyObject_Str(arg); Py_DECREF(arg); @@ -5008,14 +4939,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_TUPLE_1) { + TARGET(CALL_NO_KW_TUPLE_1) { assert(call_shape.kwnames == NULL); assert(oparg == 1); - DEOPT_IF(is_method(stack_pointer, 1), PRECALL); + DEOPT_IF(is_method(stack_pointer, 1), CALL); PyObject *callable = PEEK(2); - DEOPT_IF(callable != (PyObject *)&PyTuple_Type, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyObject *arg = TOP(); PyObject *res = PySequence_Tuple(arg); Py_DECREF(arg); @@ -5029,16 +4960,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_BUILTIN_CLASS) { + TARGET(CALL_BUILTIN_CLASS) { int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; int kwnames_len = KWNAMES_LEN(); PyObject *callable = PEEK(total_args + 1); - DEOPT_IF(!PyType_Check(callable), PRECALL); + DEOPT_IF(!PyType_Check(callable), CALL); PyTypeObject *tp = (PyTypeObject *)callable; - DEOPT_IF(tp->tp_vectorcall == NULL, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(tp->tp_vectorcall == NULL, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); STACK_SHRINK(total_args); PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, total_args-kwnames_len, call_shape.kwnames); @@ -5057,18 +4988,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_BUILTIN_O) { + TARGET(CALL_NO_KW_BUILTIN_O) { assert(cframe.use_tracing == 0); /* Builtin METH_O functions */ assert(call_shape.kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; - DEOPT_IF(total_args != 1, PRECALL); + DEOPT_IF(total_args != 1, CALL); PyObject *callable = PEEK(total_args + 1); - DEOPT_IF(!PyCFunction_CheckExact(callable), PRECALL); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); // This is slower but CPython promises to check all non-vectorcall // function calls. @@ -5091,18 +5022,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_BUILTIN_FAST) { + TARGET(CALL_NO_KW_BUILTIN_FAST) { assert(cframe.use_tracing == 0); /* Builtin METH_FASTCALL functions, without keywords */ assert(call_shape.kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyObject *callable = PEEK(total_args + 1); - DEOPT_IF(!PyCFunction_CheckExact(callable), PRECALL); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, - PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); STACK_SHRINK(total_args); /* res = func(self, args, nargs) */ @@ -5131,17 +5062,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_BUILTIN_FAST_WITH_KEYWORDS) { + TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) { assert(cframe.use_tracing == 0); /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyObject *callable = PEEK(total_args + 1); - DEOPT_IF(!PyCFunction_CheckExact(callable), PRECALL); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL); DEOPT_IF(PyCFunction_GET_FLAGS(callable) != - (METH_FASTCALL | METH_KEYWORDS), PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + (METH_FASTCALL | METH_KEYWORDS), CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); STACK_SHRINK(total_args); /* res = func(self, args, nargs, kwnames) */ _PyCFunctionFastWithKeywords cfunc = @@ -5170,18 +5101,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_LEN) { + TARGET(CALL_NO_KW_LEN) { assert(cframe.use_tracing == 0); assert(call_shape.kwnames == NULL); /* len(o) */ int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; - DEOPT_IF(total_args != 1, PRECALL); + DEOPT_IF(total_args != 1, CALL); PyObject *callable = PEEK(total_args + 1); PyInterpreterState *interp = _PyInterpreterState_GET(); - DEOPT_IF(callable != interp->callable_cache.len, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(callable != interp->callable_cache.len, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyObject *arg = TOP(); Py_ssize_t len_i = PyObject_Length(arg); if (len_i < 0) { @@ -5200,18 +5131,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_ISINSTANCE) { + TARGET(CALL_NO_KW_ISINSTANCE) { assert(cframe.use_tracing == 0); assert(call_shape.kwnames == NULL); /* isinstance(o, o2) */ int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyObject *callable = PEEK(total_args + 1); - DEOPT_IF(total_args != 2, PRECALL); + DEOPT_IF(total_args != 2, CALL); PyInterpreterState *interp = _PyInterpreterState_GET(); - DEOPT_IF(callable != interp->callable_cache.isinstance, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(callable != interp->callable_cache.isinstance, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyObject *cls = POP(); PyObject *inst = TOP(); int retval = PyObject_IsInstance(inst, cls); @@ -5233,18 +5164,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_LIST_APPEND) { + TARGET(CALL_NO_KW_LIST_APPEND) { assert(cframe.use_tracing == 0); assert(call_shape.kwnames == NULL); assert(oparg == 1); PyObject *callable = PEEK(3); PyInterpreterState *interp = _PyInterpreterState_GET(); - DEOPT_IF(callable != interp->callable_cache.list_append, PRECALL); + DEOPT_IF(callable != interp->callable_cache.list_append, CALL); PyObject *list = SECOND(); - DEOPT_IF(!PyList_Check(list), PRECALL); - STAT_INC(PRECALL, hit); - // PRECALL + CALL + POP_TOP - JUMPBY(INLINE_CACHE_ENTRIES_PRECALL + 1 + INLINE_CACHE_ENTRIES_CALL + 1); + DEOPT_IF(!PyList_Check(list), CALL); + STAT_INC(CALL, hit); + // CALL + POP_TOP + JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1); assert(_Py_OPCODE(next_instr[-1]) == POP_TOP); PyObject *arg = POP(); if (_PyList_AppendTakeRef((PyListObject *)list, arg) < 0) { @@ -5256,21 +5187,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } - TARGET(PRECALL_NO_KW_METHOD_DESCRIPTOR_O) { + TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { assert(call_shape.kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyMethodDescrObject *callable = (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(total_args != 2, PRECALL); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), PRECALL); + DEOPT_IF(total_args != 2, CALL); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_O, PRECALL); + DEOPT_IF(meth->ml_flags != METH_O, CALL); PyObject *arg = TOP(); PyObject *self = SECOND(); - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. @@ -5292,19 +5223,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) { + TARGET(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) { int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyMethodDescrObject *callable = (PyMethodDescrObject *)PEEK(total_args + 1); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), PRECALL); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), PRECALL); + DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL); PyTypeObject *d_type = callable->d_common.d_type; PyObject *self = PEEK(total_args); - DEOPT_IF(!Py_IS_TYPE(self, d_type), PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); int nargs = total_args-1; STACK_SHRINK(nargs); _PyCFunctionFastWithKeywords cfunc = @@ -5329,20 +5260,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) { + TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) { assert(call_shape.kwnames == NULL); assert(oparg == 0 || oparg == 1); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; - DEOPT_IF(total_args != 1, PRECALL); + DEOPT_IF(total_args != 1, CALL); PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND(); - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), PRECALL); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); PyMethodDef *meth = callable->d_method; PyObject *self = TOP(); - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), PRECALL); - DEOPT_IF(meth->ml_flags != METH_NOARGS, PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); PyCFunction cfunc = meth->ml_meth; // This is slower but CPython promises to check all non-vectorcall // function calls. @@ -5363,20 +5294,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST) { + TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) { assert(call_shape.kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyMethodDescrObject *callable = (PyMethodDescrObject *)PEEK(total_args + 1); /* Builtin METH_FASTCALL methods, without keywords */ - DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), PRECALL); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL); PyMethodDef *meth = callable->d_method; - DEOPT_IF(meth->ml_flags != METH_FASTCALL, PRECALL); + DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL); PyObject *self = PEEK(total_args); - DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), PRECALL); - STAT_INC(PRECALL, hit); - SKIP_CALL(); + DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL); + STAT_INC(CALL, hit); + JUMPBY(INLINE_CACHE_ENTRIES_CALL); _PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth; int nargs = total_args-1; diff --git a/Python/compile.c b/Python/compile.c index fdf2e5b85adac7..c42deb54ba3dee 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1116,12 +1116,10 @@ stack_effect(int opcode, int oparg, int jump) return -oparg; /* Functions and calls */ - case PRECALL: - return -oparg; case KW_NAMES: return 0; case CALL: - return -1; + return -1-oparg; case CALL_FUNCTION_EX: return -2 - ((oparg & 0x01) != 0); @@ -1947,7 +1945,6 @@ compiler_call_exit_with_nones(struct compiler *c) { ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None); - ADDOP_I(c, PRECALL, 2); ADDOP_I(c, CALL, 2); return 1; } @@ -2325,7 +2322,6 @@ 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, PRECALL, 0); ADDOP_I(c, CALL, 0); } c->u->u_lineno = old_lineno; @@ -4002,7 +3998,6 @@ 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, PRECALL, 0); ADDOP_I(c, CALL, 0); } ADDOP_I(c, RAISE_VARARGS, 1); @@ -4831,7 +4826,6 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) return 0; }; } - ADDOP_I(c, PRECALL, argsl + kwdsl); ADDOP_I(c, CALL, argsl + kwdsl); c->u->u_lineno = old_lineno; return 1; @@ -4897,7 +4891,6 @@ 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, PRECALL, 1); ADDOP_I(c, CALL, 1); } else { @@ -5071,7 +5064,6 @@ compiler_call_helper(struct compiler *c, return 0; }; } - ADDOP_I(c, PRECALL, n + nelts + nkwelts); ADDOP_I(c, CALL, n + nelts + nkwelts); return 1; @@ -5462,7 +5454,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, ADDOP(c, GET_ITER); } - ADDOP_I(c, PRECALL, 0); ADDOP_I(c, CALL, 0); if (is_async_generator && type != COMP_GENEXP) { diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index d37c1326247185..3a6768bd228bda 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -25,62 +25,62 @@ static void *opcode_targets[256] = { &&TARGET_CALL_PY_EXACT_ARGS, &&TARGET_CALL_PY_WITH_DEFAULTS, &&TARGET_BINARY_SUBSCR, - &&TARGET_COMPARE_OP_ADAPTIVE, - &&TARGET_COMPARE_OP_FLOAT_JUMP, - &&TARGET_COMPARE_OP_INT_JUMP, - &&TARGET_COMPARE_OP_STR_JUMP, + &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS, + &&TARGET_CALL_BUILTIN_CLASS, + &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS, + &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_EXTENDED_ARG_QUICK, + &&TARGET_CALL_NO_KW_BUILTIN_FAST, &&TARGET_PUSH_EXC_INFO, &&TARGET_CHECK_EXC_MATCH, &&TARGET_CHECK_EG_MATCH, + &&TARGET_CALL_NO_KW_BUILTIN_O, + &&TARGET_CALL_NO_KW_ISINSTANCE, + &&TARGET_CALL_NO_KW_LEN, + &&TARGET_CALL_NO_KW_LIST_APPEND, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O, + &&TARGET_CALL_NO_KW_STR_1, + &&TARGET_CALL_NO_KW_TUPLE_1, + &&TARGET_CALL_NO_KW_TYPE_1, + &&TARGET_COMPARE_OP_ADAPTIVE, + &&TARGET_WITH_EXCEPT_START, + &&TARGET_GET_AITER, + &&TARGET_GET_ANEXT, + &&TARGET_BEFORE_ASYNC_WITH, + &&TARGET_BEFORE_WITH, + &&TARGET_END_ASYNC_FOR, + &&TARGET_COMPARE_OP_FLOAT_JUMP, + &&TARGET_COMPARE_OP_INT_JUMP, + &&TARGET_COMPARE_OP_STR_JUMP, + &&TARGET_EXTENDED_ARG_QUICK, &&TARGET_JUMP_BACKWARD_QUICK, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_WITH_HINT, &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_GET_ITER, + &&TARGET_GET_YIELD_FROM_ITER, + &&TARGET_PRINT_EXPR, + &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_RETURN_GENERATOR, &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_WITH_EXCEPT_START, - &&TARGET_GET_AITER, - &&TARGET_GET_ANEXT, - &&TARGET_BEFORE_ASYNC_WITH, - &&TARGET_BEFORE_WITH, - &&TARGET_END_ASYNC_FOR, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, - &&TARGET_LOAD_METHOD_NO_DICT, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, - &&TARGET_LOAD_METHOD_WITH_DICT, - &&TARGET_LOAD_METHOD_WITH_VALUES, - &&TARGET_PRECALL_ADAPTIVE, - &&TARGET_PRECALL_BOUND_METHOD, - &&TARGET_PRECALL_BUILTIN_CLASS, - &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, - &&TARGET_GET_ITER, - &&TARGET_GET_YIELD_FROM_ITER, - &&TARGET_PRINT_EXPR, - &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, - &&TARGET_LOAD_ASSERTION_ERROR, - &&TARGET_RETURN_GENERATOR, - &&TARGET_PRECALL_NO_KW_BUILTIN_O, - &&TARGET_PRECALL_NO_KW_ISINSTANCE, - &&TARGET_PRECALL_NO_KW_LEN, - &&TARGET_PRECALL_NO_KW_LIST_APPEND, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, + &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_POP_JUMP_FORWARD_IF_FALSE, &&TARGET_POP_JUMP_FORWARD_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -120,13 +120,13 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_PRECALL_NO_KW_STR_1, + &&TARGET_LOAD_METHOD_WITH_DICT, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, - &&TARGET_PRECALL_NO_KW_TUPLE_1, + &&TARGET_LOAD_METHOD_WITH_VALUES, &&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_FORWARD_IF_NONE, &&TARGET_RAISE_VARARGS, @@ -140,45 +140,42 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_PRECALL_NO_KW_TYPE_1, + &&TARGET_RESUME_QUICK, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_PRECALL_PYFUNC, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_RESUME_QUICK, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_LOAD_METHOD, &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_LOAD_METHOD, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, - &&TARGET_PRECALL, - &&TARGET_STORE_FAST__STORE_FAST, - &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, + &&TARGET_UNPACK_SEQUENCE_LIST, + &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, - &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, - &&TARGET_UNPACK_SEQUENCE_LIST, - &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, @@ -254,5 +251,8 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/specialize.c b/Python/specialize.c index 5469285e16c4d0..9579369a599d92 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -24,7 +24,6 @@ uint8_t _PyOpcode_Adaptive[256] = { [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE, [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE, [CALL] = CALL_ADAPTIVE, - [PRECALL] = PRECALL_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, [COMPARE_OP] = COMPARE_OP_ADAPTIVE, @@ -121,7 +120,6 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, BINARY_OP, "binary_op"); err += add_stat_dict(stats, COMPARE_OP, "compare_op"); err += add_stat_dict(stats, UNPACK_SEQUENCE, "unpack_sequence"); - err += add_stat_dict(stats, PRECALL, "precall"); if (err < 0) { Py_DECREF(stats); return NULL; @@ -1358,38 +1356,39 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins static int specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames, int oparg) + PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); PyTypeObject *tp = _PyType_CAST(callable); if (tp->tp_new == PyBaseObject_Type.tp_new) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_PYTHON_CLASS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PYTHON_CLASS); return -1; } if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { + int oparg = _Py_OPARG(*instr); if (nargs == 1 && kwnames == NULL && oparg == 1) { if (tp == &PyUnicode_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_STR_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_STR_1); return 0; } else if (tp == &PyType_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_TYPE_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_TYPE_1); return 0; } else if (tp == &PyTuple_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_TUPLE_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_TUPLE_1); return 0; } } if (tp->tp_vectorcall != NULL) { - _Py_SET_OPCODE(*instr, PRECALL_BUILTIN_CLASS); + _Py_SET_OPCODE(*instr, CALL_BUILTIN_CLASS); return 0; } - SPECIALIZATION_FAIL(PRECALL, tp == &PyUnicode_Type ? + SPECIALIZATION_FAIL(CALL, tp == &PyUnicode_Type ? SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL); return -1; } - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_CLASS_MUTABLE); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_CLASS_MUTABLE); return -1; } @@ -1419,11 +1418,11 @@ builtin_call_fail_kind(int ml_flags) static int specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, - int nargs, PyObject *kwnames, int oparg) + int nargs, PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } @@ -1432,45 +1431,45 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, METH_KEYWORDS | METH_METHOD)) { case METH_NOARGS: { if (nargs != 1) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS); return 0; } case METH_O: { if (nargs != 2) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } PyInterpreterState *interp = _PyInterpreterState_GET(); PyObject *list_append = interp->callable_cache.list_append; - _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_PRECALL + 1 - + INLINE_CACHE_ENTRIES_CALL + 1]; + _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1]; bool pop = (_Py_OPCODE(next) == POP_TOP); + int oparg = _Py_OPARG(*instr); if ((PyObject *)descr == list_append && oparg == 1 && pop) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_LIST_APPEND); + _Py_SET_OPCODE(*instr, CALL_NO_KW_LIST_APPEND); return 0; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_O); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_O); return 0; } case METH_FASTCALL: { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_FAST); return 0; } case METH_FASTCALL|METH_KEYWORDS: { - _Py_SET_OPCODE(*instr, PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); + _Py_SET_OPCODE(*instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); return 0; } } - SPECIALIZATION_FAIL(PRECALL, builtin_call_fail_kind(descr->d_method->ml_flags)); + SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(descr->d_method->ml_flags)); return -1; } static int specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) + PyObject *kwnames, bool bound_method) { _PyCallCache *cache = (_PyCallCache *)(instr + 1); assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); @@ -1512,7 +1511,11 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, write_u32(cache->func_version, version); cache->min_args = min_args; if (argcount == nargs) { - _Py_SET_OPCODE(*instr, CALL_PY_EXACT_ARGS); + _Py_SET_OPCODE(*instr, bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS); + } + else if (bound_method) { + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD); + return -1; } else { _Py_SET_OPCODE(*instr, CALL_PY_WITH_DEFAULTS); @@ -1524,7 +1527,7 @@ static int specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); if (PyCFunction_GET_FUNCTION(callable) == NULL) { return 1; } @@ -1533,44 +1536,44 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, METH_KEYWORDS | METH_METHOD)) { case METH_O: { if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } if (nargs != 1) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return 1; } /* len(o) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.len) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_LEN); + _Py_SET_OPCODE(*instr, CALL_NO_KW_LEN); return 0; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_BUILTIN_O); + _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_O); return 0; } case METH_FASTCALL: { if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } if (nargs == 2) { /* isinstance(o1, o2) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.isinstance) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_ISINSTANCE); + _Py_SET_OPCODE(*instr, CALL_NO_KW_ISINSTANCE); return 0; } } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_BUILTIN_FAST); + _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_FAST); return 0; } case METH_FASTCALL | METH_KEYWORDS: { - _Py_SET_OPCODE(*instr, PRECALL_BUILTIN_FAST_WITH_KEYWORDS); + _Py_SET_OPCODE(*instr, CALL_BUILTIN_FAST_WITH_KEYWORDS); return 0; } default: - SPECIALIZATION_FAIL(PRECALL, + SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable))); return 1; } @@ -1618,62 +1621,39 @@ call_fail_kind(PyObject *callable) #endif +/* TODO: + - Specialize calling classes. +*/ int -_Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames, int oparg) +_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, + PyObject *kwnames) { - assert(_PyOpcode_Caches[PRECALL] == INLINE_CACHE_ENTRIES_PRECALL); - _PyPrecallCache *cache = (_PyPrecallCache *)(instr + 1); + assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); + _PyCallCache *cache = (_PyCallCache *)(instr + 1); int fail; if (PyCFunction_CheckExact(callable)) { fail = specialize_c_call(callable, instr, nargs, kwnames); } else if (PyFunction_Check(callable)) { - _Py_SET_OPCODE(*instr, PRECALL_PYFUNC); - fail = 0; + fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, + kwnames, false); } else if (PyType_Check(callable)) { - fail = specialize_class_call(callable, instr, nargs, kwnames, oparg); + fail = specialize_class_call(callable, instr, nargs, kwnames); } else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) { fail = specialize_method_descriptor((PyMethodDescrObject *)callable, - instr, nargs, kwnames, oparg); + instr, nargs, kwnames); } else if (Py_TYPE(callable) == &PyMethod_Type) { - _Py_SET_OPCODE(*instr, PRECALL_BOUND_METHOD); - fail = 0; - } - else { - SPECIALIZATION_FAIL(PRECALL, call_fail_kind(callable)); - fail = -1; - } - if (fail) { - STAT_INC(PRECALL, failure); - assert(!PyErr_Occurred()); - cache->counter = ADAPTIVE_CACHE_BACKOFF; - } - else { - STAT_INC(PRECALL, success); - assert(!PyErr_Occurred()); - cache->counter = initial_counter_value(); - } - return 0; -} - - -/* TODO: - - Specialize calling classes. -*/ -int -_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) -{ - assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); - _PyCallCache *cache = (_PyCallCache *)(instr + 1); - int fail; - if (PyFunction_Check(callable)) { - fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, - kwnames); + PyObject *func = ((PyMethodObject *)callable)->im_func; + if (PyFunction_Check(func)) { + fail = specialize_py_call((PyFunctionObject *)func, + instr, nargs+1, kwnames, true); + } else { + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD); + fail = -1; + } } else { SPECIALIZATION_FAIL(CALL, call_fail_kind(callable)); From 137fd3d88aa46669f5717734e823f4c594ab2843 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Thu, 19 May 2022 12:43:16 +0200 Subject: [PATCH 07/19] gh-90473: Decrease recursion limit and skip tests on WASI (GH-92803) --- Include/internal/pycore_ceval.h | 8 ++++++- Lib/platform.py | 4 ++++ Lib/test/pythoninfo.py | 10 +++++++-- Lib/test/support/__init__.py | 5 +++++ Lib/test/test_compile.py | 4 +++- Lib/test/test_fileio.py | 5 ++++- Lib/test/test_largefile.py | 2 ++ Lib/test/test_logging.py | 2 ++ Lib/test/test_os.py | 9 ++++++-- Lib/test/test_signal.py | 6 ++++++ Lib/test/test_tomllib/test_misc.py | 7 +++++-- Lib/test/test_zipimport.py | 1 + ...2-05-15-15-25-05.gh-issue-90473.MoPHYW.rst | 1 + Modules/timemodule.c | 2 +- Parser/parser.c | 6 +++++- Tools/peg_generator/pegen/c_generator.py | 6 +++++- Tools/wasm/README.md | 21 +++++++++++++++++-- Tools/wasm/config.site-wasm32-wasi | 21 +++++++++++++++++++ configure | 1 + configure.ac | 2 ++ 20 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-15-15-25-05.gh-issue-90473.MoPHYW.rst diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 8dd89c6850794a..3efd6beb035a1a 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -12,8 +12,14 @@ extern "C" { struct pyruntimestate; struct _ceval_runtime_state; +/* WASI has limited call stack. wasmtime 0.36 can handle sufficient amount of + C stack frames for little more than 750 recursions. */ #ifndef Py_DEFAULT_RECURSION_LIMIT -# define Py_DEFAULT_RECURSION_LIMIT 1000 +# ifdef __wasi__ +# define Py_DEFAULT_RECURSION_LIMIT 750 +# else +# define Py_DEFAULT_RECURSION_LIMIT 1000 +# endif #endif #include "pycore_interp.h" // PyInterpreterState.eval_frame diff --git a/Lib/platform.py b/Lib/platform.py index 3f3f25a2c92d3b..c272c407c77768 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -186,6 +186,10 @@ def libc_ver(executable=None, lib='', version='', chunksize=16384): executable = sys.executable + if not executable: + # sys.executable is not set. + return lib, version + V = _comparable_version # We use os.path.realpath() # here to work around problems with Cygwin not being diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 28549a645b0f57..84e1c047f92191 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -545,8 +545,14 @@ def format_attr(attr, value): def collect_socket(info_add): import socket - hostname = socket.gethostname() - info_add('socket.hostname', hostname) + try: + hostname = socket.gethostname() + except OSError: + # WASI SDK 15.0 does not have gethostname(2). + if sys.platform != "wasi": + raise + else: + info_add('socket.hostname', hostname) def collect_sqlite(info_add): diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index e4bda940b3dd60..c284fc67b64026 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -199,6 +199,11 @@ def get_original_stdout(): def _force_run(path, func, *args): try: return func(*args) + except FileNotFoundError as err: + # chmod() won't fix a missing file. + if verbose >= 2: + print('%s: %s' % (err.__class__.__name__, err)) + raise except OSError as err: if verbose >= 2: print('%s: %s' % (err.__class__.__name__, err)) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 487a4fa2a9540d..d4357243ddabf4 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -109,7 +109,9 @@ def __getitem__(self, key): self.assertEqual(d['z'], 12) def test_extended_arg(self): - longexpr = 'x = x or ' + '-x' * 2500 + # default: 1000 * 2.5 = 2500 repetitions + repeat = int(sys.getrecursionlimit() * 2.5) + longexpr = 'x = x or ' + '-x' * repeat g = {} code = ''' def f(x): diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index e4984d3cd559e3..c26cdc028cc890 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -9,7 +9,9 @@ from weakref import proxy from functools import wraps -from test.support import cpython_only, swap_attr, gc_collect, is_emscripten +from test.support import ( + cpython_only, swap_attr, gc_collect, is_emscripten, is_wasi +) from test.support.os_helper import (TESTFN, TESTFN_UNICODE, make_bad_fd) from test.support.warnings_helper import check_warnings from collections import UserList @@ -65,6 +67,7 @@ def testAttributes(self): self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops') + @unittest.skipIf(is_wasi, "WASI does not expose st_blksize.") def testBlksize(self): # test private _blksize attribute blksize = io.DEFAULT_BUFFER_SIZE diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 8f6bec16200534..3c11c59baef6e5 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -156,6 +156,8 @@ def test_seekable(self): def skip_no_disk_space(path, required): def decorator(fun): def wrapper(*args, **kwargs): + if not hasattr(shutil, "disk_usage"): + raise unittest.SkipTest("requires shutil.disk_usage") if shutil.disk_usage(os.path.realpath(path)).free < required: hsize = int(required / 1024 / 1024) raise unittest.SkipTest( diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index e69afae484aa77..fd562322a76372 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -5280,6 +5280,7 @@ def test_emit_after_closing_in_write_mode(self): self.assertEqual(fp.read().strip(), '1') class RotatingFileHandlerTest(BaseFileTest): + @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.") def test_should_not_rollover(self): # If maxbytes is zero rollover never occurs rh = logging.handlers.RotatingFileHandler( @@ -5387,6 +5388,7 @@ def rotator(source, dest): rh.close() class TimedRotatingFileHandlerTest(BaseFileTest): + @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.") def test_should_not_rollover(self): # See bpo-45401. Should only ever rollover regular files fh = logging.handlers.TimedRotatingFileHandler( diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 36ad587760d701..ae071821e1ccfa 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -11,7 +11,6 @@ import fractions import itertools import locale -import mmap import os import pickle import select @@ -59,6 +58,10 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize +try: + import mmap +except ImportError: + mmap = None from test.support.script_helper import assert_python_ok from test.support import unix_shell @@ -2167,7 +2170,8 @@ def test_fchown(self): @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()') @unittest.skipIf( - support.is_emscripten, "musl libc issue on Emscripten, bpo-46390" + support.is_emscripten or support.is_wasi, + "musl libc issue on Emscripten/WASI, bpo-46390" ) def test_fpathconf(self): self.check(os.pathconf, "PC_NAME_MAX") @@ -2460,6 +2464,7 @@ def test_kill_int(self): # os.kill on Windows can take an int which gets set as the exit code self._kill(100) + @unittest.skipIf(mmap is None, "requires mmap") def _kill_with_event(self, event, name): tagname = "test_os_%s" % uuid.uuid1() m = mmap.mmap(-1, 1, tagname) diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 6d3b299b24ccac..6aa529b0620001 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -107,6 +107,10 @@ def test_interprocess_signal(self): script = os.path.join(dirname, 'signalinterproctester.py') assert_python_ok(script) + @unittest.skipUnless( + hasattr(signal, "valid_signals"), + "requires signal.valid_signals" + ) def test_valid_signals(self): s = signal.valid_signals() self.assertIsInstance(s, set) @@ -212,6 +216,7 @@ def test_invalid_fd(self): self.assertRaises((ValueError, OSError), signal.set_wakeup_fd, fd) + @unittest.skipUnless(support.has_socket_support, "needs working sockets.") def test_invalid_socket(self): sock = socket.socket() fd = sock.fileno() @@ -241,6 +246,7 @@ def test_set_wakeup_fd_result(self): self.assertEqual(signal.set_wakeup_fd(-1), -1) @unittest.skipIf(support.is_emscripten, "Emscripten cannot fstat pipes.") + @unittest.skipUnless(support.has_socket_support, "needs working sockets.") def test_set_wakeup_fd_socket_result(self): sock1 = socket.socket() self.addCleanup(sock1.close) diff --git a/Lib/test/test_tomllib/test_misc.py b/Lib/test/test_tomllib/test_misc.py index 76fa5905fa49ef..378db58f255945 100644 --- a/Lib/test/test_tomllib/test_misc.py +++ b/Lib/test/test_tomllib/test_misc.py @@ -6,6 +6,7 @@ import datetime from decimal import Decimal as D from pathlib import Path +import sys import tempfile import unittest @@ -91,11 +92,13 @@ def test_deepcopy(self): self.assertEqual(obj_copy, expected_obj) def test_inline_array_recursion_limit(self): - nest_count = 470 + # 470 with default recursion limit + nest_count = int(sys.getrecursionlimit() * 0.47) recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]" tomllib.loads(recursive_array_toml) def test_inline_table_recursion_limit(self): - nest_count = 310 + # 310 with default recursion limit + nest_count = int(sys.getrecursionlimit() * 0.31) recursive_table_toml = nest_count * "key = {" + nest_count * "}" tomllib.loads(recursive_table_toml) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 85dbf4d8f68eb6..66789262dd6ca1 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -804,6 +804,7 @@ def testEmptyFile(self): os_helper.create_empty_file(TESTMOD) self.assertZipFailure(TESTMOD) + @unittest.skipIf(support.is_wasi, "mode 000 not supported.") def testFileUnreadable(self): os_helper.unlink(TESTMOD) fd = os.open(TESTMOD, os.O_CREAT, 000) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-15-15-25-05.gh-issue-90473.MoPHYW.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-15-15-25-05.gh-issue-90473.MoPHYW.rst new file mode 100644 index 00000000000000..1f9f45a511fbae --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-15-15-25-05.gh-issue-90473.MoPHYW.rst @@ -0,0 +1 @@ +Decrease default recursion limit on WASI to address limited call stack size. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 7475ef344b72b2..18f9ddb909c028 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1481,7 +1481,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(HAVE_CLOCK_GETTIME) && \ defined(CLOCK_PROCESS_CPUTIME_ID) && \ - !defined(__EMSCRIPTEN__) + !defined(__EMSCRIPTEN__) && !defined(__wasi__) #define HAVE_THREAD_TIME #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability) diff --git a/Parser/parser.c b/Parser/parser.c index adc8d509eb7d7d..08bf6d2945600d 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -7,7 +7,11 @@ # define D(x) #endif -# define MAXSTACK 6000 +#ifdef __wasi__ +# define MAXSTACK 4000 +#else +# define MAXSTACK 6000 +#endif static const int n_keyword_lists = 9; static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 56a1e5a5a14fb0..65bfd5900a6961 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -37,7 +37,11 @@ # define D(x) #endif -# define MAXSTACK 6000 +#ifdef __wasi__ +# define MAXSTACK 4000 +#else +# define MAXSTACK 6000 +#endif """ diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md index 83806f0581ace3..977b2bb2a8ab93 100644 --- a/Tools/wasm/README.md +++ b/Tools/wasm/README.md @@ -220,10 +220,27 @@ AddType application/wasm wasm # WASI (wasm32-wasi) -WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) and -currently [wasix](https://github.com/singlestore-labs/wasix) for POSIX +WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 15.0+ +and currently [wasix](https://github.com/singlestore-labs/wasix) for POSIX compatibility stubs. +## WASI limitations and issues (WASI SDK 15.0) + +A lot of Emscripten limitations also apply to WASI. Noticable restrictions +are: + +- Call stack size is limited. Default recursion limit and parser stack size + are smaller than in regular Python builds. +- ``socket(2)`` cannot create new socket file descriptors. WASI programs can + call read/write/accept on a file descriptor that is passed into the process. +- ``socket.gethostname()`` and host name resolution APIs like + ``socket.gethostbyname()`` are not implemented and always fail. +- ``chmod(2)`` is not available. It's not possible to modify file permissions, + yet. A future version of WASI may provide a limited ``set_permissions`` API. +- File locking (``fcntl``) is not available. +- ``os.pipe()``, ``os.mkfifo()``, and ``os.mknod()`` are not supported. + + # Detect WebAssembly builds ## Python code diff --git a/Tools/wasm/config.site-wasm32-wasi b/Tools/wasm/config.site-wasm32-wasi index 255e99c279a0a3..ee3fc830e3d8a3 100644 --- a/Tools/wasm/config.site-wasm32-wasi +++ b/Tools/wasm/config.site-wasm32-wasi @@ -17,3 +17,24 @@ ac_cv_header_sys_resource_h=no # undefined symbols / unsupported features ac_cv_func_eventfd=no + +# WASI SDK 15.0 has no pipe syscall. +ac_cv_func_pipe=no + +# WASI SDK 15.0 cannot create fifos and special files. +ac_cv_func_mkfifo=no +ac_cv_func_mkfifoat=no +ac_cv_func_mknod=no +ac_cv_func_mknodat=no + +# fdopendir() fails on SDK 15.0, +# OSError: [Errno 28] Invalid argument: '.' +ac_cv_func_fdopendir=no + +# WASIX stubs we don't want to use. +ac_cv_func_kill=no + +# WASI sockets are limited to operations on given socket fd and inet sockets. +# Disable AF_UNIX and AF_PACKET support, see socketmodule.h. +ac_cv_header_sys_un_h=no +ac_cv_header_netpacket_packet_h=no diff --git a/configure b/configure index 02810880e914f9..6fa4051310b124 100755 --- a/configure +++ b/configure @@ -22611,6 +22611,7 @@ case $ac_sys_system in #( py_cv_module__ctypes_test=n/a + py_cv_module_fcntl=n/a py_cv_module_=n/a diff --git a/configure.ac b/configure.ac index eab326232b14d7..bef4904325b521 100644 --- a/configure.ac +++ b/configure.ac @@ -6690,8 +6690,10 @@ AS_CASE([$ac_sys_system], ], [Emscripten/node*], [], [WASI/*], [ + dnl WASI SDK 15.0 does not support file locking. PY_STDLIB_MOD_SET_NA( [_ctypes_test], + [fcntl], ) ] ) From c5f5f978ca6b8b62effcbc4aa61932b76718da78 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Thu, 19 May 2022 19:25:22 +0530 Subject: [PATCH 08/19] GH-92955: fix memory leak in code object lines and positions iterators (gh-92956) --- .../2022-05-19-13-25-50.gh-issue-92955.kmNV33.rst | 1 + Objects/codeobject.c | 8 ++++---- Objects/object.c | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-19-13-25-50.gh-issue-92955.kmNV33.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-19-13-25-50.gh-issue-92955.kmNV33.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-19-13-25-50.gh-issue-92955.kmNV33.rst new file mode 100644 index 00000000000000..09f03e520c436a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-19-13-25-50.gh-issue-92955.kmNV33.rst @@ -0,0 +1 @@ +Fix memory leak in code object's lines and positions iterators as they were not finalized at exit. Patch by Kumar Aditya. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index c2b29be1fe8693..68b0b1efb2e14c 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -1096,7 +1096,7 @@ lineiter_next(lineiterator *li) return result; } -static PyTypeObject LineIterator = { +PyTypeObject _PyLineIterator = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "line_iterator", /* tp_name */ sizeof(lineiterator), /* tp_basicsize */ @@ -1142,7 +1142,7 @@ static PyTypeObject LineIterator = { static lineiterator * new_linesiterator(PyCodeObject *code) { - lineiterator *li = (lineiterator *)PyType_GenericAlloc(&LineIterator, 0); + lineiterator *li = (lineiterator *)PyType_GenericAlloc(&_PyLineIterator, 0); if (li == NULL) { return NULL; } @@ -1196,7 +1196,7 @@ positionsiter_next(positionsiterator* pi) _source_offset_converter, &pi->pi_endcolumn); } -static PyTypeObject PositionsIterator = { +PyTypeObject _PyPositionsIterator = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "positions_iterator", /* tp_name */ sizeof(positionsiterator), /* tp_basicsize */ @@ -1242,7 +1242,7 @@ static PyTypeObject PositionsIterator = { static PyObject* code_positionsiterator(PyCodeObject* code, PyObject* Py_UNUSED(args)) { - positionsiterator* pi = (positionsiterator*)PyType_GenericAlloc(&PositionsIterator, 0); + positionsiterator* pi = (positionsiterator*)PyType_GenericAlloc(&_PyPositionsIterator, 0); if (pi == NULL) { return NULL; } diff --git a/Objects/object.c b/Objects/object.c index c9bb60eaed87c1..95045ed03d5dbc 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1846,6 +1846,8 @@ extern PyTypeObject PyHKEY_Type; #endif extern PyTypeObject _Py_GenericAliasIterType; extern PyTypeObject _PyMemoryIter_Type; +extern PyTypeObject _PyLineIterator; +extern PyTypeObject _PyPositionsIterator; static PyTypeObject* static_types[] = { // The two most important base types: must be initialized first and @@ -1944,12 +1946,14 @@ static PyTypeObject* static_types[] = { &_PyHamt_CollisionNode_Type, &_PyHamt_Type, &_PyInterpreterID_Type, + &_PyLineIterator, &_PyManagedBuffer_Type, &_PyMemoryIter_Type, &_PyMethodWrapper_Type, &_PyNamespace_Type, &_PyNone_Type, &_PyNotImplemented_Type, + &_PyPositionsIterator, &_PyUnicodeASCIIIter_Type, &_PyUnion_Type, &_PyWeakref_CallableProxyType, From 6b51773afd5658e15d23ce220f66fcc39c02dcae Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 19 May 2022 07:07:54 -0700 Subject: [PATCH 09/19] gh-91491: Complete Whats New in 3.11 for typing (#92708) Fixes #91491 Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Co-authored-by: Alex Waygood --- Doc/whatsnew/3.11.rst | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 0cbb0ba77217f6..1fd5b35695ee35 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -730,6 +730,12 @@ For major changes, see :ref:`new-feat-related-type-hints-311`. the given type. At runtime it simply returns the received value. (Contributed by Jelle Zijlstra in :gh:`90638`.) +* :data:`typing.TypedDict` types can now be generic. (Contributed by + Samodya Abey in :gh:`89026`.) + +* :class:`~typing.NamedTuple` types can now be generic. + (Contributed by Serhiy Storchaka in :issue:`43923`.) + * Allow subclassing of :class:`typing.Any`. This is useful for avoiding type checker errors related to highly dynamic class, such as mocks. (Contributed by Shantanu Jain in :gh:`91154`.) @@ -743,11 +749,33 @@ For major changes, see :ref:`new-feat-related-type-hints-311`. to clear all registered overloads of a function. (Contributed by Jelle Zijlstra in :gh:`89263`.) -* :data:`typing.TypedDict` subclasses can now be generic. (Contributed by - Samodya Abey in :gh:`89026`.) +* The :meth:`__init__` method of :class:`~typing.Protocol` subclasses + is now preserved. (Contributed by Adrian Garcia Badarasco in :gh:`88970`.) -* :class:`~typing.NamedTuple` subclasses can now be generic. - (Contributed by Serhiy Storchaka in :issue:`43923`.) +* The representation of empty tuple types (``Tuple[()]``) is simplified. + This affects introspection, e.g. ``get_args(Tuple[()])`` now evaluates + to ``()`` instead of ``((),)``. + (Contributed by Serhiy Storchaka in :gh:`91137`.) + +* Loosen runtime requirements for type annotations by removing the callable + check in the private ``typing._type_check`` function. (Contributed by + Gregory Beauregard in :gh:`90802`.) + +* :func:`typing.get_type_hints` now supports evaluating strings as forward + references in :ref:`PEP 585 generic aliases `. + (Contributed by Niklas Rosenstein in :gh:`85542`.) + +* :func:`typing.get_type_hints` no longer adds :data:`~typing.Optional` + to parameters with ``None`` as a default. (Contributed by Nikita Sobolev + in :gh:`90353`.) + +* :func:`typing.get_type_hints` now supports evaluating bare stringified + :data:`~typing.ClassVar` annotations. (Contributed by Gregory Beauregard + in :gh:`90711`.) + +* :func:`typing.no_type_check` no longer modifies external classes and functions. + It also now correctly marks classmethods as not to be type checked. (Contributed + by Nikita Sobolev in :gh:`90729`.) tkinter @@ -1236,6 +1264,10 @@ Deprecated wherever possible. (Contributed by Alex Waygood in :gh:`92332`.) +* The keyword argument syntax for constructing :data:`~typing.TypedDict` types + is now deprecated. Support will be removed in Python 3.13. (Contributed by + Jingchen Ye in :gh:`90224`.) + Pending Removal in Python 3.12 ============================== From 30deeac64925effe46cb5f1cd091ccb4c850ce83 Mon Sep 17 00:00:00 2001 From: David Foster Date: Thu, 19 May 2022 08:47:16 -0600 Subject: [PATCH 10/19] gh-92675: venv: Fix ensure_directories() to again accept a Path for env_dir (#92676) Co-authored-by: Jelle Zijlstra Co-authored-by: Alex Waygood --- Lib/test/test_venv.py | 20 ++++++++++++++++--- Lib/venv/__init__.py | 2 +- ...2-05-19-13-33-18.gh-issue-92675.ZeerMZ.rst | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-05-19-13-33-18.gh-issue-92675.ZeerMZ.rst diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 9f2ecf3be644a5..37b61a780cb07b 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -8,6 +8,7 @@ import ensurepip import os import os.path +import pathlib import re import shutil import struct @@ -99,12 +100,23 @@ def isdir(self, *args): fn = self.get_env_file(*args) self.assertTrue(os.path.isdir(fn)) - def test_defaults(self): + def test_defaults_with_str_path(self): """ - Test the create function with default arguments. + Test the create function with default arguments and a str path. """ rmtree(self.env_dir) self.run_with_capture(venv.create, self.env_dir) + self._check_output_of_default_create() + + def test_defaults_with_pathlib_path(self): + """ + Test the create function with default arguments and a pathlib.Path path. + """ + rmtree(self.env_dir) + self.run_with_capture(venv.create, pathlib.Path(self.env_dir)) + self._check_output_of_default_create() + + def _check_output_of_default_create(self): self.isdir(self.bindir) self.isdir(self.include) self.isdir(*self.lib) @@ -474,7 +486,9 @@ def test_pathsep_error(self): the path separator. """ rmtree(self.env_dir) - self.assertRaises(ValueError, venv.create, self.env_dir + os.pathsep) + bad_itempath = self.env_dir + os.pathsep + self.assertRaises(ValueError, venv.create, bad_itempath) + self.assertRaises(ValueError, venv.create, pathlib.Path(bad_itempath)) @requireVenvCreate class EnsurePipTest(BaseTest): diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 7bfbadda7b4970..6032f3648e15ff 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -116,7 +116,7 @@ def create_if_needed(d): elif os.path.islink(d) or os.path.isfile(d): raise ValueError('Unable to create directory %r' % d) - if os.pathsep in env_dir: + if os.pathsep in os.fspath(env_dir): raise ValueError(f'Refusing to create a venv in {env_dir} because ' f'it contains the PATH separator {os.pathsep}.') if os.path.exists(env_dir) and self.clear: diff --git a/Misc/NEWS.d/next/Library/2022-05-19-13-33-18.gh-issue-92675.ZeerMZ.rst b/Misc/NEWS.d/next/Library/2022-05-19-13-33-18.gh-issue-92675.ZeerMZ.rst new file mode 100644 index 00000000000000..6adc024fc54154 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-19-13-33-18.gh-issue-92675.ZeerMZ.rst @@ -0,0 +1,2 @@ +Fix :func:`venv.ensure_directories` to accept :class:`pathlib.Path` arguments +in addition to :class:`str` paths. Patch by David Foster. From 97b9c1096feff77a564787ef520cc7d4e1d1c45f Mon Sep 17 00:00:00 2001 From: CAM Gerlach Date: Thu, 19 May 2022 08:59:07 -0600 Subject: [PATCH 11/19] gh-92417: Update docs and examples of doctest.IGNORE_EXCEPTION_DETAIL for Py>=3 (GH-92502) --- Doc/library/doctest.rst | 48 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index be5651d15a0c9a..2d50a49c6415e9 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -563,41 +563,35 @@ doctest decides whether actual output matches an example's expected output: .. data:: IGNORE_EXCEPTION_DETAIL - When specified, an example that expects an exception passes if an exception of - the expected type is raised, even if the exception detail does not match. For - example, an example expecting ``ValueError: 42`` will pass if the actual - exception raised is ``ValueError: 3*14``, but will fail, e.g., if - :exc:`TypeError` is raised. + When specified, doctests expecting exceptions pass so long as an exception + of the expected type is raised, even if the details + (message and fully-qualified exception name) don't match. - It will also ignore the module name used in Python 3 doctest reports. Hence - both of these variations will work with the flag specified, regardless of - whether the test is run under Python 2.7 or Python 3.2 (or later versions):: + For example, an example expecting ``ValueError: 42`` will pass if the actual + exception raised is ``ValueError: 3*14``, but will fail if, say, a + :exc:`TypeError` is raised instead. + It will also ignore any fully-qualified name included before the + exception class, which can vary between implementations and versions + of Python and the code/libraries in use. + Hence, all three of these variations will work with the flag specified: - >>> raise CustomError('message') + .. code-block:: pycon + + >>> raise Exception('message') Traceback (most recent call last): - CustomError: message + Exception: message - >>> raise CustomError('message') + >>> raise Exception('message') Traceback (most recent call last): - my_module.CustomError: message + builtins.Exception: message - Note that :const:`ELLIPSIS` can also be used to ignore the - details of the exception message, but such a test may still fail based - on whether or not the module details are printed as part of the - exception name. Using :const:`IGNORE_EXCEPTION_DETAIL` and the details - from Python 2.3 is also the only clear way to write a doctest that doesn't - care about the exception detail yet continues to pass under Python 2.3 or - earlier (those releases do not support :ref:`doctest directives - ` and ignore them as irrelevant comments). For example:: - - >>> (1, 2)[3] = 'moo' + >>> raise Exception('message') Traceback (most recent call last): - File "", line 1, in - TypeError: object doesn't support item assignment + __main__.Exception: message - passes under Python 2.3 and later Python versions with the flag specified, - even though the detail - changed in Python 2.4 to say "does not" instead of "doesn't". + Note that :const:`ELLIPSIS` can also be used to ignore the + details of the exception message, but such a test may still fail based + on whether the module name is present or matches exactly. .. versionchanged:: 3.2 :const:`IGNORE_EXCEPTION_DETAIL` now also ignores any information relating From fb082c2fc5a925085b179e63ca10b7f60b356d2f Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Thu, 19 May 2022 08:05:04 -0700 Subject: [PATCH 12/19] bpo-45393: help() on operator precedence has misleading entries (GH-31246) Fix the formatting for "await x" and "not x" in the operator precedence table. --- Doc/reference/expressions.rst | 4 ++-- .../next/Library/2022-02-09-23-44-27.bpo-45393.9v5Y8U.rst | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-02-09-23-44-27.bpo-45393.9v5Y8U.rst diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index b914c48d3d4cd5..1f461e3fed8e57 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1898,7 +1898,7 @@ precedence and have a left-to-right chaining feature as described in the | ``x[index]``, ``x[index:index]``, | Subscription, slicing, | | ``x(arguments...)``, ``x.attribute`` | call, attribute reference | +-----------------------------------------------+-------------------------------------+ -| :keyword:`await` ``x`` | Await expression | +| :keyword:`await x ` | Await expression | +-----------------------------------------------+-------------------------------------+ | ``**`` | Exponentiation [#]_ | +-----------------------------------------------+-------------------------------------+ @@ -1922,7 +1922,7 @@ precedence and have a left-to-right chaining feature as described in the | :keyword:`is`, :keyword:`is not`, ``<``, | tests and identity tests | | ``<=``, ``>``, ``>=``, ``!=``, ``==`` | | +-----------------------------------------------+-------------------------------------+ -| :keyword:`not` ``x`` | Boolean NOT | +| :keyword:`not x ` | Boolean NOT | +-----------------------------------------------+-------------------------------------+ | :keyword:`and` | Boolean AND | +-----------------------------------------------+-------------------------------------+ diff --git a/Misc/NEWS.d/next/Library/2022-02-09-23-44-27.bpo-45393.9v5Y8U.rst b/Misc/NEWS.d/next/Library/2022-02-09-23-44-27.bpo-45393.9v5Y8U.rst new file mode 100644 index 00000000000000..0a239b07d76bd1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-02-09-23-44-27.bpo-45393.9v5Y8U.rst @@ -0,0 +1,2 @@ +Fix the formatting for ``await x`` and ``not x`` in the operator precedence +table when using the :func:`help` system. From 639b62c9c479e38a6f91a80b261097574a1e7ac7 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 19 May 2022 16:25:58 +0100 Subject: [PATCH 13/19] gh-92417: `socket` docs: remove references to Python <3.3 (GH-92544) --- Doc/library/socket.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 4c193b892bda8f..95cd37a415df1e 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -233,9 +233,9 @@ resolution and/or the host configuration. For deterministic behavior use a numeric address in *host* portion. All errors raise exceptions. The normal exceptions for invalid argument types -and out-of-memory conditions can be raised; starting from Python 3.3, errors +and out-of-memory conditions can be raised. Errors related to socket or address semantics raise :exc:`OSError` or one of its -subclasses (they used to raise :exc:`socket.error`). +subclasses. Non-blocking mode is supported through :meth:`~socket.setblocking`. A generalization of this based on timeouts is supported through From 090df844ea16af3a5df79aba2b9c89ac6a31ba06 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 19 May 2022 16:28:51 +0100 Subject: [PATCH 14/19] gh-92417: `fractions`, `decimal`: Improve docs for alternative constructor methods (GH-92421) Co-authored-by: Ezio Melotti --- Doc/library/decimal.rst | 5 +++-- Doc/library/fractions.rst | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index 2ad84f20b5560f..d052581c970124 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -571,9 +571,10 @@ Decimal objects >>> Decimal(321).exp() Decimal('2.561702493119680037517373933E+139') - .. method:: from_float(f) + .. classmethod:: from_float(f) - Classmethod that converts a float to a decimal number, exactly. + Alternative constructor that only accepts instances of :class:`float` or + :class:`int`. Note `Decimal.from_float(0.1)` is not the same as `Decimal('0.1')`. Since 0.1 is not exactly representable in binary floating point, the diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index c893f2d5389d57..5f0ecf1f135ea5 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -114,10 +114,10 @@ another rational number, or from a string. .. versionadded:: 3.8 - .. method:: from_float(flt) + .. classmethod:: from_float(flt) - This class method constructs a :class:`Fraction` representing the exact - value of *flt*, which must be a :class:`float`. Beware that + Alternative constructor which only accepts instances of + :class:`float` or :class:`numbers.Integral`. Beware that ``Fraction.from_float(0.3)`` is not the same value as ``Fraction(3, 10)``. .. note:: @@ -126,10 +126,10 @@ another rational number, or from a string. :class:`Fraction` instance directly from a :class:`float`. - .. method:: from_decimal(dec) + .. classmethod:: from_decimal(dec) - This class method constructs a :class:`Fraction` representing the exact - value of *dec*, which must be a :class:`decimal.Decimal` instance. + Alternative constructor which only accepts instances of + :class:`decimal.Decimal` or :class:`numbers.Integral`. .. note:: From 84b86000e2bc32b0fbb6dfb6445a7ffc882067d2 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 19 May 2022 16:31:51 +0100 Subject: [PATCH 15/19] gh-92417: `subprocess` docs: remove note on compatibility with Python <3.5 (GH-92538) --- Doc/library/subprocess.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index ce581abdd1dced..4031a5f62167f0 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -33,9 +33,6 @@ The recommended approach to invoking subprocesses is to use the :func:`run` function for all use cases it can handle. For more advanced use cases, the underlying :class:`Popen` interface can be used directly. -The :func:`run` function was added in Python 3.5; if you need to retain -compatibility with older versions, see the :ref:`call-function-trio` section. - .. function:: run(args, *, stdin=None, input=None, stdout=None, stderr=None,\ capture_output=False, shell=False, cwd=None, timeout=None, \ From 2cdd57f119e3b85f1bfd28c7ff040e0d9bcaf115 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Thu, 19 May 2022 17:34:58 +0200 Subject: [PATCH 16/19] bpo-46879: Fix incorrect sphinx object names in doc (GH-31615) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API members documented in sphinx have an object name, which allow the documentation to be linked from other projects. Sphinx calculates the object name by prefixing the current module name to the directive argument, e.g: .. module:: foo .. function:: bar.baz becomes foo.bar.baz. Since these anchors aren't displayed in the documentation, some mistakes have crept in, namely the Python stdlib documentation currently contains the objects: * asyncio.asyncio.subprocess.DEVNULL * asyncio.asyncio.subprocess.PIPE * asyncio.asyncio.subprocess.STDOUT * asyncio.asyncio.subprocess.Process * multiprocessing.sharedctypes.multiprocessing.Manager * xml.etree.ElementTree.xml.etree.ElementInclude This commit fixes this by making use of the :module: option which without an argument makes sphinx take the directive argument as is for the object name (avoiding the prefixing of the current module name that led to these broken object names). Co-authored-by: Łukasz Langa --- Doc/library/asyncio-subprocess.rst | 4 ++++ Doc/library/multiprocessing.rst | 1 + Doc/library/xml.etree.elementtree.rst | 2 ++ 3 files changed, 7 insertions(+) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst index e5000532a895dd..28d0b21e8180b6 100644 --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -124,6 +124,7 @@ Constants ========= .. data:: asyncio.subprocess.PIPE + :module: Can be passed to the *stdin*, *stdout* or *stderr* parameters. @@ -137,11 +138,13 @@ Constants attributes will point to :class:`StreamReader` instances. .. data:: asyncio.subprocess.STDOUT + :module: Special value that can be used as the *stderr* argument and indicates that standard error should be redirected into standard output. .. data:: asyncio.subprocess.DEVNULL + :module: Special value that can be used as the *stdin*, *stdout* or *stderr* argument to process creation functions. It indicates that the special file @@ -157,6 +160,7 @@ wrapper that allows communicating with subprocesses and watching for their completion. .. class:: asyncio.subprocess.Process + :module: An object that wraps OS processes created by the :func:`create_subprocess_exec` and :func:`create_subprocess_shell` diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 70802ee1fdecb9..2a66b0f65c0882 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1666,6 +1666,7 @@ different machines. A manager object controls a server process which manages proxies. .. function:: multiprocessing.Manager() + :module: Returns a started :class:`~multiprocessing.managers.SyncManager` object which can be used for sharing objects between processes. The returned manager diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index e3932bc9e659fe..2fe0d2e082fb3a 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -826,6 +826,7 @@ Functions ^^^^^^^^^ .. function:: xml.etree.ElementInclude.default_loader( href, parse, encoding=None) + :module: Default loader. This default loader reads an included resource from disk. *href* is a URL. *parse* is for parse mode either "xml" or "text". *encoding* @@ -837,6 +838,7 @@ Functions .. function:: xml.etree.ElementInclude.include( elem, loader=None, base_url=None, \ max_depth=6) + :module: This function expands XInclude directives. *elem* is the root element. *loader* is an optional resource loader. If omitted, it defaults to :func:`default_loader`. From 09be18a73d81aa82cc57a782f3b0a9811e43ad3b Mon Sep 17 00:00:00 2001 From: Michael Osipov Date: Thu, 19 May 2022 17:42:21 +0200 Subject: [PATCH 17/19] gh-78630: Drop invalid HP aCC compiler switch -fPIC on HP-UX (#8847) At compile time, '+z' is already properly used with HP aCC, and shared libraries are correctly linked with '+b'. The '-fPIC' switch can safely be dropped. --- .../NEWS.d/next/Build/2018-08-21-11-10-18.bpo-34449.Z3qm3c.rst | 1 + setup.py | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2018-08-21-11-10-18.bpo-34449.Z3qm3c.rst diff --git a/Misc/NEWS.d/next/Build/2018-08-21-11-10-18.bpo-34449.Z3qm3c.rst b/Misc/NEWS.d/next/Build/2018-08-21-11-10-18.bpo-34449.Z3qm3c.rst new file mode 100644 index 00000000000000..53b75aee9cc272 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-08-21-11-10-18.bpo-34449.Z3qm3c.rst @@ -0,0 +1 @@ +Drop invalid compiler switch ``-fPIC`` for HP aCC on HP-UX. Patch by Michael Osipov. diff --git a/setup.py b/setup.py index f45cd6de33749b..4c497346e8d7e2 100644 --- a/setup.py +++ b/setup.py @@ -1408,9 +1408,6 @@ def detect_ctypes(self): # finding some -z option for the Sun compiler. extra_link_args.append('-mimpure-text') - elif HOST_PLATFORM.startswith('hp-ux'): - extra_link_args.append('-fPIC') - ext = Extension('_ctypes', include_dirs=include_dirs, extra_compile_args=extra_compile_args, From 8db2b3b6878aba9f12844526bce966b7eed81aee Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 19 May 2022 18:46:15 +0300 Subject: [PATCH 18/19] bpo-28249: fix `lineno` location for empty `DocTest` instances (GH-30498) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Co-authored-by: Łukasz Langa --- Lib/doctest.py | 14 ++++-- Lib/test/doctest_lineno.py | 50 +++++++++++++++++++ Lib/test/test_doctest.py | 23 ++++++++- .../2022-01-09-14-23-00.bpo-28249.4dzB80.rst | 2 + 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 Lib/test/doctest_lineno.py create mode 100644 Misc/NEWS.d/next/Library/2022-01-09-14-23-00.bpo-28249.4dzB80.rst diff --git a/Lib/doctest.py b/Lib/doctest.py index ed94d15c0e2da4..b2ef2ce63672eb 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1085,19 +1085,21 @@ def _get_test(self, obj, name, module, globs, source_lines): def _find_lineno(self, obj, source_lines): """ - Return a line number of the given object's docstring. Note: - this method assumes that the object has a docstring. + Return a line number of the given object's docstring. + + Returns `None` if the given object does not have a docstring. """ lineno = None + docstring = getattr(obj, '__doc__', None) # Find the line number for modules. - if inspect.ismodule(obj): + if inspect.ismodule(obj) and docstring is not None: lineno = 0 # Find the line number for classes. # Note: this could be fooled if a class is defined multiple # times in a single file. - if inspect.isclass(obj): + if inspect.isclass(obj) and docstring is not None: if source_lines is None: return None pat = re.compile(r'^\s*class\s*%s\b' % @@ -1109,7 +1111,9 @@ def _find_lineno(self, obj, source_lines): # Find the line number for functions & methods. if inspect.ismethod(obj): obj = obj.__func__ - if inspect.isfunction(obj): obj = obj.__code__ + if inspect.isfunction(obj) and getattr(obj, '__doc__', None): + # We don't use `docstring` var here, because `obj` can be changed. + obj = obj.__code__ if inspect.istraceback(obj): obj = obj.tb_frame if inspect.isframe(obj): obj = obj.f_code if inspect.iscode(obj): diff --git a/Lib/test/doctest_lineno.py b/Lib/test/doctest_lineno.py new file mode 100644 index 00000000000000..be198513a1502c --- /dev/null +++ b/Lib/test/doctest_lineno.py @@ -0,0 +1,50 @@ +# This module is used in `test_doctest`. +# It must not have a docstring. + +def func_with_docstring(): + """Some unrelated info.""" + + +def func_without_docstring(): + pass + + +def func_with_doctest(): + """ + This function really contains a test case. + + >>> func_with_doctest.__name__ + 'func_with_doctest' + """ + return 3 + + +class ClassWithDocstring: + """Some unrelated class information.""" + + +class ClassWithoutDocstring: + pass + + +class ClassWithDoctest: + """This class really has a test case in it. + + >>> ClassWithDoctest.__name__ + 'ClassWithDoctest' + """ + + +class MethodWrapper: + def method_with_docstring(self): + """Method with a docstring.""" + + def method_without_docstring(self): + pass + + def method_with_doctest(self): + """ + This has a doctest! + >>> MethodWrapper.method_with_doctest.__name__ + 'method_with_doctest' + """ diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 3e7f3782d89f42..a4aab6cf4db3b5 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -25,6 +25,7 @@ # NOTE: There are some additional tests relating to interaction with # zipimport in the test_zipimport_support test module. +# There are also related tests in `test_doctest2` module. ###################################################################### ## Sample Objects (used by test cases) @@ -460,7 +461,7 @@ def basics(): r""" >>> tests = finder.find(sample_func) >>> print(tests) # doctest: +ELLIPSIS - [] + [] The exact name depends on how test_doctest was invoked, so allow for leading path components. @@ -642,6 +643,26 @@ def basics(): r""" 1 SampleClass.double 1 SampleClass.get +When used with `exclude_empty=False` we are also interested in line numbers +of doctests that are empty. +It used to be broken for quite some time until `bpo-28249`. + + >>> from test import doctest_lineno + >>> tests = doctest.DocTestFinder(exclude_empty=False).find(doctest_lineno) + >>> for t in tests: + ... print('%5s %s' % (t.lineno, t.name)) + None test.doctest_lineno + 22 test.doctest_lineno.ClassWithDocstring + 30 test.doctest_lineno.ClassWithDoctest + None test.doctest_lineno.ClassWithoutDocstring + None test.doctest_lineno.MethodWrapper + 39 test.doctest_lineno.MethodWrapper.method_with_docstring + 45 test.doctest_lineno.MethodWrapper.method_with_doctest + None test.doctest_lineno.MethodWrapper.method_without_docstring + 4 test.doctest_lineno.func_with_docstring + 12 test.doctest_lineno.func_with_doctest + None test.doctest_lineno.func_without_docstring + Turning off Recursion ~~~~~~~~~~~~~~~~~~~~~ DocTestFinder can be told not to look for tests in contained objects diff --git a/Misc/NEWS.d/next/Library/2022-01-09-14-23-00.bpo-28249.4dzB80.rst b/Misc/NEWS.d/next/Library/2022-01-09-14-23-00.bpo-28249.4dzB80.rst new file mode 100644 index 00000000000000..b5f1312d768669 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-09-14-23-00.bpo-28249.4dzB80.rst @@ -0,0 +1,2 @@ +Set :attr:`doctest.DocTest.lineno` to ``None`` when object does not have +:attr:`__doc__`. From 70aa1b9b912d8254df3c61ae0a55464962f4c087 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 19 May 2022 16:48:44 +0100 Subject: [PATCH 19/19] gh-92417: `importlib` docs: remove references to unsupported Python versions (GH-92424) Co-authored-by: CAM Gerlach --- Doc/library/importlib.metadata.rst | 6 +++--- Doc/library/importlib.rst | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index b3740178d6f9c7..d40ed70d5cd83f 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -17,9 +17,9 @@ package metadata. Built in part on Python's import system, this library intends to replace similar functionality in the `entry point API`_ and `metadata API`_ of ``pkg_resources``. Along with -:mod:`importlib.resources` in Python 3.7 -and newer (backported as `importlib_resources`_ for older versions of -Python), this can eliminate the need to use the older and less efficient +:mod:`importlib.resources` (with new features backported to the +`importlib_resources`_ package), this can eliminate the need to use the older +and less efficient ``pkg_resources`` package. By "installed package" we generally mean a third-party package installed into diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 0241fb30b6efb2..f19532213940e2 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -414,8 +414,8 @@ ABC hierarchy:: .. versionadded:: 3.4 - .. versionchanged:: 3.5 - Starting in Python 3.6, this method will not be optional when + .. versionchanged:: 3.6 + This method is no longer optional when :meth:`exec_module` is defined. .. method:: exec_module(module) @@ -1273,8 +1273,7 @@ import, then you should use :func:`importlib.util.find_spec`. Importing a source file directly '''''''''''''''''''''''''''''''' -To import a Python source file directly, use the following recipe -(Python 3.5 and newer only):: +To import a Python source file directly, use the following recipe:: import importlib.util import sys @@ -1355,9 +1354,7 @@ Import itself is implemented in Python code, making it possible to expose most of the import machinery through importlib. The following helps illustrate the various APIs that importlib exposes by providing an approximate implementation of -:func:`importlib.import_module` (Python 3.4 and newer for the importlib usage, -Python 3.6 and newer for other parts of the code). -:: +:func:`importlib.import_module`:: import importlib.util import sys