Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 504 discussions
[3.13] gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084) (#129100)
by gpshead Jan. 20, 2025
by gpshead Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/c5e1131cfba5c6f083b149ea58a550db0f…
commit: c5e1131cfba5c6f083b149ea58a550db0f9e3a7a
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: gpshead <greg(a)krypto.org>
date: 2025-01-20T21:05:52Z
summary:
[3.13] gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084) (#129100)
gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084)
fix UBSan failures for `SemLockObject`
(cherry picked from commit 5ed5572cac7ef204767ddf8e8888e15672ba558e)
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
M Modules/_multiprocessing/semaphore.c
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
index 4de4ee6c78fbd1..8c6a4a279205d3 100644
--- a/Modules/_multiprocessing/semaphore.c
+++ b/Modules/_multiprocessing/semaphore.c
@@ -27,6 +27,8 @@ typedef struct {
char *name;
} SemLockObject;
+#define _SemLockObject_CAST(op) ((SemLockObject *)(op))
+
/*[python input]
class SEM_HANDLE_converter(CConverter):
type = "SEM_HANDLE"
@@ -575,8 +577,9 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
}
static void
-semlock_dealloc(SemLockObject* self)
+semlock_dealloc(PyObject *op)
{
+ SemLockObject *self = _SemLockObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
if (self->handle != SEM_FAILED)
@@ -717,7 +720,7 @@ _multiprocessing_SemLock___exit___impl(SemLockObject *self,
}
static int
-semlock_traverse(SemLockObject *s, visitproc visit, void *arg)
+semlock_traverse(PyObject *s, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(s));
return 0;
1
0
[3.12] gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084) (#129101)
by gpshead Jan. 20, 2025
by gpshead Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/9b335cc8104dd83a5a1343dc649d1f3606…
commit: 9b335cc8104dd83a5a1343dc649d1f3606682098
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: gpshead <greg(a)krypto.org>
date: 2025-01-20T21:00:09Z
summary:
[3.12] gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084) (#129101)
gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (GH-129084)
fix UBSan failures for `SemLockObject`
(cherry picked from commit 5ed5572cac7ef204767ddf8e8888e15672ba558e)
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
M Modules/_multiprocessing/semaphore.c
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
index c7df82dfe2d0cc..bc718e273a8721 100644
--- a/Modules/_multiprocessing/semaphore.c
+++ b/Modules/_multiprocessing/semaphore.c
@@ -23,6 +23,8 @@ typedef struct {
char *name;
} SemLockObject;
+#define _SemLockObject_CAST(op) ((SemLockObject *)(op))
+
/*[python input]
class SEM_HANDLE_converter(CConverter):
type = "SEM_HANDLE"
@@ -567,8 +569,9 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
}
static void
-semlock_dealloc(SemLockObject* self)
+semlock_dealloc(PyObject *op)
{
+ SemLockObject *self = _SemLockObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
if (self->handle != SEM_FAILED)
@@ -706,7 +709,7 @@ _multiprocessing_SemLock___exit___impl(SemLockObject *self,
}
static int
-semlock_traverse(SemLockObject *s, visitproc visit, void *arg)
+semlock_traverse(PyObject *s, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(s));
return 0;
1
0
gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (#129084)
by gpshead Jan. 20, 2025
by gpshead Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/5ed5572cac7ef204767ddf8e8888e15672…
commit: 5ed5572cac7ef204767ddf8e8888e15672ba558e
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: gpshead <greg(a)krypto.org>
date: 2025-01-20T20:43:55Z
summary:
gh-111178: fix UBSan failures in `Modules/_multiprocessing/semaphore.c` (#129084)
fix UBSan failures for `SemLockObject`
files:
M Modules/_multiprocessing/semaphore.c
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
index 9eef7c25636899..036db2cd4c6c85 100644
--- a/Modules/_multiprocessing/semaphore.c
+++ b/Modules/_multiprocessing/semaphore.c
@@ -28,6 +28,8 @@ typedef struct {
char *name;
} SemLockObject;
+#define _SemLockObject_CAST(op) ((SemLockObject *)(op))
+
/*[python input]
class SEM_HANDLE_converter(CConverter):
type = "SEM_HANDLE"
@@ -576,8 +578,9 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
}
static void
-semlock_dealloc(SemLockObject* self)
+semlock_dealloc(PyObject *op)
{
+ SemLockObject *self = _SemLockObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
if (self->handle != SEM_FAILED)
@@ -718,7 +721,7 @@ _multiprocessing_SemLock___exit___impl(SemLockObject *self,
}
static int
-semlock_traverse(SemLockObject *s, visitproc visit, void *arg)
+semlock_traverse(PyObject *s, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(s));
return 0;
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/382340d5594a05d8a5362a06fe55119eec…
commit: 382340d5594a05d8a5362a06fe55119eec1d8e04
branch: main
author: Filipe Laíns 🇵🇸 <lains(a)riseup.net>
committer: FFY00 <filipe.lains(a)gmail.com>
date: 2025-01-20T20:41:27Z
summary:
doc: add social cards generation support in sphinxext-opengraph (#129085)
files:
A Doc/requirements-no-build.txt
M Doc/Makefile
diff --git a/Doc/Makefile b/Doc/Makefile
index b8896da4a91869..53af6aca659cef 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -13,7 +13,8 @@ JOBS = auto
PAPER =
SOURCES =
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
-REQUIREMENTS = requirements.txt
+IS_PYTHON_BUILD = $(shell $(PYTHON) -c 'import sysconfig; print("true") if sysconfig.is_python_build() else None')
+REQUIREMENTS = $(if $(IS_PYTHON_BUILD),requirements.txt,requirements-no-build.txt)
SPHINXERRORHANDLING = --fail-on-warning
# Internal variables.
diff --git a/Doc/requirements-no-build.txt b/Doc/requirements-no-build.txt
new file mode 100644
index 00000000000000..8b3c4d410a75a3
--- /dev/null
+++ b/Doc/requirements-no-build.txt
@@ -0,0 +1,7 @@
+-r requirements.txt
+
+# Requirements when not running the build Python,
+# such as optional native extensions.
+
+# Needed to support generating social cards in sphinxext-opengraph.
+--only-binary matplotlib
1
0
[3.12] GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143) (#129092)
by jaraco Jan. 20, 2025
by jaraco Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/03bce18992fd49f5f87697a21c0390fc60…
commit: 03bce18992fd49f5f87697a21c0390fc6082bfc7
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: jaraco <jaraco(a)jaraco.com>
date: 2025-01-20T20:40:28Z
summary:
[3.12] GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143) (#129092)
GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143)
(cherry picked from commit dda02eb7be62bf0af850a7521c77c90ea997df6c)
Co-authored-by: 5ec1cff <56485584+5ec1cff(a)users.noreply.github.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot](a)users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
M Lib/test/test_zipfile/test_core.py
M Lib/zipfile/__init__.py
diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py
index adb74345486b65..03520e57303c9d 100644
--- a/Lib/test/test_zipfile/test_core.py
+++ b/Lib/test/test_zipfile/test_core.py
@@ -1,3 +1,4 @@
+import _pyio
import array
import contextlib
import importlib.util
@@ -3440,5 +3441,87 @@ def test_too_short(self):
b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,)))
+class StatIO(_pyio.BytesIO):
+ """Buffer which remembers the number of bytes that were read."""
+
+ def __init__(self):
+ super().__init__()
+ self.bytes_read = 0
+
+ def read(self, size=-1):
+ bs = super().read(size)
+ self.bytes_read += len(bs)
+ return bs
+
+
+class StoredZipExtFileRandomReadTest(unittest.TestCase):
+ """Tests whether an uncompressed, unencrypted zip entry can be randomly
+ seek and read without reading redundant bytes."""
+ def test_stored_seek_and_read(self):
+
+ sio = StatIO()
+ # 20000 bytes
+ txt = b'0123456789' * 2000
+
+ # The seek length must be greater than ZipExtFile.MIN_READ_SIZE
+ # as `ZipExtFile._read2()` reads in blocks of this size and we
+ # need to seek out of the buffered data
+ read_buffer_size = zipfile.ZipExtFile.MIN_READ_SIZE
+ self.assertGreaterEqual(10002, read_buffer_size) # for forward seek test
+ self.assertGreaterEqual(5003, read_buffer_size) # for backward seek test
+ # The read length must be less than MIN_READ_SIZE, since we assume that
+ # only 1 block is read in the test.
+ read_length = 100
+ self.assertGreaterEqual(read_buffer_size, read_length) # for read() calls
+
+ with zipfile.ZipFile(sio, "w", compression=zipfile.ZIP_STORED) as zipf:
+ zipf.writestr("foo.txt", txt)
+
+ # check random seek and read on a file
+ with zipfile.ZipFile(sio, "r") as zipf:
+ with zipf.open("foo.txt", "r") as fp:
+ # Test this optimized read hasn't rewound and read from the
+ # start of the file (as in the case of the unoptimized path)
+
+ # forward seek
+ old_count = sio.bytes_read
+ forward_seek_len = 10002
+ current_pos = 0
+ fp.seek(forward_seek_len, os.SEEK_CUR)
+ current_pos += forward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # backward seek
+ old_count = sio.bytes_read
+ backward_seek_len = 5003
+ fp.seek(-backward_seek_len, os.SEEK_CUR)
+ current_pos -= backward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # eof flags test
+ fp.seek(0, os.SEEK_END)
+ fp.seek(12345, os.SEEK_SET)
+ current_pos = 12345
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 3e1cca472865b5..91b2e032e5f2d9 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -1140,13 +1140,15 @@ def seek(self, offset, whence=os.SEEK_SET):
self._offset = buff_offset
read_offset = 0
# Fast seek uncompressed unencrypted file
- elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0:
+ elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset != 0:
# disable CRC checking after first seeking - it would be invalid
self._expected_crc = None
# seek actual file taking already buffered data into account
read_offset -= len(self._readbuffer) - self._offset
self._fileobj.seek(read_offset, os.SEEK_CUR)
self._left -= read_offset
+ self._compress_left -= read_offset
+ self._eof = self._left <= 0
read_offset = 0
# flush read buffer
self._readbuffer = b''
diff --git a/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
new file mode 100644
index 00000000000000..f4c4ebce10729c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
@@ -0,0 +1,2 @@
+Completely support random access of uncompressed unencrypted read-only
+zip files obtained by :meth:`ZipFile.open <zipfile.ZipFile.open>`.
1
0
[3.12] doc: fix venv creating for the local Python using uv (GH-129094) (#129097)
by hugovk Jan. 20, 2025
by hugovk Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/728c6b89a66b7cb431a99fef835674ddbd…
commit: 728c6b89a66b7cb431a99fef835674ddbd765d37
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-20T21:13:23+02:00
summary:
[3.12] doc: fix venv creating for the local Python using uv (GH-129094) (#129097)
Co-authored-by: Filipe Laíns 🇵🇸 <lains(a)riseup.net>
files:
M Doc/Makefile
diff --git a/Doc/Makefile b/Doc/Makefile
index 1a66642a4a03ed..b8896da4a91869 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -172,7 +172,7 @@ venv:
else \
echo "Creating venv in $(VENVDIR)"; \
if $(UV) --version >/dev/null 2>&1; then \
- $(UV) venv $(VENVDIR); \
+ $(UV) venv --python=$(PYTHON) $(VENVDIR); \
VIRTUAL_ENV=$(VENVDIR) $(UV) pip install -r $(REQUIREMENTS); \
else \
$(PYTHON) -m venv $(VENVDIR); \
1
0
[3.13] doc: fix venv creating for the local Python using uv (GH-129094) (#129096)
by hugovk Jan. 20, 2025
by hugovk Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/207708246327c8b179529020007cedd94b…
commit: 207708246327c8b179529020007cedd94b19cd86
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-20T21:13:12+02:00
summary:
[3.13] doc: fix venv creating for the local Python using uv (GH-129094) (#129096)
Co-authored-by: Filipe Laíns 🇵🇸 <lains(a)riseup.net>
files:
M Doc/Makefile
diff --git a/Doc/Makefile b/Doc/Makefile
index 1a66642a4a03ed..b8896da4a91869 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -172,7 +172,7 @@ venv:
else \
echo "Creating venv in $(VENVDIR)"; \
if $(UV) --version >/dev/null 2>&1; then \
- $(UV) venv $(VENVDIR); \
+ $(UV) venv --python=$(PYTHON) $(VENVDIR); \
VIRTUAL_ENV=$(VENVDIR) $(UV) pip install -r $(REQUIREMENTS); \
else \
$(PYTHON) -m venv $(VENVDIR); \
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/da36bccdac6d45bda6f83563410567c04f…
commit: da36bccdac6d45bda6f83563410567c04f4b288c
branch: main
author: Filipe Laíns 🇵🇸 <lains(a)riseup.net>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-20T21:04:05+02:00
summary:
doc: fix venv creating for the local Python using uv (#129094)
files:
M Doc/Makefile
diff --git a/Doc/Makefile b/Doc/Makefile
index 1a66642a4a03ed..b8896da4a91869 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -172,7 +172,7 @@ venv:
else \
echo "Creating venv in $(VENVDIR)"; \
if $(UV) --version >/dev/null 2>&1; then \
- $(UV) venv $(VENVDIR); \
+ $(UV) venv --python=$(PYTHON) $(VENVDIR); \
VIRTUAL_ENV=$(VENVDIR) $(UV) pip install -r $(REQUIREMENTS); \
else \
$(PYTHON) -m venv $(VENVDIR); \
1
0
[3.13] GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143) (#129091)
by jaraco Jan. 20, 2025
by jaraco Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/03b2ecf41c6f4cc57aac3dd147b8b5dedc…
commit: 03b2ecf41c6f4cc57aac3dd147b8b5dedcafcd3d
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: jaraco <jaraco(a)jaraco.com>
date: 2025-01-20T18:28:52Z
summary:
[3.13] GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143) (#129091)
GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (GH-128143)
(cherry picked from commit dda02eb7be62bf0af850a7521c77c90ea997df6c)
Co-authored-by: 5ec1cff <56485584+5ec1cff(a)users.noreply.github.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot](a)users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
M Lib/test/test_zipfile/test_core.py
M Lib/zipfile/__init__.py
diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py
index 4ff9f9c34237c6..4b56f6a380f219 100644
--- a/Lib/test/test_zipfile/test_core.py
+++ b/Lib/test/test_zipfile/test_core.py
@@ -1,3 +1,4 @@
+import _pyio
import array
import contextlib
import importlib.util
@@ -3454,5 +3455,87 @@ def test_too_short(self):
b"zzz", zipfile._Extra.strip(b"zzz", (self.ZIP64_EXTRA,)))
+class StatIO(_pyio.BytesIO):
+ """Buffer which remembers the number of bytes that were read."""
+
+ def __init__(self):
+ super().__init__()
+ self.bytes_read = 0
+
+ def read(self, size=-1):
+ bs = super().read(size)
+ self.bytes_read += len(bs)
+ return bs
+
+
+class StoredZipExtFileRandomReadTest(unittest.TestCase):
+ """Tests whether an uncompressed, unencrypted zip entry can be randomly
+ seek and read without reading redundant bytes."""
+ def test_stored_seek_and_read(self):
+
+ sio = StatIO()
+ # 20000 bytes
+ txt = b'0123456789' * 2000
+
+ # The seek length must be greater than ZipExtFile.MIN_READ_SIZE
+ # as `ZipExtFile._read2()` reads in blocks of this size and we
+ # need to seek out of the buffered data
+ read_buffer_size = zipfile.ZipExtFile.MIN_READ_SIZE
+ self.assertGreaterEqual(10002, read_buffer_size) # for forward seek test
+ self.assertGreaterEqual(5003, read_buffer_size) # for backward seek test
+ # The read length must be less than MIN_READ_SIZE, since we assume that
+ # only 1 block is read in the test.
+ read_length = 100
+ self.assertGreaterEqual(read_buffer_size, read_length) # for read() calls
+
+ with zipfile.ZipFile(sio, "w", compression=zipfile.ZIP_STORED) as zipf:
+ zipf.writestr("foo.txt", txt)
+
+ # check random seek and read on a file
+ with zipfile.ZipFile(sio, "r") as zipf:
+ with zipf.open("foo.txt", "r") as fp:
+ # Test this optimized read hasn't rewound and read from the
+ # start of the file (as in the case of the unoptimized path)
+
+ # forward seek
+ old_count = sio.bytes_read
+ forward_seek_len = 10002
+ current_pos = 0
+ fp.seek(forward_seek_len, os.SEEK_CUR)
+ current_pos += forward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # backward seek
+ old_count = sio.bytes_read
+ backward_seek_len = 5003
+ fp.seek(-backward_seek_len, os.SEEK_CUR)
+ current_pos -= backward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # eof flags test
+ fp.seek(0, os.SEEK_END)
+ fp.seek(12345, os.SEEK_SET)
+ current_pos = 12345
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 8b636094fad3ca..82e307f78e8e3d 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -1163,13 +1163,15 @@ def seek(self, offset, whence=os.SEEK_SET):
self._offset = buff_offset
read_offset = 0
# Fast seek uncompressed unencrypted file
- elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0:
+ elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset != 0:
# disable CRC checking after first seeking - it would be invalid
self._expected_crc = None
# seek actual file taking already buffered data into account
read_offset -= len(self._readbuffer) - self._offset
self._fileobj.seek(read_offset, os.SEEK_CUR)
self._left -= read_offset
+ self._compress_left -= read_offset
+ self._eof = self._left <= 0
read_offset = 0
# flush read buffer
self._readbuffer = b''
diff --git a/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
new file mode 100644
index 00000000000000..f4c4ebce10729c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
@@ -0,0 +1,2 @@
+Completely support random access of uncompressed unencrypted read-only
+zip files obtained by :meth:`ZipFile.open <zipfile.ZipFile.open>`.
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/5d57959d7da8cfcef8df072a6ad53795c6…
commit: 5d57959d7da8cfcef8df072a6ad53795c60546aa
branch: main
author: Wulian <1055917385(a)qq.com>
committer: jaraco <jaraco(a)jaraco.com>
date: 2025-01-20T13:12:29-05:00
summary:
gh-91279: ZipFile.writestr now respect SOURCE_DATE_EPOCH (#124435)
files:
A Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst
M Doc/whatsnew/3.14.rst
M Lib/test/test_zipfile/test_core.py
M Lib/zipfile/__init__.py
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 7f149d5c03dfbb..0dcecd4944f2f6 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -730,6 +730,12 @@ zipinfo
(Contributed by Bénédikt Tran in :gh:`123424`.)
+* :meth:`zipfile.ZipFile.writestr` now respect ``SOURCE_DATE_EPOCH`` that
+ distributions can set centrally and have build tools consume this in order
+ to produce reproducible output.
+
+ (Contributed by Jiahao Li in :gh:`91279`.)
+
.. Add improved modules above alphabetically, not here at the end.
Optimizations
diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py
index 02e28d4004c01a..ab5fb650084327 100644
--- a/Lib/test/test_zipfile/test_core.py
+++ b/Lib/test/test_zipfile/test_core.py
@@ -20,7 +20,7 @@
from random import randint, random, randbytes
from test import archiver_tests
-from test.support import script_helper
+from test.support import script_helper, os_helper
from test.support import (
findfile, requires_zlib, requires_bz2, requires_lzma,
captured_stdout, captured_stderr, requires_subprocess,
@@ -1784,6 +1784,35 @@ def test_writestr_extended_local_header_issue1202(self):
zinfo.flag_bits |= zipfile._MASK_USE_DATA_DESCRIPTOR # Include an extended local header.
orig_zip.writestr(zinfo, data)
+ def test_write_with_source_date_epoch(self):
+ with os_helper.EnvironmentVarGuard() as env:
+ # Set the SOURCE_DATE_EPOCH environment variable to a specific timestamp
+ env['SOURCE_DATE_EPOCH'] = "1735715999"
+
+ with zipfile.ZipFile(TESTFN, "w") as zf:
+ zf.writestr("test_source_date_epoch.txt", "Testing SOURCE_DATE_EPOCH")
+
+ with zipfile.ZipFile(TESTFN, "r") as zf:
+ zip_info = zf.getinfo("test_source_date_epoch.txt")
+ get_time = time.localtime(int(os.environ['SOURCE_DATE_EPOCH']))[:6]
+ # Compare each element of the date_time tuple
+ # Allow for a 1-second difference
+ for z_time, g_time in zip(zip_info.date_time, get_time):
+ self.assertAlmostEqual(z_time, g_time, delta=1)
+
+ def test_write_without_source_date_epoch(self):
+ if 'SOURCE_DATE_EPOCH' in os.environ:
+ del os.environ['SOURCE_DATE_EPOCH']
+
+ with zipfile.ZipFile(TESTFN, "w") as zf:
+ zf.writestr("test_no_source_date_epoch.txt", "Testing without SOURCE_DATE_EPOCH")
+
+ with zipfile.ZipFile(TESTFN, "r") as zf:
+ zip_info = zf.getinfo("test_no_source_date_epoch.txt")
+ current_time = time.localtime()[:6]
+ for z_time, c_time in zip(zip_info.date_time, current_time):
+ self.assertAlmostEqual(z_time, c_time, delta=1)
+
def test_close(self):
"""Check that the zipfile is closed after the 'with' block."""
with zipfile.ZipFile(TESTFN2, "w") as zipfp:
diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 24531c1c2b7804..49c40032d848f1 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -614,7 +614,11 @@ def _for_archive(self, archive: ZipFile) -> Self:
Return self.
"""
- self.date_time = time.localtime(time.time())[:6]
+ # gh-91279: Set the SOURCE_DATE_EPOCH to a specific timestamp
+ epoch = os.environ.get('SOURCE_DATE_EPOCH')
+ get_time = int(epoch) if epoch else time.time()
+ self.date_time = time.localtime(get_time)[:6]
+
self.compress_type = archive.compression
self.compress_level = archive.compresslevel
if self.filename.endswith('/'): # pragma: no cover
diff --git a/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst b/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst
new file mode 100644
index 00000000000000..30ee2ea5efd069
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst
@@ -0,0 +1,3 @@
+:meth:`zipfile.ZipFile.writestr` now respect ``SOURCE_DATE_EPOCH`` that
+distributions can set centrally and have build tools consume this in order
+to produce reproducible output.
1
0
GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (#128143)
by jaraco Jan. 20, 2025
by jaraco Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/dda02eb7be62bf0af850a7521c77c90ea9…
commit: dda02eb7be62bf0af850a7521c77c90ea997df6c
branch: main
author: 5ec1cff <56485584+5ec1cff(a)users.noreply.github.com>
committer: jaraco <jaraco(a)jaraco.com>
date: 2025-01-20T13:04:43-05:00
summary:
GH-128131: Completely support random read access of uncompressed unencrypted files in ZipFile (#128143)
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot](a)users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
M Lib/test/test_zipfile/test_core.py
M Lib/zipfile/__init__.py
diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py
index 79e7337606b4bc..02e28d4004c01a 100644
--- a/Lib/test/test_zipfile/test_core.py
+++ b/Lib/test/test_zipfile/test_core.py
@@ -1,3 +1,4 @@
+import _pyio
import array
import contextlib
import importlib.util
@@ -3491,5 +3492,87 @@ def test_too_short(self):
b"zzz", zipfile._Extra.strip(b"zzz", (self.ZIP64_EXTRA,)))
+class StatIO(_pyio.BytesIO):
+ """Buffer which remembers the number of bytes that were read."""
+
+ def __init__(self):
+ super().__init__()
+ self.bytes_read = 0
+
+ def read(self, size=-1):
+ bs = super().read(size)
+ self.bytes_read += len(bs)
+ return bs
+
+
+class StoredZipExtFileRandomReadTest(unittest.TestCase):
+ """Tests whether an uncompressed, unencrypted zip entry can be randomly
+ seek and read without reading redundant bytes."""
+ def test_stored_seek_and_read(self):
+
+ sio = StatIO()
+ # 20000 bytes
+ txt = b'0123456789' * 2000
+
+ # The seek length must be greater than ZipExtFile.MIN_READ_SIZE
+ # as `ZipExtFile._read2()` reads in blocks of this size and we
+ # need to seek out of the buffered data
+ read_buffer_size = zipfile.ZipExtFile.MIN_READ_SIZE
+ self.assertGreaterEqual(10002, read_buffer_size) # for forward seek test
+ self.assertGreaterEqual(5003, read_buffer_size) # for backward seek test
+ # The read length must be less than MIN_READ_SIZE, since we assume that
+ # only 1 block is read in the test.
+ read_length = 100
+ self.assertGreaterEqual(read_buffer_size, read_length) # for read() calls
+
+ with zipfile.ZipFile(sio, "w", compression=zipfile.ZIP_STORED) as zipf:
+ zipf.writestr("foo.txt", txt)
+
+ # check random seek and read on a file
+ with zipfile.ZipFile(sio, "r") as zipf:
+ with zipf.open("foo.txt", "r") as fp:
+ # Test this optimized read hasn't rewound and read from the
+ # start of the file (as in the case of the unoptimized path)
+
+ # forward seek
+ old_count = sio.bytes_read
+ forward_seek_len = 10002
+ current_pos = 0
+ fp.seek(forward_seek_len, os.SEEK_CUR)
+ current_pos += forward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # backward seek
+ old_count = sio.bytes_read
+ backward_seek_len = 5003
+ fp.seek(-backward_seek_len, os.SEEK_CUR)
+ current_pos -= backward_seek_len
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(fp._left, fp._compress_left)
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(fp.tell(), current_pos)
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+ self.assertEqual(fp._left, fp._compress_left)
+ read_count = sio.bytes_read - old_count
+ self.assertLessEqual(read_count, read_buffer_size)
+
+ # eof flags test
+ fp.seek(0, os.SEEK_END)
+ fp.seek(12345, os.SEEK_SET)
+ current_pos = 12345
+ arr = fp.read(read_length)
+ current_pos += read_length
+ self.assertEqual(arr, txt[current_pos - read_length:current_pos])
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 052ef47b8f6598..24531c1c2b7804 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -1184,13 +1184,15 @@ def seek(self, offset, whence=os.SEEK_SET):
self._offset = buff_offset
read_offset = 0
# Fast seek uncompressed unencrypted file
- elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0:
+ elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset != 0:
# disable CRC checking after first seeking - it would be invalid
self._expected_crc = None
# seek actual file taking already buffered data into account
read_offset -= len(self._readbuffer) - self._offset
self._fileobj.seek(read_offset, os.SEEK_CUR)
self._left -= read_offset
+ self._compress_left -= read_offset
+ self._eof = self._left <= 0
read_offset = 0
# flush read buffer
self._readbuffer = b''
diff --git a/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
new file mode 100644
index 00000000000000..f4c4ebce10729c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst
@@ -0,0 +1,2 @@
+Completely support random access of uncompressed unencrypted read-only
+zip files obtained by :meth:`ZipFile.open <zipfile.ZipFile.open>`.
1
0
[3.13] gh-128588: gh-128550: remove eager tasks optimization that missed and introduced incorrect cancellations (GH-129063) (#129089)
by kumaraditya303 Jan. 20, 2025
by kumaraditya303 Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/a1c48a750cc52332b0ed16ea8ffa07c18e…
commit: a1c48a750cc52332b0ed16ea8ffa07c18eaee201
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-20T17:36:50Z
summary:
[3.13] gh-128588: gh-128550: remove eager tasks optimization that missed and introduced incorrect cancellations (GH-129063) (#129089)
gh-128588: gh-128550: remove eager tasks optimization that missed and introduced incorrect cancellations (GH-129063)
(cherry picked from commit ed6934e71e55d398df8263f4697f58e4a3815f69)
Co-authored-by: Thomas Grainger <tagrain(a)gmail.com>
Co-authored-by: Kumar Aditya <kumaraditya(a)python.org>
files:
A Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
M Lib/asyncio/taskgroups.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 8af199d6dcc41a..8fda6c8d55e16c 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -197,14 +197,12 @@ def create_task(self, coro, *, name=None, context=None):
else:
task = self._loop.create_task(coro, name=name, context=context)
- # optimization: Immediately call the done callback if the task is
+ # Always schedule the done callback even if the task is
# already done (e.g. if the coro was able to complete eagerly),
- # and skip scheduling a done callback
- if task.done():
- self._on_task_done(task)
- else:
- self._tasks.add(task)
- task.add_done_callback(self._on_task_done)
+ # otherwise if the task completes with an exception then it will cancel
+ # the current task too early. gh-128550, gh-128588
+ self._tasks.add(task)
+ task.add_done_callback(self._on_task_done)
try:
return task
finally:
diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py
index e52061aac923cc..ad61cb46c7c07c 100644
--- a/Lib/test/test_asyncio/test_taskgroups.py
+++ b/Lib/test/test_asyncio/test_taskgroups.py
@@ -1032,6 +1032,56 @@ class MyKeyboardInterrupt(KeyboardInterrupt):
self.assertListEqual(gc.get_referrers(exc), [])
+ async def test_cancels_task_if_created_during_creation(self):
+ # regression test for gh-128550
+ ran = False
+ class MyError(Exception):
+ pass
+
+ exc = None
+ try:
+ async with asyncio.TaskGroup() as tg:
+ async def third_task():
+ raise MyError("third task failed")
+
+ async def second_task():
+ nonlocal ran
+ tg.create_task(third_task())
+ with self.assertRaises(asyncio.CancelledError):
+ await asyncio.sleep(0) # eager tasks cancel here
+ await asyncio.sleep(0) # lazy tasks cancel here
+ ran = True
+
+ tg.create_task(second_task())
+ except* MyError as excs:
+ exc = excs.exceptions[0]
+
+ self.assertTrue(ran)
+ self.assertIsInstance(exc, MyError)
+
+
+ async def test_cancellation_does_not_leak_out_of_tg(self):
+ class MyError(Exception):
+ pass
+
+ async def throw_error():
+ raise MyError
+
+ try:
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(throw_error())
+ except* MyError:
+ pass
+ else:
+ self.fail("should have raised one MyError in group")
+
+ # if this test fails this current task will be cancelled
+ # outside the task group and inside unittest internals
+ # we yield to the event loop with sleep(0) so that
+ # cancellation happens here and error is more understandable
+ await asyncio.sleep(0)
+
+
class TestTaskGroup(BaseTestTaskGroup, unittest.IsolatedAsyncioTestCase):
loop_factory = asyncio.EventLoop
diff --git a/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst b/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
new file mode 100644
index 00000000000000..f59feac795ea18
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
@@ -0,0 +1 @@
+Removed an incorrect optimization relating to eager tasks in :class:`asyncio.TaskGroup` that resulted in cancellations being missed.
1
0
gh-128588: gh-128550: remove eager tasks optimization that missed and introduced incorrect cancellations (#129063)
by kumaraditya303 Jan. 20, 2025
by kumaraditya303 Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/ed6934e71e55d398df8263f4697f58e4a3…
commit: ed6934e71e55d398df8263f4697f58e4a3815f69
branch: main
author: Thomas Grainger <tagrain(a)gmail.com>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-20T17:13:01Z
summary:
gh-128588: gh-128550: remove eager tasks optimization that missed and introduced incorrect cancellations (#129063)
Co-authored-by: Kumar Aditya <kumaraditya(a)python.org>
files:
A Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
M Lib/asyncio/taskgroups.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 8af199d6dcc41a..8fda6c8d55e16c 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -197,14 +197,12 @@ def create_task(self, coro, *, name=None, context=None):
else:
task = self._loop.create_task(coro, name=name, context=context)
- # optimization: Immediately call the done callback if the task is
+ # Always schedule the done callback even if the task is
# already done (e.g. if the coro was able to complete eagerly),
- # and skip scheduling a done callback
- if task.done():
- self._on_task_done(task)
- else:
- self._tasks.add(task)
- task.add_done_callback(self._on_task_done)
+ # otherwise if the task completes with an exception then it will cancel
+ # the current task too early. gh-128550, gh-128588
+ self._tasks.add(task)
+ task.add_done_callback(self._on_task_done)
try:
return task
finally:
diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py
index 7859b33532fa27..0d69a436fdb840 100644
--- a/Lib/test/test_asyncio/test_taskgroups.py
+++ b/Lib/test/test_asyncio/test_taskgroups.py
@@ -1053,6 +1053,56 @@ async def asyncfn():
self.assertEqual(name, "example name")
+ async def test_cancels_task_if_created_during_creation(self):
+ # regression test for gh-128550
+ ran = False
+ class MyError(Exception):
+ pass
+
+ exc = None
+ try:
+ async with asyncio.TaskGroup() as tg:
+ async def third_task():
+ raise MyError("third task failed")
+
+ async def second_task():
+ nonlocal ran
+ tg.create_task(third_task())
+ with self.assertRaises(asyncio.CancelledError):
+ await asyncio.sleep(0) # eager tasks cancel here
+ await asyncio.sleep(0) # lazy tasks cancel here
+ ran = True
+
+ tg.create_task(second_task())
+ except* MyError as excs:
+ exc = excs.exceptions[0]
+
+ self.assertTrue(ran)
+ self.assertIsInstance(exc, MyError)
+
+
+ async def test_cancellation_does_not_leak_out_of_tg(self):
+ class MyError(Exception):
+ pass
+
+ async def throw_error():
+ raise MyError
+
+ try:
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(throw_error())
+ except* MyError:
+ pass
+ else:
+ self.fail("should have raised one MyError in group")
+
+ # if this test fails this current task will be cancelled
+ # outside the task group and inside unittest internals
+ # we yield to the event loop with sleep(0) so that
+ # cancellation happens here and error is more understandable
+ await asyncio.sleep(0)
+
+
class TestTaskGroup(BaseTestTaskGroup, unittest.IsolatedAsyncioTestCase):
loop_factory = asyncio.EventLoop
diff --git a/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst b/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
new file mode 100644
index 00000000000000..f59feac795ea18
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst
@@ -0,0 +1 @@
+Removed an incorrect optimization relating to eager tasks in :class:`asyncio.TaskGroup` that resulted in cancellations being missed.
1
0
GH-128914: Remove conditional stack effects from `bytecodes.c` and the code generators (GH-128918)
by markshannon Jan. 20, 2025
by markshannon Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/ab61d3f4303d14a413bc9ae6557c730ffd…
commit: ab61d3f4303d14a413bc9ae6557c730ffdf7579e
branch: main
author: Mark Shannon <mark(a)hotpy.org>
committer: markshannon <mark(a)hotpy.org>
date: 2025-01-20T17:09:23Z
summary:
GH-128914: Remove conditional stack effects from `bytecodes.c` and the code generators (GH-128918)
files:
A Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-10-17-01.gh-issue-128914.dn6RaW.rst
M Doc/library/dis.rst
M Include/internal/pycore_code.h
M Include/internal/pycore_magic_number.h
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Include/opcode_ids.h
M Lib/_opcode_metadata.py
M Lib/dis.py
M Lib/inspect.py
M Lib/opcode.py
M Lib/test/test__opcode.py
M Lib/test/test_capi/test_opt.py
M Lib/test/test_compile.py
M Lib/test/test_dis.py
M Lib/test/test_generated_cases.py
M Lib/test/test_monitoring.py
M Lib/test/test_opcache.py
M Objects/frameobject.c
M Objects/object.c
M Programs/test_frozenmain.h
M Python/bytecodes.c
M Python/codegen.c
M Python/executor_cases.c.h
M Python/flowgraph.c
M Python/generated_cases.c.h
M Python/instrumentation.c
M Python/opcode_targets.h
M Python/optimizer.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/specialize.c
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/lexer.py
M Tools/cases_generator/opcode_metadata_generator.py
M Tools/cases_generator/optimizer_generator.py
M Tools/cases_generator/parsing.py
M Tools/cases_generator/stack.py
M Tools/cases_generator/tier1_generator.py
M Tools/cases_generator/tier2_generator.py
M Tools/scripts/summarize_stats.py
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index f8f4188d27b472..225ef321aed3b8 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -75,7 +75,8 @@ the following command can be used to display the disassembly of
>>> dis.dis(myfunc)
2 RESUME 0
<BLANKLINE>
- 3 LOAD_GLOBAL 1 (len + NULL)
+ 3 LOAD_GLOBAL 0 (len)
+ PUSH_NULL
LOAD_FAST 0 (alist)
CALL 1
RETURN_VALUE
@@ -207,6 +208,7 @@ Example:
...
RESUME
LOAD_GLOBAL
+ PUSH_NULL
LOAD_FAST
CALL
RETURN_VALUE
@@ -1215,11 +1217,20 @@ iterations of the loop.
.. opcode:: LOAD_ATTR (namei)
- If the low bit of ``namei`` is not set, this replaces ``STACK[-1]`` with
- ``getattr(STACK[-1], co_names[namei>>1])``.
+ Replaces ``STACK[-1]`` with ``getattr(STACK[-1], co_names[namei>>1])``.
- If the low bit of ``namei`` is set, this will attempt to load a method named
- ``co_names[namei>>1]`` from the ``STACK[-1]`` object. ``STACK[-1]`` is popped.
+ .. versionchanged:: 3.12
+ If the low bit of ``namei`` is set, then a ``NULL`` or ``self`` is
+ pushed to the stack before the attribute or unbound method respectively.
+
+ .. versionchanged:: 3.14
+ Reverted change from 3.12. The low bit of ``namei`` has no special meaning.
+
+
+.. opcode:: LOAD_METHOD (namei)
+
+ Attempt to load a method named ``co_names[namei>>1]`` from the ``STACK[-1]`` object.
+ ``STACK[-1]`` is popped.
This bytecode distinguishes two cases: if ``STACK[-1]`` has a method with the
correct name, the bytecode pushes the unbound method and ``STACK[-1]``.
``STACK[-1]`` will be used as the first argument (``self``) by :opcode:`CALL`
@@ -1227,9 +1238,7 @@ iterations of the loop.
Otherwise, ``NULL`` and the object returned by
the attribute lookup are pushed.
- .. versionchanged:: 3.12
- If the low bit of ``namei`` is set, then a ``NULL`` or ``self`` is
- pushed to the stack before the attribute or unbound method respectively.
+ .. versionadded:: 3.14
.. opcode:: LOAD_SUPER_ATTR (namei)
@@ -1926,12 +1935,6 @@ but are replaced by real opcodes or removed before bytecode is generated.
This opcode is now a pseudo-instruction.
-.. opcode:: LOAD_METHOD
-
- Optimized unbound method lookup. Emitted as a ``LOAD_ATTR`` opcode
- with a flag set in the arg.
-
-
.. _opcode_collections:
Opcode collections
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 01d41446fdb0cf..f5eddab6e90e41 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -334,6 +334,8 @@ extern void _Py_Specialize_LoadSuperAttr(_PyStackRef global_super, _PyStackRef c
_Py_CODEUNIT *instr, int load_method);
extern void _Py_Specialize_LoadAttr(_PyStackRef owner, _Py_CODEUNIT *instr,
PyObject *name);
+extern void _Py_Specialize_LoadMethod(_PyStackRef owner, _Py_CODEUNIT *instr,
+ PyObject *name);
extern void _Py_Specialize_StoreAttr(_PyStackRef owner, _Py_CODEUNIT *instr,
PyObject *name);
extern void _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins,
diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h
index 1dd155abf3babf..0d94b6d81d2936 100644
--- a/Include/internal/pycore_magic_number.h
+++ b/Include/internal/pycore_magic_number.h
@@ -267,6 +267,7 @@ Known values:
Python 3.14a4 3612 (Add POP_ITER and INSTRUMENTED_POP_ITER)
Python 3.14a4 3613 (Add LOAD_CONST_MORTAL instruction)
Python 3.14a5 3614 (Add BINARY_OP_EXTEND)
+ Python 3.14a5 3615 (Remove conditional stack effects)
Python 3.15 will start with 3650
@@ -279,7 +280,7 @@ PC/launcher.c must also be updated.
*/
-#define PYC_MAGIC_NUMBER 3614
+#define PYC_MAGIC_NUMBER 3615
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h
index f7c23ad634d6be..396b3a58ad08ec 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -76,7 +76,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
case BUILD_SET:
return oparg;
case BUILD_SLICE:
- return 2 + ((oparg == 3) ? 1 : 0);
+ return oparg;
case BUILD_STRING:
return oparg;
case BUILD_TUPLE:
@@ -100,7 +100,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
case CALL_BUILTIN_O:
return 2 + oparg;
case CALL_FUNCTION_EX:
- return 3 + (oparg & 1);
+ return 4;
case CALL_INTRINSIC_1:
return 1;
case CALL_INTRINSIC_2:
@@ -245,6 +245,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR:
return 0;
+ case INSTRUMENTED_LOAD_SUPER_METHOD:
+ return 0;
case INSTRUMENTED_NOT_TAKEN:
return 0;
case INSTRUMENTED_POP_ITER:
@@ -295,12 +297,6 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 1;
case LOAD_ATTR_INSTANCE_VALUE:
return 1;
- case LOAD_ATTR_METHOD_LAZY_DICT:
- return 1;
- case LOAD_ATTR_METHOD_NO_DICT:
- return 1;
- case LOAD_ATTR_METHOD_WITH_VALUES:
- return 1;
case LOAD_ATTR_MODULE:
return 1;
case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
@@ -347,6 +343,14 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 0;
case LOAD_LOCALS:
return 0;
+ case LOAD_METHOD:
+ return 1;
+ case LOAD_METHOD_LAZY_DICT:
+ return 1;
+ case LOAD_METHOD_NO_DICT:
+ return 1;
+ case LOAD_METHOD_WITH_VALUES:
+ return 1;
case LOAD_NAME:
return 0;
case LOAD_SMALL_INT:
@@ -357,7 +361,9 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 3;
case LOAD_SUPER_ATTR_ATTR:
return 3;
- case LOAD_SUPER_ATTR_METHOD:
+ case LOAD_SUPER_METHOD:
+ return 3;
+ case LOAD_SUPER_METHOD_METHOD:
return 3;
case MAKE_CELL:
return 0;
@@ -716,6 +722,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR:
return 0;
+ case INSTRUMENTED_LOAD_SUPER_METHOD:
+ return 0;
case INSTRUMENTED_NOT_TAKEN:
return 0;
case INSTRUMENTED_POP_ITER:
@@ -757,23 +765,17 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LIST_EXTEND:
return 1 + (oparg-1);
case LOAD_ATTR:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_ATTR_CLASS:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
return 1;
case LOAD_ATTR_INSTANCE_VALUE:
- return 1 + (oparg & 1);
- case LOAD_ATTR_METHOD_LAZY_DICT:
- return 2;
- case LOAD_ATTR_METHOD_NO_DICT:
- return 2;
- case LOAD_ATTR_METHOD_WITH_VALUES:
- return 2;
+ return 1;
case LOAD_ATTR_MODULE:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
return 1;
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
@@ -781,9 +783,9 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_ATTR_PROPERTY:
return 0;
case LOAD_ATTR_SLOT:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_ATTR_WITH_HINT:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_BUILD_CLASS:
return 1;
case LOAD_CLOSURE:
@@ -811,13 +813,21 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_GLOBAL_BUILTIN:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_GLOBAL_MODULE:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_LOCALS:
return 1;
+ case LOAD_METHOD:
+ return 2;
+ case LOAD_METHOD_LAZY_DICT:
+ return 2;
+ case LOAD_METHOD_NO_DICT:
+ return 2;
+ case LOAD_METHOD_WITH_VALUES:
+ return 2;
case LOAD_NAME:
return 1;
case LOAD_SMALL_INT:
@@ -825,10 +835,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_SPECIAL:
return 2;
case LOAD_SUPER_ATTR:
- return 1 + (oparg & 1);
+ return 1;
case LOAD_SUPER_ATTR_ATTR:
return 1;
- case LOAD_SUPER_ATTR_METHOD:
+ case LOAD_SUPER_METHOD:
+ return 2;
+ case LOAD_SUPER_METHOD_METHOD:
return 2;
case MAKE_CELL:
return 0;
@@ -1058,7 +1070,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case BUILD_SLICE: {
- *effect = -1 - ((oparg == 3) ? 1 : 0);
+ *effect = 1 - oparg;
return 0;
}
case BUILD_STRING: {
@@ -1114,7 +1126,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case CALL_FUNCTION_EX: {
- *effect = Py_MAX(0, -2 - (oparg & 1));
+ *effect = 0;
return 0;
}
case CALL_INTRINSIC_1: {
@@ -1415,6 +1427,10 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
*effect = 0;
return 0;
}
+ case INSTRUMENTED_LOAD_SUPER_METHOD: {
+ *effect = 0;
+ return 0;
+ }
case INSTRUMENTED_NOT_TAKEN: {
*effect = 0;
return 0;
@@ -1496,15 +1512,15 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR: {
- *effect = Py_MAX(1, (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_ATTR_CLASS: {
- *effect = Py_MAX(0, (oparg & 1));
+ *effect = 0;
return 0;
}
case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK: {
- *effect = Py_MAX(0, (oparg & 1));
+ *effect = 0;
return 0;
}
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: {
@@ -1512,23 +1528,11 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR_INSTANCE_VALUE: {
- *effect = Py_MAX(0, (oparg & 1));
- return 0;
- }
- case LOAD_ATTR_METHOD_LAZY_DICT: {
- *effect = 1;
- return 0;
- }
- case LOAD_ATTR_METHOD_NO_DICT: {
- *effect = 1;
- return 0;
- }
- case LOAD_ATTR_METHOD_WITH_VALUES: {
- *effect = 1;
+ *effect = 0;
return 0;
}
case LOAD_ATTR_MODULE: {
- *effect = Py_MAX(1, (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
@@ -1544,11 +1548,11 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR_SLOT: {
- *effect = Py_MAX(0, (oparg & 1));
+ *effect = 0;
return 0;
}
case LOAD_ATTR_WITH_HINT: {
- *effect = Py_MAX(1, (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_BUILD_CLASS: {
@@ -1604,21 +1608,37 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_GLOBAL: {
- *effect = Py_MAX(1, 1 + (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_GLOBAL_BUILTIN: {
- *effect = Py_MAX(1, 1 + (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_GLOBAL_MODULE: {
- *effect = Py_MAX(1, 1 + (oparg & 1));
+ *effect = 1;
return 0;
}
case LOAD_LOCALS: {
*effect = 1;
return 0;
}
+ case LOAD_METHOD: {
+ *effect = 1;
+ return 0;
+ }
+ case LOAD_METHOD_LAZY_DICT: {
+ *effect = 1;
+ return 0;
+ }
+ case LOAD_METHOD_NO_DICT: {
+ *effect = 1;
+ return 0;
+ }
+ case LOAD_METHOD_WITH_VALUES: {
+ *effect = 1;
+ return 0;
+ }
case LOAD_NAME: {
*effect = 1;
return 0;
@@ -1632,14 +1652,18 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_SUPER_ATTR: {
- *effect = Py_MAX(0, -2 + (oparg & 1));
+ *effect = 0;
return 0;
}
case LOAD_SUPER_ATTR_ATTR: {
*effect = -2;
return 0;
}
- case LOAD_SUPER_ATTR_METHOD: {
+ case LOAD_SUPER_METHOD: {
+ *effect = 0;
+ return 0;
+ }
+ case LOAD_SUPER_METHOD_METHOD: {
*effect = -1;
return 0;
}
@@ -1934,6 +1958,7 @@ enum InstructionFormat {
INSTR_FMT_IXC00 = 9,
INSTR_FMT_IXC000 = 10,
INSTR_FMT_IXC0000 = 11,
+ INSTR_FMT_IXC00000000 = 12,
};
#define IS_VALID_OPCODE(OP) \
@@ -1953,9 +1978,8 @@ enum InstructionFormat {
#define HAS_EXIT_FLAG (1024)
#define HAS_PURE_FLAG (2048)
#define HAS_PASSTHROUGH_FLAG (4096)
-#define HAS_OPARG_AND_1_FLAG (8192)
-#define HAS_ERROR_NO_POP_FLAG (16384)
-#define HAS_NO_SAVE_IP_FLAG (32768)
+#define HAS_ERROR_NO_POP_FLAG (8192)
+#define HAS_NO_SAVE_IP_FLAG (16384)
#define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG))
#define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG))
#define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG))
@@ -1969,7 +1993,6 @@ enum InstructionFormat {
#define OPCODE_HAS_EXIT(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_EXIT_FLAG))
#define OPCODE_HAS_PURE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_PURE_FLAG))
#define OPCODE_HAS_PASSTHROUGH(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_PASSTHROUGH_FLAG))
-#define OPCODE_HAS_OPARG_AND_1(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_OPARG_AND_1_FLAG))
#define OPCODE_HAS_ERROR_NO_POP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ERROR_NO_POP_FLAG))
#define OPCODE_HAS_NO_SAVE_IP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NO_SAVE_IP_FLAG))
@@ -2023,7 +2046,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
+ [CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_ISINSTANCE] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
@@ -2096,6 +2119,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_LINE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IXC, 0 },
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = { true, INSTR_FMT_IXC, 0 },
[INSTRUMENTED_NOT_TAKEN] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
@@ -2113,18 +2137,15 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[LIST_APPEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
[LIST_EXTEND] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG },
+ [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IXC00000000, HAS_EXIT_FLAG },
+ [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IXC00000000, HAS_EXIT_FLAG },
[LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG },
- [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
- [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
+ [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
+ [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
+ [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IXC00000000, HAS_EXIT_FLAG },
+ [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
- [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
+ [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_COMMON_CONSTANT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
@@ -2139,15 +2160,20 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[LOAD_GLOBAL] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
- [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
+ [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
+ [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG },
[LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+ [LOAD_METHOD] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+ [LOAD_METHOD_LAZY_DICT] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
+ [LOAD_METHOD_NO_DICT] = { true, INSTR_FMT_IXC00000000, HAS_EXIT_FLAG },
+ [LOAD_METHOD_WITH_VALUES] = { true, INSTR_FMT_IXC00000000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SMALL_INT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
+ [LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+ [LOAD_SUPER_METHOD_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@@ -2327,9 +2353,6 @@ _PyOpcode_macro_expansion[256] = {
[LOAD_ATTR_CLASS] = { .nuops = 2, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 } } },
[LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { .nuops = 3, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _GUARD_TYPE_VERSION, 2, 3 }, { _LOAD_ATTR_CLASS, 4, 5 } } },
[LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, 0, 0 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 } } },
- [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 1, 3 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } },
- [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } },
- [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } },
[LOAD_ATTR_MODULE] = { .nuops = 2, .uops = { { _CHECK_ATTR_MODULE_PUSH_KEYS, 2, 1 }, { _LOAD_ATTR_MODULE_FROM_KEYS, 1, 3 } } },
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } },
[LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } },
@@ -2350,11 +2373,15 @@ _PyOpcode_macro_expansion[256] = {
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION_PUSH_KEYS, 1, 2 }, { _LOAD_GLOBAL_BUILTINS_FROM_KEYS, 1, 3 } } },
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION_PUSH_KEYS, 1, 1 }, { _LOAD_GLOBAL_MODULE_FROM_KEYS, 1, 3 } } },
[LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, 0, 0 } } },
+ [LOAD_METHOD] = { .nuops = 1, .uops = { { _LOAD_METHOD, 0, 0 } } },
+ [LOAD_METHOD_LAZY_DICT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 1, 3 }, { _LOAD_METHOD_LAZY_DICT, 4, 5 } } },
+ [LOAD_METHOD_NO_DICT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_METHOD_NO_DICT, 4, 5 } } },
+ [LOAD_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_METHOD_WITH_VALUES, 4, 5 } } },
[LOAD_NAME] = { .nuops = 1, .uops = { { _LOAD_NAME, 0, 0 } } },
[LOAD_SMALL_INT] = { .nuops = 1, .uops = { { _LOAD_SMALL_INT, 0, 0 } } },
[LOAD_SPECIAL] = { .nuops = 1, .uops = { { _LOAD_SPECIAL, 0, 0 } } },
[LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, 0, 0 } } },
- [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_METHOD, 0, 0 } } },
+ [LOAD_SUPER_METHOD_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_METHOD_METHOD, 0, 0 } } },
[MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, 0, 0 } } },
[MAKE_FUNCTION] = { .nuops = 1, .uops = { { _MAKE_FUNCTION, 0, 0 } } },
[MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, 0, 0 } } },
@@ -2524,6 +2551,7 @@ const char *_PyOpcode_OpName[266] = {
[INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD",
[INSTRUMENTED_LINE] = "INSTRUMENTED_LINE",
[INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR",
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = "INSTRUMENTED_LOAD_SUPER_METHOD",
[INSTRUMENTED_NOT_TAKEN] = "INSTRUMENTED_NOT_TAKEN",
[INSTRUMENTED_POP_ITER] = "INSTRUMENTED_POP_ITER",
[INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE",
@@ -2549,9 +2577,6 @@ const char *_PyOpcode_OpName[266] = {
[LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK",
[LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN",
[LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE",
- [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT",
- [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT",
- [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES",
[LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE",
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "LOAD_ATTR_NONDESCRIPTOR_NO_DICT",
[LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES",
@@ -2575,12 +2600,17 @@ const char *_PyOpcode_OpName[266] = {
[LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
[LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
[LOAD_LOCALS] = "LOAD_LOCALS",
+ [LOAD_METHOD] = "LOAD_METHOD",
+ [LOAD_METHOD_LAZY_DICT] = "LOAD_METHOD_LAZY_DICT",
+ [LOAD_METHOD_NO_DICT] = "LOAD_METHOD_NO_DICT",
+ [LOAD_METHOD_WITH_VALUES] = "LOAD_METHOD_WITH_VALUES",
[LOAD_NAME] = "LOAD_NAME",
[LOAD_SMALL_INT] = "LOAD_SMALL_INT",
[LOAD_SPECIAL] = "LOAD_SPECIAL",
[LOAD_SUPER_ATTR] = "LOAD_SUPER_ATTR",
[LOAD_SUPER_ATTR_ATTR] = "LOAD_SUPER_ATTR_ATTR",
- [LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD",
+ [LOAD_SUPER_METHOD] = "LOAD_SUPER_METHOD",
+ [LOAD_SUPER_METHOD_METHOD] = "LOAD_SUPER_METHOD_METHOD",
[MAKE_CELL] = "MAKE_CELL",
[MAKE_FUNCTION] = "MAKE_FUNCTION",
[MAP_ADD] = "MAP_ADD",
@@ -2663,7 +2693,9 @@ const uint8_t _PyOpcode_Caches[256] = {
[STORE_ATTR] = 4,
[LOAD_GLOBAL] = 4,
[LOAD_SUPER_ATTR] = 1,
+ [LOAD_SUPER_METHOD] = 1,
[LOAD_ATTR] = 9,
+ [LOAD_METHOD] = 9,
[COMPARE_OP] = 1,
[CONTAINS_OP] = 1,
[JUMP_BACKWARD] = 1,
@@ -2786,6 +2818,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
[INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,
[INSTRUMENTED_LINE] = INSTRUMENTED_LINE,
[INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = INSTRUMENTED_LOAD_SUPER_METHOD,
[INSTRUMENTED_NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN,
[INSTRUMENTED_POP_ITER] = INSTRUMENTED_POP_ITER,
[INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,
@@ -2807,9 +2840,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
[LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = LOAD_ATTR,
[LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = LOAD_ATTR,
[LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR,
- [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR,
- [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR,
- [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR,
[LOAD_ATTR_MODULE] = LOAD_ATTR,
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = LOAD_ATTR,
[LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = LOAD_ATTR,
@@ -2832,12 +2862,17 @@ const uint8_t _PyOpcode_Deopt[256] = {
[LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL,
[LOAD_GLOBAL_MODULE] = LOAD_GLOBAL,
[LOAD_LOCALS] = LOAD_LOCALS,
+ [LOAD_METHOD] = LOAD_METHOD,
+ [LOAD_METHOD_LAZY_DICT] = LOAD_METHOD,
+ [LOAD_METHOD_NO_DICT] = LOAD_METHOD,
+ [LOAD_METHOD_WITH_VALUES] = LOAD_METHOD,
[LOAD_NAME] = LOAD_NAME,
[LOAD_SMALL_INT] = LOAD_SMALL_INT,
[LOAD_SPECIAL] = LOAD_SPECIAL,
[LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,
[LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR,
- [LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR,
+ [LOAD_SUPER_METHOD] = LOAD_SUPER_METHOD,
+ [LOAD_SUPER_METHOD_METHOD] = LOAD_SUPER_METHOD,
[MAKE_CELL] = MAKE_CELL,
[MAKE_FUNCTION] = MAKE_FUNCTION,
[MAP_ADD] = MAP_ADD,
@@ -2906,8 +2941,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
#endif // NEED_OPCODE_METADATA
#define EXTRA_CASES \
- case 118: \
- case 119: \
case 120: \
case 121: \
case 122: \
@@ -2941,7 +2974,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
case 231: \
case 232: \
case 233: \
- case 234: \
;
struct pseudo_targets {
uint8_t as_sequence;
diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h
index 066165a2c810d5..2bf8542bdb67a9 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -159,6 +159,7 @@ extern "C" {
#define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD
#define _INSTRUMENTED_LINE INSTRUMENTED_LINE
#define _INSTRUMENTED_LOAD_SUPER_ATTR INSTRUMENTED_LOAD_SUPER_ATTR
+#define _INSTRUMENTED_LOAD_SUPER_METHOD INSTRUMENTED_LOAD_SUPER_METHOD
#define _INSTRUMENTED_NOT_TAKEN INSTRUMENTED_NOT_TAKEN
#define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE
#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
@@ -180,127 +181,122 @@ extern "C" {
#define _LIST_EXTEND LIST_EXTEND
#define _LOAD_ATTR 410
#define _LOAD_ATTR_CLASS 411
-#define _LOAD_ATTR_CLASS_0 412
-#define _LOAD_ATTR_CLASS_1 413
#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
-#define _LOAD_ATTR_INSTANCE_VALUE 414
-#define _LOAD_ATTR_INSTANCE_VALUE_0 415
-#define _LOAD_ATTR_INSTANCE_VALUE_1 416
-#define _LOAD_ATTR_METHOD_LAZY_DICT 417
-#define _LOAD_ATTR_METHOD_NO_DICT 418
-#define _LOAD_ATTR_METHOD_WITH_VALUES 419
-#define _LOAD_ATTR_MODULE 420
-#define _LOAD_ATTR_MODULE_FROM_KEYS 421
-#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 422
-#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 423
-#define _LOAD_ATTR_PROPERTY_FRAME 424
-#define _LOAD_ATTR_SLOT 425
-#define _LOAD_ATTR_SLOT_0 426
-#define _LOAD_ATTR_SLOT_1 427
-#define _LOAD_ATTR_WITH_HINT 428
+#define _LOAD_ATTR_INSTANCE_VALUE 412
+#define _LOAD_ATTR_MODULE 413
+#define _LOAD_ATTR_MODULE_FROM_KEYS 414
+#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 415
+#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 416
+#define _LOAD_ATTR_PROPERTY_FRAME 417
+#define _LOAD_ATTR_SLOT 418
+#define _LOAD_ATTR_WITH_HINT 419
#define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS
-#define _LOAD_BYTECODE 429
+#define _LOAD_BYTECODE 420
#define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT
#define _LOAD_CONST LOAD_CONST
#define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL
-#define _LOAD_CONST_INLINE 430
-#define _LOAD_CONST_INLINE_BORROW 431
-#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 432
-#define _LOAD_CONST_INLINE_WITH_NULL 433
+#define _LOAD_CONST_INLINE 421
+#define _LOAD_CONST_INLINE_BORROW 422
+#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 423
+#define _LOAD_CONST_INLINE_WITH_NULL 424
#define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL
#define _LOAD_DEREF LOAD_DEREF
-#define _LOAD_FAST 434
-#define _LOAD_FAST_0 435
-#define _LOAD_FAST_1 436
-#define _LOAD_FAST_2 437
-#define _LOAD_FAST_3 438
-#define _LOAD_FAST_4 439
-#define _LOAD_FAST_5 440
-#define _LOAD_FAST_6 441
-#define _LOAD_FAST_7 442
+#define _LOAD_FAST 425
+#define _LOAD_FAST_0 426
+#define _LOAD_FAST_1 427
+#define _LOAD_FAST_2 428
+#define _LOAD_FAST_3 429
+#define _LOAD_FAST_4 430
+#define _LOAD_FAST_5 431
+#define _LOAD_FAST_6 432
+#define _LOAD_FAST_7 433
#define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR
#define _LOAD_FAST_CHECK LOAD_FAST_CHECK
#define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST
#define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF
#define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS
-#define _LOAD_GLOBAL 443
-#define _LOAD_GLOBAL_BUILTINS 444
-#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 445
-#define _LOAD_GLOBAL_MODULE 446
-#define _LOAD_GLOBAL_MODULE_FROM_KEYS 447
+#define _LOAD_GLOBAL 434
+#define _LOAD_GLOBAL_BUILTINS 435
+#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 436
+#define _LOAD_GLOBAL_MODULE 437
+#define _LOAD_GLOBAL_MODULE_FROM_KEYS 438
#define _LOAD_LOCALS LOAD_LOCALS
+#define _LOAD_METHOD 439
+#define _LOAD_METHOD_LAZY_DICT 440
+#define _LOAD_METHOD_NO_DICT 441
+#define _LOAD_METHOD_WITH_VALUES 442
#define _LOAD_NAME LOAD_NAME
-#define _LOAD_SMALL_INT 448
-#define _LOAD_SMALL_INT_0 449
-#define _LOAD_SMALL_INT_1 450
-#define _LOAD_SMALL_INT_2 451
-#define _LOAD_SMALL_INT_3 452
+#define _LOAD_SMALL_INT 443
+#define _LOAD_SMALL_INT_0 444
+#define _LOAD_SMALL_INT_1 445
+#define _LOAD_SMALL_INT_2 446
+#define _LOAD_SMALL_INT_3 447
#define _LOAD_SPECIAL LOAD_SPECIAL
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
-#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
-#define _MAKE_CALLARGS_A_TUPLE 453
+#define _LOAD_SUPER_METHOD_METHOD LOAD_SUPER_METHOD_METHOD
+#define _MAKE_CALLARGS_A_TUPLE 448
#define _MAKE_CELL MAKE_CELL
#define _MAKE_FUNCTION MAKE_FUNCTION
-#define _MAKE_WARM 454
+#define _MAKE_WARM 449
#define _MAP_ADD MAP_ADD
#define _MATCH_CLASS MATCH_CLASS
#define _MATCH_KEYS MATCH_KEYS
#define _MATCH_MAPPING MATCH_MAPPING
#define _MATCH_SEQUENCE MATCH_SEQUENCE
-#define _MAYBE_EXPAND_METHOD 455
-#define _MAYBE_EXPAND_METHOD_KW 456
-#define _MONITOR_CALL 457
-#define _MONITOR_JUMP_BACKWARD 458
-#define _MONITOR_RESUME 459
+#define _MAYBE_EXPAND_METHOD 450
+#define _MAYBE_EXPAND_METHOD_KW 451
+#define _MONITOR_CALL 452
+#define _MONITOR_JUMP_BACKWARD 453
+#define _MONITOR_RESUME 454
#define _NOP NOP
#define _POP_EXCEPT POP_EXCEPT
-#define _POP_JUMP_IF_FALSE 460
-#define _POP_JUMP_IF_TRUE 461
+#define _POP_JUMP_IF_FALSE 455
+#define _POP_JUMP_IF_TRUE 456
#define _POP_TOP POP_TOP
-#define _POP_TOP_LOAD_CONST_INLINE_BORROW 462
+#define _POP_TOP_LOAD_CONST_INLINE_BORROW 457
#define _PUSH_EXC_INFO PUSH_EXC_INFO
-#define _PUSH_FRAME 463
+#define _PUSH_FRAME 458
#define _PUSH_NULL PUSH_NULL
-#define _PY_FRAME_GENERAL 464
-#define _PY_FRAME_KW 465
-#define _QUICKEN_RESUME 466
-#define _REPLACE_WITH_TRUE 467
+#define _PY_FRAME_GENERAL 459
+#define _PY_FRAME_KW 460
+#define _QUICKEN_RESUME 461
+#define _REPLACE_WITH_TRUE 462
#define _RESUME_CHECK RESUME_CHECK
#define _RETURN_GENERATOR RETURN_GENERATOR
#define _RETURN_VALUE RETURN_VALUE
-#define _SAVE_RETURN_OFFSET 468
-#define _SEND 469
-#define _SEND_GEN_FRAME 470
+#define _SAVE_RETURN_OFFSET 463
+#define _SEND 464
+#define _SEND_GEN_FRAME 465
#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
#define _SET_ADD SET_ADD
#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
#define _SET_UPDATE SET_UPDATE
-#define _START_EXECUTOR 471
-#define _STORE_ATTR 472
-#define _STORE_ATTR_INSTANCE_VALUE 473
-#define _STORE_ATTR_SLOT 474
-#define _STORE_ATTR_WITH_HINT 475
+#define _START_EXECUTOR 466
+#define _STORE_ATTR 467
+#define _STORE_ATTR_INSTANCE_VALUE 468
+#define _STORE_ATTR_SLOT 469
+#define _STORE_ATTR_WITH_HINT 470
#define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 476
-#define _STORE_FAST_0 477
-#define _STORE_FAST_1 478
-#define _STORE_FAST_2 479
-#define _STORE_FAST_3 480
-#define _STORE_FAST_4 481
-#define _STORE_FAST_5 482
-#define _STORE_FAST_6 483
-#define _STORE_FAST_7 484
+#define _STORE_FAST 471
+#define _STORE_FAST_0 472
+#define _STORE_FAST_1 473
+#define _STORE_FAST_2 474
+#define _STORE_FAST_3 475
+#define _STORE_FAST_4 476
+#define _STORE_FAST_5 477
+#define _STORE_FAST_6 478
+#define _STORE_FAST_7 479
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
#define _STORE_GLOBAL STORE_GLOBAL
#define _STORE_NAME STORE_NAME
-#define _STORE_SLICE 485
-#define _STORE_SUBSCR 486
+#define _STORE_SLICE 480
+#define _STORE_SUBSCR 481
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 487
-#define _TO_BOOL 488
+#define _TIER2_RESUME_CHECK 482
+#define _TO_BOOL 483
#define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST
@@ -310,13 +306,13 @@ extern "C" {
#define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 489
+#define _UNPACK_SEQUENCE 484
#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
#define _WITH_EXCEPT_START WITH_EXCEPT_START
#define _YIELD_VALUE YIELD_VALUE
-#define MAX_UOP_ID 489
+#define MAX_UOP_ID 484
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 7b28667a26e94d..6cc825ed62ed95 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -127,8 +127,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_GUARD_GLOBALS_VERSION] = HAS_DEOPT_FLAG,
[_GUARD_GLOBALS_VERSION_PUSH_KEYS] = HAS_DEOPT_FLAG,
[_GUARD_BUILTINS_VERSION_PUSH_KEYS] = HAS_DEOPT_FLAG,
- [_LOAD_GLOBAL_MODULE_FROM_KEYS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
- [_LOAD_GLOBAL_BUILTINS_FROM_KEYS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
+ [_LOAD_GLOBAL_MODULE_FROM_KEYS] = HAS_DEOPT_FLAG,
+ [_LOAD_GLOBAL_BUILTINS_FROM_KEYS] = HAS_DEOPT_FLAG,
[_DELETE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_MAKE_CELL] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_DELETE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
@@ -148,26 +148,21 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_DICT_MERGE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_MAP_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
- [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
+ [_LOAD_SUPER_METHOD_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
+ [_LOAD_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG,
[_GUARD_TYPE_VERSION_AND_LOCK] = HAS_EXIT_FLAG,
[_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_INSTANCE_VALUE_0] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_INSTANCE_VALUE_1] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_INSTANCE_VALUE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_OPARG_AND_1_FLAG,
+ [_LOAD_ATTR_INSTANCE_VALUE] = HAS_DEOPT_FLAG,
[_CHECK_ATTR_MODULE_PUSH_KEYS] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_MODULE_FROM_KEYS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
+ [_LOAD_ATTR_MODULE_FROM_KEYS] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
[_CHECK_ATTR_WITH_HINT] = HAS_EXIT_FLAG,
[_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG,
- [_LOAD_ATTR_SLOT_0] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_SLOT_1] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_SLOT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_OPARG_AND_1_FLAG,
+ [_LOAD_ATTR_SLOT] = HAS_DEOPT_FLAG,
[_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG,
- [_LOAD_ATTR_CLASS_0] = 0,
- [_LOAD_ATTR_CLASS_1] = 0,
- [_LOAD_ATTR_CLASS] = HAS_ARG_FLAG | HAS_OPARG_AND_1_FLAG,
- [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
+ [_LOAD_ATTR_CLASS] = 0,
+ [_LOAD_ATTR_PROPERTY_FRAME] = HAS_DEOPT_FLAG,
[_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG,
[_STORE_ATTR_INSTANCE_VALUE] = HAS_ESCAPES_FLAG,
[_STORE_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
@@ -208,12 +203,12 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_PUSH_EXC_INFO] = 0,
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_DEOPT_FLAG,
[_GUARD_KEYS_VERSION] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG,
- [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG,
- [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG,
- [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG,
+ [_LOAD_METHOD_WITH_VALUES] = 0,
+ [_LOAD_METHOD_NO_DICT] = 0,
+ [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = 0,
+ [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = 0,
[_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG,
+ [_LOAD_METHOD_LAZY_DICT] = 0,
[_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG,
[_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_CHECK_FUNCTION_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
@@ -258,7 +253,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_EXPAND_METHOD_KW] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG,
[_CHECK_IS_NOT_PY_CALLABLE_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
[_CALL_KW_NON_PY] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
- [_MAKE_CALLARGS_A_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
+ [_MAKE_CALLARGS_A_TUPLE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG,
[_RETURN_GENERATOR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
@@ -285,9 +280,9 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_LOAD_CONST_INLINE_WITH_NULL] = HAS_PURE_FLAG,
[_LOAD_CONST_INLINE_BORROW_WITH_NULL] = HAS_PURE_FLAG,
[_CHECK_FUNCTION] = HAS_DEOPT_FLAG,
- [_LOAD_GLOBAL_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
- [_LOAD_GLOBAL_BUILTINS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
- [_LOAD_ATTR_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
+ [_LOAD_GLOBAL_MODULE] = HAS_DEOPT_FLAG,
+ [_LOAD_GLOBAL_BUILTINS] = HAS_DEOPT_FLAG,
+ [_LOAD_ATTR_MODULE] = HAS_DEOPT_FLAG,
[_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG,
[_START_EXECUTOR] = HAS_ESCAPES_FLAG,
[_MAKE_WARM] = 0,
@@ -457,22 +452,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LIST_EXTEND] = "_LIST_EXTEND",
[_LOAD_ATTR] = "_LOAD_ATTR",
[_LOAD_ATTR_CLASS] = "_LOAD_ATTR_CLASS",
- [_LOAD_ATTR_CLASS_0] = "_LOAD_ATTR_CLASS_0",
- [_LOAD_ATTR_CLASS_1] = "_LOAD_ATTR_CLASS_1",
[_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE",
- [_LOAD_ATTR_INSTANCE_VALUE_0] = "_LOAD_ATTR_INSTANCE_VALUE_0",
- [_LOAD_ATTR_INSTANCE_VALUE_1] = "_LOAD_ATTR_INSTANCE_VALUE_1",
- [_LOAD_ATTR_METHOD_LAZY_DICT] = "_LOAD_ATTR_METHOD_LAZY_DICT",
- [_LOAD_ATTR_METHOD_NO_DICT] = "_LOAD_ATTR_METHOD_NO_DICT",
- [_LOAD_ATTR_METHOD_WITH_VALUES] = "_LOAD_ATTR_METHOD_WITH_VALUES",
[_LOAD_ATTR_MODULE] = "_LOAD_ATTR_MODULE",
[_LOAD_ATTR_MODULE_FROM_KEYS] = "_LOAD_ATTR_MODULE_FROM_KEYS",
[_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = "_LOAD_ATTR_NONDESCRIPTOR_NO_DICT",
[_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES",
[_LOAD_ATTR_PROPERTY_FRAME] = "_LOAD_ATTR_PROPERTY_FRAME",
[_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT",
- [_LOAD_ATTR_SLOT_0] = "_LOAD_ATTR_SLOT_0",
- [_LOAD_ATTR_SLOT_1] = "_LOAD_ATTR_SLOT_1",
[_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT",
[_LOAD_BUILD_CLASS] = "_LOAD_BUILD_CLASS",
[_LOAD_COMMON_CONSTANT] = "_LOAD_COMMON_CONSTANT",
@@ -502,6 +488,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE",
[_LOAD_GLOBAL_MODULE_FROM_KEYS] = "_LOAD_GLOBAL_MODULE_FROM_KEYS",
[_LOAD_LOCALS] = "_LOAD_LOCALS",
+ [_LOAD_METHOD] = "_LOAD_METHOD",
+ [_LOAD_METHOD_LAZY_DICT] = "_LOAD_METHOD_LAZY_DICT",
+ [_LOAD_METHOD_NO_DICT] = "_LOAD_METHOD_NO_DICT",
+ [_LOAD_METHOD_WITH_VALUES] = "_LOAD_METHOD_WITH_VALUES",
[_LOAD_NAME] = "_LOAD_NAME",
[_LOAD_SMALL_INT] = "_LOAD_SMALL_INT",
[_LOAD_SMALL_INT_0] = "_LOAD_SMALL_INT_0",
@@ -510,7 +500,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_SMALL_INT_3] = "_LOAD_SMALL_INT_3",
[_LOAD_SPECIAL] = "_LOAD_SPECIAL",
[_LOAD_SUPER_ATTR_ATTR] = "_LOAD_SUPER_ATTR_ATTR",
- [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD",
+ [_LOAD_SUPER_METHOD_METHOD] = "_LOAD_SUPER_METHOD_METHOD",
[_MAKE_CALLARGS_A_TUPLE] = "_MAKE_CALLARGS_A_TUPLE",
[_MAKE_CELL] = "_MAKE_CELL",
[_MAKE_FUNCTION] = "_MAKE_FUNCTION",
@@ -845,8 +835,10 @@ int _PyUop_num_popped(int opcode, int oparg)
return 2;
case _LOAD_SUPER_ATTR_ATTR:
return 3;
- case _LOAD_SUPER_ATTR_METHOD:
+ case _LOAD_SUPER_METHOD_METHOD:
return 3;
+ case _LOAD_METHOD:
+ return 1;
case _LOAD_ATTR:
return 1;
case _GUARD_TYPE_VERSION:
@@ -855,10 +847,6 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _CHECK_MANAGED_OBJECT_HAS_VALUES:
return 0;
- case _LOAD_ATTR_INSTANCE_VALUE_0:
- return 1;
- case _LOAD_ATTR_INSTANCE_VALUE_1:
- return 1;
case _LOAD_ATTR_INSTANCE_VALUE:
return 1;
case _CHECK_ATTR_MODULE_PUSH_KEYS:
@@ -869,18 +857,10 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _LOAD_ATTR_WITH_HINT:
return 2;
- case _LOAD_ATTR_SLOT_0:
- return 1;
- case _LOAD_ATTR_SLOT_1:
- return 1;
case _LOAD_ATTR_SLOT:
return 1;
case _CHECK_ATTR_CLASS:
return 0;
- case _LOAD_ATTR_CLASS_0:
- return 1;
- case _LOAD_ATTR_CLASS_1:
- return 1;
case _LOAD_ATTR_CLASS:
return 1;
case _LOAD_ATTR_PROPERTY_FRAME:
@@ -965,9 +945,9 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _GUARD_KEYS_VERSION:
return 0;
- case _LOAD_ATTR_METHOD_WITH_VALUES:
+ case _LOAD_METHOD_WITH_VALUES:
return 1;
- case _LOAD_ATTR_METHOD_NO_DICT:
+ case _LOAD_METHOD_NO_DICT:
return 1;
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
return 1;
@@ -975,7 +955,7 @@ int _PyUop_num_popped(int opcode, int oparg)
return 1;
case _CHECK_ATTR_METHOD_LAZY_DICT:
return 0;
- case _LOAD_ATTR_METHOD_LAZY_DICT:
+ case _LOAD_METHOD_LAZY_DICT:
return 1;
case _MAYBE_EXPAND_METHOD:
return 2 + oparg;
@@ -1066,7 +1046,7 @@ int _PyUop_num_popped(int opcode, int oparg)
case _CALL_KW_NON_PY:
return 3 + oparg;
case _MAKE_CALLARGS_A_TUPLE:
- return 1 + (oparg & 1);
+ return 2;
case _MAKE_FUNCTION:
return 1;
case _SET_FUNCTION_ATTRIBUTE:
@@ -1074,7 +1054,7 @@ int _PyUop_num_popped(int opcode, int oparg)
case _RETURN_GENERATOR:
return 0;
case _BUILD_SLICE:
- return 2 + ((oparg == 3) ? 1 : 0);
+ return oparg;
case _CONVERT_VALUE:
return 1;
case _FORMAT_SIMPLE:
diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h
index 06b207b347e504..e931e76bdb193a 100644
--- a/Include/opcode_ids.h
+++ b/Include/opcode_ids.h
@@ -14,55 +14,55 @@ extern "C" {
#define BINARY_SLICE 1
#define BINARY_SUBSCR 2
#define BINARY_OP_INPLACE_ADD_UNICODE 3
-#define CHECK_EG_MATCH 4
-#define CHECK_EXC_MATCH 5
-#define CLEANUP_THROW 6
-#define DELETE_SUBSCR 7
-#define END_ASYNC_FOR 8
-#define END_FOR 9
-#define END_SEND 10
-#define EXIT_INIT_CHECK 11
-#define FORMAT_SIMPLE 12
-#define FORMAT_WITH_SPEC 13
-#define GET_AITER 14
-#define GET_ANEXT 15
-#define GET_ITER 16
+#define CALL_FUNCTION_EX 4
+#define CHECK_EG_MATCH 5
+#define CHECK_EXC_MATCH 6
+#define CLEANUP_THROW 7
+#define DELETE_SUBSCR 8
+#define END_ASYNC_FOR 9
+#define END_FOR 10
+#define END_SEND 11
+#define EXIT_INIT_CHECK 12
+#define FORMAT_SIMPLE 13
+#define FORMAT_WITH_SPEC 14
+#define GET_AITER 15
+#define GET_ANEXT 16
#define RESERVED 17
-#define GET_LEN 18
-#define GET_YIELD_FROM_ITER 19
-#define INTERPRETER_EXIT 20
-#define LOAD_BUILD_CLASS 21
-#define LOAD_LOCALS 22
-#define MAKE_FUNCTION 23
-#define MATCH_KEYS 24
-#define MATCH_MAPPING 25
-#define MATCH_SEQUENCE 26
-#define NOP 27
-#define NOT_TAKEN 28
-#define POP_EXCEPT 29
-#define POP_ITER 30
-#define POP_TOP 31
-#define PUSH_EXC_INFO 32
-#define PUSH_NULL 33
-#define RETURN_GENERATOR 34
-#define RETURN_VALUE 35
-#define SETUP_ANNOTATIONS 36
-#define STORE_SLICE 37
-#define STORE_SUBSCR 38
-#define TO_BOOL 39
-#define UNARY_INVERT 40
-#define UNARY_NEGATIVE 41
-#define UNARY_NOT 42
-#define WITH_EXCEPT_START 43
-#define BINARY_OP 44
-#define BUILD_LIST 45
-#define BUILD_MAP 46
-#define BUILD_SET 47
-#define BUILD_SLICE 48
-#define BUILD_STRING 49
-#define BUILD_TUPLE 50
-#define CALL 51
-#define CALL_FUNCTION_EX 52
+#define GET_ITER 18
+#define GET_LEN 19
+#define GET_YIELD_FROM_ITER 20
+#define INTERPRETER_EXIT 21
+#define LOAD_BUILD_CLASS 22
+#define LOAD_LOCALS 23
+#define MAKE_FUNCTION 24
+#define MATCH_KEYS 25
+#define MATCH_MAPPING 26
+#define MATCH_SEQUENCE 27
+#define NOP 28
+#define NOT_TAKEN 29
+#define POP_EXCEPT 30
+#define POP_ITER 31
+#define POP_TOP 32
+#define PUSH_EXC_INFO 33
+#define PUSH_NULL 34
+#define RETURN_GENERATOR 35
+#define RETURN_VALUE 36
+#define SETUP_ANNOTATIONS 37
+#define STORE_SLICE 38
+#define STORE_SUBSCR 39
+#define TO_BOOL 40
+#define UNARY_INVERT 41
+#define UNARY_NEGATIVE 42
+#define UNARY_NOT 43
+#define WITH_EXCEPT_START 44
+#define BINARY_OP 45
+#define BUILD_LIST 46
+#define BUILD_MAP 47
+#define BUILD_SET 48
+#define BUILD_SLICE 49
+#define BUILD_STRING 50
+#define BUILD_TUPLE 51
+#define CALL 52
#define CALL_INTRINSIC_1 53
#define CALL_INTRINSIC_2 54
#define CALL_KW 55
@@ -100,34 +100,36 @@ extern "C" {
#define LOAD_FROM_DICT_OR_DEREF 87
#define LOAD_FROM_DICT_OR_GLOBALS 88
#define LOAD_GLOBAL 89
-#define LOAD_NAME 90
-#define LOAD_SMALL_INT 91
-#define LOAD_SPECIAL 92
-#define LOAD_SUPER_ATTR 93
-#define MAKE_CELL 94
-#define MAP_ADD 95
-#define MATCH_CLASS 96
-#define POP_JUMP_IF_FALSE 97
-#define POP_JUMP_IF_NONE 98
-#define POP_JUMP_IF_NOT_NONE 99
-#define POP_JUMP_IF_TRUE 100
-#define RAISE_VARARGS 101
-#define RERAISE 102
-#define SEND 103
-#define SET_ADD 104
-#define SET_FUNCTION_ATTRIBUTE 105
-#define SET_UPDATE 106
-#define STORE_ATTR 107
-#define STORE_DEREF 108
-#define STORE_FAST 109
-#define STORE_FAST_LOAD_FAST 110
-#define STORE_FAST_STORE_FAST 111
-#define STORE_GLOBAL 112
-#define STORE_NAME 113
-#define SWAP 114
-#define UNPACK_EX 115
-#define UNPACK_SEQUENCE 116
-#define YIELD_VALUE 117
+#define LOAD_METHOD 90
+#define LOAD_NAME 91
+#define LOAD_SMALL_INT 92
+#define LOAD_SPECIAL 93
+#define LOAD_SUPER_ATTR 94
+#define LOAD_SUPER_METHOD 95
+#define MAKE_CELL 96
+#define MAP_ADD 97
+#define MATCH_CLASS 98
+#define POP_JUMP_IF_FALSE 99
+#define POP_JUMP_IF_NONE 100
+#define POP_JUMP_IF_NOT_NONE 101
+#define POP_JUMP_IF_TRUE 102
+#define RAISE_VARARGS 103
+#define RERAISE 104
+#define SEND 105
+#define SET_ADD 106
+#define SET_FUNCTION_ATTRIBUTE 107
+#define SET_UPDATE 108
+#define STORE_ATTR 109
+#define STORE_DEREF 110
+#define STORE_FAST 111
+#define STORE_FAST_LOAD_FAST 112
+#define STORE_FAST_STORE_FAST 113
+#define STORE_GLOBAL 114
+#define STORE_NAME 115
+#define SWAP 116
+#define UNPACK_EX 117
+#define UNPACK_SEQUENCE 118
+#define YIELD_VALUE 119
#define RESUME 149
#define BINARY_OP_ADD_FLOAT 150
#define BINARY_OP_ADD_INT 151
@@ -178,21 +180,21 @@ extern "C" {
#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 196
#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 197
#define LOAD_ATTR_INSTANCE_VALUE 198
-#define LOAD_ATTR_METHOD_LAZY_DICT 199
-#define LOAD_ATTR_METHOD_NO_DICT 200
-#define LOAD_ATTR_METHOD_WITH_VALUES 201
-#define LOAD_ATTR_MODULE 202
-#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 203
-#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 204
-#define LOAD_ATTR_PROPERTY 205
-#define LOAD_ATTR_SLOT 206
-#define LOAD_ATTR_WITH_HINT 207
-#define LOAD_CONST_IMMORTAL 208
-#define LOAD_CONST_MORTAL 209
-#define LOAD_GLOBAL_BUILTIN 210
-#define LOAD_GLOBAL_MODULE 211
+#define LOAD_ATTR_MODULE 199
+#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 200
+#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 201
+#define LOAD_ATTR_PROPERTY 202
+#define LOAD_ATTR_SLOT 203
+#define LOAD_ATTR_WITH_HINT 204
+#define LOAD_CONST_IMMORTAL 205
+#define LOAD_CONST_MORTAL 206
+#define LOAD_GLOBAL_BUILTIN 207
+#define LOAD_GLOBAL_MODULE 208
+#define LOAD_METHOD_LAZY_DICT 209
+#define LOAD_METHOD_NO_DICT 210
+#define LOAD_METHOD_WITH_VALUES 211
#define LOAD_SUPER_ATTR_ATTR 212
-#define LOAD_SUPER_ATTR_METHOD 213
+#define LOAD_SUPER_METHOD_METHOD 213
#define RESUME_CHECK 214
#define SEND_GEN 215
#define STORE_ATTR_INSTANCE_VALUE 216
@@ -209,10 +211,11 @@ extern "C" {
#define UNPACK_SEQUENCE_LIST 227
#define UNPACK_SEQUENCE_TUPLE 228
#define UNPACK_SEQUENCE_TWO_TUPLE 229
-#define INSTRUMENTED_END_FOR 235
-#define INSTRUMENTED_POP_ITER 236
-#define INSTRUMENTED_END_SEND 237
-#define INSTRUMENTED_LOAD_SUPER_ATTR 238
+#define INSTRUMENTED_END_FOR 234
+#define INSTRUMENTED_POP_ITER 235
+#define INSTRUMENTED_END_SEND 236
+#define INSTRUMENTED_LOAD_SUPER_ATTR 237
+#define INSTRUMENTED_LOAD_SUPER_METHOD 238
#define INSTRUMENTED_FOR_ITER 239
#define INSTRUMENTED_CALL_KW 240
#define INSTRUMENTED_CALL_FUNCTION_EX 241
@@ -241,9 +244,9 @@ extern "C" {
#define SETUP_WITH 264
#define STORE_FAST_MAYBE_NULL 265
-#define HAVE_ARGUMENT 43
+#define HAVE_ARGUMENT 44
#define MIN_SPECIALIZED_OPCODE 150
-#define MIN_INSTRUMENTED_OPCODE 235
+#define MIN_INSTRUMENTED_OPCODE 234
#ifdef __cplusplus
}
diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py
index 7dd528ef74df33..a32e6fe953b782 100644
--- a/Lib/_opcode_metadata.py
+++ b/Lib/_opcode_metadata.py
@@ -59,7 +59,9 @@
],
"LOAD_SUPER_ATTR": [
"LOAD_SUPER_ATTR_ATTR",
- "LOAD_SUPER_ATTR_METHOD",
+ ],
+ "LOAD_SUPER_METHOD": [
+ "LOAD_SUPER_METHOD_METHOD",
],
"LOAD_ATTR": [
"LOAD_ATTR_INSTANCE_VALUE",
@@ -70,12 +72,14 @@
"LOAD_ATTR_CLASS_WITH_METACLASS_CHECK",
"LOAD_ATTR_PROPERTY",
"LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN",
- "LOAD_ATTR_METHOD_WITH_VALUES",
- "LOAD_ATTR_METHOD_NO_DICT",
- "LOAD_ATTR_METHOD_LAZY_DICT",
"LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES",
"LOAD_ATTR_NONDESCRIPTOR_NO_DICT",
],
+ "LOAD_METHOD": [
+ "LOAD_METHOD_WITH_VALUES",
+ "LOAD_METHOD_NO_DICT",
+ "LOAD_METHOD_LAZY_DICT",
+ ],
"COMPARE_OP": [
"COMPARE_OP_FLOAT",
"COMPARE_OP_INT",
@@ -171,21 +175,21 @@
'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 196,
'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 197,
'LOAD_ATTR_INSTANCE_VALUE': 198,
- 'LOAD_ATTR_METHOD_LAZY_DICT': 199,
- 'LOAD_ATTR_METHOD_NO_DICT': 200,
- 'LOAD_ATTR_METHOD_WITH_VALUES': 201,
- 'LOAD_ATTR_MODULE': 202,
- 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 203,
- 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 204,
- 'LOAD_ATTR_PROPERTY': 205,
- 'LOAD_ATTR_SLOT': 206,
- 'LOAD_ATTR_WITH_HINT': 207,
- 'LOAD_CONST_IMMORTAL': 208,
- 'LOAD_CONST_MORTAL': 209,
- 'LOAD_GLOBAL_BUILTIN': 210,
- 'LOAD_GLOBAL_MODULE': 211,
+ 'LOAD_ATTR_MODULE': 199,
+ 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 200,
+ 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 201,
+ 'LOAD_ATTR_PROPERTY': 202,
+ 'LOAD_ATTR_SLOT': 203,
+ 'LOAD_ATTR_WITH_HINT': 204,
+ 'LOAD_CONST_IMMORTAL': 205,
+ 'LOAD_CONST_MORTAL': 206,
+ 'LOAD_GLOBAL_BUILTIN': 207,
+ 'LOAD_GLOBAL_MODULE': 208,
+ 'LOAD_METHOD_LAZY_DICT': 209,
+ 'LOAD_METHOD_NO_DICT': 210,
+ 'LOAD_METHOD_WITH_VALUES': 211,
'LOAD_SUPER_ATTR_ATTR': 212,
- 'LOAD_SUPER_ATTR_METHOD': 213,
+ 'LOAD_SUPER_METHOD_METHOD': 213,
'RESUME_CHECK': 214,
'SEND_GEN': 215,
'STORE_ATTR_INSTANCE_VALUE': 216,
@@ -212,54 +216,54 @@
'ENTER_EXECUTOR': 255,
'BINARY_SLICE': 1,
'BINARY_SUBSCR': 2,
- 'CHECK_EG_MATCH': 4,
- 'CHECK_EXC_MATCH': 5,
- 'CLEANUP_THROW': 6,
- 'DELETE_SUBSCR': 7,
- 'END_ASYNC_FOR': 8,
- 'END_FOR': 9,
- 'END_SEND': 10,
- 'EXIT_INIT_CHECK': 11,
- 'FORMAT_SIMPLE': 12,
- 'FORMAT_WITH_SPEC': 13,
- 'GET_AITER': 14,
- 'GET_ANEXT': 15,
- 'GET_ITER': 16,
- 'GET_LEN': 18,
- 'GET_YIELD_FROM_ITER': 19,
- 'INTERPRETER_EXIT': 20,
- 'LOAD_BUILD_CLASS': 21,
- 'LOAD_LOCALS': 22,
- 'MAKE_FUNCTION': 23,
- 'MATCH_KEYS': 24,
- 'MATCH_MAPPING': 25,
- 'MATCH_SEQUENCE': 26,
- 'NOP': 27,
- 'NOT_TAKEN': 28,
- 'POP_EXCEPT': 29,
- 'POP_ITER': 30,
- 'POP_TOP': 31,
- 'PUSH_EXC_INFO': 32,
- 'PUSH_NULL': 33,
- 'RETURN_GENERATOR': 34,
- 'RETURN_VALUE': 35,
- 'SETUP_ANNOTATIONS': 36,
- 'STORE_SLICE': 37,
- 'STORE_SUBSCR': 38,
- 'TO_BOOL': 39,
- 'UNARY_INVERT': 40,
- 'UNARY_NEGATIVE': 41,
- 'UNARY_NOT': 42,
- 'WITH_EXCEPT_START': 43,
- 'BINARY_OP': 44,
- 'BUILD_LIST': 45,
- 'BUILD_MAP': 46,
- 'BUILD_SET': 47,
- 'BUILD_SLICE': 48,
- 'BUILD_STRING': 49,
- 'BUILD_TUPLE': 50,
- 'CALL': 51,
- 'CALL_FUNCTION_EX': 52,
+ 'CALL_FUNCTION_EX': 4,
+ 'CHECK_EG_MATCH': 5,
+ 'CHECK_EXC_MATCH': 6,
+ 'CLEANUP_THROW': 7,
+ 'DELETE_SUBSCR': 8,
+ 'END_ASYNC_FOR': 9,
+ 'END_FOR': 10,
+ 'END_SEND': 11,
+ 'EXIT_INIT_CHECK': 12,
+ 'FORMAT_SIMPLE': 13,
+ 'FORMAT_WITH_SPEC': 14,
+ 'GET_AITER': 15,
+ 'GET_ANEXT': 16,
+ 'GET_ITER': 18,
+ 'GET_LEN': 19,
+ 'GET_YIELD_FROM_ITER': 20,
+ 'INTERPRETER_EXIT': 21,
+ 'LOAD_BUILD_CLASS': 22,
+ 'LOAD_LOCALS': 23,
+ 'MAKE_FUNCTION': 24,
+ 'MATCH_KEYS': 25,
+ 'MATCH_MAPPING': 26,
+ 'MATCH_SEQUENCE': 27,
+ 'NOP': 28,
+ 'NOT_TAKEN': 29,
+ 'POP_EXCEPT': 30,
+ 'POP_ITER': 31,
+ 'POP_TOP': 32,
+ 'PUSH_EXC_INFO': 33,
+ 'PUSH_NULL': 34,
+ 'RETURN_GENERATOR': 35,
+ 'RETURN_VALUE': 36,
+ 'SETUP_ANNOTATIONS': 37,
+ 'STORE_SLICE': 38,
+ 'STORE_SUBSCR': 39,
+ 'TO_BOOL': 40,
+ 'UNARY_INVERT': 41,
+ 'UNARY_NEGATIVE': 42,
+ 'UNARY_NOT': 43,
+ 'WITH_EXCEPT_START': 44,
+ 'BINARY_OP': 45,
+ 'BUILD_LIST': 46,
+ 'BUILD_MAP': 47,
+ 'BUILD_SET': 48,
+ 'BUILD_SLICE': 49,
+ 'BUILD_STRING': 50,
+ 'BUILD_TUPLE': 51,
+ 'CALL': 52,
'CALL_INTRINSIC_1': 53,
'CALL_INTRINSIC_2': 54,
'CALL_KW': 55,
@@ -297,38 +301,41 @@
'LOAD_FROM_DICT_OR_DEREF': 87,
'LOAD_FROM_DICT_OR_GLOBALS': 88,
'LOAD_GLOBAL': 89,
- 'LOAD_NAME': 90,
- 'LOAD_SMALL_INT': 91,
- 'LOAD_SPECIAL': 92,
- 'LOAD_SUPER_ATTR': 93,
- 'MAKE_CELL': 94,
- 'MAP_ADD': 95,
- 'MATCH_CLASS': 96,
- 'POP_JUMP_IF_FALSE': 97,
- 'POP_JUMP_IF_NONE': 98,
- 'POP_JUMP_IF_NOT_NONE': 99,
- 'POP_JUMP_IF_TRUE': 100,
- 'RAISE_VARARGS': 101,
- 'RERAISE': 102,
- 'SEND': 103,
- 'SET_ADD': 104,
- 'SET_FUNCTION_ATTRIBUTE': 105,
- 'SET_UPDATE': 106,
- 'STORE_ATTR': 107,
- 'STORE_DEREF': 108,
- 'STORE_FAST': 109,
- 'STORE_FAST_LOAD_FAST': 110,
- 'STORE_FAST_STORE_FAST': 111,
- 'STORE_GLOBAL': 112,
- 'STORE_NAME': 113,
- 'SWAP': 114,
- 'UNPACK_EX': 115,
- 'UNPACK_SEQUENCE': 116,
- 'YIELD_VALUE': 117,
- 'INSTRUMENTED_END_FOR': 235,
- 'INSTRUMENTED_POP_ITER': 236,
- 'INSTRUMENTED_END_SEND': 237,
- 'INSTRUMENTED_LOAD_SUPER_ATTR': 238,
+ 'LOAD_METHOD': 90,
+ 'LOAD_NAME': 91,
+ 'LOAD_SMALL_INT': 92,
+ 'LOAD_SPECIAL': 93,
+ 'LOAD_SUPER_ATTR': 94,
+ 'LOAD_SUPER_METHOD': 95,
+ 'MAKE_CELL': 96,
+ 'MAP_ADD': 97,
+ 'MATCH_CLASS': 98,
+ 'POP_JUMP_IF_FALSE': 99,
+ 'POP_JUMP_IF_NONE': 100,
+ 'POP_JUMP_IF_NOT_NONE': 101,
+ 'POP_JUMP_IF_TRUE': 102,
+ 'RAISE_VARARGS': 103,
+ 'RERAISE': 104,
+ 'SEND': 105,
+ 'SET_ADD': 106,
+ 'SET_FUNCTION_ATTRIBUTE': 107,
+ 'SET_UPDATE': 108,
+ 'STORE_ATTR': 109,
+ 'STORE_DEREF': 110,
+ 'STORE_FAST': 111,
+ 'STORE_FAST_LOAD_FAST': 112,
+ 'STORE_FAST_STORE_FAST': 113,
+ 'STORE_GLOBAL': 114,
+ 'STORE_NAME': 115,
+ 'SWAP': 116,
+ 'UNPACK_EX': 117,
+ 'UNPACK_SEQUENCE': 118,
+ 'YIELD_VALUE': 119,
+ 'INSTRUMENTED_END_FOR': 234,
+ 'INSTRUMENTED_POP_ITER': 235,
+ 'INSTRUMENTED_END_SEND': 236,
+ 'INSTRUMENTED_LOAD_SUPER_ATTR': 237,
+ 'INSTRUMENTED_LOAD_SUPER_METHOD': 238,
'INSTRUMENTED_FOR_ITER': 239,
'INSTRUMENTED_CALL_KW': 240,
'INSTRUMENTED_CALL_FUNCTION_EX': 241,
@@ -356,5 +363,5 @@
'STORE_FAST_MAYBE_NULL': 265,
}
-HAVE_ARGUMENT = 43
-MIN_INSTRUMENTED_OPCODE = 235
+HAVE_ARGUMENT = 44
+MIN_INSTRUMENTED_OPCODE = 234
diff --git a/Lib/dis.py b/Lib/dis.py
index 109c986bbe3d7d..5a34e228079481 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -42,7 +42,9 @@
FOR_ITER = opmap['FOR_ITER']
SEND = opmap['SEND']
LOAD_ATTR = opmap['LOAD_ATTR']
+LOAD_METHOD = opmap['LOAD_METHOD']
LOAD_SUPER_ATTR = opmap['LOAD_SUPER_ATTR']
+LOAD_SUPER_METHOD = opmap['LOAD_SUPER_METHOD']
CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1']
CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2']
LOAD_COMMON_CONSTANT = opmap['LOAD_COMMON_CONSTANT']
@@ -580,16 +582,14 @@ def get_argval_argrepr(self, op, arg, offset):
argval, argrepr = _get_const_info(deop, arg, self.co_consts)
elif deop in hasname:
if deop == LOAD_GLOBAL:
- argval, argrepr = _get_name_info(arg//2, get_name)
- if (arg & 1) and argrepr:
- argrepr = f"{argrepr} + NULL"
- elif deop == LOAD_ATTR:
- argval, argrepr = _get_name_info(arg//2, get_name)
- if (arg & 1) and argrepr:
+ argval, argrepr = _get_name_info(arg, get_name)
+ elif deop == LOAD_ATTR or deop == LOAD_METHOD:
+ argval, argrepr = _get_name_info(arg, get_name)
+ if deop == LOAD_METHOD and argrepr:
argrepr = f"{argrepr} + NULL|self"
- elif deop == LOAD_SUPER_ATTR:
+ elif deop == LOAD_SUPER_ATTR or deop == LOAD_SUPER_METHOD:
argval, argrepr = _get_name_info(arg//4, get_name)
- if (arg & 1) and argrepr:
+ if deop == LOAD_SUPER_METHOD and argrepr:
argrepr = f"{argrepr} + NULL|self"
else:
argval, argrepr = _get_name_info(arg, get_name)
diff --git a/Lib/inspect.py b/Lib/inspect.py
index facad478103668..3d9ff07a3cfb7b 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -1511,7 +1511,7 @@ def getclosurevars(func):
for instruction in dis.get_instructions(code):
opname = instruction.opname
name = instruction.argval
- if opname == "LOAD_ATTR":
+ if opname == "LOAD_ATTR" or opname == "LOAD_METHOD":
unbound_names.add(name)
elif opname == "LOAD_GLOBAL":
global_names.add(name)
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 4ee0d64026bd0a..d87149e95b5a33 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -72,12 +72,21 @@
"LOAD_SUPER_ATTR": {
"counter": 1,
},
+ "LOAD_SUPER_METHOD": {
+ "counter": 1,
+ },
"LOAD_ATTR": {
"counter": 1,
"version": 2,
"keys_version": 2,
"descr": 4,
},
+ "LOAD_METHOD": {
+ "counter": 1,
+ "version": 2,
+ "keys_version": 2,
+ "descr": 4,
+ },
"STORE_ATTR": {
"counter": 1,
"version": 2,
diff --git a/Lib/test/test__opcode.py b/Lib/test/test__opcode.py
index 95e09500df51d0..4b11e83ae59a78 100644
--- a/Lib/test/test__opcode.py
+++ b/Lib/test/test__opcode.py
@@ -65,8 +65,7 @@ def check_function(self, func, expected):
class StackEffectTests(unittest.TestCase):
def test_stack_effect(self):
self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1)
- self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
- self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
+ self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 2), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
self.assertRaises(ValueError, stack_effect, 30000)
# All defined opcodes
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 9cfc6c142da6cd..6a2f7726222f9b 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -711,7 +711,7 @@ def testfunc(n):
assert ex is not None
uops = get_opnames(ex)
assert "_LOAD_GLOBAL_BUILTINS" not in uops
- assert "_LOAD_CONST_INLINE_BORROW_WITH_NULL" in uops
+ assert "_LOAD_CONST_INLINE_BORROW" in uops
"""))
self.assertEqual(result[0].rc, 0, result)
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index b5cf2ad18fe60b..f4123d2a85f52b 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -2157,7 +2157,7 @@ def test_method_call(self):
source = "(\n lhs \n . \n rhs \n )()"
code = compile(source, "<test>", "exec")
self.assertOpcodeSourcePositionIs(
- code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8
+ code, "LOAD_METHOD", line=4, end_line=4, column=5, end_column=8
)
self.assertOpcodeSourcePositionIs(
code, "CALL", line=4, end_line=5, column=5, end_column=10
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index da57aad2f84fbd..6fdcdbb0d9a3ad 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -113,7 +113,8 @@ def _f(a):
dis_f = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 1 (print + NULL)
+%3d LOAD_GLOBAL 0 (print)
+ PUSH_NULL
LOAD_FAST 0 (a)
CALL 1
POP_TOP
@@ -127,13 +128,14 @@ def _f(a):
dis_f_with_offsets = """\
%3d 0 RESUME 0
-%3d 2 LOAD_GLOBAL 1 (print + NULL)
- 12 LOAD_FAST 0 (a)
- 14 CALL 1
- 22 POP_TOP
+%3d 2 LOAD_GLOBAL 0 (print)
+ 12 PUSH_NULL
+ 14 LOAD_FAST 0 (a)
+ 16 CALL 1
+ 24 POP_TOP
-%3d 24 LOAD_SMALL_INT 1
- 26 RETURN_VALUE
+%3d 26 LOAD_SMALL_INT 1
+ 28 RETURN_VALUE
""" % (_f.__code__.co_firstlineno,
_f.__code__.co_firstlineno + 1,
_f.__code__.co_firstlineno + 2)
@@ -141,7 +143,8 @@ def _f(a):
dis_f_with_positions_format = f"""\
%-14s RESUME 0
-%-14s LOAD_GLOBAL 1 (print + NULL)
+%-14s LOAD_GLOBAL 0 (print)
+%-14s PUSH_NULL
%-14s LOAD_FAST 0 (a)
%-14s CALL 1
%-14s POP_TOP
@@ -152,7 +155,8 @@ def _f(a):
dis_f_co_code = """\
RESUME 0
- LOAD_GLOBAL 1
+ LOAD_GLOBAL 0
+ PUSH_NULL
LOAD_FAST 0
CALL 1
POP_TOP
@@ -168,7 +172,8 @@ def bug708901():
dis_bug708901 = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 1 (range + NULL)
+%3d LOAD_GLOBAL 0 (range)
+ PUSH_NULL
LOAD_SMALL_INT 1
%3d LOAD_SMALL_INT 10
@@ -276,7 +281,8 @@ def wrap_func_w_kwargs():
dis_kw_names = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 1 (func_w_kwargs + NULL)
+%3d LOAD_GLOBAL 0 (func_w_kwargs)
+ PUSH_NULL
LOAD_SMALL_INT 1
LOAD_SMALL_INT 2
LOAD_SMALL_INT 5
@@ -463,7 +469,7 @@ def foo(a: int, b: str) -> str:
STORE_FAST 0 (e)
%4d L4: LOAD_FAST 0 (e)
- LOAD_ATTR 2 (__traceback__)
+ LOAD_ATTR 1 (__traceback__)
STORE_FAST 1 (tb)
L5: POP_EXCEPT
LOAD_CONST 0 (None)
@@ -814,7 +820,8 @@ def foo(x):
%4d RESUME 0
-%4d LOAD_GLOBAL 1 (list + NULL)
+%4d LOAD_GLOBAL 0 (list)
+ PUSH_NULL
LOAD_FAST 0 (x)
BUILD_TUPLE 1
LOAD_CONST 1 (<code object <genexpr> at 0x..., file "%s", line %d>)
@@ -897,14 +904,15 @@ def loop_test():
LOAD_SMALL_INT 3
BINARY_OP 5 (*)
GET_ITER
- L1: FOR_ITER_LIST 14 (to L2)
+ L1: FOR_ITER_LIST 15 (to L2)
STORE_FAST 0 (i)
-%3d LOAD_GLOBAL_MODULE 1 (load_test + NULL)
+%3d LOAD_GLOBAL_MODULE 0 (load_test)
+ PUSH_NULL
LOAD_FAST 0 (i)
CALL_PY_GENERAL 1
POP_TOP
- JUMP_BACKWARD 16 (to L1)
+ JUMP_BACKWARD 17 (to L1)
%3d L2: END_FOR
POP_ITER
@@ -1705,203 +1713,215 @@ def _prepare_test_cases():
Instruction = dis.Instruction
expected_opinfo_outer = [
- Instruction(opname='MAKE_CELL', opcode=94, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='MAKE_CELL', opcode=94, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_CELL', opcode=96, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_CELL', opcode=96, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='BUILD_TUPLE', opcode=50, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
+ Instruction(opname='BUILD_TUPLE', opcode=51, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=105, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=105, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='STORE_FAST', opcode=109, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=1, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='BUILD_LIST', opcode=45, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='BUILD_MAP', opcode=46, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=2, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None, cache_info=None),
- Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=107, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=107, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
+ Instruction(opname='STORE_FAST', opcode=111, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=0, argval='print', argrepr='print', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=0, argval='a', argrepr='a', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=1, argval='b', argrepr='b', offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=1, argval='', argrepr="''", offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='BUILD_LIST', opcode=46, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='BUILD_MAP', opcode=47, arg=0, argval=0, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=2, argval='Hello world!', argrepr="'Hello world!'", offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=7, argval=7, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=2, argval='f', argrepr='f', offset=60, start_offset=60, starts_line=True, line_number=8, label=None, positions=None, cache_info=None),
+ Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=8, label=None, positions=None, cache_info=None),
]
expected_opinfo_f = [
Instruction(opname='COPY_FREE_VARS', opcode=60, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='MAKE_CELL', opcode=94, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='MAKE_CELL', opcode=94, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_CELL', opcode=96, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_CELL', opcode=96, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=81, arg=1, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=83, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='BUILD_TUPLE', opcode=50, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='BUILD_TUPLE', opcode=51, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=105, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=105, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='STORE_FAST', opcode=109, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6, label=None, positions=None, cache_info=None),
- Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6, label=None, positions=None, cache_info=None),
+ Instruction(opname='MAKE_FUNCTION', opcode=24, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=107, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=107, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='STORE_FAST', opcode=111, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=0, argval='print', argrepr='print', offset=30, start_offset=30, starts_line=True, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=3, argval='a', argrepr='a', offset=42, start_offset=42, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=4, argval='b', argrepr='b', offset=44, start_offset=44, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=0, argval='c', argrepr='c', offset=46, start_offset=46, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=1, argval='d', argrepr='d', offset=48, start_offset=48, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=4, argval=4, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=2, argval='inner', argrepr='inner', offset=60, start_offset=60, starts_line=True, line_number=6, label=None, positions=None, cache_info=None),
+ Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=6, label=None, positions=None, cache_info=None),
]
expected_opinfo_inner = [
Instruction(opname='COPY_FREE_VARS', opcode=60, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_DEREF', opcode=82, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=86, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=36, start_offset=36, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=0, argval='print', argrepr='print', offset=4, start_offset=4, starts_line=True, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=2, argval='a', argrepr='a', offset=16, start_offset=16, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=3, argval='b', argrepr='b', offset=18, start_offset=18, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=4, argval='c', argrepr='c', offset=20, start_offset=20, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_DEREF', opcode=82, arg=5, argval='d', argrepr='d', offset=22, start_offset=22, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=86, arg=1, argval=('e', 'f'), argrepr='e, f', offset=24, start_offset=24, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=6, argval=6, argrepr='', offset=26, start_offset=26, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=34, start_offset=34, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval=None, argrepr='None', offset=36, start_offset=36, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=38, start_offset=38, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
]
expected_opinfo_jumpy = [
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='GET_ITER', opcode=16, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='FOR_ITER', opcode=69, arg=32, argval=92, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='STORE_FAST', opcode=109, arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=4, argval=4, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=3, argval=70, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=64, start_offset=64, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD', opcode=74, arg=23, argval=24, argrepr='to L1', offset=66, start_offset=66, starts_line=True, line_number=6, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=70, start_offset=70, starts_line=True, line_number=7, label=2, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=6, argval=6, argrepr='', offset=72, start_offset=72, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=74, start_offset=74, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=3, argval=88, argrepr='to L3', offset=78, start_offset=78, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD', opcode=74, arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3, positions=None, cache_info=None),
- Instruction(opname='JUMP_FORWARD', opcode=76, arg=13, argval=118, argrepr='to L5', offset=90, start_offset=90, starts_line=False, line_number=8, label=None, positions=None, cache_info=None),
- Instruction(opname='END_FOR', opcode=9, arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=3, label=4, positions=None, cache_info=None),
- Instruction(opname='POP_ITER', opcode=30, arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=96, start_offset=96, starts_line=True, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=106, start_offset=106, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=108, start_offset=108, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=116, start_offset=116, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST_CHECK', opcode=85, arg=0, argval='i', argrepr='i', offset=118, start_offset=118, starts_line=True, line_number=11, label=5, positions=None, cache_info=None),
- Instruction(opname='TO_BOOL', opcode=39, arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=40, argval=212, argrepr='to L8', offset=128, start_offset=128, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=132, start_offset=132, starts_line=False, line_number=11, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=134, start_offset=134, starts_line=True, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=144, start_offset=144, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=146, start_offset=146, starts_line=False, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=154, start_offset=154, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=156, start_offset=156, starts_line=True, line_number=13, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
- Instruction(opname='BINARY_OP', opcode=44, arg=23, argval=23, argrepr='-=', offset=160, start_offset=160, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
- Instruction(opname='STORE_FAST', opcode=109, arg=0, argval='i', argrepr='i', offset=172, start_offset=172, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=True, line_number=14, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=6, argval=6, argrepr='', offset=176, start_offset=176, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
- Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=178, start_offset=178, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=3, argval=192, argrepr='to L6', offset=182, start_offset=182, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=186, start_offset=186, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD', opcode=74, arg=37, argval=118, argrepr='to L5', offset=188, start_offset=188, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=192, start_offset=192, starts_line=True, line_number=16, label=6, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=4, argval=4, argrepr='', offset=194, start_offset=194, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
- Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=196, start_offset=196, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=3, argval=210, argrepr='to L7', offset=200, start_offset=200, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=204, start_offset=204, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD', opcode=74, arg=46, argval=118, argrepr='to L5', offset=206, start_offset=206, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='JUMP_FORWARD', opcode=76, arg=11, argval=234, argrepr='to L9', offset=210, start_offset=210, starts_line=True, line_number=17, label=7, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=212, start_offset=212, starts_line=True, line_number=19, label=8, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=222, start_offset=222, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=224, start_offset=224, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=232, start_offset=232, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
- Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=True, line_number=20, label=9, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=21, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=0, argval=0, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
- Instruction(opname='BINARY_OP', opcode=44, arg=11, argval=11, argrepr='/', offset=240, start_offset=240, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=252, start_offset=252, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=254, start_offset=254, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='COPY', opcode=59, arg=1, argval=1, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SPECIAL', opcode=92, arg=1, argval=1, argrepr='__exit__', offset=258, start_offset=258, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='SWAP', opcode=114, arg=2, argval=2, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='SWAP', opcode=114, arg=3, argval=3, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_SPECIAL', opcode=92, arg=0, argval=0, argrepr='__enter__', offset=264, start_offset=264, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=0, argval=0, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='STORE_FAST', opcode=109, arg=1, argval='dodgy', argrepr='dodgy', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=276, start_offset=276, starts_line=True, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=286, start_offset=286, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=288, start_offset=288, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=298, start_offset=298, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=3, argval=3, argrepr='', offset=304, start_offset=304, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=314, start_offset=314, starts_line=True, line_number=28, label=10, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=324, start_offset=324, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=326, start_offset=326, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=334, start_offset=334, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=336, start_offset=336, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='WITH_EXCEPT_START', opcode=43, arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='TO_BOOL', opcode=39, arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=2, argval=360, argrepr='to L11', offset=352, start_offset=352, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=356, start_offset=356, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=2, argval=2, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25, label=11, positions=None, cache_info=None),
- Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=29, argval=314, argrepr='to L10', offset=370, start_offset=370, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
- Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=372, start_offset=372, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=380, start_offset=380, starts_line=True, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='CHECK_EXC_MATCH', opcode=5, arg=None, argval=None, argrepr='', offset=390, start_offset=390, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=15, argval=426, argrepr='to L12', offset=392, start_offset=392, starts_line=False, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
- Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=396, start_offset=396, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=400, start_offset=400, starts_line=True, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=410, start_offset=410, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=412, start_offset=412, starts_line=False, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=420, start_offset=420, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
- Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=56, argval=314, argrepr='to L10', offset=424, start_offset=424, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=426, start_offset=426, starts_line=True, line_number=22, label=12, positions=None, cache_info=None),
- Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=430, start_offset=430, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=436, start_offset=436, starts_line=True, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
- Instruction(opname='LOAD_CONST', opcode=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=446, start_offset=446, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=448, start_offset=448, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
- Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=456, start_offset=456, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
- Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=460, start_offset=460, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
- Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=0, argval='range', argrepr='range', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=10, argval=10, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='GET_ITER', opcode=18, arg=None, argval=None, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='FOR_ITER', opcode=69, arg=33, argval=96, argrepr='to L4', offset=26, start_offset=26, starts_line=False, line_number=3, label=1, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='STORE_FAST', opcode=111, arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=32, start_offset=32, starts_line=True, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=44, start_offset=44, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=4, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=56, start_offset=56, starts_line=True, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=4, argval=4, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=60, start_offset=60, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=99, arg=3, argval=74, argrepr='to L2', offset=64, start_offset=64, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=68, start_offset=68, starts_line=False, line_number=5, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=74, arg=24, argval=26, argrepr='to L1', offset=70, start_offset=70, starts_line=True, line_number=6, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=74, start_offset=74, starts_line=True, line_number=7, label=2, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=6, argval=6, argrepr='', offset=76, start_offset=76, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=78, start_offset=78, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=102, arg=3, argval=92, argrepr='to L3', offset=82, start_offset=82, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=86, start_offset=86, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=74, arg=33, argval=26, argrepr='to L1', offset=88, start_offset=88, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=8, label=3, positions=None, cache_info=None),
+ Instruction(opname='JUMP_FORWARD', opcode=76, arg=14, argval=124, argrepr='to L5', offset=94, start_offset=94, starts_line=False, line_number=8, label=None, positions=None, cache_info=None),
+ Instruction(opname='END_FOR', opcode=10, arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=True, line_number=3, label=4, positions=None, cache_info=None),
+ Instruction(opname='POP_ITER', opcode=31, arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=100, start_offset=100, starts_line=True, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=112, start_offset=112, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=114, start_offset=114, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST_CHECK', opcode=85, arg=0, argval='i', argrepr='i', offset=124, start_offset=124, starts_line=True, line_number=11, label=5, positions=None, cache_info=None),
+ Instruction(opname='TO_BOOL', opcode=40, arg=None, argval=None, argrepr='', offset=126, start_offset=126, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=99, arg=41, argval=220, argrepr='to L8', offset=134, start_offset=134, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=138, start_offset=138, starts_line=False, line_number=11, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=140, start_offset=140, starts_line=True, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=150, start_offset=150, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=152, start_offset=152, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=154, start_offset=154, starts_line=False, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=164, start_offset=164, starts_line=True, line_number=13, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=1, argval=1, argrepr='', offset=166, start_offset=166, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
+ Instruction(opname='BINARY_OP', opcode=45, arg=23, argval=23, argrepr='-=', offset=168, start_offset=168, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
+ Instruction(opname='STORE_FAST', opcode=111, arg=0, argval='i', argrepr='i', offset=180, start_offset=180, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=182, start_offset=182, starts_line=True, line_number=14, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=6, argval=6, argrepr='', offset=184, start_offset=184, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
+ Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=186, start_offset=186, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=99, arg=3, argval=200, argrepr='to L6', offset=190, start_offset=190, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=194, start_offset=194, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=74, arg=38, argval=124, argrepr='to L5', offset=196, start_offset=196, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=200, start_offset=200, starts_line=True, line_number=16, label=6, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=4, argval=4, argrepr='', offset=202, start_offset=202, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
+ Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=204, start_offset=204, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=102, arg=3, argval=218, argrepr='to L7', offset=208, start_offset=208, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=212, start_offset=212, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=74, arg=47, argval=124, argrepr='to L5', offset=214, start_offset=214, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='JUMP_FORWARD', opcode=76, arg=12, argval=244, argrepr='to L9', offset=218, start_offset=218, starts_line=True, line_number=17, label=7, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=220, start_offset=220, starts_line=True, line_number=19, label=8, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=232, start_offset=232, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
+ Instruction(opname='NOP', opcode=28, arg=None, argval=None, argrepr='', offset=244, start_offset=244, starts_line=True, line_number=20, label=9, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=1, argval=1, argrepr='', offset=246, start_offset=246, starts_line=True, line_number=21, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SMALL_INT', opcode=92, arg=0, argval=0, argrepr='', offset=248, start_offset=248, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
+ Instruction(opname='BINARY_OP', opcode=45, arg=11, argval=11, argrepr='/', offset=250, start_offset=250, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=264, start_offset=264, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='COPY', opcode=59, arg=1, argval=1, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SPECIAL', opcode=93, arg=1, argval=1, argrepr='__exit__', offset=268, start_offset=268, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='SWAP', opcode=116, arg=2, argval=2, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='SWAP', opcode=116, arg=3, argval=3, argrepr='', offset=272, start_offset=272, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_SPECIAL', opcode=93, arg=0, argval=0, argrepr='__enter__', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=0, argval=0, argrepr='', offset=276, start_offset=276, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='STORE_FAST', opcode=111, arg=1, argval='dodgy', argrepr='dodgy', offset=284, start_offset=284, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=286, start_offset=286, starts_line=True, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=298, start_offset=298, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=310, start_offset=310, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=312, start_offset=312, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=314, start_offset=314, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=3, argval=3, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=324, start_offset=324, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=326, start_offset=326, starts_line=True, line_number=28, label=10, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=338, start_offset=338, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=350, start_offset=350, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=352, start_offset=352, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=354, start_offset=354, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='WITH_EXCEPT_START', opcode=44, arg=None, argval=None, argrepr='', offset=356, start_offset=356, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='TO_BOOL', opcode=40, arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=102, arg=2, argval=374, argrepr='to L11', offset=366, start_offset=366, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=2, argval=2, argrepr='', offset=372, start_offset=372, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=25, label=11, positions=None, cache_info=None),
+ Instruction(opname='POP_EXCEPT', opcode=30, arg=None, argval=None, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=30, argval=326, argrepr='to L10', offset=384, start_offset=384, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+ Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=386, start_offset=386, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_EXCEPT', opcode=30, arg=None, argval=None, argrepr='', offset=388, start_offset=388, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=1, argval=1, argrepr='', offset=390, start_offset=390, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=394, start_offset=394, starts_line=True, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='CHECK_EXC_MATCH', opcode=6, arg=None, argval=None, argrepr='', offset=404, start_offset=404, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=99, arg=16, argval=442, argrepr='to L12', offset=406, start_offset=406, starts_line=False, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+ Instruction(opname='NOT_TAKEN', opcode=29, arg=None, argval=None, argrepr='', offset=410, start_offset=410, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=412, start_offset=412, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=414, start_offset=414, starts_line=True, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=426, start_offset=426, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=428, start_offset=428, starts_line=False, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_EXCEPT', opcode=30, arg=None, argval=None, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+ Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=58, argval=326, argrepr='to L10', offset=440, start_offset=440, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=0, argval=0, argrepr='', offset=442, start_offset=442, starts_line=True, line_number=22, label=12, positions=None, cache_info=None),
+ Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=444, start_offset=444, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_EXCEPT', opcode=30, arg=None, argval=None, argrepr='', offset=446, start_offset=446, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=1, argval=1, argrepr='', offset=448, start_offset=448, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=33, arg=None, argval=None, argrepr='', offset=450, start_offset=450, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=89, arg=1, argval='print', argrepr='print', offset=452, start_offset=452, starts_line=True, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
+ Instruction(opname='PUSH_NULL', opcode=34, arg=None, argval=None, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='LOAD_CONST', opcode=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=464, start_offset=464, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='CALL', opcode=52, arg=1, argval=1, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
+ Instruction(opname='POP_TOP', opcode=32, arg=None, argval=None, argrepr='', offset=474, start_offset=474, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=0, argval=0, argrepr='', offset=476, start_offset=476, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+ Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=478, start_offset=478, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='POP_EXCEPT', opcode=30, arg=None, argval=None, argrepr='', offset=480, start_offset=480, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+ Instruction(opname='RERAISE', opcode=104, arg=1, argval=1, argrepr='', offset=482, start_offset=482, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
]
# One last piece of inspect fodder to check the default line number handling
@@ -1909,7 +1929,7 @@ def simple(): pass
expected_opinfo_simple = [
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=simple.__code__.co_firstlineno, label=None, positions=None),
Instruction(opname='LOAD_CONST', opcode=81, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None),
- Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None),
+ Instruction(opname='RETURN_VALUE', opcode=36, arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None),
]
@@ -2133,7 +2153,7 @@ def f(opcode, oparg, offset, *init_args):
args = (offset, co_consts, names, varname_from_oparg, labels_map)
self.assertEqual(f(opcode.opmap["POP_TOP"], None, *args), (None, ''))
self.assertEqual(f(opcode.opmap["LOAD_CONST"], 1, *args), (1, '1'))
- self.assertEqual(f(opcode.opmap["LOAD_GLOBAL"], 2, *args), ('a', 'a'))
+ self.assertEqual(f(opcode.opmap["LOAD_GLOBAL"], 1, *args), ('a', 'a'))
self.assertEqual(f(opcode.opmap["JUMP_BACKWARD"], 11, *args), (24, 'to L1'))
self.assertEqual(f(opcode.opmap["COMPARE_OP"], 3, *args), ('<', '<'))
self.assertEqual(f(opcode.opmap["SET_FUNCTION_ATTRIBUTE"], 2, *args), (2, 'kwdefaults'))
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index aa92145266961a..4b17bd5c797375 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -59,14 +59,14 @@ class TestEffects(unittest.TestCase):
def test_effect_sizes(self):
stack = Stack()
inputs = [
- x := StackItem("x", None, "", "1"),
- y := StackItem("y", None, "", "oparg"),
- z := StackItem("z", None, "", "oparg*2"),
+ x := StackItem("x", None, "1"),
+ y := StackItem("y", None, "oparg"),
+ z := StackItem("z", None, "oparg*2"),
]
outputs = [
- StackItem("x", None, "", "1"),
- StackItem("b", None, "", "oparg*4"),
- StackItem("c", None, "", "1"),
+ StackItem("x", None, "1"),
+ StackItem("b", None, "oparg*4"),
+ StackItem("c", None, "1"),
]
stack.pop(z)
stack.pop(y)
@@ -104,20 +104,6 @@ def test_push_one(self):
"""
self.check(input, output)
- def test_cond_push(self):
- input = """
- inst(OP, (a -- b, c if (oparg))) {
- SPAM();
- }
- """
- output = """
- case OP: {
- *effect = ((oparg) ? 1 : 0);
- return 0;
- }
- """
- self.check(input, output)
-
def test_ops_pass_two(self):
input = """
op(A, (-- val1)) {
@@ -138,25 +124,6 @@ def test_ops_pass_two(self):
"""
self.check(input, output)
- def test_ops_pass_two_cond_push(self):
- input = """
- op(A, (-- val1, val2)) {
- val1 = 0;
- val2 = 1;
- }
- op(B, (val1, val2 -- val1, val2, val3 if (oparg))) {
- val3 = SPAM();
- }
- macro(OP) = A + B;
- """
- output = """
- case OP: {
- *effect = Py_MAX(2, 2 + ((oparg) ? 1 : 0));
- return 0;
- }
- """
- self.check(input, output)
-
def test_pop_push_array(self):
input = """
inst(OP, (values[oparg] -- values[oparg], above)) {
@@ -938,90 +905,6 @@ def test_array_error_if(self):
"""
self.run_cases_test(input, output)
- def test_cond_effect(self):
- input = """
- inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
- output = SPAM(oparg, aa, cc, input);
- INPUTS_DEAD();
- xx = 0;
- zz = 0;
- }
- """
- output = """
- TARGET(OP) {
- frame->instr_ptr = next_instr;
- next_instr += 1;
- INSTRUCTION_STATS(OP);
- _PyStackRef aa;
- _PyStackRef input = PyStackRef_NULL;
- _PyStackRef cc;
- _PyStackRef xx;
- _PyStackRef output = PyStackRef_NULL;
- _PyStackRef zz;
- cc = stack_pointer[-1];
- if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; }
- aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)];
- output = SPAM(oparg, aa, cc, input);
- xx = 0;
- zz = 0;
- stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx;
- if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] = output;
- stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0)] = zz;
- stack_pointer += -(((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0);
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
- """
- self.run_cases_test(input, output)
-
- def test_macro_cond_effect(self):
- input = """
- op(A, (left, middle, right --)) {
- USE(left, middle, right);
- INPUTS_DEAD();
- }
- op(B, (-- deep, extra if (oparg), res)) {
- deep = -1;
- res = 0;
- extra = 1;
- INPUTS_DEAD();
- }
- macro(M) = A + B;
- """
- output = """
- TARGET(M) {
- frame->instr_ptr = next_instr;
- next_instr += 1;
- INSTRUCTION_STATS(M);
- _PyStackRef left;
- _PyStackRef middle;
- _PyStackRef right;
- _PyStackRef deep;
- _PyStackRef extra = PyStackRef_NULL;
- _PyStackRef res;
- // A
- {
- right = stack_pointer[-1];
- middle = stack_pointer[-2];
- left = stack_pointer[-3];
- USE(left, middle, right);
- }
- // B
- {
- deep = -1;
- res = 0;
- extra = 1;
- }
- stack_pointer[-3] = deep;
- if (oparg) stack_pointer[-2] = extra;
- stack_pointer[-2 + ((oparg) ? 1 : 0)] = res;
- stack_pointer += -1 + ((oparg) ? 1 : 0);
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
- """
- self.run_cases_test(input, output)
-
def test_macro_push_push(self):
input = """
op(A, (-- val1)) {
diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py
index 364381e7dce00a..7ac2910cfb7854 100644
--- a/Lib/test/test_monitoring.py
+++ b/Lib/test/test_monitoring.py
@@ -1588,11 +1588,11 @@ def whilefunc(n=0):
('branch right', 'whilefunc', 1, 3)])
self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [
- ('branch left', 'func', 28, 32),
- ('branch right', 'func', 44, 58),
- ('branch left', 'func', 28, 32),
- ('branch left', 'func', 44, 50),
- ('branch right', 'func', 28, 70)])
+ ('branch left', 'func', 30, 34),
+ ('branch right', 'func', 46, 60),
+ ('branch left', 'func', 30, 34),
+ ('branch left', 'func', 46, 52),
+ ('branch right', 'func', 30, 72)])
def test_except_star(self):
@@ -1762,7 +1762,8 @@ def _exec_super(self, codestr, optimized=False):
return self._exec(co)
def _has_load_super_attr(self, co):
- has = any(instr.opname == "LOAD_SUPER_ATTR" for instr in dis.get_instructions(co))
+ has = any(instr.opname in ("LOAD_SUPER_ATTR", "LOAD_SUPER_METHOD")
+ for instr in dis.get_instructions(co))
if not has:
has = any(
isinstance(c, types.CodeType) and self._has_load_super_attr(c)
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index 4d7304b1c9abb6..1895a5001fd318 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -868,7 +868,7 @@ def write(items):
pass
type(item).m = lambda self: None
- opname = "LOAD_ATTR_METHOD_LAZY_DICT"
+ opname = "LOAD_METHOD_LAZY_DICT"
self.assert_races_do_not_crash(opname, get_items, read, write)
@requires_specialization_ft
@@ -899,7 +899,7 @@ def write(items):
pass
type(item).m = lambda self: None
- opname = "LOAD_ATTR_METHOD_NO_DICT"
+ opname = "LOAD_METHOD_NO_DICT"
self.assert_races_do_not_crash(opname, get_items, read, write)
@requires_specialization_ft
@@ -929,7 +929,7 @@ def write(items):
pass
type(item).m = lambda self: None
- opname = "LOAD_ATTR_METHOD_WITH_VALUES"
+ opname = "LOAD_METHOD_WITH_VALUES"
self.assert_races_do_not_crash(opname, get_items, read, write)
@requires_specialization_ft
@@ -1424,8 +1424,9 @@ def __init__(self):
A()
self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_ATTR")
- self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_METHOD")
+ self.assert_specialized(A.__init__, "LOAD_SUPER_METHOD_METHOD")
self.assert_no_opcode(A.__init__, "LOAD_SUPER_ATTR")
+ self.assert_no_opcode(A.__init__, "LOAD_SUPER_METHOD")
# Temporarily replace super() with something else.
real_super = super
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-10-17-01.gh-issue-128914.dn6RaW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-10-17-01.gh-issue-128914.dn6RaW.rst
new file mode 100644
index 00000000000000..63f71590363273
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-10-17-01.gh-issue-128914.dn6RaW.rst
@@ -0,0 +1,3 @@
+:opcode:`LOAD_ATTR` no longer pushes an extra ``NULL`` to the stack.
+:opcode:`LOAD_METHOD` has been added. ``LOAD_METHOD`` is equivalent to
+``LOAD_ATTR; PUSH_NULL`` but is optimized for use in method calls.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 4f0040df4f3017..bf5067bba58f71 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1261,27 +1261,18 @@ mark_stacks(PyCodeObject *code_obj, int len)
stacks[next_i] = next_stack;
break;
case LOAD_GLOBAL:
- {
- int j = oparg;
next_stack = push_value(next_stack, Object);
- if (j & 1) {
- next_stack = push_value(next_stack, Null);
- }
stacks[next_i] = next_stack;
break;
- }
case LOAD_ATTR:
- {
assert(top_of_stack(next_stack) == Object);
- int j = oparg;
- if (j & 1) {
- next_stack = pop_value(next_stack);
- next_stack = push_value(next_stack, Object);
- next_stack = push_value(next_stack, Null);
- }
stacks[next_i] = next_stack;
break;
- }
+ case LOAD_METHOD:
+ assert(top_of_stack(next_stack) == Object);
+ next_stack = push_value(next_stack, Null);
+ stacks[next_i] = next_stack;
+ break;
case SWAP:
{
int n = oparg;
diff --git a/Objects/object.c b/Objects/object.c
index 51b6016b9c191c..0a15c1e1de5499 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1551,7 +1551,7 @@ _PyObject_NextNotImplemented(PyObject *self)
/* Specialized version of _PyObject_GenericGetAttrWithDict
- specifically for the LOAD_METHOD opcode.
+ specifically for the loading methods
Return 1 if a method is found, 0 if it's a regular attribute
from __dict__ or something returned by using a descriptor
diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h
index 4f6933ac0ddcd6..be05fae1a6d831 100644
--- a/Programs/test_frozenmain.h
+++ b/Programs/test_frozenmain.h
@@ -1,18 +1,18 @@
// 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,9,0,0,
- 0,0,0,0,0,243,168,0,0,0,149,0,91,0,81,0,
- 72,0,113,0,91,0,81,0,72,1,113,1,90,2,33,0,
- 81,1,51,1,0,0,0,0,0,0,31,0,90,2,33,0,
- 81,2,90,0,79,6,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,51,2,0,0,0,0,0,0,
- 31,0,90,1,79,8,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,33,0,51,0,0,0,0,0,
- 0,0,81,3,2,0,0,0,113,5,81,4,16,0,69,20,
- 0,0,113,6,90,2,33,0,81,5,90,6,12,0,81,6,
- 90,5,90,6,2,0,0,0,12,0,49,4,51,1,0,0,
- 0,0,0,0,31,0,74,22,0,0,9,0,30,0,81,0,
- 35,0,41,7,78,122,18,70,114,111,122,101,110,32,72,101,
+ 0,0,0,0,0,243,168,0,0,0,149,0,92,0,81,0,
+ 72,0,115,0,92,0,81,0,72,1,115,1,91,2,34,0,
+ 81,1,52,1,0,0,0,0,0,0,32,0,91,2,34,0,
+ 81,2,91,0,79,3,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0,
+ 32,0,91,1,79,4,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,34,0,52,0,0,0,0,0,
+ 0,0,81,3,2,0,0,0,115,5,81,4,18,0,69,20,
+ 0,0,115,6,91,2,34,0,81,5,91,6,13,0,81,6,
+ 91,5,91,6,2,0,0,0,13,0,50,4,52,1,0,0,
+ 0,0,0,0,32,0,74,22,0,0,10,0,31,0,81,0,
+ 36,0,41,7,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,114,97,109,95,110,97,109,101,218,10,101,120,101,
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c0ef767a9dd68b..398f1d564fad4a 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -348,8 +348,8 @@ dummy_func(
DECREF_INPUTS();
}
- pure inst(PUSH_NULL, (-- res)) {
- res = PyStackRef_NULL;
+ pure inst(PUSH_NULL, (-- null)) {
+ null = PyStackRef_NULL;
}
no_save_ip inst(END_FOR, (value -- )) {
@@ -1658,7 +1658,7 @@ dummy_func(
specializing op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr = this_instr;
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1669,11 +1669,10 @@ dummy_func(
}
// res[1] because we need a pointer to res to pass it to _PyEval_LoadGlobalStackRef
- op(_LOAD_GLOBAL, ( -- res[1], null if (oparg & 1))) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ op(_LOAD_GLOBAL, ( -- res[1])) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
ERROR_IF(PyStackRef_IsNull(*res), error);
- null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL) =
@@ -1711,7 +1710,7 @@ dummy_func(
assert(DK_IS_UNICODE(builtins_keys));
}
- op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
+ op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res)) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(globals_keys);
@@ -1725,10 +1724,9 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
}
- op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
+ op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res)) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(builtins_keys);
@@ -1742,7 +1740,6 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL_MODULE) =
@@ -2012,17 +2009,27 @@ dummy_func(
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
}
+ inst(INSTRUMENTED_LOAD_SUPER_METHOD, (unused/1 -- )) {
+ // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
+ // don't want to specialize instrumented instructions
+ PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ GO_TO_INSTRUCTION(LOAD_SUPER_METHOD);
+ }
+
family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR_ATTR,
- LOAD_SUPER_ATTR_METHOD,
+ };
+
+
+ family(LOAD_SUPER_METHOD, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
+ LOAD_SUPER_METHOD_METHOD,
};
specializing op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super_st, class_st, unused -- global_super_st, class_st, unused)) {
#if ENABLE_SPECIALIZATION_FT
- int load_method = oparg & 1;
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
- _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 0);
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(LOAD_SUPER_ATTR);
@@ -2030,12 +2037,24 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- tier1 op(_LOAD_SUPER_ATTR, (global_super_st, class_st, self_st -- attr, null if (oparg & 1))) {
+ specializing op(_SPECIALIZE_LOAD_SUPER_METHOD, (counter/1, global_super_st, class_st, unused -- global_super_st, class_st, unused)) {
+ #if ENABLE_SPECIALIZATION_FT
+ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
+ next_instr = this_instr;
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 1);
+ DISPATCH_SAME_OPARG();
+ }
+ OPCODE_DEFERRED_INC(LOAD_SUPER_METHOD);
+ ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ #endif /* ENABLE_SPECIALIZATION_FT */
+ }
+
+ tier1 op(_LOAD_SUPER_ATTR, (global_super_st, class_st, self_st -- attr)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
- if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -2049,7 +2068,7 @@ dummy_func(
// handle any case whose performance we care about
PyObject *stack[] = {class, self};
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
- if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_Py_call_instrumentation_exc2(
@@ -2072,12 +2091,13 @@ dummy_func(
Py_DECREF(super);
ERROR_IF(attr_o == NULL, error);
attr = PyStackRef_FromPyObjectSteal(attr_o);
- null = PyStackRef_NULL;
}
macro(LOAD_SUPER_ATTR) = _SPECIALIZE_LOAD_SUPER_ATTR + _LOAD_SUPER_ATTR;
+ macro(LOAD_SUPER_METHOD) = _SPECIALIZE_LOAD_SUPER_METHOD + _LOAD_SUPER_ATTR + PUSH_NULL;
+
- inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st, unused if (0))) {
+ inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
@@ -2093,7 +2113,7 @@ dummy_func(
attr_st = PyStackRef_FromPyObjectSteal(attr);
}
- inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) {
+ inst(LOAD_SUPER_METHOD_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
@@ -2132,17 +2152,20 @@ dummy_func(
LOAD_ATTR_CLASS_WITH_METACLASS_CHECK,
LOAD_ATTR_PROPERTY,
LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
- LOAD_ATTR_METHOD_WITH_VALUES,
- LOAD_ATTR_METHOD_NO_DICT,
- LOAD_ATTR_METHOD_LAZY_DICT,
LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
};
+ family(LOAD_METHOD, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
+ LOAD_METHOD_WITH_VALUES,
+ LOAD_METHOD_NO_DICT,
+ LOAD_METHOD_LAZY_DICT,
+ };
+
specializing op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr = this_instr;
_Py_Specialize_LoadAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -2152,50 +2175,67 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
+ specializing op(_SPECIALIZE_LOAD_METHOD, (counter/1, owner -- owner)) {
+ #if ENABLE_SPECIALIZATION_FT
+ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ next_instr = this_instr;
+ _Py_Specialize_LoadMethod(owner, next_instr, name);
+ DISPATCH_SAME_OPARG();
+ }
+ OPCODE_DEFERRED_INC(LOAD_METHOD);
+ ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ #endif /* ENABLE_SPECIALIZATION_FT */
+ }
+
+ op(_LOAD_METHOD, (owner -- attr, self_or_null)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *attr_o;
- if (oparg & 1) {
- /* Designed to work in tandem with CALL, pushes two values. */
- attr_o = NULL;
- int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
- if (is_meth) {
- /* We can bypass temporary bound method object.
- meth is unbound method and obj is self.
- meth | self | arg1 | ... | argN
- */
- assert(attr_o != NULL); // No errors on this branch
- self_or_null = owner; // Transfer ownership
- DEAD(owner);
- }
- else {
- /* 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
- CALL that it's not a method call.
- meth | NULL | arg1 | ... | argN
+ /* Designed to work in tandem with CALL, pushes two values. */
+ attr_o = NULL;
+ int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
+ if (is_meth) {
+ /* We can bypass temporary bound method object.
+ meth is unbound method and obj is self.
+ meth | self | arg1 | ... | argN
*/
- DECREF_INPUTS();
- ERROR_IF(attr_o == NULL, error);
- self_or_null = PyStackRef_NULL;
- }
+ assert(attr_o != NULL); // No errors on this branch
+ self_or_null = owner; // Transfer ownership
+ DEAD(owner);
}
else {
- /* Classic, pushes one value. */
- attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
+ /* 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
+ CALL that it's not a method call.
+ meth | NULL | arg1 | ... | argN
+ */
DECREF_INPUTS();
ERROR_IF(attr_o == NULL, error);
- /* We need to define self_or_null on all paths */
self_or_null = PyStackRef_NULL;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
}
+ op(_LOAD_ATTR, (owner -- attr)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
+ DECREF_INPUTS();
+ ERROR_IF(attr_o == NULL, error);
+ attr = PyStackRef_FromPyObjectSteal(attr_o);
+ }
+
macro(LOAD_ATTR) =
_SPECIALIZE_LOAD_ATTR +
unused/8 +
_LOAD_ATTR;
+
+ macro(LOAD_METHOD) =
+ _SPECIALIZE_LOAD_METHOD +
+ unused/8 +
+ _LOAD_METHOD;
+
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
assert(type_version != 0);
@@ -2220,7 +2260,7 @@ dummy_func(
DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid));
}
- split op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
@@ -2233,7 +2273,6 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2254,7 +2293,7 @@ dummy_func(
mod_keys = keys;
}
- op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr)) {
assert(mod_keys->dk_kind == DICT_KEYS_UNICODE);
assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(mod_keys->dk_nentries));
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mod_keys) + index;
@@ -2272,7 +2311,6 @@ dummy_func(
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
@@ -2292,7 +2330,7 @@ dummy_func(
dict = dict_o;
}
- op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr)) {
PyObject *attr_o;
if (!LOCK_OBJECT(dict)) {
POP_INPUT(dict);
@@ -2304,7 +2342,7 @@ dummy_func(
POP_INPUT(dict);
DEOPT_IF(true);
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
POP_INPUT(dict);
@@ -2326,7 +2364,6 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
DEAD(dict);
- null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2337,7 +2374,7 @@ dummy_func(
_LOAD_ATTR_WITH_HINT +
unused/5;
- split op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_SLOT, (index/1, owner -- attr)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **addr = (PyObject **)((char *)owner_o + index);
@@ -2350,7 +2387,6 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2368,11 +2404,10 @@ dummy_func(
EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(((PyTypeObject *)owner_o)->tp_version_tag) != type_version);
}
- split op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
- null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2389,7 +2424,6 @@ dummy_func(
_LOAD_ATTR_CLASS;
op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame: _PyInterpreterFrame *)) {
- assert((oparg & 1) == 0);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
PyCodeObject *code = (PyCodeObject *)f->func_code;
@@ -2412,10 +2446,8 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
- inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused, unused if (0))) {
+ inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
-
- assert((oparg & 1) == 0);
DEOPT_IF(tstate->interp->eval_frame);
PyTypeObject *cls = Py_TYPE(owner_o);
assert(type_version != 0);
@@ -2429,7 +2461,7 @@ dummy_func(
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -3348,8 +3380,7 @@ dummy_func(
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version);
}
- split op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
- assert(oparg & 1);
+ op(_LOAD_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3359,15 +3390,14 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_ATTR_METHOD_WITH_VALUES) =
+ macro(LOAD_METHOD_WITH_VALUES) =
unused/1 +
_GUARD_TYPE_VERSION +
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
_GUARD_KEYS_VERSION +
- _LOAD_ATTR_METHOD_WITH_VALUES;
+ _LOAD_METHOD_WITH_VALUES;
- op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
- assert(oparg & 1);
+ op(_LOAD_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3377,14 +3407,13 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_ATTR_METHOD_NO_DICT) =
+ macro(LOAD_METHOD_NO_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
unused/2 +
- _LOAD_ATTR_METHOD_NO_DICT;
+ _LOAD_METHOD_NO_DICT;
- op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr, unused if (0))) {
- assert((oparg & 1) == 0);
+ op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) {
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
DECREF_INPUTS();
@@ -3398,8 +3427,7 @@ dummy_func(
_GUARD_KEYS_VERSION +
_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
- op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr, unused if (0))) {
- assert((oparg & 1) == 0);
+ op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3420,8 +3448,7 @@ dummy_func(
DEOPT_IF(dict != NULL);
}
- op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
- assert(oparg & 1);
+ op(_LOAD_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
@@ -3430,12 +3457,12 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_ATTR_METHOD_LAZY_DICT) =
+ macro(LOAD_METHOD_LAZY_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
_CHECK_ATTR_METHOD_LAZY_DICT +
unused/1 +
- _LOAD_ATTR_METHOD_LAZY_DICT;
+ _LOAD_METHOD_LAZY_DICT;
// Cache layout: counter/1, func_version/2
// CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members!
@@ -4537,7 +4564,7 @@ dummy_func(
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
- op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in if (oparg & 1) -- func, unused, tuple, kwargs_out if (oparg & 1))) {
+ op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -4561,7 +4588,7 @@ dummy_func(
}
}
- op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
+ op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st -- result)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
// DICT_MERGE is called before this opcode if there are kwargs.
@@ -4695,11 +4722,16 @@ dummy_func(
LLTRACE_RESUME_FRAME();
}
- inst(BUILD_SLICE, (start, stop, step if (oparg == 3) -- slice)) {
+ inst(BUILD_SLICE, (args[oparg] -- slice)) {
+ assert(oparg == 2 || oparg == 3);
+ _PyStackRef start = args[0];
+ _PyStackRef stop = args[1];
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
-
+ PyObject * step_o = NULL;
+ if (oparg == 3) {
+ step_o = PyStackRef_AsPyObjectBorrow(args[2]);
+ }
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
DECREF_INPUTS();
ERROR_IF(slice_o == NULL, error);
@@ -5041,27 +5073,25 @@ dummy_func(
DEOPT_IF(func->func_version != func_version);
}
- tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res, null if (oparg & 1))) {
+ tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res)) {
PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res_o = entries[index].me_value;
DEOPT_IF(res_o == NULL);
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
- null = PyStackRef_NULL;
}
- tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res, null if (oparg & 1))) {
+ tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res)) {
PyDictObject *dict = (PyDictObject *)BUILTINS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res_o = entries[index].me_value;
DEOPT_IF(res_o == NULL);
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
- null = PyStackRef_NULL;
}
- tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
+ tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
@@ -5072,7 +5102,6 @@ dummy_func(
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr_o);
attr = PyStackRef_FromPyObjectSteal(attr_o);
- null = PyStackRef_NULL;
DECREF_INPUTS();
}
diff --git a/Python/codegen.c b/Python/codegen.c
index 61707ba677097c..b3f845569684de 100644
--- a/Python/codegen.c
+++ b/Python/codegen.c
@@ -348,8 +348,6 @@ codegen_addop_o(compiler *c, location loc,
RETURN_IF_ERROR_IN_SCOPE((C), ret); \
} while (0)
-#define LOAD_METHOD -1
-#define LOAD_SUPER_METHOD -2
#define LOAD_ZERO_SUPER_ATTR -3
#define LOAD_ZERO_SUPER_METHOD -4
@@ -366,20 +364,11 @@ codegen_addop_name(compiler *c, location loc,
if (arg < 0) {
return ERROR;
}
- if (opcode == LOAD_ATTR) {
- arg <<= 1;
- }
- if (opcode == LOAD_METHOD) {
- opcode = LOAD_ATTR;
- arg <<= 1;
- arg |= 1;
- }
if (opcode == LOAD_SUPER_ATTR) {
arg <<= 2;
arg |= 2;
}
if (opcode == LOAD_SUPER_METHOD) {
- opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 3;
}
@@ -388,7 +377,7 @@ codegen_addop_name(compiler *c, location loc,
arg <<= 2;
}
if (opcode == LOAD_ZERO_SUPER_METHOD) {
- opcode = LOAD_SUPER_ATTR;
+ opcode = LOAD_SUPER_METHOD;
arg <<= 2;
arg |= 1;
}
@@ -3165,9 +3154,6 @@ codegen_nameop(compiler *c, location loc,
assert(op);
Py_DECREF(mangled);
- if (op == LOAD_GLOBAL) {
- arg <<= 1;
- }
ADDOP_I(c, loc, op, arg);
return SUCCESS;
@@ -4108,7 +4094,10 @@ codegen_call_helper_impl(compiler *c, location loc,
}
assert(have_dict);
}
- ADDOP_I(c, loc, CALL_FUNCTION_EX, nkwelts > 0);
+ if (nkwelts == 0) {
+ ADDOP(c, loc, PUSH_NULL);
+ }
+ ADDOP(c, loc, CALL_FUNCTION_EX);
return SUCCESS;
}
@@ -4841,8 +4830,10 @@ codegen_async_with(compiler *c, stmt_ty s, int pos)
SETUP_WITH E
<code to store to VAR> or POP_TOP
<code for BLOCK>
- LOAD_CONST (None, None, None)
- CALL_FUNCTION_EX 0
+ LOAD_CONST None
+ LOAD_CONST None
+ LOAD_CONST None
+ CALL 3
JUMP EXIT
E: WITH_EXCEPT_START (calls EXPR.__exit__)
POP_JUMP_IF_TRUE T:
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index e2eaca2c90fa76..049073162b6c5f 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -406,9 +406,9 @@
}
case _PUSH_NULL: {
- _PyStackRef res;
- res = PyStackRef_NULL;
- stack_pointer[0] = res;
+ _PyStackRef null;
+ null = PyStackRef_NULL;
+ stack_pointer[0] = null;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -1957,17 +1957,14 @@
case _LOAD_GLOBAL: {
_PyStackRef *res;
- _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
res = &stack_pointer[0];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(*res)) JUMP_TO_ERROR();
- null = PyStackRef_NULL;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2033,8 +2030,6 @@
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
PyDictKeysObject *globals_keys;
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
globals_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
@@ -2056,10 +2051,8 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2067,8 +2060,6 @@
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
PyDictKeysObject *builtins_keys;
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
builtins_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
@@ -2090,10 +2081,8 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2519,6 +2508,8 @@
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 because it is instrumented */
+ /* _INSTRUMENTED_LOAD_SUPER_METHOD is not a viable micro-op for tier 2 because it is instrumented */
+
case _LOAD_SUPER_ATTR_ATTR: {
_PyStackRef self_st;
_PyStackRef class_st;
@@ -2556,7 +2547,7 @@
break;
}
- case _LOAD_SUPER_ATTR_METHOD: {
+ case _LOAD_SUPER_METHOD_METHOD: {
_PyStackRef self_st;
_PyStackRef class_st;
_PyStackRef global_super_st;
@@ -2605,58 +2596,62 @@
break;
}
- case _LOAD_ATTR: {
+ case _LOAD_METHOD: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self_or_null = PyStackRef_NULL;
+ _PyStackRef self_or_null;
oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *attr_o;
- if (oparg & 1) {
- /* Designed to work in tandem with CALL, pushes two values. */
- attr_o = NULL;
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- if (is_meth) {
- /* We can bypass temporary bound method object.
- meth is unbound method and obj is self.
- meth | self | arg1 | ... | argN
- */
- assert(attr_o != NULL); // No errors on this branch
- self_or_null = owner; // Transfer ownership
- }
- else {
- /* 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
- CALL that it's not a method call.
- meth | NULL | arg1 | ... | argN
- */
- PyStackRef_CLOSE(owner);
- if (attr_o == NULL) JUMP_TO_ERROR();
- self_or_null = PyStackRef_NULL;
- }
+ /* Designed to work in tandem with CALL, pushes two values. */
+ attr_o = NULL;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (is_meth) {
+ /* We can bypass temporary bound method object.
+ meth is unbound method and obj is self.
+ meth | self | arg1 | ... | argN
+ */
+ assert(attr_o != NULL); // No errors on this branch
+ self_or_null = owner; // Transfer ownership
}
else {
- /* Classic, pushes one value. */
- _PyFrame_SetStackPointer(frame, stack_pointer);
- attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
- stack_pointer = _PyFrame_GetStackPointer(frame);
+ /* 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
+ CALL that it's not a method call.
+ meth | NULL | arg1 | ... | argN
+ */
PyStackRef_CLOSE(owner);
if (attr_o == NULL) JUMP_TO_ERROR();
- /* We need to define self_or_null on all paths */
self_or_null = PyStackRef_NULL;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = self_or_null;
- stack_pointer += (oparg & 1);
+ stack_pointer[0] = self_or_null;
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
+ case _LOAD_ATTR: {
+ _PyStackRef owner;
+ _PyStackRef attr;
+ oparg = CURRENT_OPARG();
+ owner = stack_pointer[-1];
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ PyStackRef_CLOSE(owner);
+ if (attr_o == NULL) JUMP_TO_ERROR();
+ attr = PyStackRef_FromPyObjectSteal(attr_o);
+ stack_pointer[-1] = attr;
+ break;
+ }
+
case _GUARD_TYPE_VERSION: {
_PyStackRef owner;
owner = stack_pointer[-1];
@@ -2704,42 +2699,9 @@
break;
}
- case _LOAD_ATTR_INSTANCE_VALUE_0: {
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
- owner = stack_pointer[-1];
- uint16_t offset = (uint16_t)CURRENT_OPERAND0();
- PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
- PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
- PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
- if (attr_o == NULL) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
- #ifdef Py_GIL_DISABLED
- if (!_Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr)) {
- if (true) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
- }
- #else
- attr = PyStackRef_FromPyObjectNew(attr_o);
- #endif
- STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
- PyStackRef_CLOSE(owner);
- stack_pointer[-1] = attr;
- break;
- }
-
- case _LOAD_ATTR_INSTANCE_VALUE_1: {
+ case _LOAD_ATTR_INSTANCE_VALUE: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -2760,17 +2722,11 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
- stack_pointer[0] = null;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
break;
}
- /* _LOAD_ATTR_INSTANCE_VALUE is split on (oparg & 1) */
-
case _CHECK_ATTR_MODULE_PUSH_KEYS: {
_PyStackRef owner;
PyDictKeysObject *mod_keys;
@@ -2799,8 +2755,6 @@
PyDictKeysObject *mod_keys;
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
mod_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
@@ -2828,12 +2782,8 @@
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2860,7 +2810,6 @@
PyDictObject *dict;
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
dict = (PyDictObject *)stack_pointer[-1].bits;
owner = stack_pointer[-2];
@@ -2883,7 +2832,7 @@
JUMP_TO_JUMP_TARGET();
}
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
stack_pointer += -1;
@@ -2916,20 +2865,16 @@
STAT_INC(LOAD_ATTR, hit);
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-2] = attr;
- if (oparg & 1) stack_pointer[-1] = null;
- stack_pointer += -1 + (oparg & 1);
+ stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
- case _LOAD_ATTR_SLOT_0: {
+ case _LOAD_ATTR_SLOT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -2949,47 +2894,11 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
break;
}
- case _LOAD_ATTR_SLOT_1: {
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
- owner = stack_pointer[-1];
- uint16_t index = (uint16_t)CURRENT_OPERAND0();
- PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
- PyObject **addr = (PyObject **)((char *)owner_o + index);
- PyObject *attr_o = FT_ATOMIC_LOAD_PTR(*addr);
- if (attr_o == NULL) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
- #ifdef Py_GIL_DISABLED
- int increfed = _Py_TryIncrefCompareStackRef(addr, attr_o, &attr);
- if (!increfed) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
- #else
- attr = PyStackRef_FromPyObjectNew(attr_o);
- #endif
- STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
- PyStackRef_CLOSE(owner);
- stack_pointer[-1] = attr;
- stack_pointer[0] = null;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- break;
- }
-
- /* _LOAD_ATTR_SLOT is split on (oparg & 1) */
-
case _CHECK_ATTR_CLASS: {
_PyStackRef owner;
owner = stack_pointer[-1];
@@ -3007,50 +2916,24 @@
break;
}
- case _LOAD_ATTR_CLASS_0: {
+ case _LOAD_ATTR_CLASS: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
break;
}
- case _LOAD_ATTR_CLASS_1: {
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- (void)null;
- owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- STAT_INC(LOAD_ATTR, hit);
- assert(descr != NULL);
- attr = PyStackRef_FromPyObjectNew(descr);
- null = PyStackRef_NULL;
- PyStackRef_CLOSE(owner);
- stack_pointer[-1] = attr;
- stack_pointer[0] = null;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- break;
- }
-
- /* _LOAD_ATTR_CLASS is split on (oparg & 1) */
-
case _LOAD_ATTR_PROPERTY_FRAME: {
_PyStackRef owner;
_PyInterpreterFrame *new_frame;
- oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *fget = (PyObject *)CURRENT_OPERAND0();
- assert((oparg & 1) == 0);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
PyCodeObject *code = (PyCodeObject *)f->func_code;
@@ -4056,14 +3939,12 @@
break;
}
- case _LOAD_ATTR_METHOD_WITH_VALUES: {
+ case _LOAD_METHOD_WITH_VALUES: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
+ _PyStackRef self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -4077,14 +3958,12 @@
break;
}
- case _LOAD_ATTR_METHOD_NO_DICT: {
+ case _LOAD_METHOD_NO_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
+ _PyStackRef self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- assert(oparg & 1);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -4101,10 +3980,8 @@
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
_PyStackRef owner;
_PyStackRef attr;
- oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
PyStackRef_CLOSE(owner);
@@ -4116,10 +3993,8 @@
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- assert((oparg & 1) == 0);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -4143,14 +4018,12 @@
break;
}
- case _LOAD_ATTR_METHOD_LAZY_DICT: {
+ case _LOAD_METHOD_LAZY_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
+ _PyStackRef self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
- assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
@@ -5644,15 +5517,14 @@
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it is instrumented */
case _MAKE_CALLARGS_A_TUPLE: {
- _PyStackRef kwargs_in = PyStackRef_NULL;
+ _PyStackRef kwargs_in;
_PyStackRef callargs;
_PyStackRef func;
_PyStackRef tuple;
- _PyStackRef kwargs_out = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
- if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; }
- callargs = stack_pointer[-1 - (oparg & 1)];
- func = stack_pointer[-3 - (oparg & 1)];
+ _PyStackRef kwargs_out;
+ kwargs_in = stack_pointer[-1];
+ callargs = stack_pointer[-2];
+ func = stack_pointer[-4];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -5675,8 +5547,8 @@
PyStackRef_CLOSE(callargs);
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
}
- stack_pointer[-1 - (oparg & 1)] = tuple;
- if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out;
+ stack_pointer[-2] = tuple;
+ stack_pointer[-1] = kwargs_out;
break;
}
@@ -5753,25 +5625,27 @@
}
case _BUILD_SLICE: {
- _PyStackRef step = PyStackRef_NULL;
- _PyStackRef stop;
- _PyStackRef start;
+ _PyStackRef *args;
_PyStackRef slice;
oparg = CURRENT_OPARG();
- if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; }
- stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)];
- start = stack_pointer[-2 - ((oparg == 3) ? 1 : 0)];
+ args = &stack_pointer[-oparg];
+ assert(oparg == 2 || oparg == 3);
+ _PyStackRef start = args[0];
+ _PyStackRef stop = args[1];
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
+ PyObject * step_o = NULL;
+ if (oparg == 3) {
+ step_o = PyStackRef_AsPyObjectBorrow(args[2]);
+ }
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
- PyStackRef_CLOSE(start);
- PyStackRef_CLOSE(stop);
- PyStackRef_XCLOSE(step);
+ for (int _i = oparg; --_i >= 0;) {
+ PyStackRef_CLOSE(args[_i]);
+ }
if (slice_o == NULL) JUMP_TO_ERROR();
slice = PyStackRef_FromPyObjectSteal(slice_o);
- stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
- stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
+ stack_pointer[-oparg] = slice;
+ stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6138,8 +6012,6 @@
case _LOAD_GLOBAL_MODULE: {
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
@@ -6150,18 +6022,14 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
- null = PyStackRef_NULL;
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _LOAD_GLOBAL_BUILTINS: {
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictObject *dict = (PyDictObject *)BUILTINS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
@@ -6172,10 +6040,8 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
- null = PyStackRef_NULL;
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6183,8 +6049,6 @@
case _LOAD_ATTR_MODULE: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
- oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -6200,12 +6064,8 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr_o);
attr = PyStackRef_FromPyObjectSteal(attr_o);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index 24561c1ee04db9..3f8d9db166ff98 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1836,12 +1836,6 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
INSTR_SET_OP0(inst, NOP);
}
break;
- case LOAD_GLOBAL:
- if (nextop == PUSH_NULL && (oparg & 1) == 0) {
- INSTR_SET_OP1(inst, LOAD_GLOBAL, oparg | 1);
- INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
- }
- break;
case COMPARE_OP:
if (nextop == TO_BOOL) {
INSTR_SET_OP0(inst, NOP);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index dc90f75f2645e1..ec3397e1cf6e5f 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -835,28 +835,30 @@
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(BUILD_SLICE);
- _PyStackRef start;
- _PyStackRef stop;
- _PyStackRef step = PyStackRef_NULL;
+ _PyStackRef *args;
_PyStackRef slice;
- if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; }
- stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)];
- start = stack_pointer[-2 - ((oparg == 3) ? 1 : 0)];
+ args = &stack_pointer[-oparg];
+ assert(oparg == 2 || oparg == 3);
+ _PyStackRef start = args[0];
+ _PyStackRef stop = args[1];
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
+ PyObject * step_o = NULL;
+ if (oparg == 3) {
+ step_o = PyStackRef_AsPyObjectBorrow(args[2]);
+ }
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
- PyStackRef_CLOSE(start);
- PyStackRef_CLOSE(stop);
- PyStackRef_XCLOSE(step);
+ for (int _i = oparg; --_i >= 0;) {
+ PyStackRef_CLOSE(args[_i]);
+ }
if (slice_o == NULL) {
- stack_pointer += -2 - ((oparg == 3) ? 1 : 0);
+ stack_pointer += -oparg;
assert(WITHIN_STACK_BOUNDS());
goto error;
}
slice = PyStackRef_FromPyObjectSteal(slice_o);
- stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
- stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
+ stack_pointer[-oparg] = slice;
+ stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -1710,18 +1712,18 @@
(void)this_instr;
_PyStackRef func;
_PyStackRef callargs;
- _PyStackRef kwargs_in = PyStackRef_NULL;
+ _PyStackRef kwargs_in;
_PyStackRef tuple;
- _PyStackRef kwargs_out = PyStackRef_NULL;
+ _PyStackRef kwargs_out;
_PyStackRef func_st;
_PyStackRef callargs_st;
- _PyStackRef kwargs_st = PyStackRef_NULL;
+ _PyStackRef kwargs_st;
_PyStackRef result;
// _MAKE_CALLARGS_A_TUPLE
{
- if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; }
- callargs = stack_pointer[-1 - (oparg & 1)];
- func = stack_pointer[-3 - (oparg & 1)];
+ kwargs_in = stack_pointer[-1];
+ callargs = stack_pointer[-2];
+ func = stack_pointer[-4];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -1763,8 +1765,8 @@
assert(PyTuple_CheckExact(callargs));
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
- stack_pointer[-1 - (oparg & 1)] = callargs_st;
- if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st;
+ stack_pointer[-2] = callargs_st;
+ stack_pointer[-1] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -1807,7 +1809,7 @@
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- stack_pointer += -2 - (oparg & 1);
+ stack_pointer += -3;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
@@ -1828,8 +1830,8 @@
assert(PyTuple_CheckExact(callargs));
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
- stack_pointer[-1 - (oparg & 1)] = callargs_st;
- if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st;
+ stack_pointer[-2] = callargs_st;
+ stack_pointer[-1] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
result_o = PyObject_Call(func, callargs, kwargs);
stack_pointer = _PyFrame_GetStackPointer(frame);
@@ -1839,11 +1841,7 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
PyStackRef_CLOSE(callargs_st);
PyStackRef_CLOSE(func_st);
- if (result_o == NULL) {
- stack_pointer += -3 - (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
- goto error;
- }
+ if (result_o == NULL) goto pop_4_error;
result = PyStackRef_FromPyObjectSteal(result_o);
}
// _CHECK_PERIODIC
@@ -1851,19 +1849,19 @@
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
QSBR_QUIESCENT_STATE(tstate);
if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
- stack_pointer[-3 - (oparg & 1)] = result;
- stack_pointer += -2 - (oparg & 1);
+ stack_pointer[-4] = result;
+ stack_pointer += -3;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_HandlePending(tstate);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err != 0) goto error;
- stack_pointer += 2 + (oparg & 1);
+ stack_pointer += 3;
assert(WITHIN_STACK_BOUNDS());
}
}
- stack_pointer[-3 - (oparg & 1)] = result;
- stack_pointer += -2 - (oparg & 1);
+ stack_pointer[-4] = result;
+ stack_pointer += -3;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -4850,6 +4848,18 @@
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
}
+ TARGET(INSTRUMENTED_LOAD_SUPER_METHOD) {
+ _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
+ (void)this_instr;
+ next_instr += 2;
+ INSTRUCTION_STATS(INSTRUMENTED_LOAD_SUPER_METHOD);
+ /* Skip 1 cache entry */
+ // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
+ // don't want to specialize instrumented instructions
+ PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ GO_TO_INSTRUCTION(LOAD_SUPER_METHOD);
+ }
+
TARGET(INSTRUMENTED_NOT_TAKEN) {
_Py_CODEUNIT* const prev_instr = frame->instr_ptr;
_Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
@@ -5307,7 +5317,6 @@
(void)this_instr;
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self_or_null = PyStackRef_NULL;
// _SPECIALIZE_LOAD_ATTR
{
owner = stack_pointer[-1];
@@ -5315,7 +5324,7 @@
(void)counter;
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr = this_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_Specialize_LoadAttr(owner, next_instr, name);
@@ -5329,50 +5338,15 @@
/* Skip 8 cache entries */
// _LOAD_ATTR
{
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
- PyObject *attr_o;
- if (oparg & 1) {
- /* Designed to work in tandem with CALL, pushes two values. */
- attr_o = NULL;
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- if (is_meth) {
- /* We can bypass temporary bound method object.
- meth is unbound method and obj is self.
- meth | self | arg1 | ... | argN
- */
- assert(attr_o != NULL); // No errors on this branch
- self_or_null = owner; // Transfer ownership
- }
- else {
- /* 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
- CALL that it's not a method call.
- meth | NULL | arg1 | ... | argN
- */
- PyStackRef_CLOSE(owner);
- if (attr_o == NULL) goto pop_1_error;
- self_or_null = PyStackRef_NULL;
- }
- }
- else {
- /* Classic, pushes one value. */
- _PyFrame_SetStackPointer(frame, stack_pointer);
- attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- PyStackRef_CLOSE(owner);
- if (attr_o == NULL) goto pop_1_error;
- /* We need to define self_or_null on all paths */
- self_or_null = PyStackRef_NULL;
- }
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ PyStackRef_CLOSE(owner);
+ if (attr_o == NULL) goto pop_1_error;
attr = PyStackRef_FromPyObjectSteal(attr_o);
}
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = self_or_null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5383,7 +5357,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _CHECK_ATTR_CLASS
{
@@ -5401,13 +5374,9 @@
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5418,7 +5387,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _CHECK_ATTR_CLASS
{
@@ -5442,13 +5410,9 @@
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5464,7 +5428,6 @@
uint32_t func_version = read_u32(&this_instr[4].cache);
PyObject *getattribute = read_obj(&this_instr[6].cache);
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
- assert((oparg & 1) == 0);
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner_o);
assert(type_version != 0);
@@ -5477,7 +5440,7 @@
assert(code->co_argcount == 2);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -5495,7 +5458,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -5527,143 +5489,10 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
/* Skip 5 cache entries */
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
-
- TARGET(LOAD_ATTR_METHOD_LAZY_DICT) {
- _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
- next_instr += 10;
- INSTRUCTION_STATS(LOAD_ATTR_METHOD_LAZY_DICT);
- static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- /* Skip 1 cache entry */
- // _GUARD_TYPE_VERSION
- {
- owner = stack_pointer[-1];
- uint32_t type_version = read_u32(&this_instr[2].cache);
- PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
- assert(type_version != 0);
- DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_ATTR);
- }
- // _CHECK_ATTR_METHOD_LAZY_DICT
- {
- uint16_t dictoffset = read_u16(&this_instr[4].cache);
- char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset;
- PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr);
- /* This object has a __dict__, just not yet created */
- DEOPT_IF(dict != NULL, LOAD_ATTR);
- }
- /* Skip 1 cache entry */
- // _LOAD_ATTR_METHOD_LAZY_DICT
- {
- PyObject *descr = read_obj(&this_instr[6].cache);
- assert(oparg & 1);
- STAT_INC(LOAD_ATTR, hit);
- assert(descr != NULL);
- assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
- attr = PyStackRef_FromPyObjectNew(descr);
- self = owner;
- }
- stack_pointer[-1] = attr;
- stack_pointer[0] = self;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
-
- TARGET(LOAD_ATTR_METHOD_NO_DICT) {
- _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
- next_instr += 10;
- INSTRUCTION_STATS(LOAD_ATTR_METHOD_NO_DICT);
- static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- /* Skip 1 cache entry */
- // _GUARD_TYPE_VERSION
- {
- owner = stack_pointer[-1];
- uint32_t type_version = read_u32(&this_instr[2].cache);
- PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
- assert(type_version != 0);
- DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_ATTR);
- }
- /* Skip 2 cache entries */
- // _LOAD_ATTR_METHOD_NO_DICT
- {
- PyObject *descr = read_obj(&this_instr[6].cache);
- assert(oparg & 1);
- assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
- STAT_INC(LOAD_ATTR, hit);
- assert(descr != NULL);
- assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
- attr = PyStackRef_FromPyObjectNew(descr);
- self = owner;
- }
- stack_pointer[-1] = attr;
- stack_pointer[0] = self;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
-
- TARGET(LOAD_ATTR_METHOD_WITH_VALUES) {
- _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
- next_instr += 10;
- INSTRUCTION_STATS(LOAD_ATTR_METHOD_WITH_VALUES);
- static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef self = PyStackRef_NULL;
- /* Skip 1 cache entry */
- // _GUARD_TYPE_VERSION
- {
- owner = stack_pointer[-1];
- uint32_t type_version = read_u32(&this_instr[2].cache);
- PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
- assert(type_version != 0);
- DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_ATTR);
- }
- // _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
- {
- PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
- assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
- PyDictValues *ivs = _PyObject_InlineValues(owner_o);
- DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid), LOAD_ATTR);
- }
- // _GUARD_KEYS_VERSION
- {
- uint32_t keys_version = read_u32(&this_instr[4].cache);
- PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
- PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
- PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
- DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version, LOAD_ATTR);
- }
- // _LOAD_ATTR_METHOD_WITH_VALUES
- {
- PyObject *descr = read_obj(&this_instr[6].cache);
- assert(oparg & 1);
- /* Cached method object */
- STAT_INC(LOAD_ATTR, hit);
- assert(descr != NULL);
- assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
- attr = PyStackRef_FromPyObjectNew(descr);
- self = owner;
- }
- stack_pointer[-1] = attr;
- stack_pointer[0] = self;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5675,7 +5504,6 @@
_PyStackRef owner;
PyDictKeysObject *mod_keys;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _CHECK_ATTR_MODULE_PUSH_KEYS
{
@@ -5708,14 +5536,10 @@
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
/* Skip 5 cache entries */
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5739,7 +5563,6 @@
// _LOAD_ATTR_NONDESCRIPTOR_NO_DICT
{
PyObject *descr = read_obj(&this_instr[6].cache);
- assert((oparg & 1) == 0);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -5784,7 +5607,6 @@
// _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES
{
PyObject *descr = read_obj(&this_instr[6].cache);
- assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
PyStackRef_CLOSE(owner);
@@ -5818,7 +5640,6 @@
// _LOAD_ATTR_PROPERTY_FRAME
{
PyObject *fget = read_obj(&this_instr[6].cache);
- assert((oparg & 1) == 0);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
PyCodeObject *code = (PyCodeObject *)f->func_code;
@@ -5866,7 +5687,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -5890,14 +5710,10 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
/* Skip 5 cache entries */
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -5909,7 +5725,6 @@
_PyStackRef owner;
PyDictObject *dict;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -5939,7 +5754,7 @@
UNLOCK_OBJECT(dict);
DEOPT_IF(true, LOAD_ATTR);
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
DEOPT_IF(true, LOAD_ATTR);
@@ -5957,14 +5772,10 @@
STAT_INC(LOAD_ATTR, hit);
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
- null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
/* Skip 5 cache entries */
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6265,14 +6076,13 @@
_Py_CODEUNIT* const this_instr = next_instr - 5;
(void)this_instr;
_PyStackRef *res;
- _PyStackRef null = PyStackRef_NULL;
// _SPECIALIZE_LOAD_GLOBAL
{
uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter;
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
next_instr = this_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
@@ -6289,15 +6099,13 @@
// _LOAD_GLOBAL
{
res = &stack_pointer[0];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(*res)) goto error;
- null = PyStackRef_NULL;
}
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6309,7 +6117,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
PyDictKeysObject *builtins_keys;
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_GLOBALS_VERSION
{
@@ -6344,11 +6151,9 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
}
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6360,7 +6165,6 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
PyDictKeysObject *globals_keys;
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_GLOBALS_VERSION_PUSH_KEYS
{
@@ -6387,11 +6191,9 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
- null = PyStackRef_NULL;
}
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6416,6 +6218,198 @@
DISPATCH();
}
+ TARGET(LOAD_METHOD) {
+ frame->instr_ptr = next_instr;
+ next_instr += 10;
+ INSTRUCTION_STATS(LOAD_METHOD);
+ PREDICTED(LOAD_METHOD);
+ _Py_CODEUNIT* const this_instr = next_instr - 10;
+ (void)this_instr;
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef self_or_null;
+ // _SPECIALIZE_LOAD_METHOD
+ {
+ owner = stack_pointer[-1];
+ uint16_t counter = read_u16(&this_instr[1].cache);
+ (void)counter;
+ #if ENABLE_SPECIALIZATION_FT
+ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ next_instr = this_instr;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ _Py_Specialize_LoadMethod(owner, next_instr, name);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ DISPATCH_SAME_OPARG();
+ }
+ OPCODE_DEFERRED_INC(LOAD_METHOD);
+ ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ #endif /* ENABLE_SPECIALIZATION_FT */
+ }
+ /* Skip 8 cache entries */
+ // _LOAD_METHOD
+ {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *attr_o;
+ /* Designed to work in tandem with CALL, pushes two values. */
+ attr_o = NULL;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (is_meth) {
+ /* We can bypass temporary bound method object.
+ meth is unbound method and obj is self.
+ meth | self | arg1 | ... | argN
+ */
+ assert(attr_o != NULL); // No errors on this branch
+ self_or_null = owner; // Transfer ownership
+ }
+ else {
+ /* 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
+ CALL that it's not a method call.
+ meth | NULL | arg1 | ... | argN
+ */
+ PyStackRef_CLOSE(owner);
+ if (attr_o == NULL) goto pop_1_error;
+ self_or_null = PyStackRef_NULL;
+ }
+ attr = PyStackRef_FromPyObjectSteal(attr_o);
+ }
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = self_or_null;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
+ TARGET(LOAD_METHOD_LAZY_DICT) {
+ _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
+ next_instr += 10;
+ INSTRUCTION_STATS(LOAD_METHOD_LAZY_DICT);
+ static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef self;
+ /* Skip 1 cache entry */
+ // _GUARD_TYPE_VERSION
+ {
+ owner = stack_pointer[-1];
+ uint32_t type_version = read_u32(&this_instr[2].cache);
+ PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
+ assert(type_version != 0);
+ DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_METHOD);
+ }
+ // _CHECK_ATTR_METHOD_LAZY_DICT
+ {
+ uint16_t dictoffset = read_u16(&this_instr[4].cache);
+ char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset;
+ PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr);
+ /* This object has a __dict__, just not yet created */
+ DEOPT_IF(dict != NULL, LOAD_METHOD);
+ }
+ /* Skip 1 cache entry */
+ // _LOAD_METHOD_LAZY_DICT
+ {
+ PyObject *descr = read_obj(&this_instr[6].cache);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
+ attr = PyStackRef_FromPyObjectNew(descr);
+ self = owner;
+ }
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = self;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
+ TARGET(LOAD_METHOD_NO_DICT) {
+ _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
+ next_instr += 10;
+ INSTRUCTION_STATS(LOAD_METHOD_NO_DICT);
+ static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef self;
+ /* Skip 1 cache entry */
+ // _GUARD_TYPE_VERSION
+ {
+ owner = stack_pointer[-1];
+ uint32_t type_version = read_u32(&this_instr[2].cache);
+ PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
+ assert(type_version != 0);
+ DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_METHOD);
+ }
+ /* Skip 2 cache entries */
+ // _LOAD_METHOD_NO_DICT
+ {
+ PyObject *descr = read_obj(&this_instr[6].cache);
+ assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
+ attr = PyStackRef_FromPyObjectNew(descr);
+ self = owner;
+ }
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = self;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
+ TARGET(LOAD_METHOD_WITH_VALUES) {
+ _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
+ next_instr += 10;
+ INSTRUCTION_STATS(LOAD_METHOD_WITH_VALUES);
+ static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef self;
+ /* Skip 1 cache entry */
+ // _GUARD_TYPE_VERSION
+ {
+ owner = stack_pointer[-1];
+ uint32_t type_version = read_u32(&this_instr[2].cache);
+ PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
+ assert(type_version != 0);
+ DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version, LOAD_METHOD);
+ }
+ // _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
+ {
+ PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
+ assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
+ PyDictValues *ivs = _PyObject_InlineValues(owner_o);
+ DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid), LOAD_METHOD);
+ }
+ // _GUARD_KEYS_VERSION
+ {
+ uint32_t keys_version = read_u32(&this_instr[4].cache);
+ PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
+ PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
+ PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
+ DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version, LOAD_METHOD);
+ }
+ // _LOAD_METHOD_WITH_VALUES
+ {
+ PyObject *descr = read_obj(&this_instr[6].cache);
+ /* Cached method object */
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
+ attr = PyStackRef_FromPyObjectNew(descr);
+ self = owner;
+ }
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = self;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
TARGET(LOAD_NAME) {
frame->instr_ptr = next_instr;
next_instr += 1;
@@ -6495,7 +6489,6 @@
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
// _SPECIALIZE_LOAD_SUPER_ATTR
{
class_st = stack_pointer[-2];
@@ -6503,11 +6496,10 @@
uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter;
#if ENABLE_SPECIALIZATION_FT
- int load_method = oparg & 1;
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
- _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 0);
stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH_SAME_OPARG();
}
@@ -6521,7 +6513,7 @@
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
- if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
@@ -6541,7 +6533,7 @@
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
stack_pointer = _PyFrame_GetStackPointer(frame);
- if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -6574,11 +6566,9 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
if (attr_o == NULL) goto error;
attr = PyStackRef_FromPyObjectSteal(attr_o);
- null = PyStackRef_NULL;
}
stack_pointer[0] = attr;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6618,10 +6608,111 @@
DISPATCH();
}
- TARGET(LOAD_SUPER_ATTR_METHOD) {
+ TARGET(LOAD_SUPER_METHOD) {
frame->instr_ptr = next_instr;
next_instr += 2;
- INSTRUCTION_STATS(LOAD_SUPER_ATTR_METHOD);
+ INSTRUCTION_STATS(LOAD_SUPER_METHOD);
+ PREDICTED(LOAD_SUPER_METHOD);
+ _Py_CODEUNIT* const this_instr = next_instr - 2;
+ (void)this_instr;
+ _PyStackRef global_super_st;
+ _PyStackRef class_st;
+ _PyStackRef self_st;
+ _PyStackRef attr;
+ _PyStackRef null;
+ // _SPECIALIZE_LOAD_SUPER_METHOD
+ {
+ class_st = stack_pointer[-2];
+ global_super_st = stack_pointer[-3];
+ uint16_t counter = read_u16(&this_instr[1].cache);
+ (void)counter;
+ #if ENABLE_SPECIALIZATION_FT
+ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
+ next_instr = this_instr;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 1);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ DISPATCH_SAME_OPARG();
+ }
+ OPCODE_DEFERRED_INC(LOAD_SUPER_METHOD);
+ ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
+ #endif /* ENABLE_SPECIALIZATION_FT */
+ }
+ // _LOAD_SUPER_ATTR
+ {
+ self_st = stack_pointer[-1];
+ PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
+ PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
+ PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
+ PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_CALL,
+ frame, this_instr, global_super, arg);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (err) {
+ PyStackRef_CLOSE(global_super_st);
+ PyStackRef_CLOSE(class_st);
+ PyStackRef_CLOSE(self_st);
+ goto pop_3_error;
+ }
+ }
+ // we make no attempt to optimize here; specializations should
+ // handle any case whose performance we care about
+ PyObject *stack[] = {class, self};
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (opcode >= MIN_INSTRUMENTED_OPCODE) {
+ PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
+ if (super == NULL) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ _Py_call_instrumentation_exc2(
+ tstate, PY_MONITORING_EVENT_C_RAISE,
+ frame, this_instr, global_super, arg);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ }
+ else {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_C_RETURN,
+ frame, this_instr, global_super, arg);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (err < 0) {
+ Py_CLEAR(super);
+ }
+ }
+ }
+ PyStackRef_CLOSE(global_super_st);
+ PyStackRef_CLOSE(class_st);
+ PyStackRef_CLOSE(self_st);
+ if (super == NULL) goto pop_3_error;
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
+ stack_pointer += -3;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *attr_o = PyObject_GetAttr(super, name);
+ Py_DECREF(super);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (attr_o == NULL) goto error;
+ attr = PyStackRef_FromPyObjectSteal(attr_o);
+ }
+ // _PUSH_NULL
+ {
+ null = PyStackRef_NULL;
+ }
+ stack_pointer[0] = attr;
+ stack_pointer[1] = null;
+ stack_pointer += 2;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
+ TARGET(LOAD_SUPER_METHOD_METHOD) {
+ frame->instr_ptr = next_instr;
+ next_instr += 2;
+ INSTRUCTION_STATS(LOAD_SUPER_METHOD_METHOD);
static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size");
_PyStackRef global_super_st;
_PyStackRef class_st;
@@ -6636,8 +6727,8 @@
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
assert(oparg & 1);
- DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
- DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+ DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_METHOD);
+ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_METHOD);
STAT_INC(LOAD_SUPER_ATTR, hit);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyTypeObject *cls = (PyTypeObject *)class;
@@ -7002,9 +7093,9 @@
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(PUSH_NULL);
- _PyStackRef res;
- res = PyStackRef_NULL;
- stack_pointer[0] = res;
+ _PyStackRef null;
+ null = PyStackRef_NULL;
+ stack_pointer[0] = null;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index 17e5346be5ed3d..b24e2887f42ecc 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -81,6 +81,8 @@ static const int8_t EVENT_FOR_OPCODE[256] = {
[INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,
[LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,
[INSTRUMENTED_LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,
+ [LOAD_SUPER_METHOD] = PY_MONITORING_EVENT_CALL,
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = PY_MONITORING_EVENT_CALL,
[RESUME] = -1,
[YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,
[INSTRUMENTED_YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,
@@ -126,6 +128,7 @@ static const uint8_t DE_INSTRUMENT[256] = {
[INSTRUMENTED_END_FOR] = END_FOR,
[INSTRUMENTED_END_SEND] = END_SEND,
[INSTRUMENTED_LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = LOAD_SUPER_METHOD,
[INSTRUMENTED_NOT_TAKEN] = NOT_TAKEN,
};
@@ -164,6 +167,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = {
[INSTRUMENTED_POP_ITER] = INSTRUMENTED_POP_ITER,
[LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,
[INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,
+ [LOAD_SUPER_METHOD] = INSTRUMENTED_LOAD_SUPER_METHOD,
+ [INSTRUMENTED_LOAD_SUPER_METHOD] = INSTRUMENTED_LOAD_SUPER_METHOD,
[NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN,
[INSTRUMENTED_NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN,
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index cb6c33f01d3598..2e35ae710b1430 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -3,6 +3,7 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_SLICE,
&&TARGET_BINARY_SUBSCR,
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
+ &&TARGET_CALL_FUNCTION_EX,
&&TARGET_CHECK_EG_MATCH,
&&TARGET_CHECK_EXC_MATCH,
&&TARGET_CLEANUP_THROW,
@@ -15,8 +16,8 @@ static void *opcode_targets[256] = {
&&TARGET_FORMAT_WITH_SPEC,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
- &&TARGET_GET_ITER,
&&TARGET_RESERVED,
+ &&TARGET_GET_ITER,
&&TARGET_GET_LEN,
&&TARGET_GET_YIELD_FROM_ITER,
&&TARGET_INTERPRETER_EXIT,
@@ -51,7 +52,6 @@ static void *opcode_targets[256] = {
&&TARGET_BUILD_STRING,
&&TARGET_BUILD_TUPLE,
&&TARGET_CALL,
- &&TARGET_CALL_FUNCTION_EX,
&&TARGET_CALL_INTRINSIC_1,
&&TARGET_CALL_INTRINSIC_2,
&&TARGET_CALL_KW,
@@ -89,10 +89,12 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_FROM_DICT_OR_DEREF,
&&TARGET_LOAD_FROM_DICT_OR_GLOBALS,
&&TARGET_LOAD_GLOBAL,
+ &&TARGET_LOAD_METHOD,
&&TARGET_LOAD_NAME,
&&TARGET_LOAD_SMALL_INT,
&&TARGET_LOAD_SPECIAL,
&&TARGET_LOAD_SUPER_ATTR,
+ &&TARGET_LOAD_SUPER_METHOD,
&&TARGET_MAKE_CELL,
&&TARGET_MAP_ADD,
&&TARGET_MATCH_CLASS,
@@ -146,8 +148,6 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_RESUME,
&&TARGET_BINARY_OP_ADD_FLOAT,
&&TARGET_BINARY_OP_ADD_INT,
@@ -198,9 +198,6 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_ATTR_CLASS_WITH_METACLASS_CHECK,
&&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
- &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT,
- &&TARGET_LOAD_ATTR_METHOD_NO_DICT,
- &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES,
&&TARGET_LOAD_ATTR_MODULE,
&&TARGET_LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
&&TARGET_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
@@ -211,8 +208,11 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_CONST_MORTAL,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_LOAD_GLOBAL_MODULE,
+ &&TARGET_LOAD_METHOD_LAZY_DICT,
+ &&TARGET_LOAD_METHOD_NO_DICT,
+ &&TARGET_LOAD_METHOD_WITH_VALUES,
&&TARGET_LOAD_SUPER_ATTR_ATTR,
- &&TARGET_LOAD_SUPER_ATTR_METHOD,
+ &&TARGET_LOAD_SUPER_METHOD_METHOD,
&&TARGET_RESUME_CHECK,
&&TARGET_SEND_GEN,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
@@ -233,11 +233,11 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_POP_ITER,
&&TARGET_INSTRUMENTED_END_SEND,
&&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
+ &&TARGET_INSTRUMENTED_LOAD_SUPER_METHOD,
&&TARGET_INSTRUMENTED_FOR_ITER,
&&TARGET_INSTRUMENTED_CALL_KW,
&&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 9beb47246eb3d6..b91caf11ffa962 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -1274,10 +1274,7 @@ uop_optimize(
for (int pc = 0; pc < length; pc++) {
int opcode = buffer[pc].opcode;
int oparg = buffer[pc].oparg;
- if (_PyUop_Flags[opcode] & HAS_OPARG_AND_1_FLAG) {
- buffer[pc].opcode = opcode + 1 + (oparg & 1);
- }
- else if (oparg < _PyUop_Replication[opcode]) {
+ if (oparg < _PyUop_Replication[opcode]) {
buffer[pc].opcode = opcode + oparg + 1;
}
else if (is_terminator(&buffer[pc])) {
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index b9ac30ea04e4e8..05f9592e9a23fa 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -109,10 +109,10 @@ convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj)
return NULL;
}
if (_Py_IsImmortal(res)) {
- inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_BORROW_WITH_NULL : _LOAD_CONST_INLINE_BORROW;
+ inst->opcode = _LOAD_CONST_INLINE_BORROW;
}
else {
- inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_WITH_NULL : _LOAD_CONST_INLINE;
+ inst->opcode = _LOAD_CONST_INLINE;
}
inst->operand0 = (uint64_t)res;
return res;
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 881a607ca2aa29..af834b6957be22 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -528,9 +528,8 @@ dummy_func(void) {
top_out = top_in;
}
- op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)offset;
(void)owner;
}
@@ -553,15 +552,19 @@ dummy_func(void) {
}
}
- op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
+ op(_LOAD_ATTR, (owner -- attr)) {
+ (void)owner;
+ attr = sym_new_not_null(ctx);
+ }
+
+ op(_LOAD_METHOD, (owner -- attr, self_or_null)) {
(void)owner;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_unknown(ctx);
}
- op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys -- attr)) {
(void)index;
- null = sym_new_null(ctx);
attr = NULL;
if (this_instr[-1].opcode == _NOP) {
// Preceding _CHECK_ATTR_MODULE_PUSH_KEYS was removed: mod is const and dict is watched.
@@ -589,41 +592,38 @@ dummy_func(void) {
(void)owner;
}
- op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict -- attr)) {
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)hint;
(void)owner;
(void)dict;
}
- op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_SLOT, (index/1, owner -- attr)) {
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)index;
(void)owner;
}
- op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
+ op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)descr;
(void)owner;
}
- op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
+ op(_LOAD_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
(void)descr;
attr = sym_new_not_null(ctx);
self = owner;
}
- op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
+ op(_LOAD_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
(void)descr;
attr = sym_new_not_null(ctx);
self = owner;
}
- op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
+ op(_LOAD_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
(void)descr;
attr = sym_new_not_null(ctx);
self = owner;
@@ -819,7 +819,7 @@ dummy_func(void) {
Py_UNREACHABLE();
}
- op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) {
+ op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- )) {
SYNC_SP();
ctx->frame->stack_pointer = stack_pointer;
ctx->frame = new_frame;
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index fa0b4ed4345320..cb4651a5d8093c 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -928,12 +928,9 @@
case _LOAD_GLOBAL: {
JitOptSymbol **res;
- JitOptSymbol *null = NULL;
res = &stack_pointer[0];
res[0] = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -966,25 +963,15 @@
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
JitOptSymbol *res;
- JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
stack_pointer[-1] = res;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
JitOptSymbol *res;
- JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
stack_pointer[-1] = res;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1109,6 +1096,8 @@
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
+ /* _INSTRUMENTED_LOAD_SUPER_METHOD is not a viable micro-op for tier 2 */
+
case _LOAD_SUPER_ATTR_ATTR: {
JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx);
@@ -1118,7 +1107,7 @@
break;
}
- case _LOAD_SUPER_ATTR_METHOD: {
+ case _LOAD_SUPER_METHOD_METHOD: {
JitOptSymbol *attr;
JitOptSymbol *self_or_null;
attr = sym_new_not_null(ctx);
@@ -1130,21 +1119,31 @@
break;
}
- case _LOAD_ATTR: {
+ case _LOAD_METHOD: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self_or_null = NULL;
+ JitOptSymbol *self_or_null;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_unknown(ctx);
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = self_or_null;
- stack_pointer += (oparg & 1);
+ stack_pointer[0] = self_or_null;
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
+ case _LOAD_ATTR: {
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ owner = stack_pointer[-1];
+ (void)owner;
+ attr = sym_new_not_null(ctx);
+ stack_pointer[-1] = attr;
+ break;
+ }
+
case _GUARD_TYPE_VERSION: {
JitOptSymbol *owner;
owner = stack_pointer[-1];
@@ -1182,17 +1181,12 @@
case _LOAD_ATTR_INSTANCE_VALUE: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)offset;
(void)owner;
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1230,11 +1224,9 @@
case _LOAD_ATTR_MODULE_FROM_KEYS: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)this_instr->operand0;
(void)index;
- null = sym_new_null(ctx);
attr = NULL;
if (this_instr[-1].opcode == _NOP) {
// Preceding _CHECK_ATTR_MODULE_PUSH_KEYS was removed: mod is const and dict is watched.
@@ -1243,8 +1235,7 @@
assert(PyModule_CheckExact(mod));
PyObject *dict = mod->md_dict;
stack_pointer[-2] = attr;
- if (oparg & 1) stack_pointer[-1] = null;
- stack_pointer += -1 + (oparg & 1);
+ stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
PyObject *res = convert_global_to_const(this_instr, dict);
if (res != NULL) {
@@ -1254,7 +1245,7 @@
else {
this_instr->opcode = _LOAD_ATTR_MODULE;
}
- stack_pointer += 1 - (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
}
if (attr == NULL) {
@@ -1262,8 +1253,7 @@
attr = sym_new_not_null(ctx);
}
stack_pointer[-2] = attr;
- if (oparg & 1) stack_pointer[-1] = null;
- stack_pointer += -1 + (oparg & 1);
+ stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1284,18 +1274,15 @@
JitOptSymbol *dict;
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
dict = stack_pointer[-1];
owner = stack_pointer[-2];
uint16_t hint = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)hint;
(void)owner;
(void)dict;
stack_pointer[-2] = attr;
- if (oparg & 1) stack_pointer[-1] = null;
- stack_pointer += -1 + (oparg & 1);
+ stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1303,17 +1290,12 @@
case _LOAD_ATTR_SLOT: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)index;
(void)owner;
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1324,17 +1306,12 @@
case _LOAD_ATTR_CLASS: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
(void)descr;
(void)owner;
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1720,10 +1697,10 @@
break;
}
- case _LOAD_ATTR_METHOD_WITH_VALUES: {
+ case _LOAD_METHOD_WITH_VALUES: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self = NULL;
+ JitOptSymbol *self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1736,10 +1713,10 @@
break;
}
- case _LOAD_ATTR_METHOD_NO_DICT: {
+ case _LOAD_METHOD_NO_DICT: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self = NULL;
+ JitOptSymbol *self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1770,10 +1747,10 @@
break;
}
- case _LOAD_ATTR_METHOD_LAZY_DICT: {
+ case _LOAD_METHOD_LAZY_DICT: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self = NULL;
+ JitOptSymbol *self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -2262,11 +2239,11 @@
case _MAKE_CALLARGS_A_TUPLE: {
JitOptSymbol *tuple;
- JitOptSymbol *kwargs_out = NULL;
+ JitOptSymbol *kwargs_out;
tuple = sym_new_not_null(ctx);
kwargs_out = sym_new_not_null(ctx);
- stack_pointer[-1 - (oparg & 1)] = tuple;
- if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out;
+ stack_pointer[-2] = tuple;
+ stack_pointer[-1] = kwargs_out;
break;
}
@@ -2315,8 +2292,8 @@
case _BUILD_SLICE: {
JitOptSymbol *slice;
slice = sym_new_not_null(ctx);
- stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
- stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
+ stack_pointer[-oparg] = slice;
+ stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2639,37 +2616,26 @@
case _LOAD_GLOBAL_MODULE: {
JitOptSymbol *res;
- JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _LOAD_GLOBAL_BUILTINS: {
JitOptSymbol *res;
- JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
- stack_pointer += 1 + (oparg & 1);
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _LOAD_ATTR_MODULE: {
JitOptSymbol *attr;
- JitOptSymbol *null = NULL;
attr = sym_new_not_null(ctx);
- null = sym_new_null(ctx);
stack_pointer[-1] = attr;
- if (oparg & 1) stack_pointer[0] = null;
- stack_pointer += (oparg & 1);
- assert(WITHIN_STACK_BOUNDS());
break;
}
diff --git a/Python/specialize.c b/Python/specialize.c
index fa022346bdea6a..eb599028cefafa 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -804,7 +804,7 @@ _Py_Specialize_LoadSuperAttr(_PyStackRef global_super_st, _PyStackRef cls_st, _P
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
goto fail;
}
- uint8_t load_code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;
+ uint8_t load_code = load_method ? LOAD_SUPER_METHOD_METHOD : LOAD_SUPER_ATTR_ATTR;
specialize(instr, load_code);
return;
fail:
@@ -1109,7 +1109,7 @@ instance_has_key(PyObject *obj, PyObject *name, uint32_t *shared_keys_version)
static int
do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
bool shadow, uint32_t shared_keys_version,
- DescriptorClassification kind, PyObject *descr, unsigned int tp_version)
+ DescriptorClassification kind, PyObject *descr, unsigned int tp_version, bool load_method)
{
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
PyTypeObject *type = Py_TYPE(owner);
@@ -1117,17 +1117,16 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
}
- uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
switch(kind) {
case OVERRIDING:
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
return -1;
case METHOD:
{
if (shadow) {
goto try_instance;
}
- if (oparg & 1) {
+ if (load_method) {
if (specialize_attr_loadclassattr(owner, instr, name, descr,
tp_version, kind, true,
shared_keys_version)) {
@@ -1137,7 +1136,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
return -1;
}
}
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
return -1;
}
case PROPERTY:
@@ -1146,28 +1145,28 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
assert(Py_TYPE(descr) == &PyProperty_Type);
PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
if (fget == NULL) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
return -1;
}
if (!Py_IS_TYPE(fget, &PyFunction_Type)) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
return -1;
}
- if (!function_check_args(fget, 1, LOAD_ATTR)) {
+ if (load_method) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_ATTR_METHOD);
return -1;
}
- if (oparg & 1) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
+ if (!function_check_args(fget, 1, LOAD_ATTR)) {
return -1;
}
/* Don't specialize if PEP 523 is active */
if (_PyInterpreterState_GET()->eval_frame) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OTHER);
return -1;
}
#ifdef Py_GIL_DISABLED
if (!_PyObject_HasDeferredRefcount(fget)) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
return -1;
}
#endif
@@ -1180,6 +1179,10 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
}
case OBJECT_SLOT:
{
+ if (load_method) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ return -1;
+ }
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
struct PyMemberDef *dmem = member->d_member;
Py_ssize_t offset = dmem->offset;
@@ -1204,6 +1207,10 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
}
case DUNDER_CLASS:
{
+ if (load_method) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ return -1;
+ }
Py_ssize_t offset = offsetof(PyObject, ob_type);
assert(offset == (uint16_t)offset);
cache->index = (uint16_t)offset;
@@ -1212,16 +1219,20 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
return 0;
}
case OTHER_SLOT:
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
return -1;
case MUTABLE:
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
return -1;
case GETSET_OVERRIDDEN:
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
+ SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
return -1;
case GETATTRIBUTE_IS_PYTHON_FUNCTION:
{
+ if (load_method) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ return -1;
+ }
#ifndef Py_GIL_DISABLED
// In free-threaded builds it's possible for tp_getattro to change
// after the call to analyze_descriptor. That is fine: the version
@@ -1233,10 +1244,6 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
if (!function_check_args(descr, 2, LOAD_ATTR)) {
return -1;
}
- if (oparg & 1) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
- return -1;
- }
uint32_t version = function_get_version(descr, LOAD_ATTR);
if (version == 0) {
return -1;
@@ -1270,7 +1277,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
if (shadow) {
goto try_instance;
}
- if ((oparg & 1) == 0) {
+ if (!load_method) {
if (specialize_attr_loadclassattr(owner, instr, name, descr,
tp_version, kind, false,
shared_keys_version)) {
@@ -1287,6 +1294,10 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
}
Py_UNREACHABLE();
try_instance:
+ if (load_method) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ return -1;
+ }
if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
{
@@ -1296,7 +1307,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
}
static int
-specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
+specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name, bool load_method)
{
// 0 is not a valid version
uint32_t shared_keys_version = 0;
@@ -1305,7 +1316,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
unsigned int tp_version = 0;
PyTypeObject *type = Py_TYPE(owner);
DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
- int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
+ int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version, load_method);
Py_XDECREF(descr);
return result;
}
@@ -1333,7 +1344,40 @@ _Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *nam
fail = specialize_class_load_attr(owner, instr, name);
}
else {
- fail = specialize_instance_load_attr(owner, instr, name);
+ fail = specialize_instance_load_attr(owner, instr, name, false);
+ }
+
+ if (fail) {
+ unspecialize(instr);
+ }
+}
+
+void
+_Py_Specialize_LoadMethod(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
+{
+ PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
+
+ assert(ENABLE_SPECIALIZATION_FT);
+ assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
+ PyTypeObject *type = Py_TYPE(owner);
+ bool fail;
+ if (!_PyType_IsReady(type)) {
+ // We *might* not really need this check, but we inherited it from
+ // PyObject_GenericGetAttr and friends... and this way we still do the
+ // right thing if someone forgets to call PyType_Ready(type):
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ fail = true;
+ }
+ else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ fail = true;
+ }
+ else if (PyType_Check(owner)) {
+ SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OTHER);
+ fail = true;
+ }
+ else {
+ fail = specialize_instance_load_attr(owner, instr, name, true);
}
if (fail) {
@@ -1575,7 +1619,7 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
#ifdef Py_GIL_DISABLED
if (!_PyObject_HasDeferredRefcount(descr)) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
+ SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
return 0;
}
#endif
@@ -1587,11 +1631,11 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
#endif
if (shared_keys_version == 0) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
+ SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return 0;
}
write_u32(cache->keys_version, shared_keys_version);
- specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
+ specialize(instr, is_method ? LOAD_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
}
else {
Py_ssize_t dictoffset;
@@ -1601,17 +1645,17 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
else {
dictoffset = owner_cls->tp_dictoffset;
if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
+ SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
return 0;
}
}
if (dictoffset == 0) {
- specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
+ specialize(instr, is_method ? LOAD_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
}
else if (is_method) {
PyObject *dict = *(PyObject **) ((char *)owner + dictoffset);
if (dict) {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
+ SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
return 0;
}
/* Cache entries must be unsigned values, so we offset the
@@ -1620,10 +1664,10 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
dictoffset -= MANAGED_DICT_OFFSET;
assert(((uint16_t)dictoffset) == dictoffset);
cache->dict_offset = (uint16_t)dictoffset;
- specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
+ specialize(instr, LOAD_METHOD_LAZY_DICT);
}
else {
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
+ SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
return 0;
}
}
diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py
index 4013b503502df6..1f15c3bb9c88af 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -25,7 +25,6 @@ class Properties:
side_exit: bool
pure: bool
tier: int | None = None
- oparg_and_1: bool = False
const_oparg: int = -1
needs_prev: bool = False
no_save_ip: bool = False
@@ -124,16 +123,14 @@ def size(self) -> int:
class StackItem:
name: str
type: str | None
- condition: str | None
size: str
peek: bool = False
used: bool = False
def __str__(self) -> str:
- cond = f" if ({self.condition})" if self.condition else ""
size = f"[{self.size}]" if self.size else ""
type = "" if self.type is None else f"{self.type} "
- return f"{type}{self.name}{size}{cond} {self.peek}"
+ return f"{type}{self.name}{size} {self.peek}"
def is_array(self) -> bool:
return self.size != ""
@@ -315,25 +312,19 @@ def override_error(
)
-def convert_stack_item(
- item: parser.StackEffect, replace_op_arg_1: str | None
-) -> StackItem:
- cond = item.cond
- if replace_op_arg_1 and OPARG_AND_1.match(item.cond):
- cond = replace_op_arg_1
- return StackItem(item.name, item.type, cond, item.size)
+def convert_stack_item(item: parser.StackEffect) -> StackItem:
+ return StackItem(item.name, item.type, item.size)
def analyze_stack(
- op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | None = None
-) -> StackEffect:
+ op: parser.InstDef | parser.Pseudo) -> StackEffect:
inputs: list[StackItem] = [
- convert_stack_item(i, replace_op_arg_1)
+ convert_stack_item(i)
for i in op.inputs
if isinstance(i, parser.StackEffect)
]
outputs: list[StackItem] = [
- convert_stack_item(i, replace_op_arg_1) for i in op.outputs
+ convert_stack_item(i) for i in op.outputs
]
# Mark variables with matching names at the base of the stack as "peek"
modified = False
@@ -756,40 +747,6 @@ def always_exits(op: parser.InstDef) -> bool:
return True
return False
-
-def stack_effect_only_peeks(instr: parser.InstDef) -> bool:
- stack_inputs = [s for s in instr.inputs if not isinstance(s, parser.CacheEffect)]
- if len(stack_inputs) != len(instr.outputs):
- return False
- if len(stack_inputs) == 0:
- return False
- if any(s.cond for s in stack_inputs) or any(s.cond for s in instr.outputs):
- return False
- return all(
- (s.name == other.name and s.type == other.type and s.size == other.size)
- for s, other in zip(stack_inputs, instr.outputs)
- )
-
-
-OPARG_AND_1 = re.compile("\\(*oparg *& *1")
-
-
-def effect_depends_on_oparg_1(op: parser.InstDef) -> bool:
- for effect in op.inputs:
- if isinstance(effect, parser.CacheEffect):
- continue
- if not effect.cond:
- continue
- if OPARG_AND_1.match(effect.cond):
- return True
- for effect in op.outputs:
- if not effect.cond:
- continue
- if OPARG_AND_1.match(effect.cond):
- return True
- return False
-
-
def compute_properties(op: parser.InstDef) -> Properties:
escaping_calls = find_escaping_api_calls(op)
has_free = (
@@ -863,29 +820,6 @@ def make_uop(
body=op.block.tokens,
properties=compute_properties(op),
)
- if effect_depends_on_oparg_1(op) and "split" in op.annotations:
- result.properties.oparg_and_1 = True
- for bit in ("0", "1"):
- name_x = name + "_" + bit
- properties = compute_properties(op)
- if properties.oparg:
- # May not need oparg anymore
- properties.oparg = any(
- token.text == "oparg" for token in op.block.tokens
- )
- rep = Uop(
- name=name_x,
- context=op.context,
- annotations=op.annotations,
- stack=analyze_stack(op, bit),
- caches=analyze_caches(inputs),
- deferred_refs=analyze_deferred_refs(op),
- output_stores=find_stores_outputs(op),
- body=op.block.tokens,
- properties=properties,
- )
- rep.replicates = result
- uops[name_x] = rep
for anno in op.annotations:
if anno.startswith("replicate"):
result.replicated = int(anno[10:-1])
diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py
index f54afbb880d2fa..c441569b7e70dc 100644
--- a/Tools/cases_generator/generators_common.py
+++ b/Tools/cases_generator/generators_common.py
@@ -246,7 +246,7 @@ def decref_inputs(
if var.name == "null":
continue
close = "PyStackRef_CLOSE"
- if "null" in var.name or var.condition and var.condition != "1":
+ if "null" in var.name:
close = "PyStackRef_XCLOSE"
if var.size:
if var.size == "1":
@@ -255,9 +255,6 @@ def decref_inputs(
self.out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
self.out.emit(f"{close}({var.name}[_i]);\n")
self.out.emit("}\n")
- elif var.condition:
- if var.condition != "0":
- self.out.emit(f"{close}({var.name});\n")
else:
self.out.emit(f"{close}({var.name});\n")
for input in storage.inputs:
@@ -668,8 +665,6 @@ def cflags(p: Properties) -> str:
flags.append("HAS_PURE_FLAG")
if p.no_save_ip:
flags.append("HAS_NO_SAVE_IP_FLAG")
- if p.oparg_and_1:
- flags.append("HAS_OPARG_AND_1_FLAG")
if flags:
return " | ".join(flags)
else:
diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py
index bee2a185745f4d..303a1c02705a3b 100644
--- a/Tools/cases_generator/lexer.py
+++ b/Tools/cases_generator/lexer.py
@@ -222,7 +222,6 @@ def choice(*opts: str) -> str:
"register",
"replaced",
"pure",
- "split",
"replicate",
"tier1",
"tier2",
diff --git a/Tools/cases_generator/opcode_metadata_generator.py b/Tools/cases_generator/opcode_metadata_generator.py
index 453db6905d6842..9ef49bdc41dc99 100644
--- a/Tools/cases_generator/opcode_metadata_generator.py
+++ b/Tools/cases_generator/opcode_metadata_generator.py
@@ -51,7 +51,6 @@
"EXIT",
"PURE",
"PASSTHROUGH",
- "OPARG_AND_1",
"ERROR_NO_POP",
"NO_SAVE_IP",
]
diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py
index 5cfec4bfecbf07..7ebeff716d2900 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -48,19 +48,13 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
for var in reversed(uop.stack.inputs):
if var.used and var.name not in variables:
variables.add(var.name)
- if var.condition:
- out.emit(f"{type_name(var)}{var.name} = NULL;\n")
- else:
- out.emit(f"{type_name(var)}{var.name};\n")
+ out.emit(f"{type_name(var)}{var.name};\n")
for var in uop.stack.outputs:
if var.peek:
continue
if var.name not in variables:
variables.add(var.name)
- if var.condition:
- out.emit(f"{type_name(var)}{var.name} = NULL;\n")
- else:
- out.emit(f"{type_name(var)}{var.name};\n")
+ out.emit(f"{type_name(var)}{var.name};\n")
def decref_inputs(
diff --git a/Tools/cases_generator/parsing.py b/Tools/cases_generator/parsing.py
index 41b36b6a546360..b50bb627b6c41c 100644
--- a/Tools/cases_generator/parsing.py
+++ b/Tools/cases_generator/parsing.py
@@ -77,12 +77,11 @@ class Block(Node):
class StackEffect(Node):
name: str = field(compare=False) # __eq__ only uses type, cond, size
type: str = "" # Optional `:type`
- cond: str = "" # Optional `if (cond)`
size: str = "" # Optional `[size]`
# Note: size cannot be combined with type or cond
def __repr__(self) -> str:
- items = [self.name, self.type, self.cond, self.size]
+ items = [self.name, self.type, self.size]
while items and items[-1] == "":
del items[-1]
return f"StackEffect({', '.join(repr(item) for item in items)})"
@@ -278,22 +277,15 @@ def stack_effect(self) -> StackEffect | None:
type_text = self.require(lx.IDENTIFIER).text.strip()
if self.expect(lx.TIMES):
type_text += " *"
- cond_text = ""
- if self.expect(lx.IF):
- self.require(lx.LPAREN)
- if not (cond := self.expression()):
- raise self.make_syntax_error("Expected condition")
- self.require(lx.RPAREN)
- cond_text = cond.text.strip()
size_text = ""
if self.expect(lx.LBRACKET):
- if type_text or cond_text:
+ if type_text:
raise self.make_syntax_error("Unexpected [")
if not (size := self.expression()):
raise self.make_syntax_error("Expected expression")
self.require(lx.RBRACKET)
size_text = size.text.strip()
- return StackEffect(tkn.text, type_text, cond_text, size_text)
+ return StackEffect(tkn.text, type_text, size_text)
return None
@contextual
diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py
index 5121837ed8334b..4e9a312ce34146 100644
--- a/Tools/cases_generator/stack.py
+++ b/Tools/cases_generator/stack.py
@@ -24,17 +24,7 @@ def maybe_parenthesize(sym: str) -> str:
def var_size(var: StackItem) -> str:
- if var.condition:
- # Special case simplifications
- if var.condition == "0":
- return "0"
- elif var.condition == "1":
- return var.get_size()
- elif var.condition == "oparg & 1" and not var.size:
- return f"({var.condition})"
- else:
- return f"(({var.condition}) ? {var.get_size()} : 0)"
- elif var.size:
+ if var.size:
return var.size
else:
return "1"
@@ -90,10 +80,6 @@ def size(self) -> str:
def name(self) -> str:
return self.item.name
- @property
- def condition(self) -> str | None:
- return self.item.condition
-
def is_array(self) -> bool:
return self.item.is_array()
@@ -274,16 +260,7 @@ def pop(self, var: StackItem) -> tuple[str, Local]:
self.defined.add(var.name)
cast = f"({var.type})" if (not indirect and var.type) else ""
bits = ".bits" if cast and self.extract_bits else ""
- assign = f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};"
- if var.condition:
- if var.condition == "1":
- assign = f"{assign}\n"
- elif var.condition == "0":
- return "", Local.unused(var)
- else:
- assign = f"if ({var.condition}) {{ {assign} }}\n"
- else:
- assign = f"{assign}\n"
+ assign = f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};\n"
return assign, Local.from_memory(var)
def push(self, var: Local) -> None:
@@ -303,10 +280,6 @@ def _do_emit(
) -> None:
cast = f"({cast_type})" if var.type else ""
bits = ".bits" if cast and extract_bits else ""
- if var.condition == "0":
- return
- if var.condition and var.condition != "1":
- out.emit(f"if ({var.condition}) ")
out.emit(f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n")
def _adjust_stack_pointer(self, out: CWriter, number: str) -> None:
diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py
index 40562da99b20ea..95876c387bd745 100644
--- a/Tools/cases_generator/tier1_generator.py
+++ b/Tools/cases_generator/tier1_generator.py
@@ -37,10 +37,7 @@
def declare_variable(var: StackItem, out: CWriter) -> None:
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- if var.condition:
- out.emit(f"{type}{space}{var.name} = {null};\n")
- else:
- out.emit(f"{type}{space}{var.name};\n")
+ out.emit(f"{type}{space}{var.name};\n")
def declare_variables(inst: Instruction, out: CWriter) -> None:
diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py
index dd16a1a7eb28b5..abd9b8d7924299 100644
--- a/Tools/cases_generator/tier2_generator.py
+++ b/Tools/cases_generator/tier2_generator.py
@@ -39,14 +39,7 @@ def declare_variable(
required.remove(var.name)
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- if var.condition:
- out.emit(f"{type}{space}{var.name} = {null};\n")
- if uop.replicates:
- # Replicas may not use all their conditional variables
- # So avoid a compiler warning with a fake use
- out.emit(f"(void){var.name};\n")
- else:
- out.emit(f"{type}{space}{var.name};\n")
+ out.emit(f"{type}{space}{var.name};\n")
def declare_variables(uop: Uop, out: CWriter) -> None:
@@ -215,9 +208,6 @@ def generate_tier2(
for name, uop in analysis.uops.items():
if uop.properties.tier == 1:
continue
- if uop.properties.oparg_and_1:
- out.emit(f"/* {uop.name} is split on (oparg & 1) */\n\n")
- continue
if uop.is_super():
continue
why_not_viable = uop.why_not_viable()
diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index bc7ccfe33e777d..17478933eb68e5 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -284,7 +284,7 @@ def get_specialization_failure_kinds(self, opcode: str) -> dict[str, int]:
def kind_to_text(kind: int, opcode: str):
if kind <= 8:
return pretty(self._defines[kind][0])
- if opcode == "LOAD_SUPER_ATTR":
+ if opcode == "LOAD_SUPER_ATTR" or opcode == "LOAD_SUPER_METHOD":
opcode = "SUPER"
elif opcode.endswith("ATTR"):
opcode = "ATTR"
1
0
https://github.com/python/cpython/commit/0a6412f9cc9e694e76299cfbd73ec969b7…
commit: 0a6412f9cc9e694e76299cfbd73ec969b7d47af6
branch: main
author: Filipe Laíns 🇵🇸 <lains(a)riseup.net>
committer: FFY00 <filipe.lains(a)gmail.com>
date: 2025-01-20T17:03:44Z
summary:
GH-129064: deprecate sysconfig.expand_makefile_vars (#129082)
files:
A Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst
M Doc/deprecations/pending-removal-in-3.16.rst
M Lib/sysconfig/__init__.py
M Lib/test/test_sysconfig.py
diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst
index 41b30defdba0bc..58f7c01bf39469 100644
--- a/Doc/deprecations/pending-removal-in-3.16.rst
+++ b/Doc/deprecations/pending-removal-in-3.16.rst
@@ -80,6 +80,12 @@ Pending removal in Python 3.16
has been deprecated since Python 3.13.
Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead.
+* :mod:`sysconfig`:
+
+ * The ``~sysconfig.expand_makefile_vars`` function
+ has been deprecated since Python 3.14.
+ Use the ``vars`` argument of :func:`sysconfig.get_paths` instead.
+
* :mod:`tarfile`:
* The undocumented and unused :attr:`!TarFile.tarfile` attribute
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index ec9bb705925cdb..86dd391aa173b5 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -716,6 +716,15 @@ def expand_makefile_vars(s, vars):
variable expansions; if 'vars' is the output of 'parse_makefile()',
you're fine. Returns a variable-expanded version of 's'.
"""
+
+ import warnings
+ warnings.warn(
+ 'sysconfig.expand_makefile_vars is deprecated and will be removed in '
+ 'Python 3.16. Use sysconfig.get_paths(vars=...) instead.',
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
import re
_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index ce504dc21af85f..a5676027eb7438 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -711,5 +711,24 @@ def test_parse_makefile(self):
})
+class DeprecationTests(unittest.TestCase):
+ def deprecated(self, removal_version, deprecation_msg=None, attribute_msg=None):
+ if sys.version_info >= removal_version:
+ return self.assertRaises(AttributeError, msg=attribute_msg)
+ else:
+ return self.assertWarns(DeprecationWarning, msg=deprecation_msg)
+
+ def test_expand_makefile_vars(self):
+ with self.deprecated(
+ removal_version=(3, 16),
+ deprecation_msg=(
+ 'sysconfig.expand_makefile_vars is deprecated and will be removed in '
+ 'Python 3.16. Use sysconfig.get_paths(vars=...) instead.',
+ ),
+ attribute_msg="module 'sysconfig' has no attribute 'expand_makefile_vars'",
+ ):
+ sysconfig.expand_makefile_vars('', {})
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst b/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst
new file mode 100644
index 00000000000000..5939fdc8ef3469
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst
@@ -0,0 +1,2 @@
+Deprecate ``sysconfig.expand_makefile_vars``, in favor of using
+:func:`sysconfig.get_paths` with the ``vars`` argument.
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/38a99568763604ccec5d5027f0658100ad…
commit: 38a99568763604ccec5d5027f0658100ad76876f
branch: main
author: Thomas Grainger <tagrain(a)gmail.com>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-20T22:23:55+05:30
summary:
gh-128308: pass `**kwargs` to asyncio task_factory (#128768)
Co-authored-by: Kumar Aditya <kumaraditya(a)python.org>
files:
A Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst
M Doc/library/asyncio-eventloop.rst
M Lib/asyncio/base_events.py
M Lib/asyncio/events.py
M Lib/test/test_asyncio/test_base_events.py
M Lib/test/test_asyncio/test_eager_task_factory.py
M Lib/test/test_asyncio/test_free_threading.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
index 3bf38a2212c0e0..15ef33e195904d 100644
--- a/Doc/library/asyncio-eventloop.rst
+++ b/Doc/library/asyncio-eventloop.rst
@@ -392,9 +392,9 @@ Creating Futures and Tasks
If *factory* is ``None`` the default task factory will be set.
Otherwise, *factory* must be a *callable* with the signature matching
- ``(loop, coro, context=None)``, where *loop* is a reference to the active
+ ``(loop, coro, **kwargs)``, where *loop* is a reference to the active
event loop, and *coro* is a coroutine object. The callable
- must return a :class:`asyncio.Future`-compatible object.
+ must pass on all *kwargs*, and return a :class:`asyncio.Task`-compatible object.
.. method:: loop.get_task_factory()
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 85018797db33bb..ed852421e44212 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -458,25 +458,18 @@ def create_future(self):
"""Create a Future object attached to the loop."""
return futures.Future(loop=self)
- def create_task(self, coro, *, name=None, context=None):
+ def create_task(self, coro, **kwargs):
"""Schedule a coroutine object.
Return a task object.
"""
self._check_closed()
- if self._task_factory is None:
- task = tasks.Task(coro, loop=self, name=name, context=context)
- if task._source_traceback:
- del task._source_traceback[-1]
- else:
- if context is None:
- # Use legacy API if context is not needed
- task = self._task_factory(self, coro)
- else:
- task = self._task_factory(self, coro, context=context)
-
- task.set_name(name)
+ if self._task_factory is not None:
+ return self._task_factory(self, coro, **kwargs)
+ task = tasks.Task(coro, loop=self, **kwargs)
+ if task._source_traceback:
+ del task._source_traceback[-1]
try:
return task
finally:
@@ -490,9 +483,10 @@ def set_task_factory(self, factory):
If factory is None the default task factory will be set.
If factory is a callable, it should have a signature matching
- '(loop, coro)', where 'loop' will be a reference to the active
- event loop, 'coro' will be a coroutine object. The callable
- must return a Future.
+ '(loop, coro, **kwargs)', where 'loop' will be a reference to the active
+ event loop, 'coro' will be a coroutine object, and **kwargs will be
+ arbitrary keyword arguments that should be passed on to Task.
+ The callable must return a Task.
"""
if factory is not None and not callable(factory):
raise TypeError('task factory must be a callable or None')
diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py
index 2ee9870e80f20b..2e45b4fe6fa2dd 100644
--- a/Lib/asyncio/events.py
+++ b/Lib/asyncio/events.py
@@ -329,7 +329,7 @@ def create_future(self):
# Method scheduling a coroutine object: create a task.
- def create_task(self, coro, *, name=None, context=None):
+ def create_task(self, coro, **kwargs):
raise NotImplementedError
# Methods for interacting with threads.
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py
index 102c9be0ecf031..8cf1f6891faf97 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -833,8 +833,8 @@ async def test():
loop.close()
def test_create_named_task_with_custom_factory(self):
- def task_factory(loop, coro):
- return asyncio.Task(coro, loop=loop)
+ def task_factory(loop, coro, **kwargs):
+ return asyncio.Task(coro, loop=loop, **kwargs)
async def test():
pass
diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py
index dcf9ff716ad399..10450c11b68279 100644
--- a/Lib/test/test_asyncio/test_eager_task_factory.py
+++ b/Lib/test/test_asyncio/test_eager_task_factory.py
@@ -302,6 +302,18 @@ async def run():
self.run_coro(run())
+ def test_name(self):
+ name = None
+ async def coro():
+ nonlocal name
+ name = asyncio.current_task().get_name()
+
+ async def main():
+ task = self.loop.create_task(coro(), name="test name")
+ self.assertEqual(name, "test name")
+ await task
+
+ self.run_coro(coro())
class AsyncTaskCounter:
def __init__(self, loop, *, task_class, eager):
diff --git a/Lib/test/test_asyncio/test_free_threading.py b/Lib/test/test_asyncio/test_free_threading.py
index 8f4bba5f3b97d9..05106a2c2fe3f6 100644
--- a/Lib/test/test_asyncio/test_free_threading.py
+++ b/Lib/test/test_asyncio/test_free_threading.py
@@ -112,8 +112,8 @@ class TestPyFreeThreading(TestFreeThreading, TestCase):
all_tasks = staticmethod(asyncio.tasks._py_all_tasks)
current_task = staticmethod(asyncio.tasks._py_current_task)
- def factory(self, loop, coro, context=None):
- return asyncio.tasks._PyTask(coro, loop=loop, context=context)
+ def factory(self, loop, coro, **kwargs):
+ return asyncio.tasks._PyTask(coro, loop=loop, **kwargs)
@unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
@@ -121,16 +121,16 @@ class TestCFreeThreading(TestFreeThreading, TestCase):
all_tasks = staticmethod(getattr(asyncio.tasks, "_c_all_tasks", None))
current_task = staticmethod(getattr(asyncio.tasks, "_c_current_task", None))
- def factory(self, loop, coro, context=None):
- return asyncio.tasks._CTask(coro, loop=loop, context=context)
+ def factory(self, loop, coro, **kwargs):
+ return asyncio.tasks._CTask(coro, loop=loop, **kwargs)
class TestEagerPyFreeThreading(TestPyFreeThreading):
- def factory(self, loop, coro, context=None):
- return asyncio.tasks._PyTask(coro, loop=loop, context=context, eager_start=True)
+ def factory(self, loop, coro, eager_start=True, **kwargs):
+ return asyncio.tasks._PyTask(coro, loop=loop, **kwargs, eager_start=eager_start)
@unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
class TestEagerCFreeThreading(TestCFreeThreading, TestCase):
- def factory(self, loop, coro, context=None):
- return asyncio.tasks._CTask(coro, loop=loop, context=context, eager_start=True)
+ def factory(self, loop, coro, eager_start=True, **kwargs):
+ return asyncio.tasks._CTask(coro, loop=loop, **kwargs, eager_start=eager_start)
diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py
index 870fa8dbbf2714..7859b33532fa27 100644
--- a/Lib/test/test_asyncio/test_taskgroups.py
+++ b/Lib/test/test_asyncio/test_taskgroups.py
@@ -1040,6 +1040,18 @@ class MyKeyboardInterrupt(KeyboardInterrupt):
self.assertIsNotNone(exc)
self.assertListEqual(gc.get_referrers(exc), no_other_refs())
+ async def test_name(self):
+ name = None
+
+ async def asyncfn():
+ nonlocal name
+ name = asyncio.current_task().get_name()
+
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(asyncfn(), name="example name")
+
+ self.assertEqual(name, "example name")
+
class TestTaskGroup(BaseTestTaskGroup, unittest.IsolatedAsyncioTestCase):
loop_factory = asyncio.EventLoop
diff --git a/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst b/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst
new file mode 100644
index 00000000000000..efa613876a35fd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst
@@ -0,0 +1 @@
+Support the *name* keyword argument for eager tasks in :func:`asyncio.loop.create_task`, :func:`asyncio.create_task` and :func:`asyncio.TaskGroup.create_task`, by passing on all *kwargs* to the task factory set by :func:`asyncio.loop.set_task_factory`.
1
0
https://github.com/python/cpython/commit/6c914bf85cc3a07e22e4618d0b5607c158…
commit: 6c914bf85cc3a07e22e4618d0b5607c158e3cf66
branch: main
author: Diego Russo <diego.russo(a)arm.com>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-20T18:51:09+02:00
summary:
Move to public Linux arm64 hosted runners (#128964)
Co-authored-by: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
files:
M .github/actionlint.yaml
M .github/workflows/build.yml
M .github/workflows/jit.yml
M .pre-commit-config.yaml
diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml
index 3701f7297ffeb2..af125266ae7813 100644
--- a/.github/actionlint.yaml
+++ b/.github/actionlint.yaml
@@ -1,5 +1,5 @@
self-hosted-runner:
- labels: ["ubuntu-24.04-aarch64", "windows-aarch64"]
+ labels: ["windows-aarch64"]
config-variables: null
@@ -7,4 +7,4 @@ paths:
.github/workflows/**/*.yml:
ignore:
- 1st argument of function call is not assignable
- - SC2(015|038|086|091|097|098|129|155)
\ No newline at end of file
+ - SC2(015|038|086|091|097|098|129|155)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8a70cde3d8bc13..6667512369716d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -244,17 +244,13 @@ jobs:
- true
os:
- ubuntu-24.04
- - ubuntu-24.04-aarch64
- is-fork: # only used for the exclusion trick
- - ${{ github.repository_owner != 'python' }}
+ - ubuntu-24.04-arm
exclude:
- - os: ubuntu-24.04-aarch64
- is-fork: true
# Do not test BOLT with free-threading, to conserve resources
- bolt: true
free-threading: true
# BOLT currently crashes during instrumentation on aarch64
- - os: ubuntu-24.04-aarch64
+ - os: ubuntu-24.04-arm
bolt: true
uses: ./.github/workflows/reusable-ubuntu.yml
with:
diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml
index 9b84998a55666d..6f214ad4bc6978 100644
--- a/.github/workflows/jit.yml
+++ b/.github/workflows/jit.yml
@@ -83,8 +83,7 @@ jobs:
runner: ubuntu-24.04
- target: aarch64-unknown-linux-gnu/gcc
architecture: aarch64
- # Forks don't have access to our paid AArch64 runners. These jobs are skipped below:
- runner: ${{ github.repository_owner == 'python' && 'ubuntu-24.04-aarch64' || 'ubuntu-24.04' }}
+ runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
with:
@@ -123,8 +122,7 @@ jobs:
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
- name: Native Linux
- # Forks don't have access to our paid AArch64 runners. Skip those:
- if: runner.os == 'Linux' && (matrix.architecture == 'x86_64' || github.repository_owner == 'python')
+ if: runner.os == 'Linux'
run: |
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 74b56f060342bf..fb44c27704d455 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -56,7 +56,7 @@ repos:
- id: check-readthedocs
- repo: https://github.com/rhysd/actionlint
- rev: v1.7.6
+ rev: v1.7.7
hooks:
- id: actionlint
1
0
https://github.com/python/cpython/commit/6e02096e2f9a18671d608f79dd61c5757d…
commit: 6e02096e2f9a18671d608f79dd61c5757deca4e8
branch: main
author: Peter Bierma <zintensitydev(a)gmail.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-20T17:45:08+01:00
summary:
gh-118915: C API: Document compiler flag macros (GH-129028)
files:
M Doc/c-api/veryhigh.rst
diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst
index 9f02bdb5896563..1ef4181d52eb10 100644
--- a/Doc/c-api/veryhigh.rst
+++ b/Doc/c-api/veryhigh.rst
@@ -348,8 +348,20 @@ the same library that the Python runtime is using.
.. versionchanged:: 3.8
Added *cf_feature_version* field.
+ The available compiler flags are accessible as macros:
-.. c:var:: int CO_FUTURE_DIVISION
+ .. c:namespace:: NULL
- This bit can be set in *flags* to cause division operator ``/`` to be
- interpreted as "true division" according to :pep:`238`.
+ .. c:macro:: PyCF_ALLOW_TOP_LEVEL_AWAIT
+ PyCF_ONLY_AST
+ PyCF_OPTIMIZED_AST
+ PyCF_TYPE_COMMENTS
+
+ See :ref:`compiler flags <ast-compiler-flags>` in documentation of the
+ :py:mod:`!ast` Python module, which exports these constants under
+ the same names.
+
+ .. c:var:: int CO_FUTURE_DIVISION
+
+ This bit can be set in *flags* to cause division operator ``/`` to be
+ interpreted as "true division" according to :pep:`238`.
1
0
[3.12] Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458) (#129081)
by vstinner Jan. 20, 2025
by vstinner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/e6cb31a098a5036519fe270b4d73b2b0e8…
commit: e6cb31a098a5036519fe270b4d73b2b0e8e774ba
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:06:18Z
summary:
[3.12] Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458) (#129081)
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458)
(cherry picked from commit e792f4bc2e712bb6e2143599d2b88dd339de83e6)
Co-authored-by: Peter Bierma <zintensitydev(a)gmail.com>
Co-authored-by: Stan U. <89152624+StanFromIreland(a)users.noreply.github.com>
Co-authored-by: Tomas R. <tomas.roun8(a)gmail.com>
Co-authored-by: Victor Stinner <vstinner(a)python.org>
files:
M Doc/c-api/unicode.rst
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 9b49569ad271b0..f2263610f6fa76 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1032,6 +1032,15 @@ These are the UTF-8 codec APIs:
As :c:func:`PyUnicode_AsUTF8AndSize`, but does not store the size.
+ .. warning::
+
+ This function does not have any special behavior for
+ `null characters <https://en.wikipedia.org/wiki/Null_character>`_ embedded within
+ *unicode*. As a result, strings containing null characters will remain in the returned
+ string, which some C functions might interpret as the end of the string, leading to
+ truncation. If truncation is an issue, it is recommended to use :c:func:`PyUnicode_AsUTF8AndSize`
+ instead.
+
.. versionadded:: 3.3
.. versionchanged:: 3.7
1
0
[3.13] Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458) (#129080)
by vstinner Jan. 20, 2025
by vstinner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/22e9faf08a4b2a90c62c3486d118383913…
commit: 22e9faf08a4b2a90c62c3486d1183839132d4231
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:04:53Z
summary:
[3.13] Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458) (#129080)
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (GH-127458)
(cherry picked from commit e792f4bc2e712bb6e2143599d2b88dd339de83e6)
Co-authored-by: Peter Bierma <zintensitydev(a)gmail.com>
Co-authored-by: Stan U. <89152624+StanFromIreland(a)users.noreply.github.com>
Co-authored-by: Tomas R. <tomas.roun8(a)gmail.com>
Co-authored-by: Victor Stinner <vstinner(a)python.org>
files:
M Doc/c-api/unicode.rst
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 30592980968942..22e134c9f08ea8 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1054,6 +1054,15 @@ These are the UTF-8 codec APIs:
As :c:func:`PyUnicode_AsUTF8AndSize`, but does not store the size.
+ .. warning::
+
+ This function does not have any special behavior for
+ `null characters <https://en.wikipedia.org/wiki/Null_character>`_ embedded within
+ *unicode*. As a result, strings containing null characters will remain in the returned
+ string, which some C functions might interpret as the end of the string, leading to
+ truncation. If truncation is an issue, it is recommended to use :c:func:`PyUnicode_AsUTF8AndSize`
+ instead.
+
.. versionadded:: 3.3
.. versionchanged:: 3.7
1
0
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (#127458)
by vstinner Jan. 20, 2025
by vstinner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/e792f4bc2e712bb6e2143599d2b88dd339…
commit: e792f4bc2e712bb6e2143599d2b88dd339de83e6
branch: main
author: Peter Bierma <zintensitydev(a)gmail.com>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:54:29+01:00
summary:
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (#127458)
Co-authored-by: Stan U. <89152624+StanFromIreland(a)users.noreply.github.com>
Co-authored-by: Tomas R. <tomas.roun8(a)gmail.com>
Co-authored-by: Victor Stinner <vstinner(a)python.org>
files:
M Doc/c-api/unicode.rst
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index f19b86a8dbfb66..94110d48ed7d85 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1054,6 +1054,15 @@ These are the UTF-8 codec APIs:
As :c:func:`PyUnicode_AsUTF8AndSize`, but does not store the size.
+ .. warning::
+
+ This function does not have any special behavior for
+ `null characters <https://en.wikipedia.org/wiki/Null_character>`_ embedded within
+ *unicode*. As a result, strings containing null characters will remain in the returned
+ string, which some C functions might interpret as the end of the string, leading to
+ truncation. If truncation is an issue, it is recommended to use :c:func:`PyUnicode_AsUTF8AndSize`
+ instead.
+
.. versionadded:: 3.3
.. versionchanged:: 3.7
1
0
[3.13] gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073) (#129077)
by AA-Turner Jan. 20, 2025
by AA-Turner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/2f8eefe97ab03ecf92f85918a2b4cb23be…
commit: 2f8eefe97ab03ecf92f85918a2b4cb23be7ee04c
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: AA-Turner <9087854+AA-Turner(a)users.noreply.github.com>
date: 2025-01-20T15:51:52Z
summary:
[3.13] gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073) (#129077)
gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073)
(cherry picked from commit e1fa2fcc7c1bf5291a7f71300b7828b49be9ab72)
Co-authored-by: nikalinov <92603661+nikalinov(a)users.noreply.github.com>
Co-authored-by: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
files:
M Doc/glossary.rst
M Doc/tools/.nitignore
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index d8488ca99246d2..858c2b39ee5e33 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -801,9 +801,11 @@ Glossary
processed.
loader
- An object that loads a module. It must define a method named
- :meth:`load_module`. A loader is typically returned by a
- :term:`finder`. See also:
+ An object that loads a module.
+ It must define the :meth:`!exec_module` and :meth:`!create_module` methods
+ to implement the :class:`~importlib.abc.Loader` interface.
+ A loader is typically returned by a :term:`finder`.
+ See also:
* :ref:`finders-and-loaders`
* :class:`importlib.abc.Loader`
diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore
index 8485766034ca77..9e36087ff10c3e 100644
--- a/Doc/tools/.nitignore
+++ b/Doc/tools/.nitignore
@@ -12,7 +12,6 @@ Doc/c-api/stable.rst
Doc/c-api/type.rst
Doc/c-api/typeobj.rst
Doc/extending/extending.rst
-Doc/glossary.rst
Doc/library/ast.rst
Doc/library/asyncio-extending.rst
Doc/library/asyncio-policy.rst
1
0
https://github.com/python/cpython/commit/f0f7b978be84c432139da1b107825aa2dc…
commit: f0f7b978be84c432139da1b107825aa2dc536854
branch: main
author: Mark Shannon <mark(a)hotpy.org>
committer: markshannon <mark(a)hotpy.org>
date: 2025-01-20T15:49:15Z
summary:
GH-128939: Refactor JIT optimize structs (GH-128940)
files:
M Include/internal/pycore_optimizer.h
M Lib/test/test_capi/test_opt.py
M Lib/test/test_generated_cases.py
M Modules/_testinternalcapi.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c
M Tools/cases_generator/optimizer_generator.py
diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h
index a02b9ab4291bfc..03ce4d4491acd7 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -148,15 +148,6 @@ extern PyTypeObject _PyDefaultOptimizer_Type;
extern PyTypeObject _PyUOpExecutor_Type;
extern PyTypeObject _PyUOpOptimizer_Type;
-/* Symbols */
-/* See explanation in optimizer_symbols.c */
-
-struct _Py_UopsSymbol {
- int flags; // 0 bits: Top; 2 or more bits: Bottom
- PyTypeObject *typ; // Borrowed reference
- PyObject *const_val; // Owned reference (!)
- unsigned int type_version; // currently stores type version
-};
#define UOP_FORMAT_TARGET 0
#define UOP_FORMAT_JUMP 1
@@ -193,16 +184,63 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
+/* Symbols */
+/* See explanation in optimizer_symbols.c */
+
+
+typedef enum _JitSymType {
+ JIT_SYM_UNKNOWN_TAG = 1,
+ JIT_SYM_NULL_TAG = 2,
+ JIT_SYM_NON_NULL_TAG = 3,
+ JIT_SYM_BOTTOM_TAG = 4,
+ JIT_SYM_TYPE_VERSION_TAG = 5,
+ JIT_SYM_KNOWN_CLASS_TAG = 6,
+ JIT_SYM_KNOWN_VALUE_TAG = 7,
+ JIT_SYM_TUPLE_TAG = 8,
+} JitSymType;
+
+typedef struct _jit_opt_known_class {
+ uint8_t tag;
+ uint32_t version;
+ PyTypeObject *type;
+} JitOptKnownClass;
+
+typedef struct _jit_opt_known_version {
+ uint8_t tag;
+ uint32_t version;
+} JitOptKnownVersion;
+
+typedef struct _jit_opt_known_value {
+ uint8_t tag;
+ PyObject *value;
+} JitOptKnownValue;
+
+#define MAX_SYMBOLIC_TUPLE_SIZE 7
+
+typedef struct _jit_opt_tuple {
+ uint8_t tag;
+ uint8_t length;
+ uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
+} JitOptTuple;
+
+typedef union _jit_opt_symbol {
+ uint8_t tag;
+ JitOptKnownClass cls;
+ JitOptKnownValue value;
+ JitOptKnownVersion version;
+ JitOptTuple tuple;
+} JitOptSymbol;
+
+
struct _Py_UOpsAbstractFrame {
// Max stacklen
int stack_len;
int locals_len;
- _Py_UopsSymbol **stack_pointer;
- _Py_UopsSymbol **stack;
- _Py_UopsSymbol **locals;
+ JitOptSymbol **stack_pointer;
+ JitOptSymbol **stack;
+ JitOptSymbol **locals;
};
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
@@ -210,10 +248,10 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
typedef struct ty_arena {
int ty_curr_number;
int ty_max_number;
- _Py_UopsSymbol arena[TY_ARENA_SIZE];
+ JitOptSymbol arena[TY_ARENA_SIZE];
} ty_arena;
-struct _Py_UOpsContext {
+typedef struct _JitOptContext {
char done;
char out_of_space;
bool contradiction;
@@ -225,46 +263,47 @@ struct _Py_UOpsContext {
// Arena for the symbolic types.
ty_arena t_arena;
- _Py_UopsSymbol **n_consumed;
- _Py_UopsSymbol **limit;
- _Py_UopsSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
-};
-
-typedef struct _Py_UOpsContext _Py_UOpsContext;
-
-extern bool _Py_uop_sym_is_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_not_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_const(_Py_UopsSymbol *sym);
-extern PyObject *_Py_uop_sym_get_const(_Py_UopsSymbol *sym);
-extern _Py_UopsSymbol *_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_type(
- _Py_UOpsContext *ctx, PyTypeObject *typ);
-extern _Py_UopsSymbol *_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val);
-extern _Py_UopsSymbol *_Py_uop_sym_new_null(_Py_UOpsContext *ctx);
-extern bool _Py_uop_sym_has_type(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val);
-extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym);
-extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym);
-extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym);
-
-
-extern void _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx);
-extern void _Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx);
+ JitOptSymbol **n_consumed;
+ JitOptSymbol **limit;
+ JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
+} JitOptContext;
+
+extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_const(JitOptSymbol *sym);
+extern PyObject *_Py_uop_sym_get_const(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_type(
+ JitOptContext *ctx, PyTypeObject *typ);
+extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
+extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);
+extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);
+extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);
+extern int _Py_uop_sym_truthiness(JitOptSymbol *sym);
+extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);
+extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);
+extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);
+
+extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);
+extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);
extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len);
-extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);
+extern int _Py_uop_frame_pop(JitOptContext *ctx);
PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index a74b8fdd3923b7..9cfc6c142da6cd 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1465,6 +1465,25 @@ def f(l: complex, r: complex) -> None:
with self.subTest(l=l, r=r, x=x, y=y):
script_helper.assert_python_ok("-c", s)
+ def test_symbols_flow_through_tuples(self):
+ def testfunc(n):
+ for _ in range(n):
+ a = 1
+ b = 2
+ t = a, b
+ x, y = t
+ r = x + y
+ return r
+
+ res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+ self.assertEqual(res, 3)
+ self.assertIsNotNone(ex)
+ uops = get_opnames(ex)
+ self.assertIn("_BINARY_OP_ADD_INT", uops)
+ self.assertNotIn("_GUARD_BOTH_INT", uops)
+ self.assertNotIn("_GUARD_NOS_INT", uops)
+ self.assertNotIn("_GUARD_TOS_INT", uops)
+
def test_decref_escapes(self):
class Convert9999ToNone:
def __del__(self):
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 7a50a29bb0126c..aa92145266961a 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -1842,8 +1842,8 @@ def test_overridden_abstract_args(self):
"""
output = """
case OP: {
- _Py_UopsSymbol *arg1;
- _Py_UopsSymbol *out;
+ JitOptSymbol *arg1;
+ JitOptSymbol *out;
arg1 = stack_pointer[-1];
out = EGGS(arg1);
stack_pointer[-1] = out;
@@ -1851,7 +1851,7 @@ def test_overridden_abstract_args(self):
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
@@ -1876,14 +1876,14 @@ def test_no_overridden_case(self):
"""
output = """
case OP: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = NULL;
stack_pointer[-1] = out;
break;
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index aae09f620b8898..e77df5b57b0504 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -27,7 +27,7 @@
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
-#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
+#include "pycore_optimizer.h" // JitOptSymbol, etc.
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_AsDict()
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 0ef15c630e91db..b9ac30ea04e4e8 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -368,13 +368,17 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
#define sym_truthiness _Py_uop_sym_truthiness
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
static int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr)
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr)
{
if (sym_matches_type(value, &PyBool_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
@@ -460,8 +464,8 @@ optimize_uops(
)
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
uint32_t opcode = UINT16_MAX;
int curr_space = 0;
int max_space = 0;
@@ -486,7 +490,7 @@ optimize_uops(
int oparg = this_instr->oparg;
opcode = this_instr->opcode;
- _Py_UopsSymbol **stack_pointer = ctx->frame->stack_pointer;
+ JitOptSymbol **stack_pointer = ctx->frame->stack_pointer;
#ifdef Py_DEBUG
if (get_lltrace() >= 3) {
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 4d96ada5acf00f..881a607ca2aa29 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -6,8 +6,6 @@
#define op(name, ...) /* NAME is ignored */
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
-typedef struct _Py_UOpsContext _Py_UOpsContext;
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
/* Shortened forms for convenience */
@@ -32,13 +30,17 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
#define sym_is_bottom _Py_uop_sym_is_bottom
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
extern int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr);
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr);
extern void
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit);
@@ -50,17 +52,17 @@ dummy_func(void) {
PyCodeObject *co;
int oparg;
- _Py_UopsSymbol *flag;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *top;
- _Py_UopsSymbol *bottom;
+ JitOptSymbol *flag;
+ JitOptSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
+ JitOptSymbol *iter;
+ JitOptSymbol *top;
+ JitOptSymbol *bottom;
_Py_UOpsAbstractFrame *frame;
_Py_UOpsAbstractFrame *new_frame;
- _Py_UOpsContext *ctx;
+ JitOptContext *ctx;
_PyUOpInstruction *this_instr;
_PyBloomFilter *dependencies;
int modified;
@@ -85,7 +87,7 @@ dummy_func(void) {
op(_LOAD_FAST_AND_CLEAR, (-- value)) {
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
}
@@ -365,7 +367,7 @@ dummy_func(void) {
}
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- )) {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
@@ -949,6 +951,22 @@ dummy_func(void) {
res = sym_new_const(ctx, Py_True);
}
+ op(_BUILD_TUPLE, (values[oparg] -- tup)) {
+ tup = sym_new_tuple(ctx, oparg, values);
+ }
+
+ op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) {
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
+ }
+
+ op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) {
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
+ }
+ }
+
+
// END BYTECODES //
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 1f2b29c947434f..fa0b4ed4345320 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -26,7 +26,7 @@
/* _MONITOR_RESUME is not a viable micro-op for tier 2 */
case _LOAD_FAST_CHECK: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
// We guarantee this will error - just bail and don't optimize it.
if (sym_is_null(value)) {
@@ -39,7 +39,7 @@
}
case _LOAD_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -48,9 +48,9 @@
}
case _LOAD_FAST_AND_CLEAR: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
stack_pointer[0] = value;
stack_pointer += 1;
@@ -61,7 +61,7 @@
/* _LOAD_CONST is not a viable micro-op for tier 2 */
case _LOAD_CONST_MORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val);
@@ -73,7 +73,7 @@
}
case _LOAD_CONST_IMMORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = sym_new_const(ctx, val);
@@ -84,7 +84,7 @@
}
case _LOAD_SMALL_INT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyLong_FromLong(this_instr->oparg);
value = sym_new_const(ctx, val);
stack_pointer[0] = value;
@@ -94,7 +94,7 @@
}
case _STORE_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = stack_pointer[-1];
GETLOCAL(oparg) = value;
stack_pointer += -1;
@@ -109,7 +109,7 @@
}
case _PUSH_NULL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -124,7 +124,7 @@
}
case _END_SEND: {
- _Py_UopsSymbol *val;
+ JitOptSymbol *val;
val = sym_new_not_null(ctx);
stack_pointer[-2] = val;
stack_pointer += -1;
@@ -133,22 +133,22 @@
}
case _UNARY_NEGATIVE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _UNARY_NOT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _TO_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
@@ -158,8 +158,8 @@
}
case _TO_BOOL_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyBool_Type);
@@ -170,8 +170,8 @@
}
case _TO_BOOL_INT: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyLong_Type);
@@ -182,8 +182,8 @@
}
case _TO_BOOL_LIST: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyList_Type);
@@ -194,8 +194,8 @@
}
case _TO_BOOL_NONE: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_const(value, Py_None);
@@ -206,8 +206,8 @@
}
case _TO_BOOL_STR: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
@@ -218,22 +218,22 @@
}
case _REPLACE_WITH_TRUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_const(ctx, Py_True);
stack_pointer[-1] = res;
break;
}
case _UNARY_INVERT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _GUARD_BOTH_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyLong_Type)) {
@@ -263,9 +263,9 @@
}
case _BINARY_OP_MULTIPLY_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -296,9 +296,9 @@
}
case _BINARY_OP_ADD_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -329,9 +329,9 @@
}
case _BINARY_OP_SUBTRACT_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -362,8 +362,8 @@
}
case _GUARD_BOTH_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyFloat_Type)) {
@@ -393,9 +393,9 @@
}
case _BINARY_OP_MULTIPLY_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -427,9 +427,9 @@
}
case _BINARY_OP_ADD_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -461,9 +461,9 @@
}
case _BINARY_OP_SUBTRACT_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -495,8 +495,8 @@
}
case _GUARD_BOTH_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyUnicode_Type) &&
@@ -509,9 +509,9 @@
}
case _BINARY_OP_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -536,11 +536,11 @@
}
case _BINARY_OP_INPLACE_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
@@ -567,7 +567,7 @@
}
case _BINARY_OP_EXTEND: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -576,7 +576,7 @@
}
case _BINARY_SUBSCR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -585,7 +585,7 @@
}
case _BINARY_SLICE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -600,7 +600,7 @@
}
case _BINARY_SUBSCR_LIST_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -609,7 +609,7 @@
}
case _BINARY_SUBSCR_STR_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -618,7 +618,7 @@
}
case _BINARY_SUBSCR_TUPLE_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -627,7 +627,7 @@
}
case _BINARY_SUBSCR_DICT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -636,7 +636,7 @@
}
case _BINARY_SUBSCR_CHECK_FUNC: {
- _Py_UopsSymbol *getitem;
+ JitOptSymbol *getitem;
getitem = sym_new_not_null(ctx);
stack_pointer[0] = getitem;
stack_pointer += 1;
@@ -645,9 +645,9 @@
}
case _BINARY_SUBSCR_INIT_CALL: {
- _Py_UopsSymbol *getitem;
- _Py_UopsSymbol *sub;
- _Py_UopsSymbol *container;
+ JitOptSymbol *getitem;
+ JitOptSymbol *sub;
+ JitOptSymbol *container;
_Py_UOpsAbstractFrame *new_frame;
getitem = stack_pointer[-1];
sub = stack_pointer[-2];
@@ -657,7 +657,7 @@
(void)getitem;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3] = (JitOptSymbol *)new_frame;
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -700,14 +700,14 @@
}
case _CALL_INTRINSIC_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _CALL_INTRINSIC_2: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -716,8 +716,8 @@
}
case _RETURN_VALUE: {
- _Py_UopsSymbol *retval;
- _Py_UopsSymbol *res;
+ JitOptSymbol *retval;
+ JitOptSymbol *res;
retval = stack_pointer[-1];
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
@@ -744,14 +744,14 @@
}
case _GET_AITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_ANEXT: {
- _Py_UopsSymbol *awaitable;
+ JitOptSymbol *awaitable;
awaitable = sym_new_not_null(ctx);
stack_pointer[0] = awaitable;
stack_pointer += 1;
@@ -760,7 +760,7 @@
}
case _GET_AWAITABLE: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
@@ -775,7 +775,7 @@
}
case _YIELD_VALUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_unknown(ctx);
stack_pointer[-1] = res;
break;
@@ -788,7 +788,7 @@
}
case _LOAD_COMMON_CONSTANT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -797,7 +797,7 @@
}
case _LOAD_BUILD_CLASS: {
- _Py_UopsSymbol *bc;
+ JitOptSymbol *bc;
bc = sym_new_not_null(ctx);
stack_pointer[0] = bc;
stack_pointer += 1;
@@ -816,8 +816,8 @@
}
case _UNPACK_SEQUENCE: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
@@ -831,10 +831,12 @@
}
case _UNPACK_SEQUENCE_TWO_TUPLE: {
- _Py_UopsSymbol *val1;
- _Py_UopsSymbol *val0;
- val1 = sym_new_not_null(ctx);
- val0 = sym_new_not_null(ctx);
+ JitOptSymbol *seq;
+ JitOptSymbol *val1;
+ JitOptSymbol *val0;
+ seq = stack_pointer[-1];
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
stack_pointer[-1] = val1;
stack_pointer[0] = val0;
stack_pointer += 1;
@@ -843,10 +845,12 @@
}
case _UNPACK_SEQUENCE_TUPLE: {
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
+ seq = stack_pointer[-1];
values = &stack_pointer[-1];
- for (int _i = oparg; --_i >= 0;) {
- values[_i] = sym_new_not_null(ctx);
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
}
stack_pointer += -1 + oparg;
assert(WITHIN_STACK_BOUNDS());
@@ -854,7 +858,7 @@
}
case _UNPACK_SEQUENCE_LIST: {
- _Py_UopsSymbol **values;
+ JitOptSymbol **values;
values = &stack_pointer[-1];
for (int _i = oparg; --_i >= 0;) {
values[_i] = sym_new_not_null(ctx);
@@ -865,8 +869,8 @@
}
case _UNPACK_EX: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
@@ -903,7 +907,7 @@
}
case _LOAD_LOCALS: {
- _Py_UopsSymbol *locals;
+ JitOptSymbol *locals;
locals = sym_new_not_null(ctx);
stack_pointer[0] = locals;
stack_pointer += 1;
@@ -914,7 +918,7 @@
/* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */
case _LOAD_NAME: {
- _Py_UopsSymbol *v;
+ JitOptSymbol *v;
v = sym_new_not_null(ctx);
stack_pointer[0] = v;
stack_pointer += 1;
@@ -923,8 +927,8 @@
}
case _LOAD_GLOBAL: {
- _Py_UopsSymbol **res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol **res;
+ JitOptSymbol *null = NULL;
res = &stack_pointer[0];
res[0] = sym_new_not_null(ctx);
null = sym_new_null(ctx);
@@ -939,7 +943,7 @@
}
case _GUARD_GLOBALS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *globals_keys;
+ JitOptSymbol *globals_keys;
uint16_t version = (uint16_t)this_instr->operand0;
globals_keys = sym_new_unknown(ctx);
(void)version;
@@ -950,7 +954,7 @@
}
case _GUARD_BUILTINS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *builtins_keys;
+ JitOptSymbol *builtins_keys;
uint16_t version = (uint16_t)this_instr->operand0;
builtins_keys = sym_new_unknown(ctx);
(void)version;
@@ -961,8 +965,8 @@
}
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
@@ -973,8 +977,8 @@
}
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
@@ -997,14 +1001,14 @@
}
case _LOAD_FROM_DICT_OR_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -1023,7 +1027,7 @@
}
case _BUILD_STRING: {
- _Py_UopsSymbol *str;
+ JitOptSymbol *str;
str = sym_new_not_null(ctx);
stack_pointer[-oparg] = str;
stack_pointer += 1 - oparg;
@@ -1032,8 +1036,10 @@
}
case _BUILD_TUPLE: {
- _Py_UopsSymbol *tup;
- tup = sym_new_not_null(ctx);
+ JitOptSymbol **values;
+ JitOptSymbol *tup;
+ values = &stack_pointer[-oparg];
+ tup = sym_new_tuple(ctx, oparg, values);
stack_pointer[-oparg] = tup;
stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
@@ -1041,7 +1047,7 @@
}
case _BUILD_LIST: {
- _Py_UopsSymbol *list;
+ JitOptSymbol *list;
list = sym_new_not_null(ctx);
stack_pointer[-oparg] = list;
stack_pointer += 1 - oparg;
@@ -1062,7 +1068,7 @@
}
case _BUILD_SET: {
- _Py_UopsSymbol *set;
+ JitOptSymbol *set;
set = sym_new_not_null(ctx);
stack_pointer[-oparg] = set;
stack_pointer += 1 - oparg;
@@ -1071,7 +1077,7 @@
}
case _BUILD_MAP: {
- _Py_UopsSymbol *map;
+ JitOptSymbol *map;
map = sym_new_not_null(ctx);
stack_pointer[-oparg*2] = map;
stack_pointer += 1 - oparg*2;
@@ -1104,7 +1110,7 @@
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
case _LOAD_SUPER_ATTR_ATTR: {
- _Py_UopsSymbol *attr_st;
+ JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx);
stack_pointer[-3] = attr_st;
stack_pointer += -2;
@@ -1113,8 +1119,8 @@
}
case _LOAD_SUPER_ATTR_METHOD: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
stack_pointer[-3] = attr;
@@ -1125,9 +1131,9 @@
}
case _LOAD_ATTR: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null = NULL;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
@@ -1140,7 +1146,7 @@
}
case _GUARD_TYPE_VERSION: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
owner = stack_pointer[-1];
uint32_t type_version = (uint32_t)this_instr->operand0;
assert(type_version);
@@ -1174,9 +1180,9 @@
}
case _LOAD_ATTR_INSTANCE_VALUE: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1191,8 +1197,8 @@
}
case _CHECK_ATTR_MODULE_PUSH_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *mod_keys;
+ JitOptSymbol *owner;
+ JitOptSymbol *mod_keys;
owner = stack_pointer[-1];
uint32_t dict_version = (uint32_t)this_instr->operand0;
(void)dict_version;
@@ -1222,9 +1228,9 @@
}
case _LOAD_ATTR_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)this_instr->operand0;
(void)index;
@@ -1263,8 +1269,8 @@
}
case _CHECK_ATTR_WITH_HINT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *dict;
owner = stack_pointer[-1];
dict = sym_new_not_null(ctx);
(void)owner;
@@ -1275,10 +1281,10 @@
}
case _LOAD_ATTR_WITH_HINT: {
- _Py_UopsSymbol *dict;
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
dict = stack_pointer[-1];
owner = stack_pointer[-2];
uint16_t hint = (uint16_t)this_instr->operand0;
@@ -1295,9 +1301,9 @@
}
case _LOAD_ATTR_SLOT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1316,9 +1322,9 @@
}
case _LOAD_ATTR_CLASS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1333,7 +1339,7 @@
}
case _LOAD_ATTR_PROPERTY_FRAME: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
_Py_UOpsAbstractFrame *new_frame;
owner = stack_pointer[-1];
PyObject *fget = (PyObject *)this_instr->operand0;
@@ -1341,7 +1347,7 @@
(void)owner;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-1] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-1] = (JitOptSymbol *)new_frame;
break;
}
@@ -1370,9 +1376,9 @@
}
case _COMPARE_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1394,9 +1400,9 @@
}
case _COMPARE_OP_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1409,9 +1415,9 @@
}
case _COMPARE_OP_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1424,9 +1430,9 @@
}
case _COMPARE_OP_STR: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1439,9 +1445,9 @@
}
case _IS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1454,9 +1460,9 @@
}
case _CONTAINS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1469,7 +1475,7 @@
}
case _CONTAINS_OP_SET: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
@@ -1478,7 +1484,7 @@
}
case _CONTAINS_OP_DICT: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
@@ -1487,8 +1493,8 @@
}
case _CHECK_EG_MATCH: {
- _Py_UopsSymbol *rest;
- _Py_UopsSymbol *match;
+ JitOptSymbol *rest;
+ JitOptSymbol *match;
rest = sym_new_not_null(ctx);
match = sym_new_not_null(ctx);
stack_pointer[-2] = rest;
@@ -1497,14 +1503,14 @@
}
case _CHECK_EXC_MATCH: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _IMPORT_NAME: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -1513,7 +1519,7 @@
}
case _IMPORT_FROM: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1526,14 +1532,14 @@
/* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */
case _IS_NONE: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _GET_LEN: {
- _Py_UopsSymbol *len;
+ JitOptSymbol *len;
len = sym_new_not_null(ctx);
stack_pointer[0] = len;
stack_pointer += 1;
@@ -1542,7 +1548,7 @@
}
case _MATCH_CLASS: {
- _Py_UopsSymbol *attrs;
+ JitOptSymbol *attrs;
attrs = sym_new_not_null(ctx);
stack_pointer[-3] = attrs;
stack_pointer += -2;
@@ -1551,7 +1557,7 @@
}
case _MATCH_MAPPING: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1560,7 +1566,7 @@
}
case _MATCH_SEQUENCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1569,7 +1575,7 @@
}
case _MATCH_KEYS: {
- _Py_UopsSymbol *values_or_none;
+ JitOptSymbol *values_or_none;
values_or_none = sym_new_not_null(ctx);
stack_pointer[0] = values_or_none;
stack_pointer += 1;
@@ -1578,14 +1584,14 @@
}
case _GET_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_YIELD_FROM_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
@@ -1594,7 +1600,7 @@
/* _FOR_ITER is not a viable micro-op for tier 2 */
case _FOR_ITER_TIER_TWO: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1615,7 +1621,7 @@
}
case _ITER_NEXT_LIST: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1634,7 +1640,7 @@
}
case _ITER_NEXT_TUPLE: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1653,8 +1659,8 @@
}
case _ITER_NEXT_RANGE: {
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *next;
+ JitOptSymbol *iter;
+ JitOptSymbol *next;
iter = stack_pointer[-1];
next = sym_new_type(ctx, &PyLong_Type);
(void)iter;
@@ -1671,9 +1677,9 @@
}
case _LOAD_SPECIAL: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
@@ -1686,7 +1692,7 @@
}
case _WITH_EXCEPT_START: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1695,8 +1701,8 @@
}
case _PUSH_EXC_INFO: {
- _Py_UopsSymbol *prev_exc;
- _Py_UopsSymbol *new_exc;
+ JitOptSymbol *prev_exc;
+ JitOptSymbol *new_exc;
prev_exc = sym_new_not_null(ctx);
new_exc = sym_new_not_null(ctx);
stack_pointer[-1] = prev_exc;
@@ -1715,9 +1721,9 @@
}
case _LOAD_ATTR_METHOD_WITH_VALUES: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1731,9 +1737,9 @@
}
case _LOAD_ATTR_METHOD_NO_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1747,14 +1753,14 @@
}
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
}
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
@@ -1765,9 +1771,9 @@
}
case _LOAD_ATTR_METHOD_LAZY_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1781,11 +1787,11 @@
}
case _MAYBE_EXPAND_METHOD: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *maybe_self;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -1805,8 +1811,8 @@
/* _MONITOR_CALL is not a viable micro-op for tier 2 */
case _PY_FRAME_GENERAL: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -1822,15 +1828,15 @@
break;
}
new_frame = frame_new(ctx, co, 0, NULL, 0);
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CHECK_FUNCTION_VERSION: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
uint32_t func_version = (uint32_t)this_instr->operand0;
@@ -1853,8 +1859,8 @@
}
case _EXPAND_METHOD: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-2 - oparg];
self = &stack_pointer[-1 - oparg];
method[0] = sym_new_not_null(ctx);
@@ -1867,7 +1873,7 @@
}
case _CALL_NON_PY_GENERAL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -1876,8 +1882,8 @@
}
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
sym_set_null(null);
@@ -1886,9 +1892,9 @@
}
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *self;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *self;
callable = stack_pointer[-2 - oparg];
(void)callable;
func = sym_new_not_null(ctx);
@@ -1908,8 +1914,8 @@
}
case _CHECK_FUNCTION_EXACT_ARGS: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
assert(sym_matches_type(callable, &PyFunction_Type));
@@ -1933,9 +1939,9 @@
}
case _INIT_CALL_PY_EXACT_ARGS: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
@@ -1963,7 +1969,7 @@
} else {
new_frame = frame_new(ctx, co, 0, NULL, 0);
}
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2008,7 +2014,7 @@
}
case _CALL_TYPE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2017,7 +2023,7 @@
}
case _CALL_STR_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2026,7 +2032,7 @@
}
case _CALL_TUPLE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2035,11 +2041,11 @@
}
case _CHECK_AND_ALLOCATE_OBJECT: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *self;
- _Py_UopsSymbol *init;
+ JitOptSymbol **args;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
+ JitOptSymbol *self;
+ JitOptSymbol *init;
args = &stack_pointer[-oparg];
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -2057,9 +2063,9 @@
}
case _CREATE_INIT_FRAME: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *init;
- _Py_UopsSymbol *self;
+ JitOptSymbol **args;
+ JitOptSymbol *init;
+ JitOptSymbol *self;
_Py_UOpsAbstractFrame *init_frame;
args = &stack_pointer[-oparg];
init = stack_pointer[-1 - oparg];
@@ -2069,7 +2075,7 @@
(void)args;
init_frame = NULL;
ctx->done = true;
- stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)init_frame;
+ stack_pointer[-2 - oparg] = (JitOptSymbol *)init_frame;
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2082,7 +2088,7 @@
}
case _CALL_BUILTIN_CLASS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2091,7 +2097,7 @@
}
case _CALL_BUILTIN_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2100,7 +2106,7 @@
}
case _CALL_BUILTIN_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2109,7 +2115,7 @@
}
case _CALL_BUILTIN_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2118,7 +2124,7 @@
}
case _CALL_LEN: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2127,7 +2133,7 @@
}
case _CALL_ISINSTANCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2142,7 +2148,7 @@
}
case _CALL_METHOD_DESCRIPTOR_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2151,7 +2157,7 @@
}
case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2160,7 +2166,7 @@
}
case _CALL_METHOD_DESCRIPTOR_NOARGS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2169,7 +2175,7 @@
}
case _CALL_METHOD_DESCRIPTOR_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2180,10 +2186,10 @@
/* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */
case _MAYBE_EXPAND_METHOD_KW: {
- _Py_UopsSymbol **func;
- _Py_UopsSymbol **maybe_self;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *kwnames_out;
+ JitOptSymbol **func;
+ JitOptSymbol **maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *kwnames_out;
func = &stack_pointer[-3 - oparg];
maybe_self = &stack_pointer[-2 - oparg];
args = &stack_pointer[-1 - oparg];
@@ -2200,10 +2206,10 @@
/* _DO_CALL_KW is not a viable micro-op for tier 2 */
case _PY_FRAME_KW: {
- _Py_UopsSymbol *kwnames;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *kwnames;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
kwnames = stack_pointer[-1];
args = &stack_pointer[-1 - oparg];
@@ -2215,7 +2221,7 @@
(void)kwnames;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3 - oparg] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3 - oparg] = (JitOptSymbol *)new_frame;
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2230,8 +2236,8 @@
}
case _EXPAND_METHOD_KW: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-3 - oparg];
self = &stack_pointer[-2 - oparg];
method[0] = sym_new_not_null(ctx);
@@ -2244,7 +2250,7 @@
}
case _CALL_KW_NON_PY: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3 - oparg] = res;
stack_pointer += -2 - oparg;
@@ -2255,8 +2261,8 @@
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_CALLARGS_A_TUPLE: {
- _Py_UopsSymbol *tuple;
- _Py_UopsSymbol *kwargs_out = NULL;
+ JitOptSymbol *tuple;
+ JitOptSymbol *kwargs_out = NULL;
tuple = sym_new_not_null(ctx);
kwargs_out = sym_new_not_null(ctx);
stack_pointer[-1 - (oparg & 1)] = tuple;
@@ -2267,14 +2273,14 @@
/* _DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_FUNCTION: {
- _Py_UopsSymbol *func;
+ JitOptSymbol *func;
func = sym_new_not_null(ctx);
stack_pointer[-1] = func;
break;
}
case _SET_FUNCTION_ATTRIBUTE: {
- _Py_UopsSymbol *func_out;
+ JitOptSymbol *func_out;
func_out = sym_new_not_null(ctx);
stack_pointer[-2] = func_out;
stack_pointer += -1;
@@ -2283,7 +2289,7 @@
}
case _RETURN_GENERATOR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
ctx->frame->stack_pointer = stack_pointer;
frame_pop(ctx);
stack_pointer = ctx->frame->stack_pointer;
@@ -2307,7 +2313,7 @@
}
case _BUILD_SLICE: {
- _Py_UopsSymbol *slice;
+ JitOptSymbol *slice;
slice = sym_new_not_null(ctx);
stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
@@ -2316,21 +2322,21 @@
}
case _CONVERT_VALUE: {
- _Py_UopsSymbol *result;
+ JitOptSymbol *result;
result = sym_new_not_null(ctx);
stack_pointer[-1] = result;
break;
}
case _FORMAT_SIMPLE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _FORMAT_WITH_SPEC: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -2339,8 +2345,8 @@
}
case _COPY: {
- _Py_UopsSymbol *bottom;
- _Py_UopsSymbol *top;
+ JitOptSymbol *bottom;
+ JitOptSymbol *top;
bottom = stack_pointer[-1 - (oparg-1)];
assert(oparg > 0);
top = bottom;
@@ -2351,9 +2357,9 @@
}
case _BINARY_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
bool lhs_int = sym_matches_type(left, &PyLong_Type);
@@ -2426,10 +2432,10 @@
}
case _SWAP: {
- _Py_UopsSymbol *top_in;
- _Py_UopsSymbol *bottom_in;
- _Py_UopsSymbol *top_out;
- _Py_UopsSymbol *bottom_out;
+ JitOptSymbol *top_in;
+ JitOptSymbol *bottom_in;
+ JitOptSymbol *top_out;
+ JitOptSymbol *bottom_out;
top_in = stack_pointer[-1];
bottom_in = stack_pointer[-2 - (oparg-2)];
bottom_out = bottom_in;
@@ -2458,7 +2464,7 @@
/* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */
case _GUARD_IS_TRUE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2475,7 +2481,7 @@
}
case _GUARD_IS_FALSE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2492,7 +2498,7 @@
}
case _GUARD_IS_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2517,7 +2523,7 @@
}
case _GUARD_IS_NOT_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2575,7 +2581,7 @@
}
case _LOAD_CONST_INLINE: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
@@ -2585,7 +2591,7 @@
}
case _LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
@@ -2595,15 +2601,15 @@
}
case _POP_TOP_LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_CONST_INLINE_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
@@ -2615,8 +2621,8 @@
}
case _LOAD_CONST_INLINE_BORROW_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
@@ -2632,8 +2638,8 @@
}
case _LOAD_GLOBAL_MODULE: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
@@ -2644,8 +2650,8 @@
}
case _LOAD_GLOBAL_BUILTINS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
@@ -2656,8 +2662,8 @@
}
case _LOAD_ATTR_MODULE: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
attr = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = attr;
diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c
index 40cbf95e3d6d39..dcde8e7ce81577 100644
--- a/Python/optimizer_symbols.c
+++ b/Python/optimizer_symbols.c
@@ -28,11 +28,6 @@
- Bottom: IS_NULL and NOT_NULL flags set, type and const_val NULL.
*/
-// Flags for below.
-#define IS_NULL 1 << 0
-#define NOT_NULL 1 << 1
-#define NO_SPACE 1 << 2
-
#ifdef Py_DEBUG
static inline int get_lltrace(void) {
char *uop_debug = Py_GETENV("PYTHON_OPT_DEBUG");
@@ -48,187 +43,254 @@ static inline int get_lltrace(void) {
#define DPRINTF(level, ...)
#endif
-static _Py_UopsSymbol NO_SPACE_SYMBOL = {
- .flags = IS_NULL | NOT_NULL | NO_SPACE,
- .typ = NULL,
- .const_val = NULL,
- .type_version = 0,
+
+static JitOptSymbol NO_SPACE_SYMBOL = {
+ .tag = JIT_SYM_BOTTOM_TAG
};
-_Py_UopsSymbol *
-out_of_space(_Py_UOpsContext *ctx)
+JitOptSymbol *
+out_of_space(JitOptContext *ctx)
{
ctx->done = true;
ctx->out_of_space = true;
return &NO_SPACE_SYMBOL;
}
-static _Py_UopsSymbol *
-sym_new(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+sym_new(JitOptContext *ctx)
{
- _Py_UopsSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
+ JitOptSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
if (ctx->t_arena.ty_curr_number >= ctx->t_arena.ty_max_number) {
OPT_STAT_INC(optimizer_failure_reason_no_memory);
DPRINTF(1, "out of space for symbolic expression type\n");
return NULL;
}
ctx->t_arena.ty_curr_number++;
- self->flags = 0;
- self->typ = NULL;
- self->const_val = NULL;
- self->type_version = 0;
-
+ self->tag = JIT_SYM_UNKNOWN_TAG;
return self;
}
static inline void
-sym_set_flag(_Py_UopsSymbol *sym, int flag)
-{
- sym->flags |= flag;
-}
-
-static inline void
-sym_set_bottom(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+sym_set_bottom(JitOptContext *ctx, JitOptSymbol *sym)
{
- sym_set_flag(sym, IS_NULL | NOT_NULL);
- sym->typ = NULL;
- Py_CLEAR(sym->const_val);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
ctx->done = true;
ctx->contradiction = true;
}
bool
-_Py_uop_sym_is_bottom(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_bottom(JitOptSymbol *sym)
{
- if ((sym->flags & IS_NULL) && (sym->flags & NOT_NULL)) {
- assert(sym->flags == (IS_NULL | NOT_NULL));
- assert(sym->typ == NULL);
- assert(sym->const_val == NULL);
- return true;
- }
- return false;
+ return sym->tag == JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_not_null(_Py_UopsSymbol *sym)
-{
- return sym->flags == NOT_NULL;
+_Py_uop_sym_is_not_null(JitOptSymbol *sym) {
+ return sym->tag == JIT_SYM_NON_NULL_TAG || sym->tag > JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_null(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_const(JitOptSymbol *sym)
{
- return sym->flags == IS_NULL;
+ return sym->tag == JIT_SYM_KNOWN_VALUE_TAG;
}
bool
-_Py_uop_sym_is_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_null(JitOptSymbol *sym)
{
- return sym->const_val != NULL;
+ return sym->tag == JIT_SYM_NULL_TAG;
}
+
PyObject *
-_Py_uop_sym_get_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_const(JitOptSymbol *sym)
{
- return sym->const_val;
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return sym->value.value;
+ }
+ return NULL;
}
void
-_Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ)
{
- assert(typ != NULL && PyType_Check(typ));
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- return;
- }
- if (sym->typ != NULL) {
- if (sym->typ != typ) {
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
return;
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != typ) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == typ->tp_version_tag) {
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.type = typ;
+ sym->cls.version = typ->tp_version_tag;
+ }
+ else {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (Py_TYPE(sym->value.value) != typ) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ if (typ != &PyTuple_Type) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.version = 0;
+ sym->cls.type = typ;
+ return;
}
}
bool
-_Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version)
{
- // if the type version was already set, then it must be different and we should set it to bottom
- if (sym->type_version) {
- sym_set_bottom(ctx, sym);
- return false;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type->tp_version_tag != version) {
+ sym_set_bottom(ctx, sym);
+ return false;
+ }
+ else {
+ sym->cls.version = version;
+ return true;
+ }
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == version) {
+ return true;
+ }
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_BOTTOM_TAG:
+ return false;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_TYPE_VERSION_TAG;
+ sym->version.version = version;
+ return true;
}
- sym->type_version = version;
- return true;
+ Py_UNREACHABLE();
+}
+
+static void make_const(JitOptSymbol *sym, PyObject *val)
+{
+ sym->tag = JIT_SYM_KNOWN_VALUE_TAG;
+ sym->value.value = Py_NewRef(val);
}
void
-_Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val)
+_Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val)
{
- assert(const_val != NULL);
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- }
- PyTypeObject *typ = Py_TYPE(const_val);
- if (sym->typ != NULL && sym->typ != typ) {
- sym_set_bottom(ctx, sym);
- }
- if (sym->const_val != NULL) {
- if (sym->const_val != const_val) {
- // TODO: What if they're equal?
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
- sym->const_val = Py_NewRef(const_val);
+ return;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != Py_TYPE(const_val)) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (sym->value.value != const_val) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version != Py_TYPE(const_val)->tp_version_tag) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ make_const(sym, const_val);
+ return;
}
}
void
-_Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_not_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NULL_TAG;
+ }
+ else if (sym->tag > JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, IS_NULL);
}
void
-_Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NON_NULL_TAG;
+ }
+ else if (sym->tag == JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, NOT_NULL);
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_unknown(JitOptContext *ctx)
{
- return sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_not_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *res = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
- sym_set_flag(res, NOT_NULL);
+ res->tag = JIT_SYM_NON_NULL_TAG;
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_type(_Py_UOpsContext *ctx, PyTypeObject *typ)
+JitOptSymbol *
+_Py_uop_sym_new_type(JitOptContext *ctx, PyTypeObject *typ)
{
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
@@ -237,11 +299,11 @@ _Py_uop_sym_new_type(_Py_UOpsContext *ctx, PyTypeObject *typ)
}
// Adds a new reference to const_val, owned by the symbol.
-_Py_UopsSymbol *
-_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val)
+JitOptSymbol *
+_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val)
{
assert(const_val != NULL);
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
@@ -249,10 +311,10 @@ _Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val)
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *null_sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *null_sym = sym_new(ctx);
if (null_sym == NULL) {
return out_of_space(ctx);
}
@@ -261,64 +323,105 @@ _Py_uop_sym_new_null(_Py_UOpsContext *ctx)
}
PyTypeObject *
-_Py_uop_sym_get_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return NULL;
- }
- return sym->typ;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return NULL;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.type;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value);
+ case JIT_SYM_TUPLE_TAG:
+ return &PyTuple_Type;
+ }
+ Py_UNREACHABLE();
}
unsigned int
-_Py_uop_sym_get_type_version(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type_version(JitOptSymbol *sym)
{
- return sym->type_version;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return 0;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ return sym->version.version;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.version;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value)->tp_version_tag;
+ case JIT_SYM_TUPLE_TAG:
+ return PyTuple_Type.tp_version_tag;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_has_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_has_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return false;
- }
- return sym->typ != NULL;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ case JIT_SYM_TUPLE_TAG:
+ return true;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ)
{
assert(typ != NULL && PyType_Check(typ));
return _Py_uop_sym_get_type(sym) == typ;
}
bool
-_Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version)
{
return _Py_uop_sym_get_type_version(sym) == version;
}
-
int
-_Py_uop_sym_truthiness(_Py_UopsSymbol *sym)
-{
- /* There are some non-constant values for
- * which `bool(val)` always evaluates to
- * True or False, such as tuples with known
- * length, but unknown contents, or bound-methods.
- * This function will need updating
- * should we support those values.
- */
- if (_Py_uop_sym_is_bottom(sym)) {
- return -1;
- }
- if (!_Py_uop_sym_is_const(sym)) {
- return -1;
- }
- PyObject *value = _Py_uop_sym_get_const(sym);
+_Py_uop_sym_truthiness(JitOptSymbol *sym)
+{
+ switch(sym->tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return -1;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ /* TODO :
+ * Instances of some classes are always
+ * true. We should return 1 in those cases */
+ return -1;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ break;
+ case JIT_SYM_TUPLE_TAG:
+ return sym->tuple.length != 0;
+ }
+ PyObject *value = sym->value.value;
+ /* Only handle a few known safe types */
if (value == Py_None) {
return 0;
}
- /* Only handle a few known safe types */
PyTypeObject *tp = Py_TYPE(value);
if (tp == &PyLong_Type) {
return !_PyLong_IsZero((PyLongObject *)value);
@@ -332,13 +435,84 @@ _Py_uop_sym_truthiness(_Py_UopsSymbol *sym)
return -1;
}
+static JitOptSymbol *
+allocation_base(JitOptContext *ctx)
+{
+ return ctx->t_arena.arena;
+}
+
+JitOptSymbol *
+_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args)
+{
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ if (size > MAX_SYMBOLIC_TUPLE_SIZE) {
+ res->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ res->cls.type = &PyTuple_Type;
+ }
+ else {
+ res->tag = JIT_SYM_TUPLE_TAG;
+ res->tuple.length = size;
+ for (int i = 0; i < size; i++) {
+ res->tuple.items[i] = (uint16_t)(args[i] - allocation_base(ctx));
+ }
+ }
+ return res;
+}
+
+JitOptSymbol *
+_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item)
+{
+ assert(item >= 0);
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple) && item < PyTuple_GET_SIZE(tuple)) {
+ return _Py_uop_sym_new_const(ctx, PyTuple_GET_ITEM(tuple, item));
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG && item < sym->tuple.length) {
+ return allocation_base(ctx) + sym->tuple.items[item];
+ }
+ return _Py_uop_sym_new_unknown(ctx);
+}
+
+int
+_Py_uop_sym_tuple_length(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple)) {
+ return PyTuple_GET_SIZE(tuple);
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG) {
+ return sym->tuple.length;
+ }
+ return -1;
+}
+
+// Return true if known to be immortal.
+bool
+_Py_uop_sym_is_immortal(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return _Py_IsImmortal(sym->value.value);
+ }
+ if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) {
+ return sym->cls.type == &PyBool_Type;
+ }
+ return false;
+}
+
// 0 on success, -1 on error.
_Py_UOpsAbstractFrame *
_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len)
{
assert(ctx->curr_frame_depth < MAX_ABSTRACT_FRAME_DEPTH);
@@ -363,14 +537,14 @@ _Py_uop_frame_new(
}
for (int i = arg_len; i < co->co_nlocalsplus; i++) {
- _Py_UopsSymbol *local = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *local = _Py_uop_sym_new_unknown(ctx);
frame->locals[i] = local;
}
// Initialize the stack as well
for (int i = 0; i < curr_stackentries; i++) {
- _Py_UopsSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
frame->stack[i] = stackvar;
}
@@ -378,7 +552,7 @@ _Py_uop_frame_new(
}
void
-_Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_fini(JitOptContext *ctx)
{
if (ctx == NULL) {
return;
@@ -386,13 +560,17 @@ _Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx)
ctx->curr_frame_depth = 0;
int tys = ctx->t_arena.ty_curr_number;
for (int i = 0; i < tys; i++) {
- Py_CLEAR(ctx->t_arena.arena[i].const_val);
+ JitOptSymbol *sym = &ctx->t_arena.arena[i];
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ Py_CLEAR(sym->value.value);
+ }
}
}
void
-_Py_uop_abstractcontext_init(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_init(JitOptContext *ctx)
{
+ static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t));
ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE;
ctx->n_consumed = ctx->locals_and_stack;
#ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter.
@@ -410,7 +588,7 @@ _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx)
}
int
-_Py_uop_frame_pop(_Py_UOpsContext *ctx)
+_Py_uop_frame_pop(JitOptContext *ctx)
{
_Py_UOpsAbstractFrame *frame = ctx->frame;
ctx->n_consumed = frame->locals;
@@ -431,26 +609,25 @@ do { \
} \
} while (0)
-static _Py_UopsSymbol *
-make_bottom(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+make_bottom(JitOptContext *ctx)
{
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
- _Py_uop_sym_set_null(ctx, sym);
- _Py_uop_sym_set_non_null(ctx, sym);
+ JitOptSymbol *sym = sym_new(ctx);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
return sym;
}
PyObject *
_Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
_Py_uop_abstractcontext_init(ctx);
PyObject *val_42 = NULL;
PyObject *val_43 = NULL;
// Use a single 'sym' variable so copy-pasting tests is easier.
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *sym = _Py_uop_sym_new_unknown(ctx);
if (sym == NULL) {
goto fail;
}
@@ -510,6 +687,7 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
TEST_PREDICATE(_Py_uop_sym_is_const(sym), "42 is not a constant");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) != NULL, "42 as constant is NULL");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "42 as constant isn't 42");
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "42 is not immortal");
_Py_uop_sym_set_type(ctx, sym, &PyLong_Type); // Should be a no-op
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(42 and 42) isn't an int");
@@ -518,6 +696,9 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
_Py_uop_sym_set_type(ctx, sym, &PyFloat_Type); // Should make it bottom
TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(42 and float) isn't bottom");
+ sym = _Py_uop_sym_new_type(ctx, &PyBool_Type);
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "a bool is not immortal");
+
sym = _Py_uop_sym_new_type(ctx, &PyLong_Type);
if (sym == NULL) {
goto fail;
@@ -534,15 +715,37 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
sym = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0));
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(0) is not False");
+ JitOptSymbol *i1 = _Py_uop_sym_new_type(ctx, &PyFloat_Type);
+ JitOptSymbol *i2 = _Py_uop_sym_new_const(ctx, val_43);
+ JitOptSymbol *array[2] = { i1, i2 };
+ sym = _Py_uop_sym_new_tuple(ctx, 2, array);
+ TEST_PREDICATE(
+ _Py_uop_sym_matches_type(_Py_uop_sym_tuple_getitem(ctx, sym, 0), &PyFloat_Type),
+ "tuple item does not match value used to create tuple"
+ );
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+ PyObject *pair[2] = { val_42, val_43 };
+ PyObject *tuple = _PyTuple_FromArray(pair, 2);
+ sym = _Py_uop_sym_new_const(ctx, tuple);
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+
_Py_uop_abstractcontext_fini(ctx);
Py_DECREF(val_42);
Py_DECREF(val_43);
+ Py_DECREF(tuple);
Py_RETURN_NONE;
fail:
_Py_uop_abstractcontext_fini(ctx);
Py_XDECREF(val_42);
Py_XDECREF(val_43);
+ Py_DECREF(tuple);
return NULL;
}
diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py
index 2928440fecca0c..5cfec4bfecbf07 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -36,10 +36,10 @@ def validate_uop(override: Uop, uop: Uop) -> None:
def type_name(var: StackItem) -> str:
if var.is_array():
- return f"_Py_UopsSymbol **"
+ return f"JitOptSymbol **"
if var.type:
return var.type
- return f"_Py_UopsSymbol *"
+ return f"JitOptSymbol *"
def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
@@ -151,11 +151,11 @@ def write_uop(
var.defined = False
storage = emitter.emit_tokens(override, storage, None)
out.start_line()
- storage.flush(out, cast_type="_Py_UopsSymbol *")
+ storage.flush(out, cast_type="JitOptSymbol *")
else:
emit_default(out, uop, stack)
out.start_line()
- stack.flush(out, cast_type="_Py_UopsSymbol *")
+ stack.flush(out, cast_type="JitOptSymbol *")
except StackError as ex:
raise analysis_error(ex.args[0], prototype.body[0]) # from None
1
0
gh-129044: Update glossary entry for 'loader' to reflect current import system (#129073)
by AA-Turner Jan. 20, 2025
by AA-Turner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/e1fa2fcc7c1bf5291a7f71300b7828b49b…
commit: e1fa2fcc7c1bf5291a7f71300b7828b49be9ab72
branch: main
author: nikalinov <92603661+nikalinov(a)users.noreply.github.com>
committer: AA-Turner <9087854+AA-Turner(a)users.noreply.github.com>
date: 2025-01-20T15:46:09Z
summary:
gh-129044: Update glossary entry for 'loader' to reflect current import system (#129073)
Co-authored-by: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
files:
M Doc/glossary.rst
M Doc/tools/.nitignore
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 33e77c9de211eb..e3a14601398e89 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -811,9 +811,11 @@ Glossary
processed.
loader
- An object that loads a module. It must define a method named
- :meth:`load_module`. A loader is typically returned by a
- :term:`finder`. See also:
+ An object that loads a module.
+ It must define the :meth:`!exec_module` and :meth:`!create_module` methods
+ to implement the :class:`~importlib.abc.Loader` interface.
+ A loader is typically returned by a :term:`finder`.
+ See also:
* :ref:`finders-and-loaders`
* :class:`importlib.abc.Loader`
diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore
index 6940c95ab2c9a1..ad24fe82f754fc 100644
--- a/Doc/tools/.nitignore
+++ b/Doc/tools/.nitignore
@@ -12,7 +12,6 @@ Doc/c-api/stable.rst
Doc/c-api/type.rst
Doc/c-api/typeobj.rst
Doc/extending/extending.rst
-Doc/glossary.rst
Doc/library/ast.rst
Doc/library/asyncio-extending.rst
Doc/library/asyncio-subprocess.rst
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/8ceb6cb117c8eda8c6913547f3a7de032e…
commit: 8ceb6cb117c8eda8c6913547f3a7de032ed25880
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:31:33+01:00
summary:
gh-129033: Remove _PyInterpreterState_SetConfig() function (#129048)
Remove _PyInterpreterState_GetConfigCopy() and
_PyInterpreterState_SetConfig() private functions. PEP 741 "Python
Configuration C API" added a better public C API: PyConfig_Get() and
PyConfig_Set().
files:
A Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
D Lib/test/_test_embed_set_config.py
M Include/internal/pycore_interp.h
M Lib/test/support/__init__.py
M Lib/test/test_capi/test_misc.py
M Lib/test/test_embed.py
M Lib/test/test_regrtest.py
M Modules/_testinternalcapi.c
M Programs/_testembed.c
M Python/pylifecycle.c
M Python/pystate.c
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index a3c14dceffd7a0..f745b09796753b 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -341,43 +341,6 @@ extern void _PyInterpreterState_SetWhence(
extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp);
-// Get a copy of the current interpreter configuration.
-//
-// Return 0 on success. Raise an exception and return -1 on error.
-//
-// The caller must initialize 'config', using PyConfig_InitPythonConfig()
-// for example.
-//
-// Python must be preinitialized to call this method.
-// The caller must hold the GIL.
-//
-// Once done with the configuration, PyConfig_Clear() must be called to clear
-// it.
-//
-// Export for '_testinternalcapi' shared extension.
-PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy(
- struct PyConfig *config);
-
-// Set the configuration of the current interpreter.
-//
-// This function should be called during or just after the Python
-// initialization.
-//
-// Update the sys module with the new configuration. If the sys module was
-// modified directly after the Python initialization, these changes are lost.
-//
-// Some configuration like faulthandler or warnoptions can be updated in the
-// configuration, but don't reconfigure Python (don't enable/disable
-// faulthandler and don't reconfigure warnings filters).
-//
-// Return 0 on success. Raise an exception and return -1 on error.
-//
-// The configuration should come from _PyInterpreterState_GetConfigCopy().
-//
-// Export for '_testinternalcapi' shared extension.
-PyAPI_FUNC(int) _PyInterpreterState_SetConfig(
- const struct PyConfig *config);
-
/*
Runtime Feature Flags
diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py
deleted file mode 100644
index 7edb35da463aa0..00000000000000
--- a/Lib/test/_test_embed_set_config.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# bpo-42260: Test _PyInterpreterState_GetConfigCopy()
-# and _PyInterpreterState_SetConfig().
-#
-# Test run in a subprocess since set_config(get_config())
-# does reset sys attributes to their state of the Python startup
-# (before the site module is run).
-
-import _testinternalcapi
-import sys
-import unittest
-from test import support
-from test.support import MS_WINDOWS
-
-
-MAX_HASH_SEED = 4294967295
-
-
-BOOL_OPTIONS = [
- 'isolated',
- 'use_environment',
- 'dev_mode',
- 'install_signal_handlers',
- 'use_hash_seed',
- 'faulthandler',
- 'import_time',
- 'code_debug_ranges',
- 'show_ref_count',
- 'dump_refs',
- 'malloc_stats',
- 'parse_argv',
- 'site_import',
- 'warn_default_encoding',
- 'inspect',
- 'interactive',
- 'parser_debug',
- 'write_bytecode',
- 'quiet',
- 'user_site_directory',
- 'configure_c_stdio',
- 'buffered_stdio',
- 'use_frozen_modules',
- 'safe_path',
- 'pathconfig_warnings',
- 'module_search_paths_set',
- 'skip_source_first_line',
- '_install_importlib',
- '_init_main',
- '_is_python_build',
-]
-if MS_WINDOWS:
- BOOL_OPTIONS.append('legacy_windows_stdio')
-
-
-class SetConfigTests(unittest.TestCase):
- def setUp(self):
- self.old_config = _testinternalcapi.get_config()
- self.sys_copy = dict(sys.__dict__)
-
- def tearDown(self):
- _testinternalcapi.reset_path_config()
- _testinternalcapi.set_config(self.old_config)
- sys.__dict__.clear()
- sys.__dict__.update(self.sys_copy)
-
- def set_config(self, **kwargs):
- _testinternalcapi.set_config(self.old_config | kwargs)
-
- def check(self, **kwargs):
- self.set_config(**kwargs)
- for key, value in kwargs.items():
- self.assertEqual(getattr(sys, key), value,
- (key, value))
-
- def test_set_invalid(self):
- invalid_uint = -1
- NULL = None
- invalid_wstr = NULL
- # PyWideStringList strings must be non-NULL
- invalid_wstrlist = ["abc", NULL, "def"]
-
- type_tests = []
- value_tests = [
- # enum
- ('_config_init', 0),
- ('_config_init', 4),
- # unsigned long
- ("hash_seed", -1),
- ("hash_seed", MAX_HASH_SEED + 1),
- ]
-
- # int (unsigned)
- int_options = [
- '_config_init',
- 'bytes_warning',
- 'optimization_level',
- 'tracemalloc',
- 'verbose',
- ]
- int_options.extend(BOOL_OPTIONS)
- for key in int_options:
- value_tests.append((key, invalid_uint))
- type_tests.append((key, "abc"))
- type_tests.append((key, 2.0))
-
- # wchar_t*
- for key in (
- 'filesystem_encoding',
- 'filesystem_errors',
- 'stdio_encoding',
- 'stdio_errors',
- 'check_hash_pycs_mode',
- 'program_name',
- 'platlibdir',
- # optional wstr:
- # 'pythonpath_env'
- # 'home'
- # 'pycache_prefix'
- # 'run_command'
- # 'run_module'
- # 'run_filename'
- # 'executable'
- # 'prefix'
- # 'exec_prefix'
- # 'base_executable'
- # 'base_prefix'
- # 'base_exec_prefix'
- ):
- value_tests.append((key, invalid_wstr))
- type_tests.append((key, b'bytes'))
- type_tests.append((key, 123))
-
- # PyWideStringList
- for key in (
- 'orig_argv',
- 'argv',
- 'xoptions',
- 'warnoptions',
- 'module_search_paths',
- ):
- if key != 'xoptions':
- value_tests.append((key, invalid_wstrlist))
- type_tests.append((key, 123))
- type_tests.append((key, "abc"))
- type_tests.append((key, [123]))
- type_tests.append((key, [b"bytes"]))
-
-
- if MS_WINDOWS:
- value_tests.append(('legacy_windows_stdio', invalid_uint))
-
- for exc_type, tests in (
- (ValueError, value_tests),
- (TypeError, type_tests),
- ):
- for key, value in tests:
- config = self.old_config | {key: value}
- with self.subTest(key=key, value=value, exc_type=exc_type):
- with self.assertRaises(exc_type):
- _testinternalcapi.set_config(config)
-
- def test_flags(self):
- bool_options = set(BOOL_OPTIONS)
- for sys_attr, key, value in (
- ("debug", "parser_debug", 2),
- ("inspect", "inspect", 3),
- ("interactive", "interactive", 4),
- ("optimize", "optimization_level", 5),
- ("verbose", "verbose", 6),
- ("bytes_warning", "bytes_warning", 7),
- ("quiet", "quiet", 8),
- ("isolated", "isolated", 9),
- ):
- with self.subTest(sys=sys_attr, key=key, value=value):
- self.set_config(**{key: value, 'parse_argv': 0})
- if key in bool_options:
- self.assertEqual(getattr(sys.flags, sys_attr), int(bool(value)))
- else:
- self.assertEqual(getattr(sys.flags, sys_attr), value)
-
- self.set_config(write_bytecode=0)
- self.assertEqual(sys.flags.dont_write_bytecode, True)
- self.assertEqual(sys.dont_write_bytecode, True)
-
- self.set_config(write_bytecode=1)
- self.assertEqual(sys.flags.dont_write_bytecode, False)
- self.assertEqual(sys.dont_write_bytecode, False)
-
- self.set_config(user_site_directory=0, isolated=0)
- self.assertEqual(sys.flags.no_user_site, 1)
- self.set_config(user_site_directory=1, isolated=0)
- self.assertEqual(sys.flags.no_user_site, 0)
-
- self.set_config(site_import=0)
- self.assertEqual(sys.flags.no_site, 1)
- self.set_config(site_import=1)
- self.assertEqual(sys.flags.no_site, 0)
-
- self.set_config(dev_mode=0)
- self.assertEqual(sys.flags.dev_mode, False)
- self.set_config(dev_mode=1)
- self.assertEqual(sys.flags.dev_mode, True)
-
- self.set_config(use_environment=0, isolated=0)
- self.assertEqual(sys.flags.ignore_environment, 1)
- self.set_config(use_environment=1, isolated=0)
- self.assertEqual(sys.flags.ignore_environment, 0)
-
- self.set_config(use_hash_seed=1, hash_seed=0)
- self.assertEqual(sys.flags.hash_randomization, 0)
- self.set_config(use_hash_seed=0, hash_seed=0)
- self.assertEqual(sys.flags.hash_randomization, 1)
- self.set_config(use_hash_seed=1, hash_seed=123)
- self.assertEqual(sys.flags.hash_randomization, 1)
-
- if support.Py_GIL_DISABLED:
- self.set_config(enable_gil=-1)
- self.assertEqual(sys.flags.gil, None)
- self.set_config(enable_gil=0)
- self.assertEqual(sys.flags.gil, 0)
- self.set_config(enable_gil=1)
- self.assertEqual(sys.flags.gil, 1)
- else:
- # Builds without Py_GIL_DISABLED don't have
- # PyConfig.enable_gil. sys.flags.gil is always defined to 1, for
- # consistency.
- self.assertEqual(sys.flags.gil, 1)
-
- def test_options(self):
- self.check(warnoptions=[])
- self.check(warnoptions=["default", "ignore"])
-
- self.set_config(xoptions={})
- self.assertEqual(sys._xoptions, {})
- self.set_config(xoptions={"dev": True, "tracemalloc": "5"})
- self.assertEqual(sys._xoptions, {"dev": True, "tracemalloc": "5"})
-
- def test_pathconfig(self):
- self.check(
- executable='executable',
- prefix="prefix",
- base_prefix="base_prefix",
- exec_prefix="exec_prefix",
- base_exec_prefix="base_exec_prefix",
- platlibdir="platlibdir")
-
- self.set_config(base_executable="base_executable")
- self.assertEqual(sys._base_executable, "base_executable")
-
- # When base_xxx is NULL, value is copied from xxxx
- self.set_config(
- executable='executable',
- prefix="prefix",
- exec_prefix="exec_prefix",
- base_executable=None,
- base_prefix=None,
- base_exec_prefix=None)
- self.assertEqual(sys._base_executable, "executable")
- self.assertEqual(sys.base_prefix, "prefix")
- self.assertEqual(sys.base_exec_prefix, "exec_prefix")
-
- def test_path(self):
- self.set_config(module_search_paths_set=1,
- module_search_paths=['a', 'b', 'c'])
- self.assertEqual(sys.path, ['a', 'b', 'c'])
-
- # sys.path is reset if module_search_paths_set=0
- self.set_config(module_search_paths_set=0,
- module_search_paths=['new_path'])
- self.assertNotEqual(sys.path, ['a', 'b', 'c'])
- self.assertNotEqual(sys.path, ['new_path'])
-
- def test_argv(self):
- self.set_config(parse_argv=0,
- argv=['python_program', 'args'],
- orig_argv=['orig', 'orig_args'])
- self.assertEqual(sys.argv, ['python_program', 'args'])
- self.assertEqual(sys.orig_argv, ['orig', 'orig_args'])
-
- self.set_config(parse_argv=0,
- argv=[],
- orig_argv=[])
- self.assertEqual(sys.argv, [''])
- self.assertEqual(sys.orig_argv, [])
-
- def test_pycache_prefix(self):
- self.check(pycache_prefix=None)
- self.check(pycache_prefix="pycache_prefix")
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index e05e91babc2499..084b2411e799f4 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -505,10 +505,10 @@ def requires_lzma(reason='requires lzma'):
def has_no_debug_ranges():
try:
- import _testinternalcapi
+ import _testcapi
except ImportError:
raise unittest.SkipTest("_testinternalcapi required")
- config = _testinternalcapi.get_config()
+ return not _testcapi.config_get('code_debug_ranges')
return not bool(config['code_debug_ranges'])
def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index ac09d72c7741c9..31a4a224ec8f88 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -2141,28 +2141,27 @@ async def foo(arg): return await arg # Py 3.5
self.assertEqual(ret, 0)
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
+ # _testcapi cannot be imported in a subinterpreter on a Free Threaded build
+ @support.requires_gil_enabled()
def test_py_config_isoloated_per_interpreter(self):
# A config change in one interpreter must not leak to out to others.
#
# This test could verify ANY config value, it just happens to have been
# written around the time of int_max_str_digits. Refactoring is okay.
code = """if 1:
- import sys, _testinternalcapi
+ import sys, _testcapi
# Any config value would do, this happens to be the one being
# double checked at the time this test was written.
- config = _testinternalcapi.get_config()
- config['int_max_str_digits'] = 55555
- config['parse_argv'] = 0
- _testinternalcapi.set_config(config)
- sub_value = _testinternalcapi.get_config()['int_max_str_digits']
+ _testcapi.config_set('int_max_str_digits', 55555)
+ sub_value = _testcapi.config_get('int_max_str_digits')
assert sub_value == 55555, sub_value
"""
- before_config = _testinternalcapi.get_config()
- assert before_config['int_max_str_digits'] != 55555
+ before_config = _testcapi.config_get('int_max_str_digits')
+ assert before_config != 55555
self.assertEqual(support.run_in_subinterp(code), 0,
'subinterp code failure, check stderr.')
- after_config = _testinternalcapi.get_config()
+ after_config = _testcapi.config_get('int_max_str_digits')
self.assertIsNot(
before_config, after_config,
"Expected get_config() to return a new dict on each call")
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 6d1b4cce498276..bd01913e49d170 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1746,14 +1746,6 @@ def test_init_warnoptions(self):
self.check_all_configs("test_init_warnoptions", config, preconfig,
api=API_PYTHON)
- def test_init_set_config(self):
- config = {
- 'bytes_warning': 2,
- 'warnoptions': ['error::BytesWarning'],
- }
- self.check_all_configs("test_init_set_config", config,
- api=API_ISOLATED)
-
@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
def test_initconfig_api(self):
preconfig = {
@@ -1845,22 +1837,6 @@ def test_init_in_background_thread(self):
self.assertEqual(err, "")
-class SetConfigTests(unittest.TestCase):
- def test_set_config(self):
- # bpo-42260: Test _PyInterpreterState_SetConfig()
- import_helper.import_module('_testcapi')
- cmd = [sys.executable, '-X', 'utf8', '-I', '-m', 'test._test_embed_set_config']
- proc = subprocess.run(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- encoding='utf-8', errors='backslashreplace')
- if proc.returncode and support.verbose:
- print(proc.stdout)
- print(proc.stderr)
- self.assertEqual(proc.returncode, 0,
- (proc.returncode, proc.stdout, proc.stderr))
-
-
class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
def test_open_code_hook(self):
self.run_embedded_interpreter("test_open_code_hook")
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index ab46ccbf004a3a..5707b355e94337 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -2145,25 +2145,25 @@ def check_add_python_opts(self, option):
import unittest
from test import support
try:
- from _testinternalcapi import get_config
+ from _testcapi import config_get
except ImportError:
- get_config = None
+ config_get = None
# WASI/WASM buildbots don't use -E option
use_environment = (support.is_emscripten or support.is_wasi)
class WorkerTests(unittest.TestCase):
- @unittest.skipUnless(get_config is None, 'need get_config()')
+ @unittest.skipUnless(config_get is None, 'need config_get()')
def test_config(self):
- config = get_config()['config']
+ config = config_get()
# -u option
- self.assertEqual(config['buffered_stdio'], 0)
+ self.assertEqual(config_get('buffered_stdio'), 0)
# -W default option
- self.assertTrue(config['warnoptions'], ['default'])
+ self.assertTrue(config_get('warnoptions'), ['default'])
# -bb option
- self.assertTrue(config['bytes_warning'], 2)
+ self.assertTrue(config_get('bytes_warning'), 2)
# -E option
- self.assertTrue(config['use_environment'], use_environment)
+ self.assertTrue(config_get('use_environment'), use_environment)
def test_python_opts(self):
# -u option
diff --git a/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
new file mode 100644
index 00000000000000..c0c109d5ce1ca2
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
@@ -0,0 +1,4 @@
+Remove ``_PyInterpreterState_GetConfigCopy()`` and
+``_PyInterpreterState_SetConfig()`` private functions. Use instead
+:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set`, public C API added by
+:pep:`741` "Python Configuration C API". Patch by Victor Stinner.
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 98aea5b596e920..aae09f620b8898 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -25,7 +25,6 @@
#include "pycore_hashtable.h" // _Py_hashtable_new()
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
-#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
@@ -318,41 +317,6 @@ test_hashtable(PyObject *self, PyObject *Py_UNUSED(args))
}
-static PyObject *
-test_get_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
-{
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
- PyConfig_Clear(&config);
- return NULL;
- }
- PyObject *dict = _PyConfig_AsDict(&config);
- PyConfig_Clear(&config);
- return dict;
-}
-
-
-static PyObject *
-test_set_config(PyObject *Py_UNUSED(self), PyObject *dict)
-{
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- if (_PyConfig_FromDict(&config, dict) < 0) {
- goto error;
- }
- if (_PyInterpreterState_SetConfig(&config) < 0) {
- goto error;
- }
- PyConfig_Clear(&config);
- Py_RETURN_NONE;
-
-error:
- PyConfig_Clear(&config);
- return NULL;
-}
-
-
static PyObject *
test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
{
@@ -2062,8 +2026,6 @@ static PyMethodDef module_functions[] = {
{"test_popcount", test_popcount, METH_NOARGS},
{"test_bit_length", test_bit_length, METH_NOARGS},
{"test_hashtable", test_hashtable, METH_NOARGS},
- {"get_config", test_get_config, METH_NOARGS},
- {"set_config", test_set_config, METH_O},
{"reset_path_config", test_reset_path_config, METH_NOARGS},
{"test_edit_cost", test_edit_cost, METH_NOARGS},
{"test_bytes_find", test_bytes_find, METH_NOARGS},
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 3681a89376638a..6f6d0cae58010e 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1791,48 +1791,6 @@ static int test_init_warnoptions(void)
}
-static int tune_config(void)
-{
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
- PyConfig_Clear(&config);
- PyErr_Print();
- return -1;
- }
-
- config.bytes_warning = 2;
-
- if (_PyInterpreterState_SetConfig(&config) < 0) {
- PyConfig_Clear(&config);
- return -1;
- }
- PyConfig_Clear(&config);
- return 0;
-}
-
-
-static int test_init_set_config(void)
-{
- // Initialize core
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- config_set_string(&config, &config.program_name, PROGRAM_NAME);
- config.bytes_warning = 0;
- init_from_config_clear(&config);
-
- // Tune the configuration using _PyInterpreterState_SetConfig()
- if (tune_config() < 0) {
- PyErr_Print();
- return 1;
- }
-
- dump_config();
- Py_Finalize();
- return 0;
-}
-
-
static int initconfig_getint(PyInitConfig *config, const char *name)
{
int64_t value;
@@ -2445,7 +2403,6 @@ static struct TestCase TestCases[] = {
{"test_init_setpythonhome", test_init_setpythonhome},
{"test_init_is_python_build", test_init_is_python_build},
{"test_init_warnoptions", test_init_warnoptions},
- {"test_init_set_config", test_init_set_config},
{"test_initconfig_api", test_initconfig_api},
{"test_initconfig_get_api", test_initconfig_get_api},
{"test_initconfig_exit", test_initconfig_exit},
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 8ec12b437f8298..ea8a291a8e5eb4 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -444,40 +444,6 @@ interpreter_update_config(PyThreadState *tstate, int only_update_path_config)
}
-int
-_PyInterpreterState_SetConfig(const PyConfig *src_config)
-{
- PyThreadState *tstate = _PyThreadState_GET();
- int res = -1;
-
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- PyStatus status = _PyConfig_Copy(&config, src_config);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- status = _PyConfig_Read(&config, 1);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- status = _PyConfig_Copy(&tstate->interp->config, &config);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- res = interpreter_update_config(tstate, 0);
-
-done:
- PyConfig_Clear(&config);
- return res;
-}
-
-
/* Global initializations. Can be undone by Py_Finalize(). Don't
call this twice without an intervening Py_Finalize() call.
diff --git a/Python/pystate.c b/Python/pystate.c
index 52703b048d6022..e5003021b83f00 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2880,20 +2880,6 @@ _PyInterpreterState_GetConfig(PyInterpreterState *interp)
}
-int
-_PyInterpreterState_GetConfigCopy(PyConfig *config)
-{
- PyInterpreterState *interp = _PyInterpreterState_GET();
-
- PyStatus status = _PyConfig_Copy(config, &interp->config);
- if (PyStatus_Exception(status)) {
- _PyErr_SetFromPyStatus(status);
- return -1;
- }
- return 0;
-}
-
-
const PyConfig*
_Py_GetConfig(void)
{
1
0