Python-checkins
Threads by month
- ----- 2025 -----
- February
- 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
- 705 discussions
Jan. 23, 2025
https://github.com/python/cpython/commit/46c7e13c055c218e18b0424efc60965e6a…
commit: 46c7e13c055c218e18b0424efc60965e6a5fe6ea
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T12:07:34+01:00
summary:
gh-129185: Fix PyTraceMalloc_Untrack() at Python exit (#129191)
Support calling PyTraceMalloc_Track() and PyTraceMalloc_Untrack()
during late Python finalization.
* Call _PyTraceMalloc_Fini() later in Python finalization.
* Test also PyTraceMalloc_Untrack() without the GIL
* PyTraceMalloc_Untrack() now gets the GIL.
* Test also PyTraceMalloc_Untrack() in test_tracemalloc_track_race().
files:
M Lib/test/test_tracemalloc.py
M Modules/_testcapi/mem.c
M Modules/_testcapimodule.c
M Python/pylifecycle.c
M Python/tracemalloc.c
diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py
index 238ae14b388c76..0220a83d24b428 100644
--- a/Lib/test/test_tracemalloc.py
+++ b/Lib/test/test_tracemalloc.py
@@ -1,6 +1,7 @@
import contextlib
import os
import sys
+import textwrap
import tracemalloc
import unittest
from unittest.mock import patch
@@ -19,6 +20,7 @@
_testinternalcapi = None
+DEFAULT_DOMAIN = 0
EMPTY_STRING_SIZE = sys.getsizeof(b'')
INVALID_NFRAME = (-1, 2**30)
@@ -1027,8 +1029,8 @@ def track(self, release_gil=False, nframe=1):
release_gil)
return frames
- def untrack(self):
- _testcapi.tracemalloc_untrack(self.domain, self.ptr)
+ def untrack(self, release_gil=False):
+ _testcapi.tracemalloc_untrack(self.domain, self.ptr, release_gil)
def get_traced_memory(self):
# Get the traced size in the domain
@@ -1070,7 +1072,7 @@ def test_track_already_tracked(self):
self.assertEqual(self.get_traceback(),
tracemalloc.Traceback(frames))
- def test_untrack(self):
+ def check_untrack(self, release_gil):
tracemalloc.start()
self.track()
@@ -1078,13 +1080,19 @@ def test_untrack(self):
self.assertEqual(self.get_traced_memory(), self.size)
# untrack must remove the trace
- self.untrack()
+ self.untrack(release_gil)
self.assertIsNone(self.get_traceback())
self.assertEqual(self.get_traced_memory(), 0)
# calling _PyTraceMalloc_Untrack() multiple times must not crash
- self.untrack()
- self.untrack()
+ self.untrack(release_gil)
+ self.untrack(release_gil)
+
+ def test_untrack(self):
+ self.check_untrack(False)
+
+ def test_untrack_without_gil(self):
+ self.check_untrack(True)
def test_stop_track(self):
tracemalloc.start()
@@ -1110,6 +1118,29 @@ def test_tracemalloc_track_race(self):
# gh-128679: Test fix for tracemalloc.stop() race condition
_testcapi.tracemalloc_track_race()
+ def test_late_untrack(self):
+ code = textwrap.dedent(f"""
+ from test import support
+ import tracemalloc
+ import _testcapi
+
+ class Tracked:
+ def __init__(self, domain, size):
+ self.domain = domain
+ self.ptr = id(self)
+ self.size = size
+ _testcapi.tracemalloc_track(self.domain, self.ptr, self.size)
+
+ def __del__(self, untrack=_testcapi.tracemalloc_untrack):
+ untrack(self.domain, self.ptr, 1)
+
+ domain = {DEFAULT_DOMAIN}
+ tracemalloc.start()
+ obj = Tracked(domain, 1024 * 1024)
+ support.late_deletion(obj)
+ """)
+ assert_python_ok("-c", code)
+
if __name__ == "__main__":
unittest.main()
diff --git a/Modules/_testcapi/mem.c b/Modules/_testcapi/mem.c
index ab4ad934644c38..ecae5ba26226a6 100644
--- a/Modules/_testcapi/mem.c
+++ b/Modules/_testcapi/mem.c
@@ -557,8 +557,9 @@ tracemalloc_untrack(PyObject *self, PyObject *args)
{
unsigned int domain;
PyObject *ptr_obj;
+ int release_gil = 0;
- if (!PyArg_ParseTuple(args, "IO", &domain, &ptr_obj)) {
+ if (!PyArg_ParseTuple(args, "IO|i", &domain, &ptr_obj, &release_gil)) {
return NULL;
}
void *ptr = PyLong_AsVoidPtr(ptr_obj);
@@ -566,7 +567,15 @@ tracemalloc_untrack(PyObject *self, PyObject *args)
return NULL;
}
- int res = PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
+ int res;
+ if (release_gil) {
+ Py_BEGIN_ALLOW_THREADS
+ res = PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ res = PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
+ }
if (res < 0) {
PyErr_SetString(PyExc_RuntimeError, "PyTraceMalloc_Untrack error");
return NULL;
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 996b96bc000450..c405a352ed74a1 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3394,6 +3394,7 @@ static void
tracemalloc_track_race_thread(void *data)
{
PyTraceMalloc_Track(123, 10, 1);
+ PyTraceMalloc_Untrack(123, 10);
PyThread_type_lock lock = (PyThread_type_lock)data;
PyThread_release_lock(lock);
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index f6526725d5dccc..52890cfc5df829 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2113,7 +2113,7 @@ _Py_Finalize(_PyRuntimeState *runtime)
/* Disable tracemalloc after all Python objects have been destroyed,
so it is possible to use tracemalloc in objects destructor. */
- _PyTraceMalloc_Fini();
+ _PyTraceMalloc_Stop();
/* Finalize any remaining import state */
// XXX Move these up to where finalize_modules() is currently.
@@ -2166,6 +2166,8 @@ _Py_Finalize(_PyRuntimeState *runtime)
finalize_interp_clear(tstate);
+ _PyTraceMalloc_Fini();
+
#ifdef Py_TRACE_REFS
/* Display addresses (& refcnts) of all objects still alive.
* An address can be used to find the repr of the object, printed
diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c
index b398ea379e0607..62065e85ac8350 100644
--- a/Python/tracemalloc.c
+++ b/Python/tracemalloc.c
@@ -1256,9 +1256,17 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
size_t size)
{
PyGILState_STATE gil_state = PyGILState_Ensure();
+ int result;
+
+ // gh-129185: Check before TABLES_LOCK() to support calls after
+ // _PyTraceMalloc_Fini().
+ if (!tracemalloc_config.tracing) {
+ result = -2;
+ goto done;
+ }
+
TABLES_LOCK();
- int result;
if (tracemalloc_config.tracing) {
result = tracemalloc_add_trace_unlocked(domain, ptr, size);
}
@@ -1268,6 +1276,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
}
TABLES_UNLOCK();
+done:
PyGILState_Release(gil_state);
return result;
@@ -1277,9 +1286,19 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
int
PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
{
+ // Need the GIL to prevent races on the first 'tracing' test
+ PyGILState_STATE gil_state = PyGILState_Ensure();
+ int result;
+
+ // gh-129185: Check before TABLES_LOCK() to support calls after
+ // _PyTraceMalloc_Fini()
+ if (!tracemalloc_config.tracing) {
+ result = -2;
+ goto done;
+ }
+
TABLES_LOCK();
- int result;
if (tracemalloc_config.tracing) {
tracemalloc_remove_trace_unlocked(domain, ptr);
result = 0;
@@ -1290,6 +1309,8 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
}
TABLES_UNLOCK();
+done:
+ PyGILState_Release(gil_state);
return result;
}
1
0
Jan. 23, 2025
https://github.com/python/cpython/commit/225296cd5b505c180d3f45c355b43d7e1d…
commit: 225296cd5b505c180d3f45c355b43d7e1d99d3d5
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: picnixz <10796600+picnixz(a)users.noreply.github.com>
date: 2025-01-23T11:44:18+01:00
summary:
gh-126004: Fix positions handling in `codecs.replace_errors` (#127674)
This fixes how `PyCodec_ReplaceErrors` handles the `start` and `end` attributes
of `UnicodeError` objects via the `_PyUnicodeError_GetParams` helper.
files:
A Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst
M Lib/test/test_capi/test_codecs.py
M Python/codecs.c
diff --git a/Lib/test/test_capi/test_codecs.py b/Lib/test/test_capi/test_codecs.py
index 3e79dd2f7ca2fa..f57191ddcdbeb4 100644
--- a/Lib/test/test_capi/test_codecs.py
+++ b/Lib/test/test_capi/test_codecs.py
@@ -839,7 +839,8 @@ def test_codec_ignore_errors_handler(self):
def test_codec_replace_errors_handler(self):
handler = _testcapi.codec_replace_errors
- self.do_test_codec_errors_handler(handler, self.all_unicode_errors)
+ self.do_test_codec_errors_handler(handler, self.all_unicode_errors,
+ safe=True)
def test_codec_xmlcharrefreplace_errors_handler(self):
handler = _testcapi.codec_xmlcharrefreplace_errors
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst
new file mode 100644
index 00000000000000..de70c59ee48eec
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst
@@ -0,0 +1,3 @@
+Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end`
+values in the :func:`codecs.replace_errors` error handler. Patch by Bénédikt
+Tran.
diff --git a/Python/codecs.c b/Python/codecs.c
index 11eaca175abf13..b657dd134a668e 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -702,48 +702,46 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc)
PyObject *PyCodec_ReplaceErrors(PyObject *exc)
{
- Py_ssize_t start, end, i, len;
+ Py_ssize_t start, end, slen;
if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
- PyObject *res;
- Py_UCS1 *outp;
- if (PyUnicodeEncodeError_GetStart(exc, &start))
+ if (_PyUnicodeError_GetParams(exc, NULL, NULL,
+ &start, &end, &slen, false) < 0) {
return NULL;
- if (PyUnicodeEncodeError_GetEnd(exc, &end))
- return NULL;
- len = end - start;
- res = PyUnicode_New(len, '?');
- if (res == NULL)
+ }
+ PyObject *res = PyUnicode_New(slen, '?');
+ if (res == NULL) {
return NULL;
+ }
assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND);
- outp = PyUnicode_1BYTE_DATA(res);
- for (i = 0; i < len; ++i)
- outp[i] = '?';
+ Py_UCS1 *outp = PyUnicode_1BYTE_DATA(res);
+ memset(outp, '?', sizeof(Py_UCS1) * slen);
assert(_PyUnicode_CheckConsistency(res, 1));
return Py_BuildValue("(Nn)", res, end);
}
else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
- if (PyUnicodeDecodeError_GetEnd(exc, &end))
+ if (_PyUnicodeError_GetParams(exc, NULL, NULL,
+ NULL, &end, NULL, true) < 0) {
return NULL;
+ }
return Py_BuildValue("(Cn)",
(int)Py_UNICODE_REPLACEMENT_CHARACTER,
end);
}
else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
- PyObject *res;
- Py_UCS2 *outp;
- if (PyUnicodeTranslateError_GetStart(exc, &start))
- return NULL;
- if (PyUnicodeTranslateError_GetEnd(exc, &end))
+ if (_PyUnicodeError_GetParams(exc, NULL, NULL,
+ &start, &end, &slen, false) < 0) {
return NULL;
- len = end - start;
- res = PyUnicode_New(len, Py_UNICODE_REPLACEMENT_CHARACTER);
- if (res == NULL)
+ }
+ PyObject *res = PyUnicode_New(slen, Py_UNICODE_REPLACEMENT_CHARACTER);
+ if (res == NULL) {
return NULL;
- assert(PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND);
- outp = PyUnicode_2BYTE_DATA(res);
- for (i = 0; i < len; i++)
+ }
+ assert(slen == 0 || PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND);
+ Py_UCS2 *outp = PyUnicode_2BYTE_DATA(res);
+ for (Py_ssize_t i = 0; i < slen; ++i) {
outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER;
+ }
assert(_PyUnicode_CheckConsistency(res, 1));
return Py_BuildValue("(Nn)", res, end);
}
1
0
gh-126004: Fix positions handling in `codecs.xmlcharrefreplace_errors` (#127675)
by picnixz Jan. 23, 2025
by picnixz Jan. 23, 2025
Jan. 23, 2025
https://github.com/python/cpython/commit/70dcc847df4eb32367859bfa168f057e43…
commit: 70dcc847df4eb32367859bfa168f057e43eed11e
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: picnixz <10796600+picnixz(a)users.noreply.github.com>
date: 2025-01-23T11:42:38+01:00
summary:
gh-126004: Fix positions handling in `codecs.xmlcharrefreplace_errors` (#127675)
This fixes how `PyCodec_XMLCharRefReplaceErrors` handles the `start` and `end`
attributes of `UnicodeError` objects via the `_PyUnicodeError_GetParams` helper.
files:
A Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst
M Lib/test/test_capi/test_codecs.py
M Python/codecs.c
diff --git a/Lib/test/test_capi/test_codecs.py b/Lib/test/test_capi/test_codecs.py
index a557e35e68915d..3e79dd2f7ca2fa 100644
--- a/Lib/test/test_capi/test_codecs.py
+++ b/Lib/test/test_capi/test_codecs.py
@@ -843,7 +843,8 @@ def test_codec_replace_errors_handler(self):
def test_codec_xmlcharrefreplace_errors_handler(self):
handler = _testcapi.codec_xmlcharrefreplace_errors
- self.do_test_codec_errors_handler(handler, self.unicode_encode_errors)
+ self.do_test_codec_errors_handler(handler, self.unicode_encode_errors,
+ safe=True)
def test_codec_backslashreplace_errors_handler(self):
handler = _testcapi.codec_backslashreplace_errors
@@ -853,12 +854,12 @@ def test_codec_namereplace_errors_handler(self):
handler = _testlimitedcapi.codec_namereplace_errors
self.do_test_codec_errors_handler(handler, self.unicode_encode_errors)
- def do_test_codec_errors_handler(self, handler, exceptions):
+ def do_test_codec_errors_handler(self, handler, exceptions, *, safe=False):
at_least_one = False
for exc in exceptions:
# See https://github.com/python/cpython/issues/123378 and related
# discussion and issues for details.
- if self._exception_may_crash(exc):
+ if not safe and self._exception_may_crash(exc):
continue
at_least_one = True
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst
new file mode 100644
index 00000000000000..60b1c5d8b80793
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst
@@ -0,0 +1,3 @@
+Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end`
+values in the :func:`codecs.xmlcharrefreplace_errors` error handler.
+Patch by Bénédikt Tran.
diff --git a/Python/codecs.c b/Python/codecs.c
index 2cb3875db35058..11eaca175abf13 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -755,100 +755,113 @@ PyObject *PyCodec_ReplaceErrors(PyObject *exc)
PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
{
- if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
- PyObject *restuple;
- PyObject *object;
- Py_ssize_t i;
- Py_ssize_t start;
- Py_ssize_t end;
- PyObject *res;
- Py_UCS1 *outp;
- Py_ssize_t ressize;
- Py_UCS4 ch;
- if (PyUnicodeEncodeError_GetStart(exc, &start))
- return NULL;
- if (PyUnicodeEncodeError_GetEnd(exc, &end))
- return NULL;
- if (!(object = PyUnicodeEncodeError_GetObject(exc)))
- return NULL;
- if (end - start > PY_SSIZE_T_MAX / (2+7+1))
- end = start + PY_SSIZE_T_MAX / (2+7+1);
- for (i = start, ressize = 0; i < end; ++i) {
- /* object is guaranteed to be "ready" */
- ch = PyUnicode_READ_CHAR(object, i);
- if (ch<10)
- ressize += 2+1+1;
- else if (ch<100)
- ressize += 2+2+1;
- else if (ch<1000)
- ressize += 2+3+1;
- else if (ch<10000)
- ressize += 2+4+1;
- else if (ch<100000)
- ressize += 2+5+1;
- else if (ch<1000000)
- ressize += 2+6+1;
- else
- ressize += 2+7+1;
+ if (!PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
+ wrong_exception_type(exc);
+ return NULL;
+ }
+
+ PyObject *obj;
+ Py_ssize_t objlen, start, end, slen;
+ if (_PyUnicodeError_GetParams(exc,
+ &obj, &objlen,
+ &start, &end, &slen, false) < 0)
+ {
+ return NULL;
+ }
+
+ // The number of characters that each character 'ch' contributes
+ // in the result is 2 + k + 1, where k = min{t >= 1 | 10^t > ch}
+ // and will be formatted as "&#" + DIGITS + ";". Since the Unicode
+ // range is below 10^7, each "block" requires at most 2 + 7 + 1
+ // characters.
+ if (slen > PY_SSIZE_T_MAX / (2 + 7 + 1)) {
+ end = start + PY_SSIZE_T_MAX / (2 + 7 + 1);
+ end = Py_MIN(end, objlen);
+ slen = Py_MAX(0, end - start);
+ }
+
+ Py_ssize_t ressize = 0;
+ for (Py_ssize_t i = start; i < end; ++i) {
+ /* object is guaranteed to be "ready" */
+ Py_UCS4 ch = PyUnicode_READ_CHAR(obj, i);
+ if (ch < 10) {
+ ressize += 2 + 1 + 1;
}
- /* allocate replacement */
- res = PyUnicode_New(ressize, 127);
- if (res == NULL) {
- Py_DECREF(object);
- return NULL;
+ else if (ch < 100) {
+ ressize += 2 + 2 + 1;
}
- outp = PyUnicode_1BYTE_DATA(res);
- /* generate replacement */
- for (i = start; i < end; ++i) {
- int digits;
- int base;
- ch = PyUnicode_READ_CHAR(object, i);
- *outp++ = '&';
- *outp++ = '#';
- if (ch<10) {
- digits = 1;
- base = 1;
- }
- else if (ch<100) {
- digits = 2;
- base = 10;
- }
- else if (ch<1000) {
- digits = 3;
- base = 100;
- }
- else if (ch<10000) {
- digits = 4;
- base = 1000;
- }
- else if (ch<100000) {
- digits = 5;
- base = 10000;
- }
- else if (ch<1000000) {
- digits = 6;
- base = 100000;
- }
- else {
- digits = 7;
- base = 1000000;
- }
- while (digits-->0) {
- *outp++ = '0' + ch/base;
- ch %= base;
- base /= 10;
- }
- *outp++ = ';';
+ else if (ch < 1000) {
+ ressize += 2 + 3 + 1;
+ }
+ else if (ch < 10000) {
+ ressize += 2 + 4 + 1;
+ }
+ else if (ch < 100000) {
+ ressize += 2 + 5 + 1;
+ }
+ else if (ch < 1000000) {
+ ressize += 2 + 6 + 1;
+ }
+ else {
+ assert(ch < 10000000);
+ ressize += 2 + 7 + 1;
}
- assert(_PyUnicode_CheckConsistency(res, 1));
- restuple = Py_BuildValue("(Nn)", res, end);
- Py_DECREF(object);
- return restuple;
}
- else {
- wrong_exception_type(exc);
+
+ /* allocate replacement */
+ PyObject *res = PyUnicode_New(ressize, 127);
+ if (res == NULL) {
+ Py_DECREF(obj);
return NULL;
}
+ Py_UCS1 *outp = PyUnicode_1BYTE_DATA(res);
+ /* generate replacement */
+ for (Py_ssize_t i = start; i < end; ++i) {
+ int digits, base;
+ Py_UCS4 ch = PyUnicode_READ_CHAR(obj, i);
+ if (ch < 10) {
+ digits = 1;
+ base = 1;
+ }
+ else if (ch < 100) {
+ digits = 2;
+ base = 10;
+ }
+ else if (ch < 1000) {
+ digits = 3;
+ base = 100;
+ }
+ else if (ch < 10000) {
+ digits = 4;
+ base = 1000;
+ }
+ else if (ch < 100000) {
+ digits = 5;
+ base = 10000;
+ }
+ else if (ch < 1000000) {
+ digits = 6;
+ base = 100000;
+ }
+ else {
+ assert(ch < 10000000);
+ digits = 7;
+ base = 1000000;
+ }
+ *outp++ = '&';
+ *outp++ = '#';
+ while (digits-- > 0) {
+ assert(base >= 1);
+ *outp++ = '0' + ch / base;
+ ch %= base;
+ base /= 10;
+ }
+ *outp++ = ';';
+ }
+ assert(_PyUnicode_CheckConsistency(res, 1));
+ PyObject *restuple = Py_BuildValue("(Nn)", res, end);
+ Py_DECREF(obj);
+ return restuple;
}
PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
1
0
Revert "GH-128914: Remove conditional stack effects from `bytecodes.c` and the code generators (GH-128918)" (GH-129202)
by markshannon Jan. 23, 2025
by markshannon Jan. 23, 2025
Jan. 23, 2025
https://github.com/python/cpython/commit/a10f99375e7912df863cf101a38e9703cf…
commit: a10f99375e7912df863cf101a38e9703cfcd72f1
branch: main
author: Sam Gross <colesbury(a)gmail.com>
committer: markshannon <mark(a)hotpy.org>
date: 2025-01-23T09:26:25Z
summary:
Revert "GH-128914: Remove conditional stack effects from `bytecodes.c` and the code generators (GH-128918)" (GH-129202)
The commit introduced a ~2.5-3% regression in the free threading build.
This reverts commit ab61d3f4303d14a413bc9ae6557c730ffdf7579e.
files:
D 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 225ef321aed3b8..f8f4188d27b472 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -75,8 +75,7 @@ the following command can be used to display the disassembly of
>>> dis.dis(myfunc)
2 RESUME 0
<BLANKLINE>
- 3 LOAD_GLOBAL 0 (len)
- PUSH_NULL
+ 3 LOAD_GLOBAL 1 (len + NULL)
LOAD_FAST 0 (alist)
CALL 1
RETURN_VALUE
@@ -208,7 +207,6 @@ Example:
...
RESUME
LOAD_GLOBAL
- PUSH_NULL
LOAD_FAST
CALL
RETURN_VALUE
@@ -1217,20 +1215,11 @@ iterations of the loop.
.. opcode:: LOAD_ATTR (namei)
- Replaces ``STACK[-1]`` with ``getattr(STACK[-1], co_names[namei>>1])``.
+ If the low bit of ``namei`` is not set, this replaces ``STACK[-1]`` with
+ ``getattr(STACK[-1], co_names[namei>>1])``.
- .. 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.
+ 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.
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`
@@ -1238,7 +1227,9 @@ iterations of the loop.
Otherwise, ``NULL`` and the object returned by
the attribute lookup are pushed.
- .. versionadded:: 3.14
+ .. 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.
.. opcode:: LOAD_SUPER_ATTR (namei)
@@ -1935,6 +1926,12 @@ 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 f5eddab6e90e41..01d41446fdb0cf 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -334,8 +334,6 @@ 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 0d94b6d81d2936..1dd155abf3babf 100644
--- a/Include/internal/pycore_magic_number.h
+++ b/Include/internal/pycore_magic_number.h
@@ -267,7 +267,6 @@ 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
@@ -280,7 +279,7 @@ PC/launcher.c must also be updated.
*/
-#define PYC_MAGIC_NUMBER 3615
+#define PYC_MAGIC_NUMBER 3614
/* 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 22ed269c5f1686..10061c988d5f4b 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 oparg;
+ return 2 + ((oparg == 3) ? 1 : 0);
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 4;
+ return 3 + (oparg & 1);
case CALL_INTRINSIC_1:
return 1;
case CALL_INTRINSIC_2:
@@ -245,8 +245,6 @@ 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:
@@ -297,6 +295,12 @@ 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:
@@ -343,14 +347,6 @@ 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:
@@ -361,9 +357,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 3;
case LOAD_SUPER_ATTR_ATTR:
return 3;
- case LOAD_SUPER_METHOD:
- return 3;
- case LOAD_SUPER_METHOD_METHOD:
+ case LOAD_SUPER_ATTR_METHOD:
return 3;
case MAKE_CELL:
return 0;
@@ -722,8 +716,6 @@ 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:
@@ -765,17 +757,23 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LIST_EXTEND:
return 1 + (oparg-1);
case LOAD_ATTR:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_ATTR_CLASS:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
return 1;
case LOAD_ATTR_INSTANCE_VALUE:
- return 1;
+ 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;
case LOAD_ATTR_MODULE:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_ATTR_NONDESCRIPTOR_NO_DICT:
return 1;
case LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
@@ -783,9 +781,9 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_ATTR_PROPERTY:
return 0;
case LOAD_ATTR_SLOT:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_ATTR_WITH_HINT:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_BUILD_CLASS:
return 1;
case LOAD_CLOSURE:
@@ -813,21 +811,13 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_GLOBAL_BUILTIN:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_GLOBAL_MODULE:
- return 1;
+ return 1 + (oparg & 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:
@@ -835,12 +825,10 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case LOAD_SPECIAL:
return 2;
case LOAD_SUPER_ATTR:
- return 1;
+ return 1 + (oparg & 1);
case LOAD_SUPER_ATTR_ATTR:
return 1;
- case LOAD_SUPER_METHOD:
- return 2;
- case LOAD_SUPER_METHOD_METHOD:
+ case LOAD_SUPER_ATTR_METHOD:
return 2;
case MAKE_CELL:
return 0;
@@ -1070,7 +1058,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case BUILD_SLICE: {
- *effect = 1 - oparg;
+ *effect = -1 - ((oparg == 3) ? 1 : 0);
return 0;
}
case BUILD_STRING: {
@@ -1126,7 +1114,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case CALL_FUNCTION_EX: {
- *effect = 0;
+ *effect = Py_MAX(0, -2 - (oparg & 1));
return 0;
}
case CALL_INTRINSIC_1: {
@@ -1427,10 +1415,6 @@ 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;
@@ -1512,15 +1496,15 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR: {
- *effect = 1;
+ *effect = Py_MAX(1, (oparg & 1));
return 0;
}
case LOAD_ATTR_CLASS: {
- *effect = 0;
+ *effect = Py_MAX(0, (oparg & 1));
return 0;
}
case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK: {
- *effect = 0;
+ *effect = Py_MAX(0, (oparg & 1));
return 0;
}
case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: {
@@ -1528,13 +1512,25 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR_INSTANCE_VALUE: {
- *effect = 0;
+ *effect = Py_MAX(0, (oparg & 1));
return 0;
}
- case LOAD_ATTR_MODULE: {
+ 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;
return 0;
}
+ case LOAD_ATTR_MODULE: {
+ *effect = Py_MAX(1, (oparg & 1));
+ return 0;
+ }
case LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
*effect = 0;
return 0;
@@ -1548,11 +1544,11 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_ATTR_SLOT: {
- *effect = 0;
+ *effect = Py_MAX(0, (oparg & 1));
return 0;
}
case LOAD_ATTR_WITH_HINT: {
- *effect = 1;
+ *effect = Py_MAX(1, (oparg & 1));
return 0;
}
case LOAD_BUILD_CLASS: {
@@ -1608,37 +1604,21 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_GLOBAL: {
- *effect = 1;
+ *effect = Py_MAX(1, 1 + (oparg & 1));
return 0;
}
case LOAD_GLOBAL_BUILTIN: {
- *effect = 1;
+ *effect = Py_MAX(1, 1 + (oparg & 1));
return 0;
}
case LOAD_GLOBAL_MODULE: {
- *effect = 1;
+ *effect = Py_MAX(1, 1 + (oparg & 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;
@@ -1652,18 +1632,14 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0;
}
case LOAD_SUPER_ATTR: {
- *effect = 0;
+ *effect = Py_MAX(0, -2 + (oparg & 1));
return 0;
}
case LOAD_SUPER_ATTR_ATTR: {
*effect = -2;
return 0;
}
- case LOAD_SUPER_METHOD: {
- *effect = 0;
- return 0;
- }
- case LOAD_SUPER_METHOD_METHOD: {
+ case LOAD_SUPER_ATTR_METHOD: {
*effect = -1;
return 0;
}
@@ -1958,7 +1934,6 @@ enum InstructionFormat {
INSTR_FMT_IXC00 = 9,
INSTR_FMT_IXC000 = 10,
INSTR_FMT_IXC0000 = 11,
- INSTR_FMT_IXC00000000 = 12,
};
#define IS_VALID_OPCODE(OP) \
@@ -1978,8 +1953,9 @@ enum InstructionFormat {
#define HAS_EXIT_FLAG (1024)
#define HAS_PURE_FLAG (2048)
#define HAS_PASSTHROUGH_FLAG (4096)
-#define HAS_ERROR_NO_POP_FLAG (8192)
-#define HAS_NO_SAVE_IP_FLAG (16384)
+#define HAS_OPARG_AND_1_FLAG (8192)
+#define HAS_ERROR_NO_POP_FLAG (16384)
+#define HAS_NO_SAVE_IP_FLAG (32768)
#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))
@@ -1993,6 +1969,7 @@ 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))
@@ -2046,7 +2023,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_IX, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_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 },
@@ -2119,7 +2096,6 @@ 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 },
@@ -2137,15 +2113,18 @@ 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_IXC00000000, HAS_EXIT_FLAG },
- [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IXC00000000, HAS_EXIT_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_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_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_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_PROPERTY] = { 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_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | 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 },
@@ -2160,20 +2139,15 @@ 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_IXC000, HAS_DEOPT_FLAG },
- [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_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_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_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 },
+ [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 },
[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 },
@@ -2353,6 +2327,9 @@ _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 } } },
@@ -2373,15 +2350,11 @@ _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_METHOD_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_METHOD_METHOD, 0, 0 } } },
+ [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_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 } } },
@@ -2551,7 +2524,6 @@ 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",
@@ -2577,6 +2549,9 @@ 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",
@@ -2600,17 +2575,12 @@ 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_METHOD] = "LOAD_SUPER_METHOD",
- [LOAD_SUPER_METHOD_METHOD] = "LOAD_SUPER_METHOD_METHOD",
+ [LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD",
[MAKE_CELL] = "MAKE_CELL",
[MAKE_FUNCTION] = "MAKE_FUNCTION",
[MAP_ADD] = "MAP_ADD",
@@ -2693,9 +2663,7 @@ 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,
@@ -2818,7 +2786,6 @@ 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,
@@ -2840,6 +2807,9 @@ 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,
@@ -2862,17 +2832,12 @@ 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_METHOD] = LOAD_SUPER_METHOD,
- [LOAD_SUPER_METHOD_METHOD] = LOAD_SUPER_METHOD,
+ [LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR,
[MAKE_CELL] = MAKE_CELL,
[MAKE_FUNCTION] = MAKE_FUNCTION,
[MAP_ADD] = MAP_ADD,
@@ -2941,6 +2906,8 @@ const uint8_t _PyOpcode_Deopt[256] = {
#endif // NEED_OPCODE_METADATA
#define EXTRA_CASES \
+ case 118: \
+ case 119: \
case 120: \
case 121: \
case 122: \
@@ -2974,6 +2941,7 @@ 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 2bf8542bdb67a9..066165a2c810d5 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -159,7 +159,6 @@ 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
@@ -181,122 +180,127 @@ 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 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_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_BUILD_CLASS LOAD_BUILD_CLASS
-#define _LOAD_BYTECODE 420
+#define _LOAD_BYTECODE 429
#define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT
#define _LOAD_CONST LOAD_CONST
#define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL
-#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_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_MORTAL LOAD_CONST_MORTAL
#define _LOAD_DEREF LOAD_DEREF
-#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 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_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 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_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_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 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_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_SPECIAL LOAD_SPECIAL
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
-#define _LOAD_SUPER_METHOD_METHOD LOAD_SUPER_METHOD_METHOD
-#define _MAKE_CALLARGS_A_TUPLE 448
+#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
+#define _MAKE_CALLARGS_A_TUPLE 453
#define _MAKE_CELL MAKE_CELL
#define _MAKE_FUNCTION MAKE_FUNCTION
-#define _MAKE_WARM 449
+#define _MAKE_WARM 454
#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 450
-#define _MAYBE_EXPAND_METHOD_KW 451
-#define _MONITOR_CALL 452
-#define _MONITOR_JUMP_BACKWARD 453
-#define _MONITOR_RESUME 454
+#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 _NOP NOP
#define _POP_EXCEPT POP_EXCEPT
-#define _POP_JUMP_IF_FALSE 455
-#define _POP_JUMP_IF_TRUE 456
+#define _POP_JUMP_IF_FALSE 460
+#define _POP_JUMP_IF_TRUE 461
#define _POP_TOP POP_TOP
-#define _POP_TOP_LOAD_CONST_INLINE_BORROW 457
+#define _POP_TOP_LOAD_CONST_INLINE_BORROW 462
#define _PUSH_EXC_INFO PUSH_EXC_INFO
-#define _PUSH_FRAME 458
+#define _PUSH_FRAME 463
#define _PUSH_NULL PUSH_NULL
-#define _PY_FRAME_GENERAL 459
-#define _PY_FRAME_KW 460
-#define _QUICKEN_RESUME 461
-#define _REPLACE_WITH_TRUE 462
+#define _PY_FRAME_GENERAL 464
+#define _PY_FRAME_KW 465
+#define _QUICKEN_RESUME 466
+#define _REPLACE_WITH_TRUE 467
#define _RESUME_CHECK RESUME_CHECK
#define _RETURN_GENERATOR RETURN_GENERATOR
#define _RETURN_VALUE RETURN_VALUE
-#define _SAVE_RETURN_OFFSET 463
-#define _SEND 464
-#define _SEND_GEN_FRAME 465
+#define _SAVE_RETURN_OFFSET 468
+#define _SEND 469
+#define _SEND_GEN_FRAME 470
#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 466
-#define _STORE_ATTR 467
-#define _STORE_ATTR_INSTANCE_VALUE 468
-#define _STORE_ATTR_SLOT 469
-#define _STORE_ATTR_WITH_HINT 470
+#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 _STORE_DEREF STORE_DEREF
-#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 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_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 480
-#define _STORE_SUBSCR 481
+#define _STORE_SLICE 485
+#define _STORE_SUBSCR 486
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 482
-#define _TO_BOOL 483
+#define _TIER2_RESUME_CHECK 487
+#define _TO_BOOL 488
#define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST
@@ -306,13 +310,13 @@ extern "C" {
#define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 484
+#define _UNPACK_SEQUENCE 489
#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 484
+#define MAX_UOP_ID 489
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 4d97a26ec6478a..c9bef792e5b3e3 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_DEOPT_FLAG,
- [_LOAD_GLOBAL_BUILTINS_FROM_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,
[_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,21 +148,26 @@ 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_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_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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] = 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,
[_CHECK_ATTR_MODULE_PUSH_KEYS] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_MODULE_FROM_KEYS] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
+ [_LOAD_ATTR_MODULE_FROM_KEYS] = HAS_ARG_FLAG | 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] = 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,
[_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG,
- [_LOAD_ATTR_CLASS] = 0,
- [_LOAD_ATTR_PROPERTY_FRAME] = HAS_DEOPT_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,
[_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,
@@ -203,12 +208,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_METHOD_WITH_VALUES] = 0,
- [_LOAD_METHOD_NO_DICT] = 0,
- [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = 0,
- [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = 0,
+ [_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,
[_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG,
- [_LOAD_METHOD_LAZY_DICT] = 0,
+ [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG,
[_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,
@@ -253,7 +258,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_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
+ [_MAKE_CALLARGS_A_TUPLE] = HAS_ARG_FLAG | 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,
@@ -280,9 +285,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_DEOPT_FLAG,
- [_LOAD_GLOBAL_BUILTINS] = HAS_DEOPT_FLAG,
- [_LOAD_ATTR_MODULE] = 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,
[_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG,
[_START_EXECUTOR] = HAS_ESCAPES_FLAG,
[_MAKE_WARM] = 0,
@@ -452,13 +457,22 @@ 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",
@@ -488,10 +502,6 @@ 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",
@@ -500,7 +510,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_METHOD_METHOD] = "_LOAD_SUPER_METHOD_METHOD",
+ [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD",
[_MAKE_CALLARGS_A_TUPLE] = "_MAKE_CALLARGS_A_TUPLE",
[_MAKE_CELL] = "_MAKE_CELL",
[_MAKE_FUNCTION] = "_MAKE_FUNCTION",
@@ -835,10 +845,8 @@ int _PyUop_num_popped(int opcode, int oparg)
return 2;
case _LOAD_SUPER_ATTR_ATTR:
return 3;
- case _LOAD_SUPER_METHOD_METHOD:
+ case _LOAD_SUPER_ATTR_METHOD:
return 3;
- case _LOAD_METHOD:
- return 1;
case _LOAD_ATTR:
return 1;
case _GUARD_TYPE_VERSION:
@@ -847,6 +855,10 @@ 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:
@@ -857,10 +869,18 @@ 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:
@@ -945,9 +965,9 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _GUARD_KEYS_VERSION:
return 0;
- case _LOAD_METHOD_WITH_VALUES:
+ case _LOAD_ATTR_METHOD_WITH_VALUES:
return 1;
- case _LOAD_METHOD_NO_DICT:
+ case _LOAD_ATTR_METHOD_NO_DICT:
return 1;
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES:
return 1;
@@ -955,7 +975,7 @@ int _PyUop_num_popped(int opcode, int oparg)
return 1;
case _CHECK_ATTR_METHOD_LAZY_DICT:
return 0;
- case _LOAD_METHOD_LAZY_DICT:
+ case _LOAD_ATTR_METHOD_LAZY_DICT:
return 1;
case _MAYBE_EXPAND_METHOD:
return 2 + oparg;
@@ -1046,7 +1066,7 @@ int _PyUop_num_popped(int opcode, int oparg)
case _CALL_KW_NON_PY:
return 3 + oparg;
case _MAKE_CALLARGS_A_TUPLE:
- return 2;
+ return 1 + (oparg & 1);
case _MAKE_FUNCTION:
return 1;
case _SET_FUNCTION_ATTRIBUTE:
@@ -1054,7 +1074,7 @@ int _PyUop_num_popped(int opcode, int oparg)
case _RETURN_GENERATOR:
return 0;
case _BUILD_SLICE:
- return oparg;
+ return 2 + ((oparg == 3) ? 1 : 0);
case _CONVERT_VALUE:
return 1;
case _FORMAT_SIMPLE:
diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h
index e931e76bdb193a..06b207b347e504 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 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 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 RESERVED 17
-#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 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 CALL_INTRINSIC_1 53
#define CALL_INTRINSIC_2 54
#define CALL_KW 55
@@ -100,36 +100,34 @@ extern "C" {
#define LOAD_FROM_DICT_OR_DEREF 87
#define LOAD_FROM_DICT_OR_GLOBALS 88
#define LOAD_GLOBAL 89
-#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 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 RESUME 149
#define BINARY_OP_ADD_FLOAT 150
#define BINARY_OP_ADD_INT 151
@@ -180,21 +178,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_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_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_SUPER_ATTR_ATTR 212
-#define LOAD_SUPER_METHOD_METHOD 213
+#define LOAD_SUPER_ATTR_METHOD 213
#define RESUME_CHECK 214
#define SEND_GEN 215
#define STORE_ATTR_INSTANCE_VALUE 216
@@ -211,11 +209,10 @@ extern "C" {
#define UNPACK_SEQUENCE_LIST 227
#define UNPACK_SEQUENCE_TUPLE 228
#define UNPACK_SEQUENCE_TWO_TUPLE 229
-#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_END_FOR 235
+#define INSTRUMENTED_POP_ITER 236
+#define INSTRUMENTED_END_SEND 237
+#define INSTRUMENTED_LOAD_SUPER_ATTR 238
#define INSTRUMENTED_FOR_ITER 239
#define INSTRUMENTED_CALL_KW 240
#define INSTRUMENTED_CALL_FUNCTION_EX 241
@@ -244,9 +241,9 @@ extern "C" {
#define SETUP_WITH 264
#define STORE_FAST_MAYBE_NULL 265
-#define HAVE_ARGUMENT 44
+#define HAVE_ARGUMENT 43
#define MIN_SPECIALIZED_OPCODE 150
-#define MIN_INSTRUMENTED_OPCODE 234
+#define MIN_INSTRUMENTED_OPCODE 235
#ifdef __cplusplus
}
diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py
index a32e6fe953b782..7dd528ef74df33 100644
--- a/Lib/_opcode_metadata.py
+++ b/Lib/_opcode_metadata.py
@@ -59,9 +59,7 @@
],
"LOAD_SUPER_ATTR": [
"LOAD_SUPER_ATTR_ATTR",
- ],
- "LOAD_SUPER_METHOD": [
- "LOAD_SUPER_METHOD_METHOD",
+ "LOAD_SUPER_ATTR_METHOD",
],
"LOAD_ATTR": [
"LOAD_ATTR_INSTANCE_VALUE",
@@ -72,14 +70,12 @@
"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",
@@ -175,21 +171,21 @@
'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 196,
'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 197,
'LOAD_ATTR_INSTANCE_VALUE': 198,
- '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_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_SUPER_ATTR_ATTR': 212,
- 'LOAD_SUPER_METHOD_METHOD': 213,
+ 'LOAD_SUPER_ATTR_METHOD': 213,
'RESUME_CHECK': 214,
'SEND_GEN': 215,
'STORE_ATTR_INSTANCE_VALUE': 216,
@@ -216,54 +212,54 @@
'ENTER_EXECUTOR': 255,
'BINARY_SLICE': 1,
'BINARY_SUBSCR': 2,
- '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,
+ '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_INTRINSIC_1': 53,
'CALL_INTRINSIC_2': 54,
'CALL_KW': 55,
@@ -301,41 +297,38 @@
'LOAD_FROM_DICT_OR_DEREF': 87,
'LOAD_FROM_DICT_OR_GLOBALS': 88,
'LOAD_GLOBAL': 89,
- '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,
+ '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,
'INSTRUMENTED_FOR_ITER': 239,
'INSTRUMENTED_CALL_KW': 240,
'INSTRUMENTED_CALL_FUNCTION_EX': 241,
@@ -363,5 +356,5 @@
'STORE_FAST_MAYBE_NULL': 265,
}
-HAVE_ARGUMENT = 44
-MIN_INSTRUMENTED_OPCODE = 234
+HAVE_ARGUMENT = 43
+MIN_INSTRUMENTED_OPCODE = 235
diff --git a/Lib/dis.py b/Lib/dis.py
index 5a34e228079481..109c986bbe3d7d 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -42,9 +42,7 @@
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']
@@ -582,14 +580,16 @@ 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, get_name)
- elif deop == LOAD_ATTR or deop == LOAD_METHOD:
- argval, argrepr = _get_name_info(arg, get_name)
- if deop == LOAD_METHOD and argrepr:
+ 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:
argrepr = f"{argrepr} + NULL|self"
- elif deop == LOAD_SUPER_ATTR or deop == LOAD_SUPER_METHOD:
+ elif deop == LOAD_SUPER_ATTR:
argval, argrepr = _get_name_info(arg//4, get_name)
- if deop == LOAD_SUPER_METHOD and argrepr:
+ if (arg & 1) 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 3d9ff07a3cfb7b..facad478103668 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" or opname == "LOAD_METHOD":
+ if opname == "LOAD_ATTR":
unbound_names.add(name)
elif opname == "LOAD_GLOBAL":
global_names.add(name)
diff --git a/Lib/opcode.py b/Lib/opcode.py
index d87149e95b5a33..4ee0d64026bd0a 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -72,21 +72,12 @@
"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 4b11e83ae59a78..95e09500df51d0 100644
--- a/Lib/test/test__opcode.py
+++ b/Lib/test/test__opcode.py
@@ -65,7 +65,8 @@ 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'], 2), -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'], 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 6a2f7726222f9b..9cfc6c142da6cd 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" in uops
+ assert "_LOAD_CONST_INLINE_BORROW_WITH_NULL" in uops
"""))
self.assertEqual(result[0].rc, 0, result)
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index f4123d2a85f52b..b5cf2ad18fe60b 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_METHOD", line=4, end_line=4, column=5, end_column=8
+ code, "LOAD_ATTR", 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 6fdcdbb0d9a3ad..da57aad2f84fbd 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -113,8 +113,7 @@ def _f(a):
dis_f = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 0 (print)
- PUSH_NULL
+%3d LOAD_GLOBAL 1 (print + NULL)
LOAD_FAST 0 (a)
CALL 1
POP_TOP
@@ -128,14 +127,13 @@ def _f(a):
dis_f_with_offsets = """\
%3d 0 RESUME 0
-%3d 2 LOAD_GLOBAL 0 (print)
- 12 PUSH_NULL
- 14 LOAD_FAST 0 (a)
- 16 CALL 1
- 24 POP_TOP
+%3d 2 LOAD_GLOBAL 1 (print + NULL)
+ 12 LOAD_FAST 0 (a)
+ 14 CALL 1
+ 22 POP_TOP
-%3d 26 LOAD_SMALL_INT 1
- 28 RETURN_VALUE
+%3d 24 LOAD_SMALL_INT 1
+ 26 RETURN_VALUE
""" % (_f.__code__.co_firstlineno,
_f.__code__.co_firstlineno + 1,
_f.__code__.co_firstlineno + 2)
@@ -143,8 +141,7 @@ def _f(a):
dis_f_with_positions_format = f"""\
%-14s RESUME 0
-%-14s LOAD_GLOBAL 0 (print)
-%-14s PUSH_NULL
+%-14s LOAD_GLOBAL 1 (print + NULL)
%-14s LOAD_FAST 0 (a)
%-14s CALL 1
%-14s POP_TOP
@@ -155,8 +152,7 @@ def _f(a):
dis_f_co_code = """\
RESUME 0
- LOAD_GLOBAL 0
- PUSH_NULL
+ LOAD_GLOBAL 1
LOAD_FAST 0
CALL 1
POP_TOP
@@ -172,8 +168,7 @@ def bug708901():
dis_bug708901 = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 0 (range)
- PUSH_NULL
+%3d LOAD_GLOBAL 1 (range + NULL)
LOAD_SMALL_INT 1
%3d LOAD_SMALL_INT 10
@@ -281,8 +276,7 @@ def wrap_func_w_kwargs():
dis_kw_names = """\
%3d RESUME 0
-%3d LOAD_GLOBAL 0 (func_w_kwargs)
- PUSH_NULL
+%3d LOAD_GLOBAL 1 (func_w_kwargs + NULL)
LOAD_SMALL_INT 1
LOAD_SMALL_INT 2
LOAD_SMALL_INT 5
@@ -469,7 +463,7 @@ def foo(a: int, b: str) -> str:
STORE_FAST 0 (e)
%4d L4: LOAD_FAST 0 (e)
- LOAD_ATTR 1 (__traceback__)
+ LOAD_ATTR 2 (__traceback__)
STORE_FAST 1 (tb)
L5: POP_EXCEPT
LOAD_CONST 0 (None)
@@ -820,8 +814,7 @@ def foo(x):
%4d RESUME 0
-%4d LOAD_GLOBAL 0 (list)
- PUSH_NULL
+%4d LOAD_GLOBAL 1 (list + NULL)
LOAD_FAST 0 (x)
BUILD_TUPLE 1
LOAD_CONST 1 (<code object <genexpr> at 0x..., file "%s", line %d>)
@@ -904,15 +897,14 @@ def loop_test():
LOAD_SMALL_INT 3
BINARY_OP 5 (*)
GET_ITER
- L1: FOR_ITER_LIST 15 (to L2)
+ L1: FOR_ITER_LIST 14 (to L2)
STORE_FAST 0 (i)
-%3d LOAD_GLOBAL_MODULE 0 (load_test)
- PUSH_NULL
+%3d LOAD_GLOBAL_MODULE 1 (load_test + NULL)
LOAD_FAST 0 (i)
CALL_PY_GENERAL 1
POP_TOP
- JUMP_BACKWARD 17 (to L1)
+ JUMP_BACKWARD 16 (to L1)
%3d L2: END_FOR
POP_ITER
@@ -1713,215 +1705,203 @@ def _prepare_test_cases():
Instruction = dis.Instruction
expected_opinfo_outer = [
- 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='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='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=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='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='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=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),
+ 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),
]
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=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='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='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=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='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='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=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),
+ 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),
]
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=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),
+ 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),
]
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=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),
+ 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),
]
# One last piece of inspect fodder to check the default line number handling
@@ -1929,7 +1909,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=36, 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=35, arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None),
]
@@ -2153,7 +2133,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"], 1, *args), ('a', 'a'))
+ self.assertEqual(f(opcode.opmap["LOAD_GLOBAL"], 2, *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 c93d6fc3d237a2..b5367a0f3ca367 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,6 +104,20 @@ 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)) {
@@ -124,6 +138,25 @@ 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)) {
@@ -905,6 +938,90 @@ 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 7ac2910cfb7854..364381e7dce00a 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', 30, 34),
- ('branch right', 'func', 46, 60),
- ('branch left', 'func', 30, 34),
- ('branch left', 'func', 46, 52),
- ('branch right', 'func', 30, 72)])
+ ('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)])
def test_except_star(self):
@@ -1762,8 +1762,7 @@ def _exec_super(self, codestr, optimized=False):
return self._exec(co)
def _has_load_super_attr(self, co):
- has = any(instr.opname in ("LOAD_SUPER_ATTR", "LOAD_SUPER_METHOD")
- for instr in dis.get_instructions(co))
+ has = any(instr.opname == "LOAD_SUPER_ATTR" 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 1895a5001fd318..4d7304b1c9abb6 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_METHOD_LAZY_DICT"
+ opname = "LOAD_ATTR_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_METHOD_NO_DICT"
+ opname = "LOAD_ATTR_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_METHOD_WITH_VALUES"
+ opname = "LOAD_ATTR_METHOD_WITH_VALUES"
self.assert_races_do_not_crash(opname, get_items, read, write)
@requires_specialization_ft
@@ -1424,9 +1424,8 @@ def __init__(self):
A()
self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_ATTR")
- self.assert_specialized(A.__init__, "LOAD_SUPER_METHOD_METHOD")
+ self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_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
deleted file mode 100644
index 63f71590363273..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-10-17-01.gh-issue-128914.dn6RaW.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-: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 44b3a2a75626c9..15ec4b78235992 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1261,18 +1261,27 @@ 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 0a15c1e1de5499..51b6016b9c191c 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 loading methods
+ specifically for the LOAD_METHOD opcode.
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 be05fae1a6d831..4f6933ac0ddcd6 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,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,
+ 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,
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 c78d496adcd086..b70ed7f4d10b27 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -348,8 +348,8 @@ dummy_func(
DECREF_INPUTS();
}
- pure inst(PUSH_NULL, (-- null)) {
- null = PyStackRef_NULL;
+ pure inst(PUSH_NULL, (-- res)) {
+ res = PyStackRef_NULL;
}
no_save_ip inst(END_FOR, (value -- )) {
@@ -1654,7 +1654,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);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1665,10 +1665,11 @@ dummy_func(
}
// res[1] because we need a pointer to res to pass it to _PyEval_LoadGlobalStackRef
- op(_LOAD_GLOBAL, ( -- res[1])) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ op(_LOAD_GLOBAL, ( -- res[1], null if (oparg & 1))) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
ERROR_IF(PyStackRef_IsNull(*res), error);
+ null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL) =
@@ -1706,7 +1707,7 @@ dummy_func(
assert(DK_IS_UNICODE(builtins_keys));
}
- op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res)) {
+ op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(globals_keys);
@@ -1720,9 +1721,10 @@ 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)) {
+ op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(builtins_keys);
@@ -1736,6 +1738,7 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL_MODULE) =
@@ -2009,27 +2012,17 @@ 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,
- };
-
-
- family(LOAD_SUPER_METHOD, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
- LOAD_SUPER_METHOD_METHOD,
+ LOAD_SUPER_ATTR_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, 0);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method);
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(LOAD_SUPER_ATTR);
@@ -2037,24 +2030,12 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- 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)) {
+ tier1 op(_LOAD_SUPER_ATTR, (global_super_st, class_st, self_st -- attr, null if (oparg & 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) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -2068,7 +2049,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 >= MIN_INSTRUMENTED_OPCODE) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_Py_call_instrumentation_exc2(
@@ -2091,13 +2072,12 @@ 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)) {
+ inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st, unused if (0))) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
@@ -2113,7 +2093,7 @@ dummy_func(
attr_st = PyStackRef_FromPyObjectSteal(attr);
}
- inst(LOAD_SUPER_METHOD_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) {
+ inst(LOAD_SUPER_ATTR_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);
@@ -2152,20 +2132,17 @@ 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);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_Py_Specialize_LoadAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -2175,67 +2152,50 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- 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);
+ op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
- /* 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
+ 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
*/
- assert(attr_o != NULL); // No errors on this branch
- self_or_null = owner; // Transfer ownership
- DEAD(owner);
+ DECREF_INPUTS();
+ ERROR_IF(attr_o == NULL, error);
+ self_or_null = PyStackRef_NULL;
+ }
}
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
- */
+ /* Classic, pushes one value. */
+ attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
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);
@@ -2260,7 +2220,7 @@ dummy_func(
DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid));
}
- op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
+ split op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
@@ -2273,6 +2233,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2293,7 +2254,7 @@ dummy_func(
mod_keys = keys;
}
- op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr)) {
+ op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr, null if (oparg & 1))) {
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;
@@ -2311,6 +2272,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
@@ -2330,7 +2292,7 @@ dummy_func(
dict = dict_o;
}
- op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr)) {
+ op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr, null if (oparg & 1))) {
PyObject *attr_o;
if (!LOCK_OBJECT(dict)) {
POP_INPUT(dict);
@@ -2342,7 +2304,7 @@ dummy_func(
POP_INPUT(dict);
DEOPT_IF(true);
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
POP_INPUT(dict);
@@ -2364,6 +2326,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
DEAD(dict);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2374,7 +2337,7 @@ dummy_func(
_LOAD_ATTR_WITH_HINT +
unused/5;
- op(_LOAD_ATTR_SLOT, (index/1, owner -- attr)) {
+ split op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **addr = (PyObject **)((char *)owner_o + index);
@@ -2387,6 +2350,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2404,10 +2368,11 @@ dummy_func(
EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(((PyTypeObject *)owner_o)->tp_version_tag) != type_version);
}
- op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
+ split op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2424,6 +2389,7 @@ 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;
@@ -2446,8 +2412,10 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
- inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused)) {
+ inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused, unused if (0))) {
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);
@@ -2461,7 +2429,7 @@ dummy_func(
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -3380,7 +3348,8 @@ dummy_func(
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version);
}
- op(_LOAD_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
+ split op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3390,14 +3359,15 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_WITH_VALUES) =
+ macro(LOAD_ATTR_METHOD_WITH_VALUES) =
unused/1 +
_GUARD_TYPE_VERSION +
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
_GUARD_KEYS_VERSION +
- _LOAD_METHOD_WITH_VALUES;
+ _LOAD_ATTR_METHOD_WITH_VALUES;
- op(_LOAD_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3407,13 +3377,14 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_NO_DICT) =
+ macro(LOAD_ATTR_METHOD_NO_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
unused/2 +
- _LOAD_METHOD_NO_DICT;
+ _LOAD_ATTR_METHOD_NO_DICT;
- op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) {
+ op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr, unused if (0))) {
+ assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
DECREF_INPUTS();
@@ -3427,7 +3398,8 @@ dummy_func(
_GUARD_KEYS_VERSION +
_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
- op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
+ op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr, unused if (0))) {
+ assert((oparg & 1) == 0);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3448,7 +3420,8 @@ dummy_func(
DEOPT_IF(dict != NULL);
}
- op(_LOAD_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
@@ -3457,12 +3430,12 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_LAZY_DICT) =
+ macro(LOAD_ATTR_METHOD_LAZY_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
_CHECK_ATTR_METHOD_LAZY_DICT +
unused/1 +
- _LOAD_METHOD_LAZY_DICT;
+ _LOAD_ATTR_METHOD_LAZY_DICT;
// Cache layout: counter/1, func_version/2
// CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members!
@@ -4564,7 +4537,7 @@ dummy_func(
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
- op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) {
+ op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in if (oparg & 1) -- func, unused, tuple, kwargs_out if (oparg & 1))) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -4588,7 +4561,7 @@ dummy_func(
}
}
- op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st -- result)) {
+ op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
// DICT_MERGE is called before this opcode if there are kwargs.
@@ -4722,16 +4695,11 @@ dummy_func(
LLTRACE_RESUME_FRAME();
}
- inst(BUILD_SLICE, (args[oparg] -- slice)) {
- assert(oparg == 2 || oparg == 3);
- _PyStackRef start = args[0];
- _PyStackRef stop = args[1];
+ inst(BUILD_SLICE, (start, stop, step if (oparg == 3) -- slice)) {
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject * step_o = NULL;
- if (oparg == 3) {
- step_o = PyStackRef_AsPyObjectBorrow(args[2]);
- }
+ PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
+
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
DECREF_INPUTS();
ERROR_IF(slice_o == NULL, error);
@@ -5074,25 +5042,27 @@ dummy_func(
DEOPT_IF(func->func_version != func_version);
}
- tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res)) {
+ tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res, null if (oparg & 1))) {
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)) {
+ tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res, null if (oparg & 1))) {
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)) {
+ tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
@@ -5103,6 +5073,7 @@ 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 b3f845569684de..61707ba677097c 100644
--- a/Python/codegen.c
+++ b/Python/codegen.c
@@ -348,6 +348,8 @@ 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
@@ -364,11 +366,20 @@ 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;
}
@@ -377,7 +388,7 @@ codegen_addop_name(compiler *c, location loc,
arg <<= 2;
}
if (opcode == LOAD_ZERO_SUPER_METHOD) {
- opcode = LOAD_SUPER_METHOD;
+ opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 1;
}
@@ -3154,6 +3165,9 @@ 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;
@@ -4094,10 +4108,7 @@ codegen_call_helper_impl(compiler *c, location loc,
}
assert(have_dict);
}
- if (nkwelts == 0) {
- ADDOP(c, loc, PUSH_NULL);
- }
- ADDOP(c, loc, CALL_FUNCTION_EX);
+ ADDOP_I(c, loc, CALL_FUNCTION_EX, nkwelts > 0);
return SUCCESS;
}
@@ -4830,10 +4841,8 @@ 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
- LOAD_CONST None
- LOAD_CONST None
- CALL 3
+ LOAD_CONST (None, None, None)
+ CALL_FUNCTION_EX 0
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 d2da9a8acf9d97..d336f73c4a2de5 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -406,9 +406,9 @@
}
case _PUSH_NULL: {
- _PyStackRef null;
- null = PyStackRef_NULL;
- stack_pointer[0] = null;
+ _PyStackRef res;
+ res = PyStackRef_NULL;
+ stack_pointer[0] = res;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -1953,14 +1953,17 @@
case _LOAD_GLOBAL: {
_PyStackRef *res;
+ _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
res = &stack_pointer[0];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(*res)) JUMP_TO_ERROR();
- stack_pointer += 1;
+ null = PyStackRef_NULL;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2026,6 +2029,8 @@
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);
@@ -2047,8 +2052,10 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2056,6 +2063,8 @@
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);
@@ -2077,8 +2086,10 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2508,8 +2519,6 @@
/* _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;
@@ -2547,7 +2556,7 @@
break;
}
- case _LOAD_SUPER_METHOD_METHOD: {
+ case _LOAD_SUPER_ATTR_METHOD: {
_PyStackRef self_st;
_PyStackRef class_st;
_PyStackRef global_super_st;
@@ -2596,62 +2605,58 @@
break;
}
- case _LOAD_METHOD: {
+ case _LOAD_ATTR: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self_or_null;
+ _PyStackRef self_or_null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
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
+ 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;
+ }
}
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
- */
+ /* 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) 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;
- stack_pointer[0] = self_or_null;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[0] = self_or_null;
+ stack_pointer += (oparg & 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];
@@ -2699,9 +2704,42 @@
break;
}
- case _LOAD_ATTR_INSTANCE_VALUE: {
+ 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: {
_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);
@@ -2722,11 +2760,17 @@
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;
@@ -2755,6 +2799,8 @@
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();
@@ -2782,8 +2828,12 @@
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;
}
@@ -2810,6 +2860,7 @@
PyDictObject *dict;
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
dict = (PyDictObject *)stack_pointer[-1].bits;
owner = stack_pointer[-2];
@@ -2832,7 +2883,7 @@
JUMP_TO_JUMP_TARGET();
}
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
stack_pointer += -1;
@@ -2865,16 +2916,20 @@
STAT_INC(LOAD_ATTR, hit);
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-2] = attr;
- stack_pointer += -1;
+ if (oparg & 1) stack_pointer[-1] = null;
+ stack_pointer += -1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
- case _LOAD_ATTR_SLOT: {
+ case _LOAD_ATTR_SLOT_0: {
_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);
@@ -2894,11 +2949,47 @@
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];
@@ -2916,24 +3007,50 @@
break;
}
- case _LOAD_ATTR_CLASS: {
+ case _LOAD_ATTR_CLASS_0: {
_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;
@@ -3939,12 +4056,14 @@
break;
}
- case _LOAD_METHOD_WITH_VALUES: {
+ case _LOAD_ATTR_METHOD_WITH_VALUES: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3958,12 +4077,14 @@
break;
}
- case _LOAD_METHOD_NO_DICT: {
+ case _LOAD_ATTR_METHOD_NO_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
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);
@@ -3980,8 +4101,10 @@
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);
@@ -3993,8 +4116,10 @@
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);
@@ -4018,12 +4143,14 @@
break;
}
- case _LOAD_METHOD_LAZY_DICT: {
+ case _LOAD_ATTR_METHOD_LAZY_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
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));
@@ -5517,14 +5644,15 @@
/* _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 kwargs_in = PyStackRef_NULL;
_PyStackRef callargs;
_PyStackRef func;
_PyStackRef tuple;
- _PyStackRef kwargs_out;
- kwargs_in = stack_pointer[-1];
- callargs = stack_pointer[-2];
- func = stack_pointer[-4];
+ _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)];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -5547,8 +5675,8 @@
PyStackRef_CLOSE(callargs);
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
}
- stack_pointer[-2] = tuple;
- stack_pointer[-1] = kwargs_out;
+ stack_pointer[-1 - (oparg & 1)] = tuple;
+ if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out;
break;
}
@@ -5625,27 +5753,25 @@
}
case _BUILD_SLICE: {
- _PyStackRef *args;
+ _PyStackRef step = PyStackRef_NULL;
+ _PyStackRef stop;
+ _PyStackRef start;
_PyStackRef slice;
oparg = CURRENT_OPARG();
- args = &stack_pointer[-oparg];
- assert(oparg == 2 || oparg == 3);
- _PyStackRef start = args[0];
- _PyStackRef stop = args[1];
+ 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)];
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject * step_o = NULL;
- if (oparg == 3) {
- step_o = PyStackRef_AsPyObjectBorrow(args[2]);
- }
+ PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
- for (int _i = oparg; --_i >= 0;) {
- PyStackRef_CLOSE(args[_i]);
- }
+ PyStackRef_CLOSE(start);
+ PyStackRef_CLOSE(stop);
+ PyStackRef_XCLOSE(step);
if (slice_o == NULL) JUMP_TO_ERROR();
slice = PyStackRef_FromPyObjectSteal(slice_o);
- stack_pointer[-oparg] = slice;
- stack_pointer += 1 - oparg;
+ stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
+ stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6012,6 +6138,8 @@
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);
@@ -6022,14 +6150,18 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 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);
@@ -6040,8 +6172,10 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6049,6 +6183,8 @@
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);
@@ -6064,8 +6200,12 @@
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 3f8d9db166ff98..24561c1ee04db9 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1836,6 +1836,12 @@ 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 7b49f336383a7a..4fb3ce6f6da9cd 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -833,30 +833,28 @@
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(BUILD_SLICE);
- _PyStackRef *args;
+ _PyStackRef start;
+ _PyStackRef stop;
+ _PyStackRef step = PyStackRef_NULL;
_PyStackRef slice;
- args = &stack_pointer[-oparg];
- assert(oparg == 2 || oparg == 3);
- _PyStackRef start = args[0];
- _PyStackRef stop = args[1];
+ 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)];
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject * step_o = NULL;
- if (oparg == 3) {
- step_o = PyStackRef_AsPyObjectBorrow(args[2]);
- }
+ PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
- for (int _i = oparg; --_i >= 0;) {
- PyStackRef_CLOSE(args[_i]);
- }
+ PyStackRef_CLOSE(start);
+ PyStackRef_CLOSE(stop);
+ PyStackRef_XCLOSE(step);
if (slice_o == NULL) {
- stack_pointer += -oparg;
+ stack_pointer += -2 - ((oparg == 3) ? 1 : 0);
assert(WITHIN_STACK_BOUNDS());
goto error;
}
slice = PyStackRef_FromPyObjectSteal(slice_o);
- stack_pointer[-oparg] = slice;
- stack_pointer += 1 - oparg;
+ stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
+ stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -1708,18 +1706,18 @@
(void)this_instr;
_PyStackRef func;
_PyStackRef callargs;
- _PyStackRef kwargs_in;
+ _PyStackRef kwargs_in = PyStackRef_NULL;
_PyStackRef tuple;
- _PyStackRef kwargs_out;
+ _PyStackRef kwargs_out = PyStackRef_NULL;
_PyStackRef func_st;
_PyStackRef callargs_st;
- _PyStackRef kwargs_st;
+ _PyStackRef kwargs_st = PyStackRef_NULL;
_PyStackRef result;
// _MAKE_CALLARGS_A_TUPLE
{
- kwargs_in = stack_pointer[-1];
- callargs = stack_pointer[-2];
- func = stack_pointer[-4];
+ if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; }
+ callargs = stack_pointer[-1 - (oparg & 1)];
+ func = stack_pointer[-3 - (oparg & 1)];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -1761,8 +1759,8 @@
assert(PyTuple_CheckExact(callargs));
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
- stack_pointer[-2] = callargs_st;
- stack_pointer[-1] = kwargs_st;
+ stack_pointer[-1 - (oparg & 1)] = callargs_st;
+ if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -1805,7 +1803,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 += -3;
+ stack_pointer += -2 - (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
@@ -1826,8 +1824,8 @@
assert(PyTuple_CheckExact(callargs));
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
- stack_pointer[-2] = callargs_st;
- stack_pointer[-1] = kwargs_st;
+ stack_pointer[-1 - (oparg & 1)] = callargs_st;
+ if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
result_o = PyObject_Call(func, callargs, kwargs);
stack_pointer = _PyFrame_GetStackPointer(frame);
@@ -1837,7 +1835,11 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
PyStackRef_CLOSE(callargs_st);
PyStackRef_CLOSE(func_st);
- if (result_o == NULL) goto pop_4_error;
+ if (result_o == NULL) {
+ stack_pointer += -3 - (oparg & 1);
+ assert(WITHIN_STACK_BOUNDS());
+ goto error;
+ }
result = PyStackRef_FromPyObjectSteal(result_o);
}
// _CHECK_PERIODIC
@@ -1845,19 +1847,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[-4] = result;
- stack_pointer += -3;
+ stack_pointer[-3 - (oparg & 1)] = result;
+ stack_pointer += -2 - (oparg & 1);
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 += 3;
+ stack_pointer += 2 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
}
}
- stack_pointer[-4] = result;
- stack_pointer += -3;
+ stack_pointer[-3 - (oparg & 1)] = result;
+ stack_pointer += -2 - (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -4846,18 +4848,6 @@
goto PREDICTED_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);
- goto PREDICTED_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;
@@ -5311,6 +5301,7 @@
(void)this_instr;
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef self_or_null = PyStackRef_NULL;
// _SPECIALIZE_LOAD_ATTR
{
owner = stack_pointer[-1];
@@ -5318,7 +5309,7 @@
(void)counter;
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_Specialize_LoadAttr(owner, next_instr, name);
@@ -5332,15 +5323,50 @@
/* Skip 8 cache entries */
// _LOAD_ATTR
{
- 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;
+ 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;
+ }
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();
}
@@ -5351,6 +5377,7 @@
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
{
@@ -5368,9 +5395,13 @@
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();
}
@@ -5381,6 +5412,7 @@
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
{
@@ -5404,9 +5436,13 @@
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();
}
@@ -5422,6 +5458,7 @@
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);
@@ -5434,7 +5471,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);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -5452,6 +5489,7 @@
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
{
@@ -5483,10 +5521,143 @@
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();
}
@@ -5498,6 +5669,7 @@
_PyStackRef owner;
PyDictKeysObject *mod_keys;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _CHECK_ATTR_MODULE_PUSH_KEYS
{
@@ -5530,10 +5702,14 @@
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();
}
@@ -5557,6 +5733,7 @@
// _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);
@@ -5601,6 +5778,7 @@
// _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);
@@ -5634,6 +5812,7 @@
// _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;
@@ -5681,6 +5860,7 @@
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
{
@@ -5704,10 +5884,14 @@
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();
}
@@ -5719,6 +5903,7 @@
_PyStackRef owner;
PyDictObject *dict;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -5748,7 +5933,7 @@
UNLOCK_OBJECT(dict);
DEOPT_IF(true, LOAD_ATTR);
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
DEOPT_IF(true, LOAD_ATTR);
@@ -5766,10 +5951,14 @@
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();
}
@@ -6070,13 +6259,14 @@
_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);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
@@ -6093,13 +6283,15 @@
// _LOAD_GLOBAL
{
res = &stack_pointer[0];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_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;
}
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6111,6 +6303,7 @@
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
{
@@ -6145,9 +6338,11 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
}
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6159,6 +6354,7 @@
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
{
@@ -6185,9 +6381,11 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
}
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6212,198 +6410,6 @@
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;
@@ -6483,6 +6489,7 @@
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
// _SPECIALIZE_LOAD_SUPER_ATTR
{
class_st = stack_pointer[-2];
@@ -6490,10 +6497,11 @@
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, 0);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method);
stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH_SAME_OPARG();
}
@@ -6507,7 +6515,7 @@
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) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
@@ -6527,7 +6535,7 @@
_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) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -6560,9 +6568,11 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
if (attr_o == NULL) goto error;
attr = PyStackRef_FromPyObjectSteal(attr_o);
+ null = PyStackRef_NULL;
}
stack_pointer[0] = attr;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
@@ -6602,111 +6612,10 @@
DISPATCH();
}
- TARGET(LOAD_SUPER_METHOD) {
+ TARGET(LOAD_SUPER_ATTR_METHOD) {
frame->instr_ptr = next_instr;
next_instr += 2;
- 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);
+ INSTRUCTION_STATS(LOAD_SUPER_ATTR_METHOD);
static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size");
_PyStackRef global_super_st;
_PyStackRef class_st;
@@ -6721,8 +6630,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_METHOD);
- DEOPT_IF(!PyType_Check(class), LOAD_SUPER_METHOD);
+ DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
+ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
STAT_INC(LOAD_SUPER_ATTR, hit);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyTypeObject *cls = (PyTypeObject *)class;
@@ -7087,9 +6996,9 @@
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(PUSH_NULL);
- _PyStackRef null;
- null = PyStackRef_NULL;
- stack_pointer[0] = null;
+ _PyStackRef res;
+ res = PyStackRef_NULL;
+ stack_pointer[0] = res;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index d20195d426fc00..0e7b4810726434 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -81,8 +81,6 @@ 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,
@@ -128,7 +126,6 @@ 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,
};
@@ -167,8 +164,6 @@ 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 2e35ae710b1430..cb6c33f01d3598 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -3,7 +3,6 @@ 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,
@@ -16,8 +15,8 @@ static void *opcode_targets[256] = {
&&TARGET_FORMAT_WITH_SPEC,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
- &&TARGET_RESERVED,
&&TARGET_GET_ITER,
+ &&TARGET_RESERVED,
&&TARGET_GET_LEN,
&&TARGET_GET_YIELD_FROM_ITER,
&&TARGET_INTERPRETER_EXIT,
@@ -52,6 +51,7 @@ 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,12 +89,10 @@ 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,
@@ -148,6 +146,8 @@ 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,6 +198,9 @@ 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,
@@ -208,11 +211,8 @@ 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_METHOD_METHOD,
+ &&TARGET_LOAD_SUPER_ATTR_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 b91caf11ffa962..9beb47246eb3d6 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -1274,7 +1274,10 @@ uop_optimize(
for (int pc = 0; pc < length; pc++) {
int opcode = buffer[pc].opcode;
int oparg = buffer[pc].oparg;
- if (oparg < _PyUop_Replication[opcode]) {
+ if (_PyUop_Flags[opcode] & HAS_OPARG_AND_1_FLAG) {
+ buffer[pc].opcode = opcode + 1 + (oparg & 1);
+ }
+ else 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 05f9592e9a23fa..b9ac30ea04e4e8 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 = _LOAD_CONST_INLINE_BORROW;
+ inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_BORROW_WITH_NULL : _LOAD_CONST_INLINE_BORROW;
}
else {
- inst->opcode = _LOAD_CONST_INLINE;
+ inst->opcode = (inst->oparg & 1) ? _LOAD_CONST_INLINE_WITH_NULL : _LOAD_CONST_INLINE;
}
inst->operand0 = (uint64_t)res;
return res;
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index af834b6957be22..881a607ca2aa29 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -528,8 +528,9 @@ dummy_func(void) {
top_out = top_in;
}
- op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
+ op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) {
attr = sym_new_not_null(ctx);
+ null = sym_new_null(ctx);
(void)offset;
(void)owner;
}
@@ -552,19 +553,15 @@ dummy_func(void) {
}
}
- op(_LOAD_ATTR, (owner -- attr)) {
- (void)owner;
- attr = sym_new_not_null(ctx);
- }
-
- op(_LOAD_METHOD, (owner -- attr, self_or_null)) {
+ op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
(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)) {
+ op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys -- attr, null if (oparg & 1))) {
(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.
@@ -592,38 +589,41 @@ dummy_func(void) {
(void)owner;
}
- op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict -- attr)) {
+ op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict -- attr, null if (oparg & 1))) {
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)) {
+ op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
attr = sym_new_not_null(ctx);
+ null = sym_new_null(ctx);
(void)index;
(void)owner;
}
- op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
+ op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
attr = sym_new_not_null(ctx);
+ null = sym_new_null(ctx);
(void)descr;
(void)owner;
}
- op(_LOAD_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
(void)descr;
attr = sym_new_not_null(ctx);
self = owner;
}
- op(_LOAD_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
(void)descr;
attr = sym_new_not_null(ctx);
self = owner;
}
- op(_LOAD_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
(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 * -- )) {
+ op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) {
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 cb4651a5d8093c..fa0b4ed4345320 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -928,9 +928,12 @@
case _LOAD_GLOBAL: {
JitOptSymbol **res;
+ JitOptSymbol *null = NULL;
res = &stack_pointer[0];
res[0] = sym_new_not_null(ctx);
- stack_pointer += 1;
+ null = sym_new_null(ctx);
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -963,15 +966,25 @@
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;
}
@@ -1096,8 +1109,6 @@
/* _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);
@@ -1107,7 +1118,7 @@
break;
}
- case _LOAD_SUPER_METHOD_METHOD: {
+ case _LOAD_SUPER_ATTR_METHOD: {
JitOptSymbol *attr;
JitOptSymbol *self_or_null;
attr = sym_new_not_null(ctx);
@@ -1119,31 +1130,21 @@
break;
}
- case _LOAD_METHOD: {
+ case _LOAD_ATTR: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self_or_null;
+ JitOptSymbol *self_or_null = NULL;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_unknown(ctx);
stack_pointer[-1] = attr;
- stack_pointer[0] = self_or_null;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[0] = self_or_null;
+ stack_pointer += (oparg & 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];
@@ -1181,12 +1182,17 @@
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;
}
@@ -1224,9 +1230,11 @@
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.
@@ -1235,7 +1243,8 @@
assert(PyModule_CheckExact(mod));
PyObject *dict = mod->md_dict;
stack_pointer[-2] = attr;
- stack_pointer += -1;
+ if (oparg & 1) stack_pointer[-1] = null;
+ stack_pointer += -1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
PyObject *res = convert_global_to_const(this_instr, dict);
if (res != NULL) {
@@ -1245,7 +1254,7 @@
else {
this_instr->opcode = _LOAD_ATTR_MODULE;
}
- stack_pointer += 1;
+ stack_pointer += 1 - (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
}
if (attr == NULL) {
@@ -1253,7 +1262,8 @@
attr = sym_new_not_null(ctx);
}
stack_pointer[-2] = attr;
- stack_pointer += -1;
+ if (oparg & 1) stack_pointer[-1] = null;
+ stack_pointer += -1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1274,15 +1284,18 @@
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;
- stack_pointer += -1;
+ if (oparg & 1) stack_pointer[-1] = null;
+ stack_pointer += -1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1290,12 +1303,17 @@
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;
}
@@ -1306,12 +1324,17 @@
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;
}
@@ -1697,10 +1720,10 @@
break;
}
- case _LOAD_METHOD_WITH_VALUES: {
+ case _LOAD_ATTR_METHOD_WITH_VALUES: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1713,10 +1736,10 @@
break;
}
- case _LOAD_METHOD_NO_DICT: {
+ case _LOAD_ATTR_METHOD_NO_DICT: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1747,10 +1770,10 @@
break;
}
- case _LOAD_METHOD_LAZY_DICT: {
+ case _LOAD_ATTR_METHOD_LAZY_DICT: {
JitOptSymbol *owner;
JitOptSymbol *attr;
- JitOptSymbol *self;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -2239,11 +2262,11 @@
case _MAKE_CALLARGS_A_TUPLE: {
JitOptSymbol *tuple;
- JitOptSymbol *kwargs_out;
+ JitOptSymbol *kwargs_out = NULL;
tuple = sym_new_not_null(ctx);
kwargs_out = sym_new_not_null(ctx);
- stack_pointer[-2] = tuple;
- stack_pointer[-1] = kwargs_out;
+ stack_pointer[-1 - (oparg & 1)] = tuple;
+ if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out;
break;
}
@@ -2292,8 +2315,8 @@
case _BUILD_SLICE: {
JitOptSymbol *slice;
slice = sym_new_not_null(ctx);
- stack_pointer[-oparg] = slice;
- stack_pointer += 1 - oparg;
+ stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
+ stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2616,26 +2639,37 @@
case _LOAD_GLOBAL_MODULE: {
JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
+ null = sym_new_null(ctx);
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 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;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 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 eb599028cefafa..fa022346bdea6a 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_METHOD_METHOD : LOAD_SUPER_ATTR_ATTR;
+ uint8_t load_code = load_method ? LOAD_SUPER_ATTR_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, bool load_method)
+ DescriptorClassification kind, PyObject *descr, unsigned int tp_version)
{
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
PyTypeObject *type = Py_TYPE(owner);
@@ -1117,16 +1117,17 @@ 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_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
return -1;
case METHOD:
{
if (shadow) {
goto try_instance;
}
- if (load_method) {
+ if (oparg & 1) {
if (specialize_attr_loadclassattr(owner, instr, name, descr,
tp_version, kind, true,
shared_keys_version)) {
@@ -1136,7 +1137,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
return -1;
}
}
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
return -1;
}
case PROPERTY:
@@ -1145,28 +1146,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_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
return -1;
}
if (!Py_IS_TYPE(fget, &PyFunction_Type)) {
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
return -1;
}
- if (load_method) {
- SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_ATTR_METHOD);
+ if (!function_check_args(fget, 1, LOAD_ATTR)) {
return -1;
}
- if (!function_check_args(fget, 1, LOAD_ATTR)) {
+ if (oparg & 1) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
return -1;
}
/* Don't specialize if PEP 523 is active */
if (_PyInterpreterState_GET()->eval_frame) {
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OTHER);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
return -1;
}
#ifdef Py_GIL_DISABLED
if (!_PyObject_HasDeferredRefcount(fget)) {
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
return -1;
}
#endif
@@ -1179,10 +1180,6 @@ 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;
@@ -1207,10 +1204,6 @@ 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;
@@ -1219,20 +1212,16 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
return 0;
}
case OTHER_SLOT:
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
return -1;
case MUTABLE:
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
return -1;
case GETSET_OVERRIDDEN:
- SPECIALIZATION_FAIL(load_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
+ SPECIALIZATION_FAIL(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
@@ -1244,6 +1233,10 @@ 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;
@@ -1277,7 +1270,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
if (shadow) {
goto try_instance;
}
- if (!load_method) {
+ if ((oparg & 1) == 0) {
if (specialize_attr_loadclassattr(owner, instr, name, descr,
tp_version, kind, false,
shared_keys_version)) {
@@ -1294,10 +1287,6 @@ 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))
{
@@ -1307,7 +1296,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, bool load_method)
+specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
{
// 0 is not a valid version
uint32_t shared_keys_version = 0;
@@ -1316,7 +1305,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, load_method);
+ int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
Py_XDECREF(descr);
return result;
}
@@ -1344,40 +1333,7 @@ _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, 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);
+ fail = specialize_instance_load_attr(owner, instr, name);
}
if (fail) {
@@ -1619,7 +1575,7 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
#ifdef Py_GIL_DISABLED
if (!_PyObject_HasDeferredRefcount(descr)) {
- SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
return 0;
}
#endif
@@ -1631,11 +1587,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(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return 0;
}
write_u32(cache->keys_version, shared_keys_version);
- specialize(instr, is_method ? LOAD_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
+ specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
}
else {
Py_ssize_t dictoffset;
@@ -1645,17 +1601,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(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
return 0;
}
}
if (dictoffset == 0) {
- specialize(instr, is_method ? LOAD_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
+ specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
}
else if (is_method) {
PyObject *dict = *(PyObject **) ((char *)owner + dictoffset);
if (dict) {
- SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
return 0;
}
/* Cache entries must be unsigned values, so we offset the
@@ -1664,10 +1620,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_METHOD_LAZY_DICT);
+ specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
}
else {
- SPECIALIZATION_FAIL(is_method ? LOAD_METHOD : LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
+ SPECIALIZATION_FAIL(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 e8ee314879893d..3daae46e61fcf2 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -25,6 +25,7 @@ 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
@@ -123,14 +124,16 @@ 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} {self.peek}"
+ return f"{type}{self.name}{size}{cond} {self.peek}"
def is_array(self) -> bool:
return self.size != ""
@@ -312,19 +315,25 @@ def override_error(
)
-def convert_stack_item(item: parser.StackEffect) -> StackItem:
- return StackItem(item.name, item.type, item.size)
+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 analyze_stack(
- op: parser.InstDef | parser.Pseudo) -> StackEffect:
+ op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | None = None
+) -> StackEffect:
inputs: list[StackItem] = [
- convert_stack_item(i)
+ convert_stack_item(i, replace_op_arg_1)
for i in op.inputs
if isinstance(i, parser.StackEffect)
]
outputs: list[StackItem] = [
- convert_stack_item(i) for i in op.outputs
+ convert_stack_item(i, replace_op_arg_1) for i in op.outputs
]
# Mark variables with matching names at the base of the stack as "peek"
modified = False
@@ -746,6 +755,40 @@ 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 = (
@@ -819,6 +862,29 @@ 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 9edf3d4898eb4d..f1f166ae104ba5 100644
--- a/Tools/cases_generator/generators_common.py
+++ b/Tools/cases_generator/generators_common.py
@@ -247,7 +247,7 @@ def decref_inputs(
if var.name == "null":
continue
close = "PyStackRef_CLOSE"
- if "null" in var.name:
+ if "null" in var.name or var.condition and var.condition != "1":
close = "PyStackRef_XCLOSE"
if var.size:
if var.size == "1":
@@ -256,6 +256,9 @@ 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:
@@ -683,6 +686,8 @@ 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 303a1c02705a3b..bee2a185745f4d 100644
--- a/Tools/cases_generator/lexer.py
+++ b/Tools/cases_generator/lexer.py
@@ -222,6 +222,7 @@ 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 9ef49bdc41dc99..453db6905d6842 100644
--- a/Tools/cases_generator/opcode_metadata_generator.py
+++ b/Tools/cases_generator/opcode_metadata_generator.py
@@ -51,6 +51,7 @@
"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 7ebeff716d2900..5cfec4bfecbf07 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -48,13 +48,19 @@ 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)
- out.emit(f"{type_name(var)}{var.name};\n")
+ if var.condition:
+ out.emit(f"{type_name(var)}{var.name} = NULL;\n")
+ else:
+ 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)
- out.emit(f"{type_name(var)}{var.name};\n")
+ if var.condition:
+ out.emit(f"{type_name(var)}{var.name} = NULL;\n")
+ else:
+ 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 b50bb627b6c41c..41b36b6a546360 100644
--- a/Tools/cases_generator/parsing.py
+++ b/Tools/cases_generator/parsing.py
@@ -77,11 +77,12 @@ 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.size]
+ items = [self.name, self.type, self.cond, self.size]
while items and items[-1] == "":
del items[-1]
return f"StackEffect({', '.join(repr(item) for item in items)})"
@@ -277,15 +278,22 @@ 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:
+ if type_text or cond_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, size_text)
+ return StackEffect(tkn.text, type_text, cond_text, size_text)
return None
@contextual
diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py
index 4e9a312ce34146..5121837ed8334b 100644
--- a/Tools/cases_generator/stack.py
+++ b/Tools/cases_generator/stack.py
@@ -24,7 +24,17 @@ def maybe_parenthesize(sym: str) -> str:
def var_size(var: StackItem) -> str:
- if var.size:
+ 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:
return var.size
else:
return "1"
@@ -80,6 +90,10 @@ 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()
@@ -260,7 +274,16 @@ 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};\n"
+ 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"
return assign, Local.from_memory(var)
def push(self, var: Local) -> None:
@@ -280,6 +303,10 @@ 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 f4409da3d83ccd..441bb3f7af5bcb 100644
--- a/Tools/cases_generator/tier1_generator.py
+++ b/Tools/cases_generator/tier1_generator.py
@@ -37,7 +37,10 @@
def declare_variable(var: StackItem, out: CWriter) -> None:
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- out.emit(f"{type}{space}{var.name};\n")
+ if var.condition:
+ out.emit(f"{type}{space}{var.name} = {null};\n")
+ else:
+ 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 abd9b8d7924299..dd16a1a7eb28b5 100644
--- a/Tools/cases_generator/tier2_generator.py
+++ b/Tools/cases_generator/tier2_generator.py
@@ -39,7 +39,14 @@ def declare_variable(
required.remove(var.name)
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- out.emit(f"{type}{space}{var.name};\n")
+ 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")
def declare_variables(uop: Uop, out: CWriter) -> None:
@@ -208,6 +215,9 @@ 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 17478933eb68e5..bc7ccfe33e777d 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" or opcode == "LOAD_SUPER_METHOD":
+ if opcode == "LOAD_SUPER_ATTR":
opcode = "SUPER"
elif opcode.endswith("ATTR"):
opcode = "ATTR"
1
0
gh-127936, PEP 757: Convert marshal module to use import/export API for ints (#128530)
by vstinner Jan. 23, 2025
by vstinner Jan. 23, 2025
Jan. 23, 2025
https://github.com/python/cpython/commit/d7d066c3ab6842117f9e0fb1c9dde4bce0…
commit: d7d066c3ab6842117f9e0fb1c9dde4bce00fa1e3
branch: main
author: Sergey B Kirpichev <skirpichev(a)gmail.com>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T02:54:23Z
summary:
gh-127936, PEP 757: Convert marshal module to use import/export API for ints (#128530)
Co-authored-by: Victor Stinner <vstinner(a)python.org>
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
M Python/marshal.c
diff --git a/Python/marshal.c b/Python/marshal.c
index 72afa4ff89432c..cf7011652513ae 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -240,10 +240,6 @@ w_short_pstring(const void *s, Py_ssize_t n, WFILE *p)
#define PyLong_MARSHAL_SHIFT 15
#define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT)
#define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1)
-#if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0
-#error "PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT"
-#endif
-#define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT)
#define W_TYPE(t, p) do { \
w_byte((t) | flag, (p)); \
@@ -252,47 +248,106 @@ w_short_pstring(const void *s, Py_ssize_t n, WFILE *p)
static PyObject *
_PyMarshal_WriteObjectToString(PyObject *x, int version, int allow_code);
+#define _r_digits(bitsize) \
+static void \
+_r_digits##bitsize(const uint ## bitsize ## _t *digits, Py_ssize_t n, \
+ uint8_t negative, Py_ssize_t marshal_ratio, WFILE *p) \
+{ \
+ /* set l to number of base PyLong_MARSHAL_BASE digits */ \
+ Py_ssize_t l = (n - 1)*marshal_ratio; \
+ uint ## bitsize ## _t d = digits[n - 1]; \
+ \
+ assert(marshal_ratio > 0); \
+ assert(n >= 1); \
+ assert(d != 0); /* a PyLong is always normalized */ \
+ do { \
+ d >>= PyLong_MARSHAL_SHIFT; \
+ l++; \
+ } while (d != 0); \
+ if (l > SIZE32_MAX) { \
+ p->depth--; \
+ p->error = WFERR_UNMARSHALLABLE; \
+ return; \
+ } \
+ w_long((long)(negative ? -l : l), p); \
+ \
+ for (Py_ssize_t i = 0; i < n - 1; i++) { \
+ d = digits[i]; \
+ for (Py_ssize_t j = 0; j < marshal_ratio; j++) { \
+ w_short(d & PyLong_MARSHAL_MASK, p); \
+ d >>= PyLong_MARSHAL_SHIFT; \
+ } \
+ assert(d == 0); \
+ } \
+ d = digits[n - 1]; \
+ do { \
+ w_short(d & PyLong_MARSHAL_MASK, p); \
+ d >>= PyLong_MARSHAL_SHIFT; \
+ } while (d != 0); \
+}
+_r_digits(16)
+_r_digits(32)
+#undef _r_digits
+
static void
w_PyLong(const PyLongObject *ob, char flag, WFILE *p)
{
- Py_ssize_t i, j, n, l;
- digit d;
-
W_TYPE(TYPE_LONG, p);
if (_PyLong_IsZero(ob)) {
w_long((long)0, p);
return;
}
- /* set l to number of base PyLong_MARSHAL_BASE digits */
- n = _PyLong_DigitCount(ob);
- l = (n-1) * PyLong_MARSHAL_RATIO;
- d = ob->long_value.ob_digit[n-1];
- assert(d != 0); /* a PyLong is always normalized */
- do {
- d >>= PyLong_MARSHAL_SHIFT;
- l++;
- } while (d != 0);
- if (l > SIZE32_MAX) {
+ PyLongExport long_export;
+
+ if (PyLong_Export((PyObject *)ob, &long_export) < 0) {
p->depth--;
p->error = WFERR_UNMARSHALLABLE;
return;
}
- w_long((long)(_PyLong_IsNegative(ob) ? -l : l), p);
+ if (!long_export.digits) {
+ int8_t sign = long_export.value < 0 ? -1 : 1;
+ uint64_t abs_value = Py_ABS(long_export.value);
+ uint64_t d = abs_value;
+ long l = 0;
- for (i=0; i < n-1; i++) {
- d = ob->long_value.ob_digit[i];
- for (j=0; j < PyLong_MARSHAL_RATIO; j++) {
+ /* set l to number of base PyLong_MARSHAL_BASE digits */
+ do {
+ d >>= PyLong_MARSHAL_SHIFT;
+ l += sign;
+ } while (d);
+ w_long(l, p);
+
+ d = abs_value;
+ do {
w_short(d & PyLong_MARSHAL_MASK, p);
d >>= PyLong_MARSHAL_SHIFT;
- }
- assert (d == 0);
+ } while (d);
+ return;
}
- d = ob->long_value.ob_digit[n-1];
- do {
- w_short(d & PyLong_MARSHAL_MASK, p);
- d >>= PyLong_MARSHAL_SHIFT;
- } while (d != 0);
+
+ const PyLongLayout *layout = PyLong_GetNativeLayout();
+ Py_ssize_t marshal_ratio = layout->bits_per_digit/PyLong_MARSHAL_SHIFT;
+
+ /* must be a multiple of PyLong_MARSHAL_SHIFT */
+ assert(layout->bits_per_digit % PyLong_MARSHAL_SHIFT == 0);
+ assert(layout->bits_per_digit >= PyLong_MARSHAL_SHIFT);
+
+ /* other assumptions on PyLongObject internals */
+ assert(layout->bits_per_digit <= 32);
+ assert(layout->digits_order == -1);
+ assert(layout->digit_endianness == (PY_LITTLE_ENDIAN ? -1 : 1));
+ assert(layout->digit_size == 2 || layout->digit_size == 4);
+
+ if (layout->digit_size == 4) {
+ _r_digits32(long_export.digits, long_export.ndigits,
+ long_export.negative, marshal_ratio, p);
+ }
+ else {
+ _r_digits16(long_export.digits, long_export.ndigits,
+ long_export.negative, marshal_ratio, p);
+ }
+ PyLong_FreeExport(&long_export);
}
static void
@@ -875,17 +930,62 @@ r_long64(RFILE *p)
1 /* signed */);
}
+#define _w_digits(bitsize) \
+static int \
+_w_digits##bitsize(uint ## bitsize ## _t *digits, Py_ssize_t size, \
+ Py_ssize_t marshal_ratio, \
+ int shorts_in_top_digit, RFILE *p) \
+{ \
+ uint ## bitsize ## _t d; \
+ \
+ assert(size >= 1); \
+ for (Py_ssize_t i = 0; i < size - 1; i++) { \
+ d = 0; \
+ for (Py_ssize_t j = 0; j < marshal_ratio; j++) { \
+ int md = r_short(p); \
+ if (md < 0 || md > PyLong_MARSHAL_BASE) { \
+ goto bad_digit; \
+ } \
+ d += (uint ## bitsize ## _t)md << j*PyLong_MARSHAL_SHIFT; \
+ } \
+ digits[i] = d; \
+ } \
+ \
+ d = 0; \
+ for (Py_ssize_t j = 0; j < shorts_in_top_digit; j++) { \
+ int md = r_short(p); \
+ if (md < 0 || md > PyLong_MARSHAL_BASE) { \
+ goto bad_digit; \
+ } \
+ /* topmost marshal digit should be nonzero */ \
+ if (md == 0 && j == shorts_in_top_digit - 1) { \
+ PyErr_SetString(PyExc_ValueError, \
+ "bad marshal data (unnormalized long data)"); \
+ return -1; \
+ } \
+ d += (uint ## bitsize ## _t)md << j*PyLong_MARSHAL_SHIFT; \
+ } \
+ assert(!PyErr_Occurred()); \
+ /* top digit should be nonzero, else the resulting PyLong won't be \
+ normalized */ \
+ digits[size - 1] = d; \
+ return 0; \
+ \
+bad_digit: \
+ if (!PyErr_Occurred()) { \
+ PyErr_SetString(PyExc_ValueError, \
+ "bad marshal data (digit out of range in long)"); \
+ } \
+ return -1; \
+}
+_w_digits(32)
+_w_digits(16)
+#undef _w_digits
+
static PyObject *
r_PyLong(RFILE *p)
{
- PyLongObject *ob;
- long n, size, i;
- int j, md, shorts_in_top_digit;
- digit d;
-
- n = r_long(p);
- if (n == 0)
- return (PyObject *)_PyLong_New(0);
+ long n = r_long(p);
if (n == -1 && PyErr_Occurred()) {
return NULL;
}
@@ -895,51 +995,44 @@ r_PyLong(RFILE *p)
return NULL;
}
- size = 1 + (Py_ABS(n) - 1) / PyLong_MARSHAL_RATIO;
- shorts_in_top_digit = 1 + (Py_ABS(n) - 1) % PyLong_MARSHAL_RATIO;
- ob = _PyLong_New(size);
- if (ob == NULL)
- return NULL;
+ const PyLongLayout *layout = PyLong_GetNativeLayout();
+ Py_ssize_t marshal_ratio = layout->bits_per_digit/PyLong_MARSHAL_SHIFT;
- _PyLong_SetSignAndDigitCount(ob, n < 0 ? -1 : 1, size);
+ /* must be a multiple of PyLong_MARSHAL_SHIFT */
+ assert(layout->bits_per_digit % PyLong_MARSHAL_SHIFT == 0);
+ assert(layout->bits_per_digit >= PyLong_MARSHAL_SHIFT);
- for (i = 0; i < size-1; i++) {
- d = 0;
- for (j=0; j < PyLong_MARSHAL_RATIO; j++) {
- md = r_short(p);
- if (md < 0 || md > PyLong_MARSHAL_BASE)
- goto bad_digit;
- d += (digit)md << j*PyLong_MARSHAL_SHIFT;
- }
- ob->long_value.ob_digit[i] = d;
+ /* other assumptions on PyLongObject internals */
+ assert(layout->bits_per_digit <= 32);
+ assert(layout->digits_order == -1);
+ assert(layout->digit_endianness == (PY_LITTLE_ENDIAN ? -1 : 1));
+ assert(layout->digit_size == 2 || layout->digit_size == 4);
+
+ Py_ssize_t size = 1 + (Py_ABS(n) - 1) / marshal_ratio;
+
+ assert(size >= 1);
+
+ int shorts_in_top_digit = 1 + (Py_ABS(n) - 1) % marshal_ratio;
+ void *digits;
+ PyLongWriter *writer = PyLongWriter_Create(n < 0, size, &digits);
+
+ if (writer == NULL) {
+ return NULL;
}
- d = 0;
- for (j=0; j < shorts_in_top_digit; j++) {
- md = r_short(p);
- if (md < 0 || md > PyLong_MARSHAL_BASE)
- goto bad_digit;
- /* topmost marshal digit should be nonzero */
- if (md == 0 && j == shorts_in_top_digit - 1) {
- Py_DECREF(ob);
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (unnormalized long data)");
- return NULL;
- }
- d += (digit)md << j*PyLong_MARSHAL_SHIFT;
+ int ret;
+
+ if (layout->digit_size == 4) {
+ ret = _w_digits32(digits, size, marshal_ratio, shorts_in_top_digit, p);
}
- assert(!PyErr_Occurred());
- /* top digit should be nonzero, else the resulting PyLong won't be
- normalized */
- ob->long_value.ob_digit[size-1] = d;
- return (PyObject *)ob;
- bad_digit:
- Py_DECREF(ob);
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (digit out of range in long)");
+ else {
+ ret = _w_digits16(digits, size, marshal_ratio, shorts_in_top_digit, p);
+ }
+ if (ret < 0) {
+ PyLongWriter_Discard(writer);
+ return NULL;
}
- return NULL;
+ return PyLongWriter_Finish(writer);
}
static double
1
0
https://github.com/python/cpython/commit/1d485db953fa839942a609202ace49d037…
commit: 1d485db953fa839942a609202ace49d03708f797
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T03:11:53+01:00
summary:
gh-128863: Deprecate _PyLong_Sign() function (#129176)
Replace _PyLong_Sign() with PyLong_GetSign().
files:
M Doc/deprecations/c-api-pending-removal-in-3.18.rst
M Doc/whatsnew/3.14.rst
M Include/cpython/longobject.h
M Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
M Modules/_pickle.c
M Modules/_testinternalcapi.c
M Objects/floatobject.c
M Objects/longobject.c
M Objects/sliceobject.c
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.18.rst b/Doc/deprecations/c-api-pending-removal-in-3.18.rst
index d04c746cd9f33e..9da3d73c9e1252 100644
--- a/Doc/deprecations/c-api-pending-removal-in-3.18.rst
+++ b/Doc/deprecations/c-api-pending-removal-in-3.18.rst
@@ -6,6 +6,7 @@ Pending removal in Python 3.18
* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
* :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`.
* :c:func:`!_PyDict_Pop()`: :c:func:`PyDict_Pop`.
+ * :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`.
* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`.
* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 531c5ed6226fe4..421375ebaac184 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1395,6 +1395,7 @@ Deprecated
* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
* :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`.
* :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`.
+ * :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`.
* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`.
* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h
index 4d6e618f831ad8..7f28ad60b7467b 100644
--- a/Include/cpython/longobject.h
+++ b/Include/cpython/longobject.h
@@ -86,7 +86,7 @@ PyAPI_FUNC(int) PyLong_IsZero(PyObject *obj);
- On failure, set an exception, and return -1. */
PyAPI_FUNC(int) PyLong_GetSign(PyObject *v, int *sign);
-PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
+Py_DEPRECATED(3.14) PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
/* _PyLong_NumBits. Return the number of bits needed to represent the
absolute value of a long. For example, this returns 1 for 1 and -1, 2
diff --git a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
index a94d7933ad32ef..5e55cfb3c74a4b 100644
--- a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
+++ b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
@@ -4,6 +4,7 @@ Python 3.18:
* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
* :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`.
* :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`.
+* :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`.
* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`.
* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 599b5f92c2a1f7..a6cfb2deeb23c1 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -2159,8 +2159,10 @@ save_long(PicklerObject *self, PyObject *obj)
unsigned char *pdata;
char header[5];
int i;
- int sign = _PyLong_Sign(obj);
+ int sign;
+ assert(PyLong_Check(obj));
+ (void)PyLong_GetSign(obj, &sign);
if (sign == 0) {
header[0] = LONG1;
header[1] = 0; /* It's 0 -- an empty bytestring. */
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index e77df5b57b0504..f3d234a7f9595e 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_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
#include "pycore_optimizer.h" // JitOptSymbol, etc.
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
@@ -1798,14 +1797,14 @@ _testinternalcapi_test_long_numbits_impl(PyObject *module)
for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
uint64_t nbits;
- int sign;
+ int sign = -7;
PyObject *plong;
plong = PyLong_FromLong(testcases[i].input);
if (plong == NULL)
return NULL;
nbits = _PyLong_NumBits(plong);
- sign = _PyLong_Sign(plong);
+ (void)PyLong_GetSign(plong, &sign);
Py_DECREF(plong);
if (nbits != testcases[i].nbits)
@@ -1813,7 +1812,7 @@ _testinternalcapi_test_long_numbits_impl(PyObject *module)
"wrong result for _PyLong_NumBits");
if (sign != testcases[i].sign)
return raiseTestError("test_long_numbits",
- "wrong result for _PyLong_Sign");
+ "wrong result for PyLong_GetSign()");
}
Py_RETURN_NONE;
}
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index bcc77287454768..7ca43033d722ab 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -428,9 +428,10 @@ float_richcompare(PyObject *v, PyObject *w, int op)
else if (PyLong_Check(w)) {
int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;
- int wsign = _PyLong_Sign(w);
+ int wsign;
int exponent;
+ (void)PyLong_GetSign(w, &wsign);
if (vsign != wsign) {
/* Magnitudes are irrelevant -- the signs alone
* determine the outcome.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index d449a01cedf886..370931e64d3627 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -827,19 +827,25 @@ PyLong_IsZero(PyObject *obj)
return _PyLong_IsZero((PyLongObject *)obj);
}
-int
-_PyLong_Sign(PyObject *vv)
+static int
+long_sign(PyObject *vv)
{
+ assert(vv != NULL);
+ assert(PyLong_Check(vv));
PyLongObject *v = (PyLongObject *)vv;
- assert(v != NULL);
- assert(PyLong_Check(v));
if (_PyLong_IsCompact(v)) {
return _PyLong_CompactSign(v);
}
return _PyLong_NonCompactSign(v);
}
+int
+_PyLong_Sign(PyObject *vv)
+{
+ return long_sign(vv);
+}
+
int
PyLong_GetSign(PyObject *vv, int *sign)
{
@@ -848,7 +854,7 @@ PyLong_GetSign(PyObject *vv, int *sign)
return -1;
}
- *sign = _PyLong_Sign(vv);
+ *sign = long_sign(vv);
return 0;
}
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index 4fef0af93fe095..1b07c2a2c498b9 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -399,11 +399,14 @@ _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
step_is_negative = 0;
}
else {
- int step_sign;
step = evaluate_slice_index(self->step);
- if (step == NULL)
+ if (step == NULL) {
goto error;
- step_sign = _PyLong_Sign(step);
+ }
+ assert(PyLong_Check(step));
+
+ int step_sign;
+ (void)PyLong_GetSign(step, &step_sign);
if (step_sign == 0) {
PyErr_SetString(PyExc_ValueError,
"slice step cannot be zero");
1
0
Jan. 23, 2025
https://github.com/python/cpython/commit/0093a31273898930e5fb19ff5d1655c445…
commit: 0093a31273898930e5fb19ff5d1655c4458a2056
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T00:57:37Z
summary:
gh-119182: Use public PyUnicodeWriter in Python-ast.c (#129209)
Replace the private _PyUnicodeWriter API with the public
PyUnicodeWriter API.
Use PyUnicodeWriter_WriteRepr() in ast_repr_list().
files:
M Parser/asdl_c.py
M Python/Python-ast.c
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index 853a3e99807bca..7b2df738119115 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -1462,10 +1462,11 @@ def visitModule(self, mod):
return PyObject_Repr(list);
}
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
PyObject *items[2] = {NULL, NULL};
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto error;
+ }
items[0] = PySequence_GetItem(list, 0);
if (!items[0]) {
@@ -1479,52 +1480,54 @@ def visitModule(self, mod):
}
bool is_list = PyList_Check(list);
- if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) {
goto error;
}
for (Py_ssize_t i = 0; i < Py_MIN(length, 2); i++) {
- PyObject *item = items[i];
- PyObject *item_repr;
+ if (i > 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
+ goto error;
+ }
+ }
+ PyObject *item = items[i];
if (PyType_IsSubtype(Py_TYPE(item), (PyTypeObject *)state->AST_type)) {
+ PyObject *item_repr;
item_repr = ast_repr_max_depth((AST_object*)item, depth - 1);
- } else {
- item_repr = PyObject_Repr(item);
- }
- if (!item_repr) {
- goto error;
- }
- if (i > 0) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
+ if (!item_repr) {
+ goto error;
+ }
+ if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) {
+ Py_DECREF(item_repr);
goto error;
}
- }
- if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) {
Py_DECREF(item_repr);
- goto error;
+ } else {
+ if (PyUnicodeWriter_WriteRepr(writer, item) < 0) {
+ goto error;
+ }
}
+
if (i == 0 && length > 2) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) {
- Py_DECREF(item_repr);
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) {
goto error;
}
}
- Py_DECREF(item_repr);
}
- if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) {
goto error;
}
Py_XDECREF(items[0]);
Py_XDECREF(items[1]);
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
error:
Py_XDECREF(items[0]);
Py_XDECREF(items[1]);
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
@@ -1568,14 +1571,15 @@ def visitModule(self, mod):
}
const char* tp_name = Py_TYPE(self)->tp_name;
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto error;
+ }
- if (_PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)) < 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, tp_name, -1) < 0) {
goto error;
}
- if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, '(') < 0) {
goto error;
}
@@ -1610,13 +1614,13 @@ def visitModule(self, mod):
}
if (i > 0) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
Py_DECREF(name);
Py_DECREF(value_repr);
goto error;
}
}
- if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, name) < 0) {
Py_DECREF(name);
Py_DECREF(value_repr);
goto error;
@@ -1624,11 +1628,11 @@ def visitModule(self, mod):
Py_DECREF(name);
- if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
Py_DECREF(value_repr);
goto error;
}
- if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) {
Py_DECREF(value_repr);
goto error;
}
@@ -1636,17 +1640,17 @@ def visitModule(self, mod):
Py_DECREF(value_repr);
}
- if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, ')') < 0) {
goto error;
}
Py_ReprLeave((PyObject *)self);
Py_DECREF(fields);
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
error:
Py_ReprLeave((PyObject *)self);
Py_DECREF(fields);
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 41299b29705848..7038e3c92ab8f0 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -5661,10 +5661,11 @@ ast_repr_list(PyObject *list, int depth)
return PyObject_Repr(list);
}
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
PyObject *items[2] = {NULL, NULL};
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto error;
+ }
items[0] = PySequence_GetItem(list, 0);
if (!items[0]) {
@@ -5678,52 +5679,54 @@ ast_repr_list(PyObject *list, int depth)
}
bool is_list = PyList_Check(list);
- if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) {
goto error;
}
for (Py_ssize_t i = 0; i < Py_MIN(length, 2); i++) {
- PyObject *item = items[i];
- PyObject *item_repr;
+ if (i > 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
+ goto error;
+ }
+ }
+ PyObject *item = items[i];
if (PyType_IsSubtype(Py_TYPE(item), (PyTypeObject *)state->AST_type)) {
+ PyObject *item_repr;
item_repr = ast_repr_max_depth((AST_object*)item, depth - 1);
- } else {
- item_repr = PyObject_Repr(item);
- }
- if (!item_repr) {
- goto error;
- }
- if (i > 0) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
+ if (!item_repr) {
+ goto error;
+ }
+ if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) {
+ Py_DECREF(item_repr);
goto error;
}
- }
- if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) {
Py_DECREF(item_repr);
- goto error;
+ } else {
+ if (PyUnicodeWriter_WriteRepr(writer, item) < 0) {
+ goto error;
+ }
}
+
if (i == 0 && length > 2) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) {
- Py_DECREF(item_repr);
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) {
goto error;
}
}
- Py_DECREF(item_repr);
}
- if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) {
goto error;
}
Py_XDECREF(items[0]);
Py_XDECREF(items[1]);
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
error:
Py_XDECREF(items[0]);
Py_XDECREF(items[1]);
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
@@ -5767,14 +5770,15 @@ ast_repr_max_depth(AST_object *self, int depth)
}
const char* tp_name = Py_TYPE(self)->tp_name;
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto error;
+ }
- if (_PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)) < 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, tp_name, -1) < 0) {
goto error;
}
- if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, '(') < 0) {
goto error;
}
@@ -5809,13 +5813,13 @@ ast_repr_max_depth(AST_object *self, int depth)
}
if (i > 0) {
- if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
Py_DECREF(name);
Py_DECREF(value_repr);
goto error;
}
}
- if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, name) < 0) {
Py_DECREF(name);
Py_DECREF(value_repr);
goto error;
@@ -5823,11 +5827,11 @@ ast_repr_max_depth(AST_object *self, int depth)
Py_DECREF(name);
- if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
Py_DECREF(value_repr);
goto error;
}
- if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) {
Py_DECREF(value_repr);
goto error;
}
@@ -5835,17 +5839,17 @@ ast_repr_max_depth(AST_object *self, int depth)
Py_DECREF(value_repr);
}
- if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
+ if (PyUnicodeWriter_WriteChar(writer, ')') < 0) {
goto error;
}
Py_ReprLeave((PyObject *)self);
Py_DECREF(fields);
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
error:
Py_ReprLeave((PyObject *)self);
Py_DECREF(fields);
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
1
0
Jan. 23, 2025
https://github.com/python/cpython/commit/8eb9e76b5b2471031d6ad48ee3bc4554bb…
commit: 8eb9e76b5b2471031d6ad48ee3bc4554bb0067b7
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T01:44:43+01:00
summary:
gh-119182: Use public PyUnicodeWriter in ast_unparse.c (#129208)
Replace the private _PyUnicodeWriter API with the public
PyUnicodeWriter API.
* Add append_char() function.
* Add APPEND_CHAR() and APPEND_CHAR_FINISH() macros.
* Replace APPEND_STR() and APPEND_STR_FINISH() of single character
with APPEND_CHAR() and APPEND_CHAR_FINISH().
files:
M Python/ast_unparse.c
diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c
index 8017cfc7fcf268..f3c669c33eb07c 100644
--- a/Python/ast_unparse.c
+++ b/Python/ast_unparse.c
@@ -16,24 +16,40 @@ _Py_DECLARE_STR(dbl_close_br, "}}");
static PyObject *
expr_as_unicode(expr_ty e, int level);
static int
-append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level);
+append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level);
static int
-append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
+append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int
-append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e);
+append_formattedvalue(PyUnicodeWriter *writer, expr_ty e);
static int
-append_ast_slice(_PyUnicodeWriter *writer, expr_ty e);
+append_ast_slice(PyUnicodeWriter *writer, expr_ty e);
static int
-append_charp(_PyUnicodeWriter *writer, const char *charp)
+append_char(PyUnicodeWriter *writer, Py_UCS4 ch)
{
- return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1);
+ return PyUnicodeWriter_WriteChar(writer, ch);
}
+static int
+append_charp(PyUnicodeWriter *writer, const char *charp)
+{
+ return PyUnicodeWriter_WriteUTF8(writer, charp, -1);
+}
+
+#define APPEND_CHAR_FINISH(ch) do { \
+ return append_char(writer, (ch)); \
+ } while (0)
+
#define APPEND_STR_FINISH(str) do { \
return append_charp(writer, (str)); \
} while (0)
+#define APPEND_CHAR(ch) do { \
+ if (-1 == append_char(writer, (ch))) { \
+ return -1; \
+ } \
+ } while (0)
+
#define APPEND_STR(str) do { \
if (-1 == append_charp(writer, (str))) { \
return -1; \
@@ -64,10 +80,9 @@ append_charp(_PyUnicodeWriter *writer, const char *charp)
} while (0)
static int
-append_repr(_PyUnicodeWriter *writer, PyObject *obj)
+append_repr(PyUnicodeWriter *writer, PyObject *obj)
{
PyObject *repr = PyObject_Repr(obj);
-
if (!repr) {
return -1;
}
@@ -88,7 +103,8 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj)
}
repr = new_repr;
}
- int ret = _PyUnicodeWriter_WriteStr(writer, repr);
+
+ int ret = PyUnicodeWriter_WriteStr(writer, repr);
Py_DECREF(repr);
return ret;
}
@@ -117,7 +133,7 @@ enum {
};
static int
-append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_boolop(PyUnicodeWriter *writer, expr_ty e, int level)
{
Py_ssize_t i, value_count;
asdl_expr_seq *values;
@@ -139,7 +155,7 @@ append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_binop(PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
int pr;
@@ -174,7 +190,7 @@ append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_unaryop(PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
int pr;
@@ -198,9 +214,9 @@ append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)
+append_ast_arg(PyUnicodeWriter *writer, arg_ty arg)
{
- if (-1 == _PyUnicodeWriter_WriteStr(writer, arg->arg)) {
+ if (PyUnicodeWriter_WriteStr(writer, arg->arg) < 0) {
return -1;
}
if (arg->annotation) {
@@ -211,7 +227,7 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)
}
static int
-append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
+append_ast_args(PyUnicodeWriter *writer, arguments_ty args)
{
bool first;
Py_ssize_t i, di, arg_count, posonlyarg_count, default_count;
@@ -232,7 +248,7 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
di = i - posonlyarg_count - arg_count + default_count;
if (di >= 0) {
- APPEND_STR("=");
+ APPEND_CHAR('=');
APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);
}
if (posonlyarg_count && i + 1 == posonlyarg_count) {
@@ -260,7 +276,7 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
if (di >= 0) {
expr_ty default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);
if (default_) {
- APPEND_STR("=");
+ APPEND_CHAR('=');
APPEND_EXPR(default_, PR_TEST);
}
}
@@ -277,7 +293,7 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
}
static int
-append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_lambda(PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TEST, "(");
Py_ssize_t n_positional = (asdl_seq_LEN(e->v.Lambda.args->args) +
@@ -291,7 +307,7 @@ append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_ifexp(PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TEST, "(");
APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);
@@ -304,12 +320,12 @@ append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_dict(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_dict(PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, value_count;
expr_ty key_node;
- APPEND_STR("{");
+ APPEND_CHAR('{');
value_count = asdl_seq_LEN(e->v.Dict.values);
for (i = 0; i < value_count; i++) {
@@ -326,41 +342,41 @@ append_ast_dict(_PyUnicodeWriter *writer, expr_ty e)
}
}
- APPEND_STR_FINISH("}");
+ APPEND_CHAR_FINISH('}');
}
static int
-append_ast_set(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_set(PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, elem_count;
- APPEND_STR("{");
+ APPEND_CHAR('{');
elem_count = asdl_seq_LEN(e->v.Set.elts);
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);
}
- APPEND_STR_FINISH("}");
+ APPEND_CHAR_FINISH('}');
}
static int
-append_ast_list(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_list(PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, elem_count;
- APPEND_STR("[");
+ APPEND_CHAR('[');
elem_count = asdl_seq_LEN(e->v.List.elts);
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);
}
- APPEND_STR_FINISH("]");
+ APPEND_CHAR_FINISH(']');
}
static int
-append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_tuple(PyUnicodeWriter *writer, expr_ty e, int level)
{
Py_ssize_t i, elem_count;
@@ -383,7 +399,7 @@ append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)
+append_ast_comprehension(PyUnicodeWriter *writer, comprehension_ty gen)
{
Py_ssize_t i, if_count;
@@ -401,7 +417,7 @@ append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)
}
static int
-append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_comprehension_seq *comprehensions)
+append_ast_comprehensions(PyUnicodeWriter *writer, asdl_comprehension_seq *comprehensions)
{
Py_ssize_t i, gen_count;
gen_count = asdl_seq_LEN(comprehensions);
@@ -414,45 +430,45 @@ append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_comprehension_seq *comp
}
static int
-append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_genexp(PyUnicodeWriter *writer, expr_ty e)
{
- APPEND_STR("(");
+ APPEND_CHAR('(');
APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);
APPEND(comprehensions, e->v.GeneratorExp.generators);
- APPEND_STR_FINISH(")");
+ APPEND_CHAR_FINISH(')');
}
static int
-append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_listcomp(PyUnicodeWriter *writer, expr_ty e)
{
- APPEND_STR("[");
+ APPEND_CHAR('[');
APPEND_EXPR(e->v.ListComp.elt, PR_TEST);
APPEND(comprehensions, e->v.ListComp.generators);
- APPEND_STR_FINISH("]");
+ APPEND_CHAR_FINISH(']');
}
static int
-append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_setcomp(PyUnicodeWriter *writer, expr_ty e)
{
- APPEND_STR("{");
+ APPEND_CHAR('{');
APPEND_EXPR(e->v.SetComp.elt, PR_TEST);
APPEND(comprehensions, e->v.SetComp.generators);
- APPEND_STR_FINISH("}");
+ APPEND_CHAR_FINISH('}');
}
static int
-append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_dictcomp(PyUnicodeWriter *writer, expr_ty e)
{
- APPEND_STR("{");
+ APPEND_CHAR('{');
APPEND_EXPR(e->v.DictComp.key, PR_TEST);
APPEND_STR(": ");
APPEND_EXPR(e->v.DictComp.value, PR_TEST);
APPEND(comprehensions, e->v.DictComp.generators);
- APPEND_STR_FINISH("}");
+ APPEND_CHAR_FINISH('}');
}
static int
-append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_compare(PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
Py_ssize_t i, comparator_count;
@@ -516,17 +532,17 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)
+append_ast_keyword(PyUnicodeWriter *writer, keyword_ty kw)
{
if (kw->arg == NULL) {
APPEND_STR("**");
}
else {
- if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) {
+ if (-1 == PyUnicodeWriter_WriteStr(writer, kw->arg)) {
return -1;
}
- APPEND_STR("=");
+ APPEND_CHAR('=');
}
APPEND_EXPR(kw->value, PR_TEST);
@@ -534,7 +550,7 @@ append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)
}
static int
-append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_call(PyUnicodeWriter *writer, expr_ty e)
{
bool first;
Py_ssize_t i, arg_count, kw_count;
@@ -552,7 +568,7 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
}
}
- APPEND_STR("(");
+ APPEND_CHAR('(');
first = true;
for (i = 0; i < arg_count; i++) {
@@ -565,7 +581,7 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));
}
- APPEND_STR_FINISH(")");
+ APPEND_CHAR_FINISH(')');
}
static PyObject *
@@ -585,20 +601,20 @@ escape_braces(PyObject *orig)
}
static int
-append_fstring_unicode(_PyUnicodeWriter *writer, PyObject *unicode)
+append_fstring_unicode(PyUnicodeWriter *writer, PyObject *unicode)
{
PyObject *escaped;
int result = -1;
escaped = escape_braces(unicode);
if (escaped) {
- result = _PyUnicodeWriter_WriteStr(writer, escaped);
+ result = PyUnicodeWriter_WriteStr(writer, escaped);
Py_DECREF(escaped);
}
return result;
}
static int
-append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
+append_fstring_element(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
{
switch (e->kind) {
case Constant_kind:
@@ -619,28 +635,27 @@ append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
static PyObject *
build_fstring_body(asdl_expr_seq *values, bool is_format_spec)
{
- Py_ssize_t i, value_count;
- _PyUnicodeWriter body_writer;
- _PyUnicodeWriter_Init(&body_writer);
- body_writer.min_length = 256;
- body_writer.overallocate = 1;
+ PyUnicodeWriter *body_writer = PyUnicodeWriter_Create(256);
+ if (body_writer == NULL) {
+ return NULL;
+ }
- value_count = asdl_seq_LEN(values);
- for (i = 0; i < value_count; ++i) {
- if (-1 == append_fstring_element(&body_writer,
+ Py_ssize_t value_count = asdl_seq_LEN(values);
+ for (Py_ssize_t i = 0; i < value_count; ++i) {
+ if (-1 == append_fstring_element(body_writer,
(expr_ty)asdl_seq_GET(values, i),
is_format_spec
)) {
- _PyUnicodeWriter_Dealloc(&body_writer);
+ PyUnicodeWriter_Discard(body_writer);
return NULL;
}
}
- return _PyUnicodeWriter_Finish(&body_writer);
+ return PyUnicodeWriter_Finish(body_writer);
}
static int
-append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
+append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
{
int result = -1;
PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec);
@@ -656,14 +671,14 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
}
}
else {
- result = _PyUnicodeWriter_WriteStr(writer, body);
+ result = PyUnicodeWriter_WriteStr(writer, body);
}
Py_DECREF(body);
return result;
}
static int
-append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
+append_formattedvalue(PyUnicodeWriter *writer, expr_ty e)
{
const char *conversion;
const char *outer_brace = "{";
@@ -682,7 +697,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
Py_DECREF(temp_fv_str);
return -1;
}
- if (-1 == _PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {
+ if (-1 == PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {
Py_DECREF(temp_fv_str);
return -1;
}
@@ -707,7 +722,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
APPEND_STR(conversion);
}
if (e->v.FormattedValue.format_spec) {
- if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) ||
+ if (-1 == PyUnicodeWriter_WriteChar(writer, ':') ||
-1 == append_fstring_element(writer,
e->v.FormattedValue.format_spec,
true
@@ -717,17 +732,17 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
}
}
- APPEND_STR_FINISH("}");
+ APPEND_CHAR_FINISH('}');
}
static int
-append_ast_constant(_PyUnicodeWriter *writer, PyObject *constant)
+append_ast_constant(PyUnicodeWriter *writer, PyObject *constant)
{
if (PyTuple_CheckExact(constant)) {
Py_ssize_t i, elem_count;
elem_count = PyTuple_GET_SIZE(constant);
- APPEND_STR("(");
+ APPEND_CHAR('(');
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
if (append_ast_constant(writer, PyTuple_GET_ITEM(constant, i)) < 0) {
@@ -736,14 +751,13 @@ append_ast_constant(_PyUnicodeWriter *writer, PyObject *constant)
}
APPEND_STR_IF(elem_count == 1, ",");
- APPEND_STR(")");
- return 0;
+ APPEND_CHAR_FINISH(')');
}
return append_repr(writer, constant);
}
static int
-append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_attribute(PyUnicodeWriter *writer, expr_ty e)
{
const char *period;
expr_ty v = e->v.Attribute.value;
@@ -759,48 +773,48 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
}
APPEND_STR(period);
- return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
+ return PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
}
static int
-append_ast_slice(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_slice(PyUnicodeWriter *writer, expr_ty e)
{
if (e->v.Slice.lower) {
APPEND_EXPR(e->v.Slice.lower, PR_TEST);
}
- APPEND_STR(":");
+ APPEND_CHAR(':');
if (e->v.Slice.upper) {
APPEND_EXPR(e->v.Slice.upper, PR_TEST);
}
if (e->v.Slice.step) {
- APPEND_STR(":");
+ APPEND_CHAR(':');
APPEND_EXPR(e->v.Slice.step, PR_TEST);
}
return 0;
}
static int
-append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_subscript(PyUnicodeWriter *writer, expr_ty e)
{
APPEND_EXPR(e->v.Subscript.value, PR_ATOM);
- APPEND_STR("[");
+ APPEND_CHAR('[');
APPEND_EXPR(e->v.Subscript.slice, PR_TUPLE);
- APPEND_STR_FINISH("]");
+ APPEND_CHAR_FINISH(']');
}
static int
-append_ast_starred(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_starred(PyUnicodeWriter *writer, expr_ty e)
{
- APPEND_STR("*");
+ APPEND_CHAR('*');
APPEND_EXPR(e->v.Starred.value, PR_EXPR);
return 0;
}
static int
-append_ast_yield(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_yield(PyUnicodeWriter *writer, expr_ty e)
{
if (!e->v.Yield.value) {
APPEND_STR_FINISH("(yield)");
@@ -808,19 +822,19 @@ append_ast_yield(_PyUnicodeWriter *writer, expr_ty e)
APPEND_STR("(yield ");
APPEND_EXPR(e->v.Yield.value, PR_TEST);
- APPEND_STR_FINISH(")");
+ APPEND_CHAR_FINISH(')');
}
static int
-append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e)
+append_ast_yield_from(PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("(yield from ");
APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);
- APPEND_STR_FINISH(")");
+ APPEND_CHAR_FINISH(')');
}
static int
-append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_await(PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_AWAIT, "(");
APPEND_STR("await ");
@@ -830,7 +844,7 @@ append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_named_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_named_expr(PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TUPLE, "(");
APPEND_EXPR(e->v.NamedExpr.target, PR_ATOM);
@@ -841,7 +855,7 @@ append_named_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
}
static int
-append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
+append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level)
{
switch (e->kind) {
case BoolOp_kind:
@@ -881,7 +895,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
APPEND_STR_FINISH("...");
}
if (e->v.Constant.kind != NULL
- && -1 == _PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {
+ && -1 == PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {
return -1;
}
return append_ast_constant(writer, e->v.Constant.value);
@@ -899,7 +913,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
case Slice_kind:
return append_ast_slice(writer, e);
case Name_kind:
- return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
+ return PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
case List_kind:
return append_ast_list(writer, e);
case Tuple_kind:
@@ -916,15 +930,16 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
static PyObject *
expr_as_unicode(expr_ty e, int level)
{
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.min_length = 256;
- writer.overallocate = 1;
- if (-1 == append_ast_expr(&writer, e, level)) {
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(256);
+ if (writer == NULL) {
+ return NULL;
+ }
+
+ if (-1 == append_ast_expr(writer, e, level)) {
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
}
PyObject *
1
0
Jan. 23, 2025
https://github.com/python/cpython/commit/327a257e6ae4ad0e3b6e00b35d24937e4b…
commit: 327a257e6ae4ad0e3b6e00b35d24937e4b0a0395
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T01:18:26+01:00
summary:
gh-119182: Use public PyUnicodeWriter in wrap_strftime() (#129206)
Replace the private _PyUnicodeWriter API with the public
PyUnicodeWriter API.
files:
M Modules/_datetimemodule.c
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index cf8bd60f3e3f81..ff2e6d6a098ad9 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1849,9 +1849,10 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
* is expensive, don't unless they're actually used.
*/
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto Error;
+ }
Py_ssize_t flen = PyUnicode_GET_LENGTH(format);
Py_ssize_t i = 0;
@@ -1955,11 +1956,11 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
if (ch == 'C') {
n -= 2;
}
- if (_PyUnicodeWriter_WriteSubstring(&writer, format, start, end) < 0) {
+ if (PyUnicodeWriter_WriteSubstring(writer, format, start, end) < 0) {
goto Error;
}
start = i;
- if (_PyUnicodeWriter_WriteASCIIString(&writer, buf, n) < 0) {
+ if (PyUnicodeWriter_WriteUTF8(writer, buf, n) < 0) {
goto Error;
}
continue;
@@ -1971,25 +1972,25 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
}
assert(replacement != NULL);
assert(PyUnicode_Check(replacement));
- if (_PyUnicodeWriter_WriteSubstring(&writer, format, start, end) < 0) {
+ if (PyUnicodeWriter_WriteSubstring(writer, format, start, end) < 0) {
goto Error;
}
start = i;
- if (_PyUnicodeWriter_WriteStr(&writer, replacement) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, replacement) < 0) {
goto Error;
}
} /* end while() */
PyObject *newformat;
if (start == 0) {
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
newformat = Py_NewRef(format);
}
else {
- if (_PyUnicodeWriter_WriteSubstring(&writer, format, start, flen) < 0) {
+ if (PyUnicodeWriter_WriteSubstring(writer, format, start, flen) < 0) {
goto Error;
}
- newformat = _PyUnicodeWriter_Finish(&writer);
+ newformat = PyUnicodeWriter_Finish(writer);
if (newformat == NULL) {
goto Done;
}
@@ -2007,7 +2008,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
return result;
Error:
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
goto Done;
}
1
0
Jan. 23, 2025
https://github.com/python/cpython/commit/719c9dd72f43d81072999f0ded8209c07d…
commit: 719c9dd72f43d81072999f0ded8209c07de7fbd0
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-23T01:18:03+01:00
summary:
gh-119182: Use public PyUnicodeWriter in time_strftime() (#129207)
Replace the private _PyUnicodeWriter API with the public
PyUnicodeWriter API.
files:
M Modules/timemodule.c
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 340011fc08b551..5d0cd52a93a2d3 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -913,9 +913,10 @@ time_strftime(PyObject *module, PyObject *args)
PyErr_NoMemory();
return NULL;
}
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
+ PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto error;
+ }
Py_ssize_t i = 0;
while (i < format_size) {
fmtlen = 0;
@@ -933,7 +934,7 @@ time_strftime(PyObject *module, PyObject *args)
if (unicode == NULL) {
goto error;
}
- if (_PyUnicodeWriter_WriteStr(&writer, unicode) < 0) {
+ if (PyUnicodeWriter_WriteStr(writer, unicode) < 0) {
Py_DECREF(unicode);
goto error;
}
@@ -947,18 +948,18 @@ time_strftime(PyObject *module, PyObject *args)
break;
}
}
- if (_PyUnicodeWriter_WriteSubstring(&writer, format_arg, start, i) < 0) {
+ if (PyUnicodeWriter_WriteSubstring(writer, format_arg, start, i) < 0) {
goto error;
}
}
PyMem_Free(outbuf);
PyMem_Free(format);
- return _PyUnicodeWriter_Finish(&writer);
+ return PyUnicodeWriter_Finish(writer);
error:
PyMem_Free(outbuf);
PyMem_Free(format);
- _PyUnicodeWriter_Dealloc(&writer);
+ PyUnicodeWriter_Discard(writer);
return NULL;
}
1
0