Python-checkins
Threads by month
- ----- 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
June 2024
- 1 participants
- 770 discussions
01 Jun '24
https://github.com/python/cpython/commit/48f3378d6c620e99f17679ee11982a5764…
commit: 48f3378d6c620e99f17679ee11982a57640d3bb4
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-01T14:26:12Z
summary:
[3.13] gh-117657: Fix TSAN race in free-threaded GC (GH-119883) (#119903)
Only call `gc_restore_tid()` from stop-the-world contexts.
`worklist_pop()` can be called while other threads are running, so use a
relaxed atomic to modify `ob_tid`.
(cherry picked from commit 60593b2052ca275559c11028d50e19f8e5dfee13)
Co-authored-by: Sam Gross <colesbury(a)gmail.com>
files:
M Python/gc_free_threading.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index ee006bb4aa12b7..e6bd012c40ee82 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -86,7 +86,7 @@ worklist_pop(struct worklist *worklist)
PyObject *op = (PyObject *)worklist->head;
if (op != NULL) {
worklist->head = op->ob_tid;
- op->ob_tid = 0;
+ _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
}
return op;
}
@@ -189,6 +189,7 @@ merge_refcount(PyObject *op, Py_ssize_t extra)
static void
gc_restore_tid(PyObject *op)
{
+ assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
mi_segment_t *segment = _mi_ptr_segment(op);
if (_Py_REF_IS_MERGED(op->ob_ref_shared)) {
op->ob_tid = 0;
@@ -676,7 +677,6 @@ call_weakref_callbacks(struct collection_state *state)
Py_DECREF(temp);
}
- gc_restore_tid(op);
Py_DECREF(op); // drop worklist reference
}
}
@@ -986,7 +986,6 @@ cleanup_worklist(struct worklist *worklist)
{
PyObject *op;
while ((op = worklist_pop(worklist)) != NULL) {
- gc_restore_tid(op);
gc_clear_unreachable(op);
Py_DECREF(op);
}
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index dfa4a1fe9ca438..27568c34e1689e 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -37,7 +37,6 @@ race_top:_PyImport_ReleaseLock
race_top:_PyParkingLot_Park
race_top:_PyType_HasFeature
race_top:assign_version_tag
-race_top:gc_restore_tid
race_top:insertdict
race_top:lookup_tp_dict
race_top:mi_heap_visit_pages
@@ -65,7 +64,6 @@ race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
race_top:should_intern_string
-race_top:worklist_pop
race_top:_PyEval_IsGILEnabled
race_top:llist_insert_tail
race_top:_Py_slot_tp_getattr_hook
@@ -87,7 +85,6 @@ race_top:sock_close
race_top:tstate_delete_common
race_top:tstate_is_freed
race_top:type_modified_unlocked
-race_top:update_refs
race_top:write_thread_id
race_top:PyThreadState_Clear
1
0
https://github.com/python/cpython/commit/90ec19fd33e2452902b9788d4821f1fbf6…
commit: 90ec19fd33e2452902b9788d4821f1fbf6542304
branch: main
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-01T10:04:38-04:00
summary:
gh-117657: Fix TSAN race in QSBR assertion (#119887)
Due to a limitation in TSAN, all reads from `PyThreadState.state` must be
atomic to avoid reported races.
files:
M Python/qsbr.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Python/qsbr.c b/Python/qsbr.c
index 9cbce9044e2941..a7321154a62ffc 100644
--- a/Python/qsbr.c
+++ b/Python/qsbr.c
@@ -160,7 +160,8 @@ qsbr_poll_scan(struct _qsbr_shared *shared)
bool
_Py_qsbr_poll(struct _qsbr_thread_state *qsbr, uint64_t goal)
{
- assert(_PyThreadState_GET()->state == _Py_THREAD_ATTACHED);
+ assert(_Py_atomic_load_int_relaxed(&_PyThreadState_GET()->state) == _Py_THREAD_ATTACHED);
+
if (_Py_qbsr_goal_reached(qsbr, goal)) {
return true;
}
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index 951635e7c6533d..9a53990f8b2ff8 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -75,8 +75,6 @@ race_top:_PyFrame_GetCode
race_top:_PyFrame_Initialize
race_top:PyInterpreterState_ThreadHead
race_top:_PyObject_TryGetInstanceAttribute
-race_top:_Py_qsbr_unregister
-race_top:_Py_qsbr_poll
race_top:PyThreadState_Next
race_top:Py_TYPE
race_top:PyUnstable_InterpreterFrame_GetLine
1
0
https://github.com/python/cpython/commit/60593b2052ca275559c11028d50e19f8e5…
commit: 60593b2052ca275559c11028d50e19f8e5dfee13
branch: main
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-01T10:04:05-04:00
summary:
gh-117657: Fix TSAN race in free-threaded GC (#119883)
Only call `gc_restore_tid()` from stop-the-world contexts.
`worklist_pop()` can be called while other threads are running, so use a
relaxed atomic to modify `ob_tid`.
files:
M Python/gc_free_threading.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index ee006bb4aa12b7..e6bd012c40ee82 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -86,7 +86,7 @@ worklist_pop(struct worklist *worklist)
PyObject *op = (PyObject *)worklist->head;
if (op != NULL) {
worklist->head = op->ob_tid;
- op->ob_tid = 0;
+ _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
}
return op;
}
@@ -189,6 +189,7 @@ merge_refcount(PyObject *op, Py_ssize_t extra)
static void
gc_restore_tid(PyObject *op)
{
+ assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
mi_segment_t *segment = _mi_ptr_segment(op);
if (_Py_REF_IS_MERGED(op->ob_ref_shared)) {
op->ob_tid = 0;
@@ -676,7 +677,6 @@ call_weakref_callbacks(struct collection_state *state)
Py_DECREF(temp);
}
- gc_restore_tid(op);
Py_DECREF(op); // drop worklist reference
}
}
@@ -986,7 +986,6 @@ cleanup_worklist(struct worklist *worklist)
{
PyObject *op;
while ((op = worklist_pop(worklist)) != NULL) {
- gc_restore_tid(op);
gc_clear_unreachable(op);
Py_DECREF(op);
}
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index cda57d78067bb3..951635e7c6533d 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -37,7 +37,6 @@ race_top:_PyImport_ReleaseLock
race_top:_PyParkingLot_Park
race_top:_PyType_HasFeature
race_top:assign_version_tag
-race_top:gc_restore_tid
race_top:insertdict
race_top:lookup_tp_dict
race_top:mi_heap_visit_pages
@@ -64,7 +63,6 @@ race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
race_top:should_intern_string
-race_top:worklist_pop
race_top:_PyEval_IsGILEnabled
race_top:llist_insert_tail
race_top:_Py_slot_tp_getattr_hook
@@ -86,7 +84,6 @@ race_top:sock_close
race_top:tstate_delete_common
race_top:tstate_is_freed
race_top:type_modified_unlocked
-race_top:update_refs
race_top:write_thread_id
race_top:PyThreadState_Clear
1
0
Bump types-psutil from 5.9.5.20240423 to 5.9.5.20240516 in /Tools (#119900)
by AlexWaygood 01 Jun '24
by AlexWaygood 01 Jun '24
01 Jun '24
https://github.com/python/cpython/commit/5152120ae746516670c77e7feed5c4a891…
commit: 5152120ae746516670c77e7feed5c4a8912f2bbb
branch: main
author: dependabot[bot] <49699333+dependabot[bot](a)users.noreply.github.com>
committer: AlexWaygood <Alex.Waygood(a)Gmail.com>
date: 2024-06-01T10:38:13Z
summary:
Bump types-psutil from 5.9.5.20240423 to 5.9.5.20240516 in /Tools (#119900)
files:
M Tools/requirements-dev.txt
diff --git a/Tools/requirements-dev.txt b/Tools/requirements-dev.txt
index f430ddedb9f856..44316e3d7d8ac5 100644
--- a/Tools/requirements-dev.txt
+++ b/Tools/requirements-dev.txt
@@ -3,5 +3,5 @@
mypy==1.10.0
# needed for peg_generator:
-types-psutil==5.9.5.20240423
+types-psutil==5.9.5.20240516
types-setuptools==70.0.0.20240524
1
0
build(deps-dev): bump types-setuptools from 69.5.0.20240423 to 70.0.0.20240524 in /Tools (#119899)
by AlexWaygood 01 Jun '24
by AlexWaygood 01 Jun '24
01 Jun '24
https://github.com/python/cpython/commit/51191dbfdd115b6de481a1cb5c86b952d6…
commit: 51191dbfdd115b6de481a1cb5c86b952d622c2d7
branch: main
author: dependabot[bot] <49699333+dependabot[bot](a)users.noreply.github.com>
committer: AlexWaygood <Alex.Waygood(a)Gmail.com>
date: 2024-06-01T10:11:53Z
summary:
build(deps-dev): bump types-setuptools from 69.5.0.20240423 to 70.0.0.20240524 in /Tools (#119899)
files:
M Tools/requirements-dev.txt
diff --git a/Tools/requirements-dev.txt b/Tools/requirements-dev.txt
index 1767727373918f..f430ddedb9f856 100644
--- a/Tools/requirements-dev.txt
+++ b/Tools/requirements-dev.txt
@@ -4,4 +4,4 @@ mypy==1.10.0
# needed for peg_generator:
types-psutil==5.9.5.20240423
-types-setuptools==69.5.0.20240423
+types-setuptools==70.0.0.20240524
1
0
https://github.com/python/cpython/commit/2180991ea3d50f56595edae241cc92dd4e…
commit: 2180991ea3d50f56595edae241cc92dd4e7de642
branch: main
author: Alyssa Coghlan <ncoghlan(a)gmail.com>
committer: ncoghlan <ncoghlan(a)gmail.com>
date: 2024-06-01T16:21:48+10:00
summary:
gh-118888: Further PEP 667 docs updates (gh-119893)
* Clarify impact on default behaviour of exec, eval, etc
* Update documentation for changes to PyEval_GetLocals (gh-74929)
Closes gh-11888
files:
M Doc/c-api/reflection.rst
M Doc/whatsnew/3.13.rst
diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst
index 5dcfe40c2ce92b..af9a1a74ec137e 100644
--- a/Doc/c-api/reflection.rst
+++ b/Doc/c-api/reflection.rst
@@ -19,11 +19,24 @@ Reflection
.. deprecated:: 3.13
- Use :c:func:`PyEval_GetFrameLocals` instead.
+ To avoid creating a reference cycle in :term:`optimized scopes <optimized scope>`,
+ use either :c:func:`PyEval_GetFrameLocals` to obtain the same behaviour as calling
+ :func:`locals` in Python code, or else call :c:func:`PyFrame_GetLocals` on the result
+ of :c:func:`PyEval_GetFrame` to get the same result as this function without having to
+ cache the proxy instance on the underlying frame.
- Return a dictionary of the local variables in the current execution frame,
+ Return the :attr:`~frame.f_locals` attribute of the currently executing frame,
or ``NULL`` if no frame is currently executing.
+ If the frame refers to an :term:`optimized scope`, this returns a
+ write-through proxy object that allows modifying the locals.
+ In all other cases (classes, modules, :func:`exec`, :func:`eval`) it returns
+ the mapping representing the frame locals directly (as described for
+ :func:`locals`).
+
+ .. versionchanged:: 3.13
+ As part of :pep:`667`, return a proxy object for optimized scopes.
+
.. c:function:: PyObject* PyEval_GetGlobals(void)
@@ -57,6 +70,10 @@ Reflection
or ``NULL`` if no frame is currently executing. Equivalent to calling
:func:`locals` in Python code.
+ To access :attr:`~frame.f_locals` on the current frame without making an independent
+ snapshot in :term:`optimized scopes <optimized scope>`, call :c:func:`PyFrame_GetLocals`
+ on the result of :c:func:`PyEval_GetFrame`.
+
.. versionadded:: 3.13
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 3a52baf71310a3..ab260bf2a2d740 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -266,6 +266,21 @@ comprehensions, and generator expressions) to explicitly return independent
snapshots of the currently assigned local variables, including locally
referenced nonlocal variables captured in closures.
+This change to the semantics of :func:`locals` in optimized scopes also affects the default
+behaviour of code execution functions that implicitly target ``locals()`` if no explicit
+namespace is provided (such as :func:`exec` and :func:`eval`). In previous versions, whether
+or not changes could be accessed by calling ``locals()`` after calling the code execution
+function was implementation dependent. In CPython specifically, such code would typically
+appear to work as desired, but could sometimes fail in optimized scopes based on other code
+(including debuggers and code execution tracing tools) potentially resetting the shared
+snapshot in that scope. Now, the code will always run against an independent snapshot of the
+local variables in optimized scopes, and hence the changes will never be visible in
+subsequent calls to ``locals()``. To access the changes made in these cases, an explicit
+namespace reference must now be passed to the relevant function. Alternatively, it may make
+sense to update affected code to use a higher level code execution API that returns the
+resulting code execution namespace (e.g. :func:`runpy.run_path` when executing Python
+files from disk).
+
To ensure debuggers and similar tools can reliably update local variables in
scopes affected by this change, :attr:`FrameType.f_locals <frame.f_locals>` now
returns a write-through proxy to the frame's local and locally referenced
@@ -2235,7 +2250,10 @@ Changes in the Python API
independent snapshot on each call, and hence no longer implicitly updates
previously returned references. Obtaining the legacy CPython behaviour now
requires explicit calls to update the initially returned dictionary with the
- results of subsequent calls to ``locals()``. (Changed as part of :pep:`667`.)
+ results of subsequent calls to ``locals()``. Code execution functions that
+ implicitly target ``locals()`` (such as ``exec`` and ``eval``) must be
+ passed an explicit namespace to access their results in an optimized scope.
+ (Changed as part of :pep:`667`.)
* Calling :func:`locals` from a comprehension at module or class scope
(including via ``exec`` or ``eval``) once more behaves as if the comprehension
@@ -2323,6 +2341,12 @@ Changes in the C API
to :c:func:`PyUnstable_Code_GetFirstFree`.
(Contributed by Bogdan Romanyuk in :gh:`115781`.)
+* Calling :c:func:`PyFrame_GetLocals` or :c:func:`PyEval_GetLocals` in an
+ :term:`optimized scope` now returns a write-through proxy rather than a
+ snapshot that gets updated at ill-specified times. If a snapshot is desired,
+ it must be created explicitly (e.g. with :c:func:`PyDict_Copy`) or by calling
+ the new :c:func:`PyEval_GetFrameLocals` API. (Changed as part of :pep:`667`.)
+
* :c:func:`!PyFrame_FastToLocals` and :c:func:`!PyFrame_FastToLocalsWithError`
no longer have any effect. Calling these functions has been redundant since
Python 3.11, when :c:func:`PyFrame_GetLocals` was first introduced.
1
0
[3.12] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBALS (#119822) (#119890)
by JelleZijlstra 01 Jun '24
by JelleZijlstra 01 Jun '24
01 Jun '24
https://github.com/python/cpython/commit/6d9677d78e18012b4e53a92d43fabf0372…
commit: 6d9677d78e18012b4e53a92d43fabf0372d08c33
branch: 3.12
author: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2024-05-31T21:56:38-07:00
summary:
[3.12] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBALS (#119822) (#119890)
The implementation basically copies LOAD_GLOBAL. Possibly it could be deduplicated,
but that seems like it may get hairy since the two operations have different operands.
This is important to fix in 3.14 for PEP 649, but it's a bug in earlier versions too,
and we should backport to 3.13 and 3.12 if possible.
(cherry picked from commit 80a4e3899420faaa012c82b4e82cdb6675a6a944)
files:
A Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
M Lib/test/test_type_aliases.py
M Python/bytecodes.c
M Python/generated_cases.c.h
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index 9c325bc595f585..f8b395fdc8bb1d 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -1,4 +1,5 @@
import pickle
+import textwrap
import types
import unittest
from test.support import check_syntax_error, run_code
@@ -328,3 +329,22 @@ def test_pickling_local(self):
with self.subTest(thing=thing, proto=proto):
with self.assertRaises(pickle.PickleError):
pickle.dumps(thing, protocol=proto)
+
+
+class TypeParamsExoticGlobalsTest(unittest.TestCase):
+ def test_exec_with_unusual_globals(self):
+ class customdict(dict):
+ def __missing__(self, key):
+ return key
+
+ code = compile("type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["Alias"]
+ self.assertEqual(Alias.__value__, "undefined")
+
+ code = compile("class A: type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["A"].Alias
+ self.assertEqual(Alias.__value__, "undefined")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
new file mode 100644
index 00000000000000..cc25eee6dd6ae4
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
@@ -0,0 +1,2 @@
+Fix execution of :ref:`annotation scopes <annotation-scopes>` within classes
+when ``globals`` is set to a non-dict. Patch by Jelle Zijlstra.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 1c25486c3d4c5f..18061b692641f2 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1196,27 +1196,33 @@ dummy_func(
}
}
if (v == NULL) {
- v = PyDict_GetItemWithError(GLOBALS(), name);
- if (v != NULL) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ format_exc_check_arg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
+ ERROR_IF(true, error);
+ }
Py_INCREF(v);
}
- else if (_PyErr_Occurred(tstate)) {
- goto error;
- }
else {
- if (PyDict_CheckExact(BUILTINS())) {
- v = PyDict_GetItemWithError(BUILTINS(), name);
- if (v == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
- Py_INCREF(v);
- }
- else {
+ /* Slow-path if globals or builtins is not a dict */
+
+ /* namespace 1: globals */
+ v = PyObject_GetItem(GLOBALS(), name);
+ if (v == NULL) {
+ ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);
+ _PyErr_Clear(tstate);
+
+ /* namespace 2: builtins */
v = PyObject_GetItem(BUILTINS(), name);
if (v == NULL) {
if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
@@ -1224,7 +1230,7 @@ dummy_func(
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
- goto error;
+ ERROR_IF(true, error);
}
}
}
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index d5e3ce28ce264b..31f37ec4cdd943 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1658,27 +1658,33 @@
}
}
if (v == NULL) {
- v = PyDict_GetItemWithError(GLOBALS(), name);
- if (v != NULL) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ format_exc_check_arg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
+ if (true) goto pop_1_error;
+ }
Py_INCREF(v);
}
- else if (_PyErr_Occurred(tstate)) {
- goto error;
- }
else {
- if (PyDict_CheckExact(BUILTINS())) {
- v = PyDict_GetItemWithError(BUILTINS(), name);
- if (v == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- format_exc_check_arg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- }
- goto error;
- }
- Py_INCREF(v);
- }
- else {
+ /* Slow-path if globals or builtins is not a dict */
+
+ /* namespace 1: globals */
+ v = PyObject_GetItem(GLOBALS(), name);
+ if (v == NULL) {
+ if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto pop_1_error;
+ _PyErr_Clear(tstate);
+
+ /* namespace 2: builtins */
v = PyObject_GetItem(BUILTINS(), name);
if (v == NULL) {
if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
@@ -1686,12 +1692,12 @@
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
- goto error;
+ if (true) goto pop_1_error;
}
}
}
}
- #line 1695 "Python/generated_cases.c.h"
+ #line 1701 "Python/generated_cases.c.h"
Py_DECREF(mod_or_class_dict);
stack_pointer[-1] = v;
DISPATCH();
@@ -1699,7 +1705,7 @@
TARGET(LOAD_NAME) {
PyObject *v;
- #line 1236 "Python/bytecodes.c"
+ #line 1242 "Python/bytecodes.c"
PyObject *mod_or_class_dict = LOCALS();
if (mod_or_class_dict == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -1759,7 +1765,7 @@
}
}
}
- #line 1763 "Python/generated_cases.c.h"
+ #line 1769 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = v;
DISPATCH();
@@ -1770,7 +1776,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
PyObject *null = NULL;
PyObject *v;
- #line 1304 "Python/bytecodes.c"
+ #line 1310 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -1822,7 +1828,7 @@
}
}
null = NULL;
- #line 1826 "Python/generated_cases.c.h"
+ #line 1832 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = v;
@@ -1836,7 +1842,7 @@
PyObject *res;
uint16_t index = read_u16(&next_instr[1].cache);
uint16_t version = read_u16(&next_instr[2].cache);
- #line 1358 "Python/bytecodes.c"
+ #line 1364 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS();
DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
@@ -1847,7 +1853,7 @@
Py_INCREF(res);
STAT_INC(LOAD_GLOBAL, hit);
null = NULL;
- #line 1851 "Python/generated_cases.c.h"
+ #line 1857 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -1862,7 +1868,7 @@
uint16_t index = read_u16(&next_instr[1].cache);
uint16_t mod_version = read_u16(&next_instr[2].cache);
uint16_t bltn_version = read_u16(&next_instr[3].cache);
- #line 1371 "Python/bytecodes.c"
+ #line 1377 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
PyDictObject *mdict = (PyDictObject *)GLOBALS();
@@ -1877,7 +1883,7 @@
Py_INCREF(res);
STAT_INC(LOAD_GLOBAL, hit);
null = NULL;
- #line 1881 "Python/generated_cases.c.h"
+ #line 1887 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -1887,16 +1893,16 @@
}
TARGET(DELETE_FAST) {
- #line 1388 "Python/bytecodes.c"
+ #line 1394 "Python/bytecodes.c"
PyObject *v = GETLOCAL(oparg);
if (v == NULL) goto unbound_local_error;
SETLOCAL(oparg, NULL);
- #line 1895 "Python/generated_cases.c.h"
+ #line 1901 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(MAKE_CELL) {
- #line 1394 "Python/bytecodes.c"
+ #line 1400 "Python/bytecodes.c"
// "initial" is probably NULL but not if it's an arg (or set
// via PyFrame_LocalsToFast() before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
@@ -1905,12 +1911,12 @@
goto resume_with_error;
}
SETLOCAL(oparg, cell);
- #line 1909 "Python/generated_cases.c.h"
+ #line 1915 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(DELETE_DEREF) {
- #line 1405 "Python/bytecodes.c"
+ #line 1411 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
// Can't use ERROR_IF here.
@@ -1921,14 +1927,14 @@
}
PyCell_SET(cell, NULL);
Py_DECREF(oldobj);
- #line 1925 "Python/generated_cases.c.h"
+ #line 1931 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(LOAD_FROM_DICT_OR_DEREF) {
PyObject *class_dict = stack_pointer[-1];
PyObject *value;
- #line 1418 "Python/bytecodes.c"
+ #line 1424 "Python/bytecodes.c"
PyObject *name;
assert(class_dict);
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
@@ -1961,14 +1967,14 @@
Py_INCREF(value);
}
Py_DECREF(class_dict);
- #line 1965 "Python/generated_cases.c.h"
+ #line 1971 "Python/generated_cases.c.h"
stack_pointer[-1] = value;
DISPATCH();
}
TARGET(LOAD_DEREF) {
PyObject *value;
- #line 1453 "Python/bytecodes.c"
+ #line 1459 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
@@ -1976,7 +1982,7 @@
if (true) goto error;
}
Py_INCREF(value);
- #line 1980 "Python/generated_cases.c.h"
+ #line 1986 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -1984,18 +1990,18 @@
TARGET(STORE_DEREF) {
PyObject *v = stack_pointer[-1];
- #line 1463 "Python/bytecodes.c"
+ #line 1469 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
PyCell_SET(cell, v);
Py_XDECREF(oldobj);
- #line 1993 "Python/generated_cases.c.h"
+ #line 1999 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(COPY_FREE_VARS) {
- #line 1470 "Python/bytecodes.c"
+ #line 1476 "Python/bytecodes.c"
/* Copy closure variables to free variables */
PyCodeObject *co = frame->f_code;
assert(PyFunction_Check(frame->f_funcobj));
@@ -2006,22 +2012,22 @@
PyObject *o = PyTuple_GET_ITEM(closure, i);
frame->localsplus[offset + i] = Py_NewRef(o);
}
- #line 2010 "Python/generated_cases.c.h"
+ #line 2016 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(BUILD_STRING) {
PyObject **pieces = (stack_pointer - oparg);
PyObject *str;
- #line 1483 "Python/bytecodes.c"
+ #line 1489 "Python/bytecodes.c"
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
- #line 2019 "Python/generated_cases.c.h"
+ #line 2025 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(pieces[_i]);
}
- #line 1485 "Python/bytecodes.c"
+ #line 1491 "Python/bytecodes.c"
if (str == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2025 "Python/generated_cases.c.h"
+ #line 2031 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = str;
@@ -2031,10 +2037,10 @@
TARGET(BUILD_TUPLE) {
PyObject **values = (stack_pointer - oparg);
PyObject *tup;
- #line 1489 "Python/bytecodes.c"
+ #line 1495 "Python/bytecodes.c"
tup = _PyTuple_FromArraySteal(values, oparg);
if (tup == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2038 "Python/generated_cases.c.h"
+ #line 2044 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = tup;
@@ -2044,10 +2050,10 @@
TARGET(BUILD_LIST) {
PyObject **values = (stack_pointer - oparg);
PyObject *list;
- #line 1494 "Python/bytecodes.c"
+ #line 1500 "Python/bytecodes.c"
list = _PyList_FromArraySteal(values, oparg);
if (list == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2051 "Python/generated_cases.c.h"
+ #line 2057 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = list;
@@ -2057,7 +2063,7 @@
TARGET(LIST_EXTEND) {
PyObject *iterable = stack_pointer[-1];
PyObject *list = stack_pointer[-(2 + (oparg-1))];
- #line 1499 "Python/bytecodes.c"
+ #line 1505 "Python/bytecodes.c"
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
if (none_val == NULL) {
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -2068,13 +2074,13 @@
"Value after * must be an iterable, not %.200s",
Py_TYPE(iterable)->tp_name);
}
- #line 2072 "Python/generated_cases.c.h"
+ #line 2078 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1510 "Python/bytecodes.c"
+ #line 1516 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
assert(Py_IsNone(none_val));
- #line 2078 "Python/generated_cases.c.h"
+ #line 2084 "Python/generated_cases.c.h"
Py_DECREF(iterable);
STACK_SHRINK(1);
DISPATCH();
@@ -2083,13 +2089,13 @@
TARGET(SET_UPDATE) {
PyObject *iterable = stack_pointer[-1];
PyObject *set = stack_pointer[-(2 + (oparg-1))];
- #line 1517 "Python/bytecodes.c"
+ #line 1523 "Python/bytecodes.c"
int err = _PySet_Update(set, iterable);
- #line 2089 "Python/generated_cases.c.h"
+ #line 2095 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1519 "Python/bytecodes.c"
+ #line 1525 "Python/bytecodes.c"
if (err < 0) goto pop_1_error;
- #line 2093 "Python/generated_cases.c.h"
+ #line 2099 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -2097,7 +2103,7 @@
TARGET(BUILD_SET) {
PyObject **values = (stack_pointer - oparg);
PyObject *set;
- #line 1523 "Python/bytecodes.c"
+ #line 1529 "Python/bytecodes.c"
set = PySet_New(NULL);
if (set == NULL)
goto error;
@@ -2112,7 +2118,7 @@
Py_DECREF(set);
if (true) { STACK_SHRINK(oparg); goto error; }
}
- #line 2116 "Python/generated_cases.c.h"
+ #line 2122 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = set;
@@ -2122,18 +2128,18 @@
TARGET(BUILD_MAP) {
PyObject **values = (stack_pointer - oparg*2);
PyObject *map;
- #line 1540 "Python/bytecodes.c"
+ #line 1546 "Python/bytecodes.c"
map = _PyDict_FromItems(
values, 2,
values+1, 2,
oparg);
- #line 2131 "Python/generated_cases.c.h"
+ #line 2137 "Python/generated_cases.c.h"
for (int _i = oparg*2; --_i >= 0;) {
Py_DECREF(values[_i]);
}
- #line 1545 "Python/bytecodes.c"
+ #line 1551 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }
- #line 2137 "Python/generated_cases.c.h"
+ #line 2143 "Python/generated_cases.c.h"
STACK_SHRINK(oparg*2);
STACK_GROW(1);
stack_pointer[-1] = map;
@@ -2141,7 +2147,7 @@
}
TARGET(SETUP_ANNOTATIONS) {
- #line 1549 "Python/bytecodes.c"
+ #line 1555 "Python/bytecodes.c"
int err;
PyObject *ann_dict;
if (LOCALS() == NULL) {
@@ -2181,7 +2187,7 @@
Py_DECREF(ann_dict);
}
}
- #line 2185 "Python/generated_cases.c.h"
+ #line 2191 "Python/generated_cases.c.h"
DISPATCH();
}
@@ -2189,7 +2195,7 @@
PyObject *keys = stack_pointer[-1];
PyObject **values = (stack_pointer - (1 + oparg));
PyObject *map;
- #line 1591 "Python/bytecodes.c"
+ #line 1597 "Python/bytecodes.c"
if (!PyTuple_CheckExact(keys) ||
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -2199,14 +2205,14 @@
map = _PyDict_FromItems(
&PyTuple_GET_ITEM(keys, 0), 1,
values, 1, oparg);
- #line 2203 "Python/generated_cases.c.h"
+ #line 2209 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(values[_i]);
}
Py_DECREF(keys);
- #line 1601 "Python/bytecodes.c"
+ #line 1607 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }
- #line 2210 "Python/generated_cases.c.h"
+ #line 2216 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
stack_pointer[-1] = map;
DISPATCH();
@@ -2214,7 +2220,7 @@
TARGET(DICT_UPDATE) {
PyObject *update = stack_pointer[-1];
- #line 1605 "Python/bytecodes.c"
+ #line 1611 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 1); // update is still on the stack
if (PyDict_Update(dict, update) < 0) {
if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
@@ -2222,12 +2228,12 @@
"'%.200s' object is not a mapping",
Py_TYPE(update)->tp_name);
}
- #line 2226 "Python/generated_cases.c.h"
+ #line 2232 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1613 "Python/bytecodes.c"
+ #line 1619 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2231 "Python/generated_cases.c.h"
+ #line 2237 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
DISPATCH();
@@ -2235,17 +2241,17 @@
TARGET(DICT_MERGE) {
PyObject *update = stack_pointer[-1];
- #line 1619 "Python/bytecodes.c"
+ #line 1625 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 1); // update is still on the stack
if (_PyDict_MergeEx(dict, update, 2) < 0) {
format_kwargs_error(tstate, PEEK(3 + oparg), update);
- #line 2244 "Python/generated_cases.c.h"
+ #line 2250 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1624 "Python/bytecodes.c"
+ #line 1630 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2249 "Python/generated_cases.c.h"
+ #line 2255 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
PREDICT(CALL_FUNCTION_EX);
@@ -2255,26 +2261,26 @@
TARGET(MAP_ADD) {
PyObject *value = stack_pointer[-1];
PyObject *key = stack_pointer[-2];
- #line 1631 "Python/bytecodes.c"
+ #line 1637 "Python/bytecodes.c"
PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack
assert(PyDict_CheckExact(dict));
/* dict[key] = value */
// Do not DECREF INPUTS because the function steals the references
if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error;
- #line 2265 "Python/generated_cases.c.h"
+ #line 2271 "Python/generated_cases.c.h"
STACK_SHRINK(2);
PREDICT(JUMP_BACKWARD);
DISPATCH();
}
TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) {
- #line 1640 "Python/bytecodes.c"
+ #line 1646 "Python/bytecodes.c"
_PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;
// cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
// don't want to specialize instrumented instructions
INCREMENT_ADAPTIVE_COUNTER(cache->counter);
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
- #line 2278 "Python/generated_cases.c.h"
+ #line 2284 "Python/generated_cases.c.h"
}
TARGET(LOAD_SUPER_ATTR) {
@@ -2285,7 +2291,7 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1654 "Python/bytecodes.c"
+ #line 1660 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
int load_method = oparg & 1;
#if ENABLE_SPECIALIZATION
@@ -2327,16 +2333,16 @@
}
}
}
- #line 2331 "Python/generated_cases.c.h"
+ #line 2337 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1696 "Python/bytecodes.c"
+ #line 1702 "Python/bytecodes.c"
if (super == NULL) goto pop_3_error;
res = PyObject_GetAttr(super, name);
Py_DECREF(super);
if (res == NULL) goto pop_3_error;
- #line 2340 "Python/generated_cases.c.h"
+ #line 2346 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2351,20 +2357,20 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1703 "Python/bytecodes.c"
+ #line 1709 "Python/bytecodes.c"
assert(!(oparg & 1));
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->f_code->co_names, oparg >> 2);
res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
- #line 2362 "Python/generated_cases.c.h"
+ #line 2368 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1710 "Python/bytecodes.c"
+ #line 1716 "Python/bytecodes.c"
if (res == NULL) goto pop_3_error;
- #line 2368 "Python/generated_cases.c.h"
+ #line 2374 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2379,7 +2385,7 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2;
PyObject *res;
- #line 1714 "Python/bytecodes.c"
+ #line 1720 "Python/bytecodes.c"
assert(oparg & 1);
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
@@ -2402,7 +2408,7 @@
res = res2;
res2 = NULL;
}
- #line 2406 "Python/generated_cases.c.h"
+ #line 2412 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
stack_pointer[-2] = res2;
@@ -2416,7 +2422,7 @@
PyObject *owner = stack_pointer[-1];
PyObject *res2 = NULL;
PyObject *res;
- #line 1753 "Python/bytecodes.c"
+ #line 1759 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2450,9 +2456,9 @@
NULL | meth | arg1 | ... | argN
*/
- #line 2454 "Python/generated_cases.c.h"
+ #line 2460 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1787 "Python/bytecodes.c"
+ #line 1793 "Python/bytecodes.c"
if (meth == NULL) goto pop_1_error;
res2 = NULL;
res = meth;
@@ -2461,12 +2467,12 @@
else {
/* Classic, pushes one value. */
res = PyObject_GetAttr(owner, name);
- #line 2465 "Python/generated_cases.c.h"
+ #line 2471 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1796 "Python/bytecodes.c"
+ #line 1802 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
}
- #line 2470 "Python/generated_cases.c.h"
+ #line 2476 "Python/generated_cases.c.h"
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
@@ -2480,7 +2486,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1801 "Python/bytecodes.c"
+ #line 1807 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2493,7 +2499,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2497 "Python/generated_cases.c.h"
+ #line 2503 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2508,7 +2514,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1817 "Python/bytecodes.c"
+ #line 1823 "Python/bytecodes.c"
DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
@@ -2521,7 +2527,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2525 "Python/generated_cases.c.h"
+ #line 2531 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2536,7 +2542,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1833 "Python/bytecodes.c"
+ #line 1839 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2563,7 +2569,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2567 "Python/generated_cases.c.h"
+ #line 2573 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2578,7 +2584,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1863 "Python/bytecodes.c"
+ #line 1869 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2588,7 +2594,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2592 "Python/generated_cases.c.h"
+ #line 2598 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2603,7 +2609,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 1876 "Python/bytecodes.c"
+ #line 1882 "Python/bytecodes.c"
DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);
DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,
@@ -2615,7 +2621,7 @@
res = descr;
assert(res != NULL);
Py_INCREF(res);
- #line 2619 "Python/generated_cases.c.h"
+ #line 2625 "Python/generated_cases.c.h"
Py_DECREF(cls);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2629,7 +2635,7 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t func_version = read_u32(&next_instr[3].cache);
PyObject *fget = read_obj(&next_instr[5].cache);
- #line 1891 "Python/bytecodes.c"
+ #line 1897 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner);
@@ -2653,7 +2659,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2657 "Python/generated_cases.c.h"
+ #line 2663 "Python/generated_cases.c.h"
}
TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) {
@@ -2661,7 +2667,7 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t func_version = read_u32(&next_instr[3].cache);
PyObject *getattribute = read_obj(&next_instr[5].cache);
- #line 1917 "Python/bytecodes.c"
+ #line 1923 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner);
DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);
@@ -2687,7 +2693,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2691 "Python/generated_cases.c.h"
+ #line 2697 "Python/generated_cases.c.h"
}
TARGET(STORE_ATTR_INSTANCE_VALUE) {
@@ -2695,7 +2701,7 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1945 "Python/bytecodes.c"
+ #line 1951 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2713,7 +2719,7 @@
Py_DECREF(old_value);
}
Py_DECREF(owner);
- #line 2717 "Python/generated_cases.c.h"
+ #line 2723 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2724,7 +2730,7 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t hint = read_u16(&next_instr[3].cache);
- #line 1965 "Python/bytecodes.c"
+ #line 1971 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2763,7 +2769,7 @@
/* PEP 509 */
dict->ma_version_tag = new_version;
Py_DECREF(owner);
- #line 2767 "Python/generated_cases.c.h"
+ #line 2773 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2774,7 +2780,7 @@
PyObject *value = stack_pointer[-2];
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 2006 "Python/bytecodes.c"
+ #line 2012 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2784,7 +2790,7 @@
*(PyObject **)addr = value;
Py_XDECREF(old_value);
Py_DECREF(owner);
- #line 2788 "Python/generated_cases.c.h"
+ #line 2794 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2796,7 +2802,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2025 "Python/bytecodes.c"
+ #line 2031 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2809,12 +2815,12 @@
#endif /* ENABLE_SPECIALIZATION */
assert((oparg >> 4) <= Py_GE);
res = PyObject_RichCompare(left, right, oparg>>4);
- #line 2813 "Python/generated_cases.c.h"
+ #line 2819 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2038 "Python/bytecodes.c"
+ #line 2044 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 2818 "Python/generated_cases.c.h"
+ #line 2824 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2825,7 +2831,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2042 "Python/bytecodes.c"
+ #line 2048 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
@@ -2836,7 +2842,7 @@
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2840 "Python/generated_cases.c.h"
+ #line 2846 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2847,7 +2853,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2056 "Python/bytecodes.c"
+ #line 2062 "Python/bytecodes.c"
DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);
@@ -2862,7 +2868,7 @@
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2866 "Python/generated_cases.c.h"
+ #line 2872 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2873,7 +2879,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2074 "Python/bytecodes.c"
+ #line 2080 "Python/bytecodes.c"
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
@@ -2885,7 +2891,7 @@
assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);
assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;
- #line 2889 "Python/generated_cases.c.h"
+ #line 2895 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2896,14 +2902,14 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2088 "Python/bytecodes.c"
+ #line 2094 "Python/bytecodes.c"
int res = Py_Is(left, right) ^ oparg;
- #line 2902 "Python/generated_cases.c.h"
+ #line 2908 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2090 "Python/bytecodes.c"
+ #line 2096 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 2907 "Python/generated_cases.c.h"
+ #line 2913 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2913,15 +2919,15 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2094 "Python/bytecodes.c"
+ #line 2100 "Python/bytecodes.c"
int res = PySequence_Contains(right, left);
- #line 2919 "Python/generated_cases.c.h"
+ #line 2925 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2096 "Python/bytecodes.c"
+ #line 2102 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
b = (res ^ oparg) ? Py_True : Py_False;
- #line 2925 "Python/generated_cases.c.h"
+ #line 2931 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2932,12 +2938,12 @@
PyObject *exc_value = stack_pointer[-2];
PyObject *rest;
PyObject *match;
- #line 2101 "Python/bytecodes.c"
+ #line 2107 "Python/bytecodes.c"
if (check_except_star_type_valid(tstate, match_type) < 0) {
- #line 2938 "Python/generated_cases.c.h"
+ #line 2944 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2103 "Python/bytecodes.c"
+ #line 2109 "Python/bytecodes.c"
if (true) goto pop_2_error;
}
@@ -2945,10 +2951,10 @@
rest = NULL;
int res = exception_group_match(exc_value, match_type,
&match, &rest);
- #line 2949 "Python/generated_cases.c.h"
+ #line 2955 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2111 "Python/bytecodes.c"
+ #line 2117 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
assert((match == NULL) == (rest == NULL));
@@ -2957,7 +2963,7 @@
if (!Py_IsNone(match)) {
PyErr_SetHandledException(match);
}
- #line 2961 "Python/generated_cases.c.h"
+ #line 2967 "Python/generated_cases.c.h"
stack_pointer[-1] = match;
stack_pointer[-2] = rest;
DISPATCH();
@@ -2967,21 +2973,21 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2122 "Python/bytecodes.c"
+ #line 2128 "Python/bytecodes.c"
assert(PyExceptionInstance_Check(left));
if (check_except_type_valid(tstate, right) < 0) {
- #line 2974 "Python/generated_cases.c.h"
+ #line 2980 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2125 "Python/bytecodes.c"
+ #line 2131 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
int res = PyErr_GivenExceptionMatches(left, right);
- #line 2981 "Python/generated_cases.c.h"
+ #line 2987 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2130 "Python/bytecodes.c"
+ #line 2136 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 2985 "Python/generated_cases.c.h"
+ #line 2991 "Python/generated_cases.c.h"
stack_pointer[-1] = b;
DISPATCH();
}
@@ -2990,15 +2996,15 @@
PyObject *fromlist = stack_pointer[-1];
PyObject *level = stack_pointer[-2];
PyObject *res;
- #line 2134 "Python/bytecodes.c"
+ #line 2140 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
res = import_name(tstate, frame, name, fromlist, level);
- #line 2997 "Python/generated_cases.c.h"
+ #line 3003 "Python/generated_cases.c.h"
Py_DECREF(level);
Py_DECREF(fromlist);
- #line 2137 "Python/bytecodes.c"
+ #line 2143 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 3002 "Python/generated_cases.c.h"
+ #line 3008 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3007,29 +3013,29 @@
TARGET(IMPORT_FROM) {
PyObject *from = stack_pointer[-1];
PyObject *res;
- #line 2141 "Python/bytecodes.c"
+ #line 2147 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
res = import_from(tstate, from, name);
if (res == NULL) goto error;
- #line 3015 "Python/generated_cases.c.h"
+ #line 3021 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
}
TARGET(JUMP_FORWARD) {
- #line 2147 "Python/bytecodes.c"
+ #line 2153 "Python/bytecodes.c"
JUMPBY(oparg);
- #line 3024 "Python/generated_cases.c.h"
+ #line 3030 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(JUMP_BACKWARD) {
PREDICTED(JUMP_BACKWARD);
- #line 2151 "Python/bytecodes.c"
+ #line 2157 "Python/bytecodes.c"
assert(oparg < INSTR_OFFSET());
JUMPBY(-oparg);
- #line 3033 "Python/generated_cases.c.h"
+ #line 3039 "Python/generated_cases.c.h"
CHECK_EVAL_BREAKER();
DISPATCH();
}
@@ -3037,15 +3043,15 @@
TARGET(POP_JUMP_IF_FALSE) {
PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = stack_pointer[-1];
- #line 2157 "Python/bytecodes.c"
+ #line 2163 "Python/bytecodes.c"
if (Py_IsFalse(cond)) {
JUMPBY(oparg);
}
else if (!Py_IsTrue(cond)) {
int err = PyObject_IsTrue(cond);
- #line 3047 "Python/generated_cases.c.h"
+ #line 3053 "Python/generated_cases.c.h"
Py_DECREF(cond);
- #line 2163 "Python/bytecodes.c"
+ #line 2169 "Python/bytecodes.c"
if (err == 0) {
JUMPBY(oparg);
}
@@ -3053,22 +3059,22 @@
if (err < 0) goto pop_1_error;
}
}
- #line 3057 "Python/generated_cases.c.h"
+ #line 3063 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_TRUE) {
PyObject *cond = stack_pointer[-1];
- #line 2173 "Python/bytecodes.c"
+ #line 2179 "Python/bytecodes.c"
if (Py_IsTrue(cond)) {
JUMPBY(oparg);
}
else if (!Py_IsFalse(cond)) {
int err = PyObject_IsTrue(cond);
- #line 3070 "Python/generated_cases.c.h"
+ #line 3076 "Python/generated_cases.c.h"
Py_DECREF(cond);
- #line 2179 "Python/bytecodes.c"
+ #line 2185 "Python/bytecodes.c"
if (err > 0) {
JUMPBY(oparg);
}
@@ -3076,63 +3082,63 @@
if (err < 0) goto pop_1_error;
}
}
- #line 3080 "Python/generated_cases.c.h"
+ #line 3086 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_NOT_NONE) {
PyObject *value = stack_pointer[-1];
- #line 2189 "Python/bytecodes.c"
+ #line 2195 "Python/bytecodes.c"
if (!Py_IsNone(value)) {
- #line 3089 "Python/generated_cases.c.h"
+ #line 3095 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 2191 "Python/bytecodes.c"
+ #line 2197 "Python/bytecodes.c"
JUMPBY(oparg);
}
- #line 3094 "Python/generated_cases.c.h"
+ #line 3100 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_NONE) {
PyObject *value = stack_pointer[-1];
- #line 2196 "Python/bytecodes.c"
+ #line 2202 "Python/bytecodes.c"
if (Py_IsNone(value)) {
JUMPBY(oparg);
}
else {
- #line 3106 "Python/generated_cases.c.h"
+ #line 3112 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 2201 "Python/bytecodes.c"
+ #line 2207 "Python/bytecodes.c"
}
- #line 3110 "Python/generated_cases.c.h"
+ #line 3116 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(JUMP_BACKWARD_NO_INTERRUPT) {
- #line 2205 "Python/bytecodes.c"
+ #line 2211 "Python/bytecodes.c"
/* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost
* generator or coroutine, so we deliberately do not check it here.
* (see bpo-30039).
*/
JUMPBY(-oparg);
- #line 3123 "Python/generated_cases.c.h"
+ #line 3129 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(GET_LEN) {
PyObject *obj = stack_pointer[-1];
PyObject *len_o;
- #line 2214 "Python/bytecodes.c"
+ #line 2220 "Python/bytecodes.c"
// PUSH(len(TOS))
Py_ssize_t len_i = PyObject_Length(obj);
if (len_i < 0) goto error;
len_o = PyLong_FromSsize_t(len_i);
if (len_o == NULL) goto error;
- #line 3136 "Python/generated_cases.c.h"
+ #line 3142 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = len_o;
DISPATCH();
@@ -3143,16 +3149,16 @@
PyObject *type = stack_pointer[-2];
PyObject *subject = stack_pointer[-3];
PyObject *attrs;
- #line 2222 "Python/bytecodes.c"
+ #line 2228 "Python/bytecodes.c"
// Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or
// None on failure.
assert(PyTuple_CheckExact(names));
attrs = match_class(tstate, subject, type, oparg, names);
- #line 3152 "Python/generated_cases.c.h"
+ #line 3158 "Python/generated_cases.c.h"
Py_DECREF(subject);
Py_DECREF(type);
Py_DECREF(names);
- #line 2227 "Python/bytecodes.c"
+ #line 2233 "Python/bytecodes.c"
if (attrs) {
assert(PyTuple_CheckExact(attrs)); // Success!
}
@@ -3160,7 +3166,7 @@
if (_PyErr_Occurred(tstate)) goto pop_3_error;
attrs = Py_None; // Failure!
}
- #line 3164 "Python/generated_cases.c.h"
+ #line 3170 "Python/generated_cases.c.h"
STACK_SHRINK(2);
stack_pointer[-1] = attrs;
DISPATCH();
@@ -3169,10 +3175,10 @@
TARGET(MATCH_MAPPING) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2237 "Python/bytecodes.c"
+ #line 2243 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
res = match ? Py_True : Py_False;
- #line 3176 "Python/generated_cases.c.h"
+ #line 3182 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
PREDICT(POP_JUMP_IF_FALSE);
@@ -3182,10 +3188,10 @@
TARGET(MATCH_SEQUENCE) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2243 "Python/bytecodes.c"
+ #line 2249 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
res = match ? Py_True : Py_False;
- #line 3189 "Python/generated_cases.c.h"
+ #line 3195 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
PREDICT(POP_JUMP_IF_FALSE);
@@ -3196,11 +3202,11 @@
PyObject *keys = stack_pointer[-1];
PyObject *subject = stack_pointer[-2];
PyObject *values_or_none;
- #line 2249 "Python/bytecodes.c"
+ #line 2255 "Python/bytecodes.c"
// On successful match, PUSH(values). Otherwise, PUSH(None).
values_or_none = match_keys(tstate, subject, keys);
if (values_or_none == NULL) goto error;
- #line 3204 "Python/generated_cases.c.h"
+ #line 3210 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = values_or_none;
DISPATCH();
@@ -3209,14 +3215,14 @@
TARGET(GET_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2255 "Python/bytecodes.c"
+ #line 2261 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
iter = PyObject_GetIter(iterable);
- #line 3216 "Python/generated_cases.c.h"
+ #line 3222 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2258 "Python/bytecodes.c"
+ #line 2264 "Python/bytecodes.c"
if (iter == NULL) goto pop_1_error;
- #line 3220 "Python/generated_cases.c.h"
+ #line 3226 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -3224,7 +3230,7 @@
TARGET(GET_YIELD_FROM_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2262 "Python/bytecodes.c"
+ #line 2268 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
@@ -3247,11 +3253,11 @@
if (iter == NULL) {
goto error;
}
- #line 3251 "Python/generated_cases.c.h"
+ #line 3257 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2285 "Python/bytecodes.c"
+ #line 2291 "Python/bytecodes.c"
}
- #line 3255 "Python/generated_cases.c.h"
+ #line 3261 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
PREDICT(LOAD_CONST);
DISPATCH();
@@ -3262,7 +3268,7 @@
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2304 "Python/bytecodes.c"
+ #line 2310 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyForIterCache *cache = (_PyForIterCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -3293,7 +3299,7 @@
DISPATCH();
}
// Common case: no jump, leave it to the code generator
- #line 3297 "Python/generated_cases.c.h"
+ #line 3303 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3301,7 +3307,7 @@
}
TARGET(INSTRUMENTED_FOR_ITER) {
- #line 2337 "Python/bytecodes.c"
+ #line 2343 "Python/bytecodes.c"
_Py_CODEUNIT *here = next_instr-1;
_Py_CODEUNIT *target;
PyObject *iter = TOP();
@@ -3327,14 +3333,14 @@
target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;
}
INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);
- #line 3331 "Python/generated_cases.c.h"
+ #line 3337 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(FOR_ITER_LIST) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2365 "Python/bytecodes.c"
+ #line 2371 "Python/bytecodes.c"
DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
_PyListIterObject *it = (_PyListIterObject *)iter;
STAT_INC(FOR_ITER, hit);
@@ -3354,7 +3360,7 @@
DISPATCH();
end_for_iter_list:
// Common case: no jump, leave it to the code generator
- #line 3358 "Python/generated_cases.c.h"
+ #line 3364 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3364,7 +3370,7 @@
TARGET(FOR_ITER_TUPLE) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2387 "Python/bytecodes.c"
+ #line 2393 "Python/bytecodes.c"
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);
STAT_INC(FOR_ITER, hit);
@@ -3384,7 +3390,7 @@
DISPATCH();
end_for_iter_tuple:
// Common case: no jump, leave it to the code generator
- #line 3388 "Python/generated_cases.c.h"
+ #line 3394 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3394,7 +3400,7 @@
TARGET(FOR_ITER_RANGE) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2409 "Python/bytecodes.c"
+ #line 2415 "Python/bytecodes.c"
_PyRangeIterObject *r = (_PyRangeIterObject *)iter;
DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
STAT_INC(FOR_ITER, hit);
@@ -3412,7 +3418,7 @@
if (next == NULL) {
goto error;
}
- #line 3416 "Python/generated_cases.c.h"
+ #line 3422 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3421,7 +3427,7 @@
TARGET(FOR_ITER_GEN) {
PyObject *iter = stack_pointer[-1];
- #line 2429 "Python/bytecodes.c"
+ #line 2435 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);
PyGenObject *gen = (PyGenObject *)iter;
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER);
@@ -3437,14 +3443,14 @@
assert(next_instr[oparg].op.code == END_FOR ||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
DISPATCH_INLINED(gen_frame);
- #line 3441 "Python/generated_cases.c.h"
+ #line 3447 "Python/generated_cases.c.h"
}
TARGET(BEFORE_ASYNC_WITH) {
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2447 "Python/bytecodes.c"
+ #line 2453 "Python/bytecodes.c"
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
if (enter == NULL) {
if (!_PyErr_Occurred(tstate)) {
@@ -3467,16 +3473,16 @@
Py_DECREF(enter);
goto error;
}
- #line 3471 "Python/generated_cases.c.h"
+ #line 3477 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2470 "Python/bytecodes.c"
+ #line 2476 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3480 "Python/generated_cases.c.h"
+ #line 3486 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3488,7 +3494,7 @@
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2480 "Python/bytecodes.c"
+ #line 2486 "Python/bytecodes.c"
/* pop the context manager, push its __exit__ and the
* value returned from calling its __enter__
*/
@@ -3514,16 +3520,16 @@
Py_DECREF(enter);
goto error;
}
- #line 3518 "Python/generated_cases.c.h"
+ #line 3524 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2506 "Python/bytecodes.c"
+ #line 2512 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3527 "Python/generated_cases.c.h"
+ #line 3533 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3535,7 +3541,7 @@
PyObject *lasti = stack_pointer[-3];
PyObject *exit_func = stack_pointer[-4];
PyObject *res;
- #line 2515 "Python/bytecodes.c"
+ #line 2521 "Python/bytecodes.c"
/* At the top of the stack are 4 values:
- val: TOP = exc_info()
- unused: SECOND = previous exception
@@ -3561,7 +3567,7 @@
res = PyObject_Vectorcall(exit_func, stack + 1,
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
if (res == NULL) goto error;
- #line 3565 "Python/generated_cases.c.h"
+ #line 3571 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3570,7 +3576,7 @@
TARGET(PUSH_EXC_INFO) {
PyObject *new_exc = stack_pointer[-1];
PyObject *prev_exc;
- #line 2543 "Python/bytecodes.c"
+ #line 2549 "Python/bytecodes.c"
_PyErr_StackItem *exc_info = tstate->exc_info;
if (exc_info->exc_value != NULL) {
prev_exc = exc_info->exc_value;
@@ -3580,7 +3586,7 @@
}
assert(PyExceptionInstance_Check(new_exc));
exc_info->exc_value = Py_NewRef(new_exc);
- #line 3584 "Python/generated_cases.c.h"
+ #line 3590 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = new_exc;
stack_pointer[-2] = prev_exc;
@@ -3594,7 +3600,7 @@
uint32_t type_version = read_u32(&next_instr[1].cache);
uint32_t keys_version = read_u32(&next_instr[3].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2555 "Python/bytecodes.c"
+ #line 2561 "Python/bytecodes.c"
/* Cached method object */
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
@@ -3611,7 +3617,7 @@
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
res = self;
assert(oparg & 1);
- #line 3615 "Python/generated_cases.c.h"
+ #line 3621 "Python/generated_cases.c.h"
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
@@ -3625,7 +3631,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2574 "Python/bytecodes.c"
+ #line 2580 "Python/bytecodes.c"
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_dictoffset == 0);
@@ -3635,7 +3641,7 @@
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
- #line 3639 "Python/generated_cases.c.h"
+ #line 3645 "Python/generated_cases.c.h"
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
@@ -3649,7 +3655,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2586 "Python/bytecodes.c"
+ #line 2592 "Python/bytecodes.c"
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
Py_ssize_t dictoffset = self_cls->tp_dictoffset;
@@ -3663,7 +3669,7 @@
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
- #line 3667 "Python/generated_cases.c.h"
+ #line 3673 "Python/generated_cases.c.h"
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }
@@ -3672,16 +3678,16 @@
}
TARGET(KW_NAMES) {
- #line 2602 "Python/bytecodes.c"
+ #line 2608 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts));
kwnames = GETITEM(frame->f_code->co_consts, oparg);
- #line 3680 "Python/generated_cases.c.h"
+ #line 3686 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_CALL) {
- #line 2608 "Python/bytecodes.c"
+ #line 2614 "Python/bytecodes.c"
int is_meth = PEEK(oparg+2) != NULL;
int total_args = oparg + is_meth;
PyObject *function = PEEK(total_args + 1);
@@ -3694,7 +3700,7 @@
_PyCallCache *cache = (_PyCallCache *)next_instr;
INCREMENT_ADAPTIVE_COUNTER(cache->counter);
GO_TO_INSTRUCTION(CALL);
- #line 3698 "Python/generated_cases.c.h"
+ #line 3704 "Python/generated_cases.c.h"
}
TARGET(CALL) {
@@ -3704,7 +3710,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2653 "Python/bytecodes.c"
+ #line 2659 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -3786,7 +3792,7 @@
Py_DECREF(args[i]);
}
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3790 "Python/generated_cases.c.h"
+ #line 3796 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3798,7 +3804,7 @@
TARGET(CALL_BOUND_METHOD_EXACT_ARGS) {
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 2741 "Python/bytecodes.c"
+ #line 2747 "Python/bytecodes.c"
DEOPT_IF(method != NULL, CALL);
DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);
STAT_INC(CALL, hit);
@@ -3808,7 +3814,7 @@
PEEK(oparg + 2) = Py_NewRef(meth); // method
Py_DECREF(callable);
GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);
- #line 3812 "Python/generated_cases.c.h"
+ #line 3818 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_EXACT_ARGS) {
@@ -3817,7 +3823,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2753 "Python/bytecodes.c"
+ #line 2759 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3843,7 +3849,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3847 "Python/generated_cases.c.h"
+ #line 3853 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_WITH_DEFAULTS) {
@@ -3851,7 +3857,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2781 "Python/bytecodes.c"
+ #line 2787 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3887,7 +3893,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3891 "Python/generated_cases.c.h"
+ #line 3897 "Python/generated_cases.c.h"
}
TARGET(CALL_NO_KW_TYPE_1) {
@@ -3895,7 +3901,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2819 "Python/bytecodes.c"
+ #line 2825 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3905,7 +3911,7 @@
res = Py_NewRef(Py_TYPE(obj));
Py_DECREF(obj);
Py_DECREF(&PyType_Type); // I.e., callable
- #line 3909 "Python/generated_cases.c.h"
+ #line 3915 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3918,7 +3924,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2831 "Python/bytecodes.c"
+ #line 2837 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3929,7 +3935,7 @@
Py_DECREF(arg);
Py_DECREF(&PyUnicode_Type); // I.e., callable
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3933 "Python/generated_cases.c.h"
+ #line 3939 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3943,7 +3949,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2845 "Python/bytecodes.c"
+ #line 2851 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3954,7 +3960,7 @@
Py_DECREF(arg);
Py_DECREF(&PyTuple_Type); // I.e., tuple
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3958 "Python/generated_cases.c.h"
+ #line 3964 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3968,7 +3974,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2859 "Python/bytecodes.c"
+ #line 2865 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -3990,7 +3996,7 @@
}
Py_DECREF(tp);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3994 "Python/generated_cases.c.h"
+ #line 4000 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4004,7 +4010,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2884 "Python/bytecodes.c"
+ #line 2890 "Python/bytecodes.c"
/* Builtin METH_O functions */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4032,7 +4038,7 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4036 "Python/generated_cases.c.h"
+ #line 4042 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4046,7 +4052,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2915 "Python/bytecodes.c"
+ #line 2921 "Python/bytecodes.c"
/* Builtin METH_FASTCALL functions, without keywords */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4078,7 +4084,7 @@
'invalid'). In those cases an exception is set, so we must
handle it.
*/
- #line 4082 "Python/generated_cases.c.h"
+ #line 4088 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4092,7 +4098,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2950 "Python/bytecodes.c"
+ #line 2956 "Python/bytecodes.c"
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
int is_meth = method != NULL;
int total_args = oparg;
@@ -4124,7 +4130,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4128 "Python/generated_cases.c.h"
+ #line 4134 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4138,7 +4144,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2985 "Python/bytecodes.c"
+ #line 2991 "Python/bytecodes.c"
assert(kwnames == NULL);
/* len(o) */
int is_meth = method != NULL;
@@ -4163,7 +4169,7 @@
Py_DECREF(callable);
Py_DECREF(arg);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4167 "Python/generated_cases.c.h"
+ #line 4173 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4176,7 +4182,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3012 "Python/bytecodes.c"
+ #line 3018 "Python/bytecodes.c"
assert(kwnames == NULL);
/* isinstance(o, o2) */
int is_meth = method != NULL;
@@ -4203,7 +4209,7 @@
Py_DECREF(cls);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4207 "Python/generated_cases.c.h"
+ #line 4213 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4215,7 +4221,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *self = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 3042 "Python/bytecodes.c"
+ #line 3048 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
PyInterpreterState *interp = _PyInterpreterState_GET();
@@ -4233,14 +4239,14 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
assert(next_instr[-1].op.code == POP_TOP);
DISPATCH();
- #line 4237 "Python/generated_cases.c.h"
+ #line 4243 "Python/generated_cases.c.h"
}
TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3062 "Python/bytecodes.c"
+ #line 3068 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4271,7 +4277,7 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4275 "Python/generated_cases.c.h"
+ #line 4281 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4284,7 +4290,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3096 "Python/bytecodes.c"
+ #line 3102 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -4313,7 +4319,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4317 "Python/generated_cases.c.h"
+ #line 4323 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4326,7 +4332,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3128 "Python/bytecodes.c"
+ #line 3134 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 0 || oparg == 1);
int is_meth = method != NULL;
@@ -4355,7 +4361,7 @@
Py_DECREF(self);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4359 "Python/generated_cases.c.h"
+ #line 4365 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4368,7 +4374,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3160 "Python/bytecodes.c"
+ #line 3166 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4396,7 +4402,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4400 "Python/generated_cases.c.h"
+ #line 4406 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4406,9 +4412,9 @@
}
TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {
- #line 3191 "Python/bytecodes.c"
+ #line 3197 "Python/bytecodes.c"
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
- #line 4412 "Python/generated_cases.c.h"
+ #line 4418 "Python/generated_cases.c.h"
}
TARGET(CALL_FUNCTION_EX) {
@@ -4417,7 +4423,7 @@
PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))];
PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))];
PyObject *result;
- #line 3195 "Python/bytecodes.c"
+ #line 3201 "Python/bytecodes.c"
// DICT_MERGE is called before this opcode if there are kwargs.
// It converts all dict subtypes in kwargs into regular dicts.
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
@@ -4479,14 +4485,14 @@
}
result = PyObject_Call(func, callargs, kwargs);
}
- #line 4483 "Python/generated_cases.c.h"
+ #line 4489 "Python/generated_cases.c.h"
Py_DECREF(func);
Py_DECREF(callargs);
Py_XDECREF(kwargs);
- #line 3257 "Python/bytecodes.c"
+ #line 3263 "Python/bytecodes.c"
assert(PEEK(3 + (oparg & 1)) == NULL);
if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; }
- #line 4490 "Python/generated_cases.c.h"
+ #line 4496 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg & 1) ? 1 : 0));
STACK_SHRINK(2);
stack_pointer[-1] = result;
@@ -4501,7 +4507,7 @@
PyObject *kwdefaults = (oparg & 0x02) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0))] : NULL;
PyObject *defaults = (oparg & 0x01) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x01) ? 1 : 0))] : NULL;
PyObject *func;
- #line 3267 "Python/bytecodes.c"
+ #line 3273 "Python/bytecodes.c"
PyFunctionObject *func_obj = (PyFunctionObject *)
PyFunction_New(codeobj, GLOBALS());
@@ -4530,14 +4536,14 @@
func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;
func = (PyObject *)func_obj;
- #line 4534 "Python/generated_cases.c.h"
+ #line 4540 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0));
stack_pointer[-1] = func;
DISPATCH();
}
TARGET(RETURN_GENERATOR) {
- #line 3298 "Python/bytecodes.c"
+ #line 3304 "Python/bytecodes.c"
assert(PyFunction_Check(frame->f_funcobj));
PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
@@ -4558,7 +4564,7 @@
frame = cframe.current_frame = prev;
_PyFrame_StackPush(frame, (PyObject *)gen);
goto resume_frame;
- #line 4562 "Python/generated_cases.c.h"
+ #line 4568 "Python/generated_cases.c.h"
}
TARGET(BUILD_SLICE) {
@@ -4566,15 +4572,15 @@
PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))];
PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))];
PyObject *slice;
- #line 3321 "Python/bytecodes.c"
+ #line 3327 "Python/bytecodes.c"
slice = PySlice_New(start, stop, step);
- #line 4572 "Python/generated_cases.c.h"
+ #line 4578 "Python/generated_cases.c.h"
Py_DECREF(start);
Py_DECREF(stop);
Py_XDECREF(step);
- #line 3323 "Python/bytecodes.c"
+ #line 3329 "Python/bytecodes.c"
if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; }
- #line 4578 "Python/generated_cases.c.h"
+ #line 4584 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg == 3) ? 1 : 0));
STACK_SHRINK(1);
stack_pointer[-1] = slice;
@@ -4585,7 +4591,7 @@
PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? stack_pointer[-((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))] : NULL;
PyObject *value = stack_pointer[-(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))];
PyObject *result;
- #line 3327 "Python/bytecodes.c"
+ #line 3333 "Python/bytecodes.c"
/* Handles f-string value formatting. */
PyObject *(*conv_fn)(PyObject *);
int which_conversion = oparg & FVC_MASK;
@@ -4620,7 +4626,7 @@
Py_DECREF(value);
Py_XDECREF(fmt_spec);
if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }
- #line 4624 "Python/generated_cases.c.h"
+ #line 4630 "Python/generated_cases.c.h"
STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));
stack_pointer[-1] = result;
DISPATCH();
@@ -4629,10 +4635,10 @@
TARGET(COPY) {
PyObject *bottom = stack_pointer[-(1 + (oparg-1))];
PyObject *top;
- #line 3364 "Python/bytecodes.c"
+ #line 3370 "Python/bytecodes.c"
assert(oparg > 0);
top = Py_NewRef(bottom);
- #line 4636 "Python/generated_cases.c.h"
+ #line 4642 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = top;
DISPATCH();
@@ -4644,7 +4650,7 @@
PyObject *rhs = stack_pointer[-1];
PyObject *lhs = stack_pointer[-2];
PyObject *res;
- #line 3369 "Python/bytecodes.c"
+ #line 3375 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -4659,12 +4665,12 @@
assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
assert(binary_ops[oparg]);
res = binary_ops[oparg](lhs, rhs);
- #line 4663 "Python/generated_cases.c.h"
+ #line 4669 "Python/generated_cases.c.h"
Py_DECREF(lhs);
Py_DECREF(rhs);
- #line 3384 "Python/bytecodes.c"
+ #line 3390 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 4668 "Python/generated_cases.c.h"
+ #line 4674 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -4674,16 +4680,16 @@
TARGET(SWAP) {
PyObject *top = stack_pointer[-1];
PyObject *bottom = stack_pointer[-(2 + (oparg-2))];
- #line 3389 "Python/bytecodes.c"
+ #line 3395 "Python/bytecodes.c"
assert(oparg >= 2);
- #line 4680 "Python/generated_cases.c.h"
+ #line 4686 "Python/generated_cases.c.h"
stack_pointer[-1] = bottom;
stack_pointer[-(2 + (oparg-2))] = top;
DISPATCH();
}
TARGET(INSTRUMENTED_INSTRUCTION) {
- #line 3393 "Python/bytecodes.c"
+ #line 3399 "Python/bytecodes.c"
int next_opcode = _Py_call_instrumentation_instruction(
tstate, frame, next_instr-1);
if (next_opcode < 0) goto error;
@@ -4695,26 +4701,26 @@
assert(next_opcode > 0 && next_opcode < 256);
opcode = next_opcode;
DISPATCH_GOTO();
- #line 4699 "Python/generated_cases.c.h"
+ #line 4705 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_JUMP_FORWARD) {
- #line 3407 "Python/bytecodes.c"
+ #line 3413 "Python/bytecodes.c"
INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP);
- #line 4705 "Python/generated_cases.c.h"
+ #line 4711 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_JUMP_BACKWARD) {
- #line 3411 "Python/bytecodes.c"
+ #line 3417 "Python/bytecodes.c"
INSTRUMENTED_JUMP(next_instr-1, next_instr-oparg, PY_MONITORING_EVENT_JUMP);
- #line 4712 "Python/generated_cases.c.h"
+ #line 4718 "Python/generated_cases.c.h"
CHECK_EVAL_BREAKER();
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) {
- #line 3416 "Python/bytecodes.c"
+ #line 3422 "Python/bytecodes.c"
PyObject *cond = POP();
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
@@ -4723,12 +4729,12 @@
assert(err == 0 || err == 1);
int offset = err*oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4727 "Python/generated_cases.c.h"
+ #line 4733 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) {
- #line 3427 "Python/bytecodes.c"
+ #line 3433 "Python/bytecodes.c"
PyObject *cond = POP();
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
@@ -4737,12 +4743,12 @@
assert(err == 0 || err == 1);
int offset = (1-err)*oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4741 "Python/generated_cases.c.h"
+ #line 4747 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) {
- #line 3438 "Python/bytecodes.c"
+ #line 3444 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4754,12 +4760,12 @@
offset = 0;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4758 "Python/generated_cases.c.h"
+ #line 4764 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) {
- #line 3452 "Python/bytecodes.c"
+ #line 3458 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4771,30 +4777,30 @@
offset = oparg;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4775 "Python/generated_cases.c.h"
+ #line 4781 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(EXTENDED_ARG) {
- #line 3466 "Python/bytecodes.c"
+ #line 3472 "Python/bytecodes.c"
assert(oparg);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
PRE_DISPATCH_GOTO();
DISPATCH_GOTO();
- #line 4786 "Python/generated_cases.c.h"
+ #line 4792 "Python/generated_cases.c.h"
}
TARGET(CACHE) {
- #line 3474 "Python/bytecodes.c"
+ #line 3480 "Python/bytecodes.c"
assert(0 && "Executing a cache.");
Py_UNREACHABLE();
- #line 4793 "Python/generated_cases.c.h"
+ #line 4799 "Python/generated_cases.c.h"
}
TARGET(RESERVED) {
- #line 3479 "Python/bytecodes.c"
+ #line 3485 "Python/bytecodes.c"
assert(0 && "Executing RESERVED instruction.");
Py_UNREACHABLE();
- #line 4800 "Python/generated_cases.c.h"
+ #line 4806 "Python/generated_cases.c.h"
}
1
0
[3.13] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBALS (#119822) (#119889)
by JelleZijlstra 01 Jun '24
by JelleZijlstra 01 Jun '24
01 Jun '24
https://github.com/python/cpython/commit/a0559849ac2de604ffa410268be262a848…
commit: a0559849ac2de604ffa410268be262a8482ad23c
branch: 3.13
author: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2024-05-31T21:56:26-07:00
summary:
[3.13] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBALS (#119822) (#119889)
dSupport non-dict globals in LOAD_FROM_DICT_OR_GLOBALS
The implementation basically copies LOAD_GLOBAL. Possibly it could be deduplicated,
but that seems like it may get hairy since the two operations have different operands.
This is important to fix in 3.14 for PEP 649, but it's a bug in earlier versions too,
and we should backport to 3.13 and 3.12 if possible.
(cherry picked from commit 80a4e3899420faaa012c82b4e82cdb6675a6a944)
files:
A Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_uop_metadata.h
M Lib/test/test_type_aliases.py
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/optimizer_cases.c.h
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h
index 665b8627dfcc52..5b0d8dfd1b0b97 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -1299,7 +1299,6 @@ _PyOpcode_macro_expansion[256] = {
[LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { _LOAD_FAST_CHECK, 0, 0 } } },
[LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _LOAD_FAST, 5, 0 }, { _LOAD_FAST, 6, 0 } } },
[LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_DEREF, 0, 0 } } },
- [LOAD_FROM_DICT_OR_GLOBALS] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_GLOBALS, 0, 0 } } },
[LOAD_GLOBAL] = { .nuops = 1, .uops = { { _LOAD_GLOBAL, 0, 0 } } },
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } },
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } },
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 470e95e2b3b041..bc0ba16e24fe98 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -107,7 +107,6 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_STORE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_DELETE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_LOCALS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
- [_LOAD_FROM_DICT_OR_GLOBALS] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_GUARD_GLOBALS_VERSION] = HAS_DEOPT_FLAG,
[_GUARD_BUILTINS_VERSION] = HAS_DEOPT_FLAG,
@@ -438,7 +437,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_FAST_CHECK] = "_LOAD_FAST_CHECK",
[_LOAD_FAST_LOAD_FAST] = "_LOAD_FAST_LOAD_FAST",
[_LOAD_FROM_DICT_OR_DEREF] = "_LOAD_FROM_DICT_OR_DEREF",
- [_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS",
[_LOAD_GLOBAL] = "_LOAD_GLOBAL",
[_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS",
[_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE",
@@ -690,8 +688,6 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _LOAD_LOCALS:
return 0;
- case _LOAD_FROM_DICT_OR_GLOBALS:
- return 1;
case _LOAD_GLOBAL:
return 0;
case _GUARD_GLOBALS_VERSION:
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index 9c325bc595f585..f8b395fdc8bb1d 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -1,4 +1,5 @@
import pickle
+import textwrap
import types
import unittest
from test.support import check_syntax_error, run_code
@@ -328,3 +329,22 @@ def test_pickling_local(self):
with self.subTest(thing=thing, proto=proto):
with self.assertRaises(pickle.PickleError):
pickle.dumps(thing, protocol=proto)
+
+
+class TypeParamsExoticGlobalsTest(unittest.TestCase):
+ def test_exec_with_unusual_globals(self):
+ class customdict(dict):
+ def __missing__(self, key):
+ return key
+
+ code = compile("type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["Alias"]
+ self.assertEqual(Alias.__value__, "undefined")
+
+ code = compile("class A: type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["A"].Alias
+ self.assertEqual(Alias.__value__, "undefined")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
new file mode 100644
index 00000000000000..cc25eee6dd6ae4
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
@@ -0,0 +1,2 @@
+Fix execution of :ref:`annotation scopes <annotation-scopes>` within classes
+when ``globals`` is set to a non-dict. Patch by Jelle Zijlstra.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 8a6222c2bf0d77..0dc60bbbb6a579 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1375,18 +1375,35 @@ dummy_func(
ERROR_NO_POP();
}
if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- ERROR_NO_POP();
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
ERROR_NO_POP();
}
+ }
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+ /* namespace 1: globals */
+ ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error);
if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- ERROR_NO_POP();
+ /* namespace 2: builtins */
+ ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error);
+ if (v == NULL) {
+ _PyEval_FormatExcCheckArg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ ERROR_IF(true, error);
+ }
}
}
}
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 4699c8efebedc9..4e0f73f7e23a0a 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1394,35 +1394,7 @@
break;
}
- case _LOAD_FROM_DICT_OR_GLOBALS: {
- PyObject *mod_or_class_dict;
- PyObject *v;
- oparg = CURRENT_OPARG();
- mod_or_class_dict = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
- if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- JUMP_TO_ERROR();
- }
- }
- }
- Py_DECREF(mod_or_class_dict);
- stack_pointer[-1] = v;
- break;
- }
+ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
/* _LOAD_NAME is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 32d5b8b1c1d93c..ace91a3ca9b624 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4381,18 +4381,35 @@
goto error;
}
if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- goto error;
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
goto error;
}
+ }
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+ /* namespace 1: globals */
+ if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto pop_1_error;
if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- goto error;
+ /* namespace 2: builtins */
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto pop_1_error;
+ if (v == NULL) {
+ _PyEval_FormatExcCheckArg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ if (true) goto pop_1_error;
+ }
}
}
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 2a4efd73d794df..6c2480d4fdfe89 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -815,13 +815,7 @@
break;
}
- case _LOAD_FROM_DICT_OR_GLOBALS: {
- _Py_UopsSymbol *v;
- v = sym_new_not_null(ctx);
- if (v == NULL) goto out_of_space;
- stack_pointer[-1] = v;
- break;
- }
+ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */
/* _LOAD_NAME is not a viable micro-op for tier 2 */
1
0
https://github.com/python/cpython/commit/0a266f7e74ce1ff4ad6e88f05473cc6a22…
commit: 0a266f7e74ce1ff4ad6e88f05473cc6a22ab7e20
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: ncoghlan <ncoghlan(a)gmail.com>
date: 2024-06-01T04:23:04Z
summary:
[3.13] gh-74929: PEP 667 C API documentation (gh-119892)
* Add docs for new APIs
* Add soft-deprecation notices
* Add What's New porting entries
* Update comments referencing `PyFrame_LocalsToFast()` to mention the proxy instead
* Other related cleanups found when looking for refs to the deprecated APIs
(cherry picked from commit 3859e09e3d92d004978dd838f0511364e7edfb94)
Co-authored-by: Alyssa Coghlan <ncoghlan(a)gmail.com>
files:
M Doc/c-api/reflection.rst
M Doc/data/refcounts.dat
M Doc/whatsnew/3.13.rst
M Lib/test/test_sys.py
M Objects/frameobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/sysmodule.c
diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst
index 4b1c4770848a30..5dcfe40c2ce92b 100644
--- a/Doc/c-api/reflection.rst
+++ b/Doc/c-api/reflection.rst
@@ -7,18 +7,30 @@ Reflection
.. c:function:: PyObject* PyEval_GetBuiltins(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameBuiltins` instead.
+
Return a dictionary of the builtins in the current execution frame,
or the interpreter of the thread state if no frame is currently executing.
.. c:function:: PyObject* PyEval_GetLocals(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameLocals` instead.
+
Return a dictionary of the local variables in the current execution frame,
or ``NULL`` if no frame is currently executing.
.. c:function:: PyObject* PyEval_GetGlobals(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameGlobals` instead.
+
Return a dictionary of the global variables in the current execution frame,
or ``NULL`` if no frame is currently executing.
@@ -31,6 +43,32 @@ Reflection
See also :c:func:`PyThreadState_GetFrame`.
+.. c:function:: PyObject* PyEval_GetFrameBuiltins(void)
+
+ Return a dictionary of the builtins in the current execution frame,
+ or the interpreter of the thread state if no frame is currently executing.
+
+ .. versionadded:: 3.13
+
+
+.. c:function:: PyObject* PyEval_GetFrameLocals(void)
+
+ Return a dictionary of the local variables in the current execution frame,
+ or ``NULL`` if no frame is currently executing. Equivalent to calling
+ :func:`locals` in Python code.
+
+ .. versionadded:: 3.13
+
+
+.. c:function:: PyObject* PyEval_GetFrameGlobals(void)
+
+ Return a dictionary of the global variables in the current execution frame,
+ or ``NULL`` if no frame is currently executing. Equivalent to calling
+ :func:`globals` in Python code.
+
+ .. versionadded:: 3.13
+
+
.. c:function:: const char* PyEval_GetFuncName(PyObject *func)
Return the name of *func* if it is a function, class or instance object, else the
diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat
index 62a96146d605ff..a7d06e076a1b55 100644
--- a/Doc/data/refcounts.dat
+++ b/Doc/data/refcounts.dat
@@ -790,6 +790,12 @@ PyEval_GetGlobals:PyObject*::0:
PyEval_GetFrame:PyObject*::0:
+PyEval_GetFrameBuiltins:PyObject*::+1:
+
+PyEval_GetFrameLocals:PyObject*::+1:
+
+PyEval_GetFrameGlobals:PyObject*::+1:
+
PyEval_GetFuncDesc:const char*:::
PyEval_GetFuncDesc:PyObject*:func:0:
@@ -916,6 +922,32 @@ PyFloat_FromString:PyObject*:str:0:
PyFloat_GetInfo:PyObject*::+1:
PyFloat_GetInfo::void::
+PyFrame_GetBack:PyObject*::+1:
+PyFrame_GetBack:PyFrameObject*:frame:0:
+
+PyFrame_GetBuiltins:PyObject*::+1:
+PyFrame_GetBuiltins:PyFrameObject*:frame:0:
+
+PyFrame_GetCode:PyObject*::+1:
+PyFrame_GetCode:PyFrameObject*:frame:0:
+
+PyFrame_GetGenerator:PyObject*::+1:
+PyFrame_GetGenerator:PyFrameObject*:frame:0:
+
+PyFrame_GetGlobals:PyObject*::+1:
+PyFrame_GetGlobals:PyFrameObject*:frame:0:
+
+PyFrame_GetLocals:PyObject*::+1:
+PyFrame_GetLocals:PyFrameObject*:frame:0:
+
+PyFrame_GetVar:PyObject*::+1:
+PyFrame_GetVar:PyFrameObject*:frame:0:
+PyFrame_GetVar:PyObject*:name:0:
+
+PyFrame_GetVarString:PyObject*::+1:
+PyFrame_GetVarString:PyFrameObject*:frame:0:
+PyFrame_GetVarString:const char*:name::
+
PyFrozenSet_Check:int:::
PyFrozenSet_Check:PyObject*:p:0:
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index d09d7ce9864575..09dc5375186993 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -97,7 +97,7 @@ Interpreter improvements:
* :pep:`667`: The :func:`locals` builtin now has
:ref:`defined semantics <whatsnew313-locals-semantics>` when mutating the
returned mapping. Python debuggers and similar tools may now more reliably
- update local variables in optimized frames even during concurrent code
+ update local variables in optimized scopes even during concurrent code
execution.
New typing features:
@@ -2131,6 +2131,11 @@ New Features
destruction the same way the :mod:`tracemalloc` module does. (Contributed
by Pablo Galindo in :gh:`93502`.)
+* Add :c:func:`PyEval_GetFrameBuiltins`, :c:func:`PyEval_GetFrameGlobals`, and
+ :c:func:`PyEval_GetFrameLocals` to the C API. These replacements for
+ :c:func:`PyEval_GetBuiltins`, :c:func:`PyEval_GetGlobals`, and
+ :c:func:`PyEval_GetLocals` return :term:`strong references <strong reference>`
+ rather than borrowed references. (Added as part of :pep:`667`.)
Build Changes
=============
@@ -2306,6 +2311,15 @@ Changes in the C API
to :c:func:`PyUnstable_Code_GetFirstFree`.
(Contributed by Bogdan Romanyuk in :gh:`115781`.)
+* :c:func:`!PyFrame_FastToLocals` and :c:func:`!PyFrame_FastToLocalsWithError`
+ no longer have any effect. Calling these functions has been redundant since
+ Python 3.11, when :c:func:`PyFrame_GetLocals` was first introduced.
+ (Changed as part of :pep:`667`.)
+
+* :c:func:`!PyFrame_LocalsToFast` no longer has any effect. Calling this function
+ is redundant now that :c:func:`PyFrame_GetLocals` returns a write-through proxy
+ for :term:`optimized scopes <optimized scope>`. (Changed as part of :pep:`667`.)
+
Removed C APIs
--------------
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index ee3bd0092f9bf3..ed398060f791c9 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -394,10 +394,15 @@ def test_dlopenflags(self):
@test.support.refcount_test
def test_refcount(self):
- # n here must be a global in order for this test to pass while
- # tracing with a python function. Tracing calls PyFrame_FastToLocals
- # which will add a copy of any locals to the frame object, causing
- # the reference count to increase by 2 instead of 1.
+ # n here originally had to be a global in order for this test to pass
+ # while tracing with a python function. Tracing used to call
+ # PyFrame_FastToLocals, which would add a copy of any locals to the
+ # frame object, causing the ref count to increase by 2 instead of 1.
+ # While that no longer happens (due to PEP 667), this test case retains
+ # its original global-based implementation
+ # PEP 683's immortal objects also made this point moot, since the
+ # refcount for None doesn't change anyway. Maybe this test should be
+ # using a different constant value? (e.g. an integer)
global n
self.assertRaises(TypeError, sys.getrefcount)
c = sys.getrefcount(None)
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 64fded85de1468..0465aaa01bb38c 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1919,8 +1919,7 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
}
// (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
// with the initial value set when the frame was created...
- // (unlikely) ...or it was set to some initial value by
- // an earlier call to PyFrame_LocalsToFast().
+ // (unlikely) ...or it was set via the f_locals proxy.
}
}
}
@@ -2033,18 +2032,24 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name)
int
PyFrame_FastToLocalsWithError(PyFrameObject *f)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return 0;
}
void
PyFrame_FastToLocals(PyFrameObject *f)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return;
}
void
PyFrame_LocalsToFast(PyFrameObject *f, int clear)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return;
}
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 434eb804213810..8a6222c2bf0d77 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1543,7 +1543,7 @@ dummy_func(
inst(MAKE_CELL, (--)) {
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 347a1e677a0832..4699c8efebedc9 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1558,7 +1558,7 @@
case _MAKE_CELL: {
oparg = CURRENT_OPARG();
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 96161c5a6586fd..32d5b8b1c1d93c 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4747,7 +4747,7 @@
next_instr += 1;
INSTRUCTION_STATS(MAKE_CELL);
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 4da13e4552e786..00aa95531026b5 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -35,7 +35,6 @@ Data members:
#include "pycore_sysmodule.h" // export _PySys_GetSizeOf()
#include "pycore_tuple.h" // _PyTuple_FromArray()
-#include "frameobject.h" // PyFrame_FastToLocalsWithError()
#include "pydtrace.h" // PyDTrace_AUDIT()
#include "osdefs.h" // DELIM
#include "stdlib_module_names.h" // _Py_stdlib_module_names
1
0
https://github.com/python/cpython/commit/3859e09e3d92d004978dd838f0511364e7…
commit: 3859e09e3d92d004978dd838f0511364e7edfb94
branch: main
author: Alyssa Coghlan <ncoghlan(a)gmail.com>
committer: ncoghlan <ncoghlan(a)gmail.com>
date: 2024-06-01T13:59:35+10:00
summary:
gh-74929: PEP 667 C API documentation (gh-119379)
* Add docs for new APIs
* Add soft-deprecation notices
* Add What's New porting entries
* Update comments referencing `PyFrame_LocalsToFast()` to mention the proxy instead
* Other related cleanups found when looking for refs to the deprecated APIs
files:
M Doc/c-api/reflection.rst
M Doc/data/refcounts.dat
M Doc/whatsnew/3.13.rst
M Lib/test/test_sys.py
M Objects/frameobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/sysmodule.c
diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst
index 4b1c4770848a30..5dcfe40c2ce92b 100644
--- a/Doc/c-api/reflection.rst
+++ b/Doc/c-api/reflection.rst
@@ -7,18 +7,30 @@ Reflection
.. c:function:: PyObject* PyEval_GetBuiltins(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameBuiltins` instead.
+
Return a dictionary of the builtins in the current execution frame,
or the interpreter of the thread state if no frame is currently executing.
.. c:function:: PyObject* PyEval_GetLocals(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameLocals` instead.
+
Return a dictionary of the local variables in the current execution frame,
or ``NULL`` if no frame is currently executing.
.. c:function:: PyObject* PyEval_GetGlobals(void)
+ .. deprecated:: 3.13
+
+ Use :c:func:`PyEval_GetFrameGlobals` instead.
+
Return a dictionary of the global variables in the current execution frame,
or ``NULL`` if no frame is currently executing.
@@ -31,6 +43,32 @@ Reflection
See also :c:func:`PyThreadState_GetFrame`.
+.. c:function:: PyObject* PyEval_GetFrameBuiltins(void)
+
+ Return a dictionary of the builtins in the current execution frame,
+ or the interpreter of the thread state if no frame is currently executing.
+
+ .. versionadded:: 3.13
+
+
+.. c:function:: PyObject* PyEval_GetFrameLocals(void)
+
+ Return a dictionary of the local variables in the current execution frame,
+ or ``NULL`` if no frame is currently executing. Equivalent to calling
+ :func:`locals` in Python code.
+
+ .. versionadded:: 3.13
+
+
+.. c:function:: PyObject* PyEval_GetFrameGlobals(void)
+
+ Return a dictionary of the global variables in the current execution frame,
+ or ``NULL`` if no frame is currently executing. Equivalent to calling
+ :func:`globals` in Python code.
+
+ .. versionadded:: 3.13
+
+
.. c:function:: const char* PyEval_GetFuncName(PyObject *func)
Return the name of *func* if it is a function, class or instance object, else the
diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat
index 62a96146d605ff..a7d06e076a1b55 100644
--- a/Doc/data/refcounts.dat
+++ b/Doc/data/refcounts.dat
@@ -790,6 +790,12 @@ PyEval_GetGlobals:PyObject*::0:
PyEval_GetFrame:PyObject*::0:
+PyEval_GetFrameBuiltins:PyObject*::+1:
+
+PyEval_GetFrameLocals:PyObject*::+1:
+
+PyEval_GetFrameGlobals:PyObject*::+1:
+
PyEval_GetFuncDesc:const char*:::
PyEval_GetFuncDesc:PyObject*:func:0:
@@ -916,6 +922,32 @@ PyFloat_FromString:PyObject*:str:0:
PyFloat_GetInfo:PyObject*::+1:
PyFloat_GetInfo::void::
+PyFrame_GetBack:PyObject*::+1:
+PyFrame_GetBack:PyFrameObject*:frame:0:
+
+PyFrame_GetBuiltins:PyObject*::+1:
+PyFrame_GetBuiltins:PyFrameObject*:frame:0:
+
+PyFrame_GetCode:PyObject*::+1:
+PyFrame_GetCode:PyFrameObject*:frame:0:
+
+PyFrame_GetGenerator:PyObject*::+1:
+PyFrame_GetGenerator:PyFrameObject*:frame:0:
+
+PyFrame_GetGlobals:PyObject*::+1:
+PyFrame_GetGlobals:PyFrameObject*:frame:0:
+
+PyFrame_GetLocals:PyObject*::+1:
+PyFrame_GetLocals:PyFrameObject*:frame:0:
+
+PyFrame_GetVar:PyObject*::+1:
+PyFrame_GetVar:PyFrameObject*:frame:0:
+PyFrame_GetVar:PyObject*:name:0:
+
+PyFrame_GetVarString:PyObject*::+1:
+PyFrame_GetVarString:PyFrameObject*:frame:0:
+PyFrame_GetVarString:const char*:name::
+
PyFrozenSet_Check:int:::
PyFrozenSet_Check:PyObject*:p:0:
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 29bb3b81f6323c..3a52baf71310a3 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -97,7 +97,7 @@ Interpreter improvements:
* :pep:`667`: The :func:`locals` builtin now has
:ref:`defined semantics <whatsnew313-locals-semantics>` when mutating the
returned mapping. Python debuggers and similar tools may now more reliably
- update local variables in optimized frames even during concurrent code
+ update local variables in optimized scopes even during concurrent code
execution.
New typing features:
@@ -2143,6 +2143,11 @@ New Features
destruction the same way the :mod:`tracemalloc` module does. (Contributed
by Pablo Galindo in :gh:`93502`.)
+* Add :c:func:`PyEval_GetFrameBuiltins`, :c:func:`PyEval_GetFrameGlobals`, and
+ :c:func:`PyEval_GetFrameLocals` to the C API. These replacements for
+ :c:func:`PyEval_GetBuiltins`, :c:func:`PyEval_GetGlobals`, and
+ :c:func:`PyEval_GetLocals` return :term:`strong references <strong reference>`
+ rather than borrowed references. (Added as part of :pep:`667`.)
Build Changes
=============
@@ -2318,6 +2323,15 @@ Changes in the C API
to :c:func:`PyUnstable_Code_GetFirstFree`.
(Contributed by Bogdan Romanyuk in :gh:`115781`.)
+* :c:func:`!PyFrame_FastToLocals` and :c:func:`!PyFrame_FastToLocalsWithError`
+ no longer have any effect. Calling these functions has been redundant since
+ Python 3.11, when :c:func:`PyFrame_GetLocals` was first introduced.
+ (Changed as part of :pep:`667`.)
+
+* :c:func:`!PyFrame_LocalsToFast` no longer has any effect. Calling this function
+ is redundant now that :c:func:`PyFrame_GetLocals` returns a write-through proxy
+ for :term:`optimized scopes <optimized scope>`. (Changed as part of :pep:`667`.)
+
Removed C APIs
--------------
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 8fe1d77756866a..1e5823f8883957 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -394,10 +394,15 @@ def test_dlopenflags(self):
@test.support.refcount_test
def test_refcount(self):
- # n here must be a global in order for this test to pass while
- # tracing with a python function. Tracing calls PyFrame_FastToLocals
- # which will add a copy of any locals to the frame object, causing
- # the reference count to increase by 2 instead of 1.
+ # n here originally had to be a global in order for this test to pass
+ # while tracing with a python function. Tracing used to call
+ # PyFrame_FastToLocals, which would add a copy of any locals to the
+ # frame object, causing the ref count to increase by 2 instead of 1.
+ # While that no longer happens (due to PEP 667), this test case retains
+ # its original global-based implementation
+ # PEP 683's immortal objects also made this point moot, since the
+ # refcount for None doesn't change anyway. Maybe this test should be
+ # using a different constant value? (e.g. an integer)
global n
self.assertRaises(TypeError, sys.getrefcount)
c = sys.getrefcount(None)
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index fc8d6c7a7aee89..5c65007dae46d2 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1888,8 +1888,7 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
}
// (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
// with the initial value set when the frame was created...
- // (unlikely) ...or it was set to some initial value by
- // an earlier call to PyFrame_LocalsToFast().
+ // (unlikely) ...or it was set via the f_locals proxy.
}
}
}
@@ -2002,18 +2001,24 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name)
int
PyFrame_FastToLocalsWithError(PyFrameObject *f)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return 0;
}
void
PyFrame_FastToLocals(PyFrameObject *f)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return;
}
void
PyFrame_LocalsToFast(PyFrameObject *f, int clear)
{
+ // Nothing to do here, as f_locals is now a write-through proxy in
+ // optimized frames. Soft-deprecated, since there's no maintenance hassle.
return;
}
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 1c12e1cddbbc10..413ad1105f9428 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1570,7 +1570,7 @@ dummy_func(
inst(MAKE_CELL, (--)) {
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 0dfe490cb37047..bab629684c53f6 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1541,7 +1541,7 @@
case _MAKE_CELL: {
oparg = CURRENT_OPARG();
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 1a991608385405..355be966cbb84a 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4784,7 +4784,7 @@
next_instr += 1;
INSTRUCTION_STATS(MAKE_CELL);
// "initial" is probably NULL but not if it's an arg (or set
- // via PyFrame_LocalsToFast() before MAKE_CELL has run).
+ // via the f_locals proxy before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 4da13e4552e786..00aa95531026b5 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -35,7 +35,6 @@ Data members:
#include "pycore_sysmodule.h" // export _PySys_GetSizeOf()
#include "pycore_tuple.h" // _PyTuple_FromArray()
-#include "frameobject.h" // PyFrame_FastToLocalsWithError()
#include "pydtrace.h" // PyDTrace_AUDIT()
#include "osdefs.h" // DELIM
#include "stdlib_module_names.h" // _Py_stdlib_module_names
1
0