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

03 Jun '24
https://github.com/python/cpython/commit/79fae3b0a15be30d35131420f030c9a313…
commit: 79fae3b0a15be30d35131420f030c9a31338b357
branch: 3.13
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-03T22:47:34Z
summary:
[3.13] gh-117657: Fix itertools.count thread safety (GH-119268) (#120007)
Fix itertools.count in free-threading mode
(cherry picked from commit 87939bd5790accea77c5a81093f16f28d3f0b429)
Co-authored-by: Arnon Yaari <wiggin15(a)yahoo.com>
files:
M Lib/test/test_itertools.py
M Modules/itertoolsmodule.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index e243da309f03d8..2c92d880c10cb3 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -644,7 +644,7 @@ def test_count(self):
count(1, maxsize+5); sys.exc_info()
@pickle_deprecated
- def test_count_with_stride(self):
+ def test_count_with_step(self):
self.assertEqual(lzip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)])
self.assertEqual(lzip('abc',count(start=2,step=3)),
[('a', 2), ('b', 5), ('c', 8)])
@@ -699,6 +699,28 @@ def test_count_with_stride(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
self.pickletest(proto, count(i, j))
+ @threading_helper.requires_working_threading()
+ def test_count_threading(self, step=1):
+ # this test verifies multithreading consistency, which is
+ # mostly for testing builds without GIL, but nice to test anyway
+ count_to = 10_000
+ num_threads = 10
+ c = count(step=step)
+ def counting_thread():
+ for i in range(count_to):
+ next(c)
+ threads = []
+ for i in range(num_threads):
+ thread = threading.Thread(target=counting_thread)
+ thread.start()
+ threads.append(thread)
+ for thread in threads:
+ thread.join()
+ self.assertEqual(next(c), count_to * num_threads * step)
+
+ def test_count_with_step_threading(self):
+ self.test_count_threading(step=5)
+
def test_cycle(self):
self.assertEqual(take(10, cycle('abc')), list('abcabcabca'))
self.assertEqual(list(cycle('')), [])
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 8641c2f87e6db2..0d6ff20489aa2c 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1,13 +1,14 @@
#include "Python.h"
-#include "pycore_call.h" // _PyObject_CallNoArgs()
-#include "pycore_ceval.h" // _PyEval_GetBuiltin()
-#include "pycore_long.h" // _PyLong_GetZero()
-#include "pycore_moduleobject.h" // _PyModule_GetState()
-#include "pycore_typeobject.h" // _PyType_GetModuleState()
-#include "pycore_object.h" // _PyObject_GC_TRACK()
-#include "pycore_tuple.h" // _PyTuple_ITEMS()
+#include "pycore_call.h" // _PyObject_CallNoArgs()
+#include "pycore_ceval.h" // _PyEval_GetBuiltin()
+#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
+#include "pycore_long.h" // _PyLong_GetZero()
+#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "pycore_typeobject.h" // _PyType_GetModuleState()
+#include "pycore_object.h" // _PyObject_GC_TRACK()
+#include "pycore_tuple.h" // _PyTuple_ITEMS()
-#include <stddef.h> // offsetof()
+#include <stddef.h> // offsetof()
/* Itertools module written and maintained
by Raymond D. Hettinger <python(a)rcn.com>
@@ -4037,7 +4038,7 @@ fast_mode: when cnt an integer < PY_SSIZE_T_MAX and no step is specified.
assert(cnt != PY_SSIZE_T_MAX && long_cnt == NULL && long_step==PyLong(1));
Advances with: cnt += 1
- When count hits Y_SSIZE_T_MAX, switch to slow_mode.
+ When count hits PY_SSIZE_T_MAX, switch to slow_mode.
slow_mode: when cnt == PY_SSIZE_T_MAX, step is not int(1), or cnt is a float.
@@ -4186,9 +4187,30 @@ count_nextlong(countobject *lz)
static PyObject *
count_next(countobject *lz)
{
+#ifndef Py_GIL_DISABLED
if (lz->cnt == PY_SSIZE_T_MAX)
return count_nextlong(lz);
return PyLong_FromSsize_t(lz->cnt++);
+#else
+ // free-threading version
+ // fast mode uses compare-exchange loop
+ // slow mode uses a critical section
+ PyObject *returned;
+ Py_ssize_t cnt;
+
+ cnt = _Py_atomic_load_ssize_relaxed(&lz->cnt);
+ for (;;) {
+ if (cnt == PY_SSIZE_T_MAX) {
+ Py_BEGIN_CRITICAL_SECTION(lz);
+ returned = count_nextlong(lz);
+ Py_END_CRITICAL_SECTION();
+ return returned;
+ }
+ if (_Py_atomic_compare_exchange_ssize(&lz->cnt, &cnt, cnt + 1)) {
+ return PyLong_FromSsize_t(cnt);
+ }
+ }
+#endif
}
static PyObject *
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index 0bb0183147b722..d5fcac61f0db04 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -47,7 +47,6 @@ race_top:_PyImport_AcquireLock
race_top:_Py_dict_lookup_threadsafe
race_top:_imp_release_lock
race_top:_multiprocessing_SemLock_acquire_impl
-race_top:count_next
race_top:dictiter_new
race_top:dictresize
race_top:insert_to_emptydict
1
0

gh-117142: Support Importing ctypes in Isolated Interpreters (gh-119991)
by ericsnowcurrently 03 Jun '24
by ericsnowcurrently 03 Jun '24
03 Jun '24
https://github.com/python/cpython/commit/dba7a167dbbd50e83e58df351f3414b7a0…
commit: dba7a167dbbd50e83e58df351f3414b7a08e0188
branch: main
author: Eric Snow <ericsnowcurrently(a)gmail.com>
committer: ericsnowcurrently <ericsnowcurrently(a)gmail.com>
date: 2024-06-03T16:42:48-06:00
summary:
gh-117142: Support Importing ctypes in Isolated Interpreters (gh-119991)
This makes the support official.
Co-authored-by: Kirill Podoprigora <kirill.bast9(a)mail.ru>
files:
A Misc/NEWS.d/next/Library/2024-06-03-11-18-16.gh-issue-117142.kWTXQo.rst
M Modules/_ctypes/_ctypes.c
diff --git a/Misc/NEWS.d/next/Library/2024-06-03-11-18-16.gh-issue-117142.kWTXQo.rst b/Misc/NEWS.d/next/Library/2024-06-03-11-18-16.gh-issue-117142.kWTXQo.rst
new file mode 100644
index 00000000000000..80734ef3946300
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-06-03-11-18-16.gh-issue-117142.kWTXQo.rst
@@ -0,0 +1,2 @@
+The :mod:`ctypes` module may now be imported in all subinterpreters, including
+those that have their own GIL.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 6c1e5f58b95657..1d9534671a4ee8 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -5939,7 +5939,7 @@ module_free(void *module)
static PyModuleDef_Slot module_slots[] = {
{Py_mod_exec, _ctypes_mod_exec},
- {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED},
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};
1
0

[3.13] gh-117657: Fix race involving immortalizing objects (GH-119927) (#120005)
by colesbury 03 Jun '24
by colesbury 03 Jun '24
03 Jun '24
https://github.com/python/cpython/commit/ae705319fcde864b504987dc8e579e3eef…
commit: ae705319fcde864b504987dc8e579e3eef68e1e5
branch: 3.13
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-03T22:21:32Z
summary:
[3.13] gh-117657: Fix race involving immortalizing objects (GH-119927) (#120005)
The free-threaded build currently immortalizes objects that use deferred
reference counting (see gh-117783). This typically happens once the
first non-main thread is created, but the behavior can be suppressed for
tests, in subinterpreters, or during a compile() call.
This fixes a race condition involving the tracking of whether the
behavior is suppressed.
(cherry picked from commit 47fb4327b5c405da6df066dcaa01b7c1aefab313)
files:
M Include/internal/pycore_gc.h
M Lib/test/support/__init__.py
M Modules/_testinternalcapi.c
M Objects/codeobject.c
M Objects/object.c
M Python/bltinmodule.c
M Python/gc_free_threading.c
M Python/pystate.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index 60582521db5bd7..ba8b8e1903f307 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -347,15 +347,11 @@ struct _gc_runtime_state {
/* gh-117783: Deferred reference counting is not fully implemented yet, so
as a temporary measure we treat objects using deferred referenence
- counting as immortal. */
- struct {
- /* Immortalize objects instead of marking them as using deferred
- reference counting. */
- int enabled;
-
- /* Set enabled=1 when the first background thread is created. */
- int enable_on_thread_created;
- } immortalize;
+ counting as immortal. The value may be zero, one, or a negative number:
+ 0: immortalize deferred RC objects once the first thread is created
+ 1: immortalize all deferred RC objects immediately
+ <0: suppressed; don't immortalize objects */
+ int immortalize;
#endif
};
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index e2a854663ddb7d..d7a3a549d9cdc2 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -529,11 +529,11 @@ def suppress_immortalization(suppress=True):
yield
return
- old_values = _testinternalcapi.set_immortalize_deferred(False)
+ _testinternalcapi.suppress_immortalization(True)
try:
yield
finally:
- _testinternalcapi.set_immortalize_deferred(*old_values)
+ _testinternalcapi.suppress_immortalization(False)
def skip_if_suppress_immortalization():
try:
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 129c136906739d..8c65b80113c23e 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1965,24 +1965,18 @@ get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored))
#endif
static PyObject *
-set_immortalize_deferred(PyObject *self, PyObject *value)
+suppress_immortalization(PyObject *self, PyObject *value)
{
#ifdef Py_GIL_DISABLED
- PyInterpreterState *interp = PyInterpreterState_Get();
- int old_enabled = interp->gc.immortalize.enabled;
- int old_enabled_on_thread = interp->gc.immortalize.enable_on_thread_created;
- int enabled_on_thread = 0;
- if (!PyArg_ParseTuple(value, "i|i",
- &interp->gc.immortalize.enabled,
- &enabled_on_thread))
- {
+ int suppress = PyObject_IsTrue(value);
+ if (suppress < 0) {
return NULL;
}
- interp->gc.immortalize.enable_on_thread_created = enabled_on_thread;
- return Py_BuildValue("ii", old_enabled, old_enabled_on_thread);
-#else
- return Py_BuildValue("OO", Py_False, Py_False);
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ // Subtract two to suppress immortalization (so that 1 -> -1)
+ _Py_atomic_add_int(&interp->gc.immortalize, suppress ? -2 : 2);
#endif
+ Py_RETURN_NONE;
}
static PyObject *
@@ -1990,7 +1984,7 @@ get_immortalize_deferred(PyObject *self, PyObject *Py_UNUSED(ignored))
{
#ifdef Py_GIL_DISABLED
PyInterpreterState *interp = PyInterpreterState_Get();
- return PyBool_FromLong(interp->gc.immortalize.enable_on_thread_created);
+ return PyBool_FromLong(_Py_atomic_load_int(&interp->gc.immortalize) >= 0);
#else
Py_RETURN_FALSE;
#endif
@@ -2110,7 +2104,7 @@ static PyMethodDef module_functions[] = {
#ifdef Py_GIL_DISABLED
{"py_thread_id", get_py_thread_id, METH_NOARGS},
#endif
- {"set_immortalize_deferred", set_immortalize_deferred, METH_VARARGS},
+ {"suppress_immortalization", suppress_immortalization, METH_O},
{"get_immortalize_deferred", get_immortalize_deferred, METH_NOARGS},
#ifdef _Py_TIER2
{"uop_symbols_test", _Py_uop_symbols_test, METH_NOARGS},
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 3d804f73a54088..23fc8a76fd2df0 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -110,7 +110,7 @@ should_intern_string(PyObject *o)
// unless we've disabled immortalizing objects that use deferred reference
// counting.
PyInterpreterState *interp = _PyInterpreterState_GET();
- if (interp->gc.immortalize.enable_on_thread_created) {
+ if (_Py_atomic_load_int(&interp->gc.immortalize) < 0) {
return 1;
}
#endif
@@ -240,7 +240,7 @@ intern_constants(PyObject *tuple, int *modified)
PyThreadState *tstate = PyThreadState_GET();
if (!_Py_IsImmortal(v) && !PyCode_Check(v) &&
!PyUnicode_CheckExact(v) &&
- tstate->interp->gc.immortalize.enable_on_thread_created)
+ _Py_atomic_load_int(&tstate->interp->gc.immortalize) >= 0)
{
PyObject *interned = intern_one_constant(v);
if (interned == NULL) {
diff --git a/Objects/object.c b/Objects/object.c
index a4c69996c2cc5e..ce3df37e280b58 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -2433,7 +2433,7 @@ _PyObject_SetDeferredRefcount(PyObject *op)
assert(op->ob_ref_shared == 0);
_PyObject_SET_GC_BITS(op, _PyGC_BITS_DEFERRED);
PyInterpreterState *interp = _PyInterpreterState_GET();
- if (interp->gc.immortalize.enabled) {
+ if (_Py_atomic_load_int_relaxed(&interp->gc.immortalize) == 1) {
// gh-117696: immortalize objects instead of using deferred reference
// counting for now.
_Py_SetImmortal(op);
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index d192d5be751cfc..351fc8462a5ddc 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -870,15 +870,15 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
// gh-118527: Disable immortalization of code constants for explicit
// compile() calls to get consistent frozen outputs between the default
// and free-threaded builds.
+ // Subtract two to suppress immortalization (so that 1 -> -1)
PyInterpreterState *interp = _PyInterpreterState_GET();
- int old_value = interp->gc.immortalize.enable_on_thread_created;
- interp->gc.immortalize.enable_on_thread_created = 0;
+ _Py_atomic_add_int(&interp->gc.immortalize, -2);
#endif
result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize);
#ifdef Py_GIL_DISABLED
- interp->gc.immortalize.enable_on_thread_created = old_value;
+ _Py_atomic_add_int(&interp->gc.immortalize, 2);
#endif
Py_XDECREF(source_copy);
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index e6bd012c40ee82..d005b79ff40dbf 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -703,11 +703,9 @@ _PyGC_Init(PyInterpreterState *interp)
{
GCState *gcstate = &interp->gc;
- if (_Py_IsMainInterpreter(interp)) {
- // gh-117783: immortalize objects that would use deferred refcounting
- // once the first non-main thread is created.
- gcstate->immortalize.enable_on_thread_created = 1;
- }
+ // gh-117783: immortalize objects that would use deferred refcounting
+ // once the first non-main thread is created (but not in subinterpreters).
+ gcstate->immortalize = _Py_IsMainInterpreter(interp) ? 0 : -1;
gcstate->garbage = PyList_New(0);
if (gcstate->garbage == NULL) {
@@ -1808,8 +1806,10 @@ _PyGC_ImmortalizeDeferredObjects(PyInterpreterState *interp)
{
struct visitor_args args;
_PyEval_StopTheWorld(interp);
- gc_visit_heaps(interp, &immortalize_visitor, &args);
- interp->gc.immortalize.enabled = 1;
+ if (interp->gc.immortalize == 0) {
+ gc_visit_heaps(interp, &immortalize_visitor, &args);
+ interp->gc.immortalize = 1;
+ }
_PyEval_StartTheWorld(interp);
}
diff --git a/Python/pystate.c b/Python/pystate.c
index 36e4206b4a282e..d0293915db7689 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1583,9 +1583,7 @@ new_threadstate(PyInterpreterState *interp, int whence)
}
else {
#ifdef Py_GIL_DISABLED
- if (interp->gc.immortalize.enable_on_thread_created &&
- !interp->gc.immortalize.enabled)
- {
+ if (_Py_atomic_load_int(&interp->gc.immortalize) == 0) {
// Immortalize objects marked as using deferred reference counting
// the first time a non-main thread is created.
_PyGC_ImmortalizeDeferredObjects(interp);
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index d150e901945073..0bb0183147b722 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -47,7 +47,6 @@ race_top:_PyImport_AcquireLock
race_top:_Py_dict_lookup_threadsafe
race_top:_imp_release_lock
race_top:_multiprocessing_SemLock_acquire_impl
-race_top:builtin_compile_impl
race_top:count_next
race_top:dictiter_new
race_top:dictresize
@@ -56,7 +55,6 @@ race_top:insertdict
race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
-race_top:should_intern_string
race_top:_Py_slot_tp_getattr_hook
race_top:add_threadstate
race_top:dump_traceback
1
0
https://github.com/python/cpython/commit/d82a7ba041321e7b58a5a9bbc394670be6…
commit: d82a7ba041321e7b58a5a9bbc394670be6ceeb7c
branch: main
author: Eric Snow <ericsnowcurrently(a)gmail.com>
committer: ericsnowcurrently <ericsnowcurrently(a)gmail.com>
date: 2024-06-03T15:56:00-06:00
summary:
gh-117398: Add datetime Module State (gh-119810)
I was able to make use of the existing datetime_state struct, but there was one tricky thing I had to sort out. We mostly aren't converting to heap types, so we can't use things like PyType_GetModuleByDef() to look up the module state. The solution I came up with is somewhat novel, but I consider it straightforward. Also, it shouldn't have much impact on performance.
In summary, this main changes here are:
* I've added some macros to help hide how various objects relate to module state
* as a solution to the module state lookup problem, I've stored the last loaded module on the current interpreter's internal dict (actually a weakref)
* if the static type method is used after the module has been deleted, it is reloaded
* to avoid extra work when loading the module, we directly copy the objects (new refs only) from the old module state into the new state if the old module hasn't been deleted yet
* during module init we set various objects on the static types' __dict__s; to simplify things, we only do that the first time; once those static types have a separate __dict__ per interpreter, we'll do it every time
* we now clear the module state when the module is destroyed (before, we were leaking everything in _datetime_global_state)
files:
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_datetimemodule.c
diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h
index b9fae11dfaa85c..b186408931c92e 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -829,6 +829,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_call));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_exception));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_return));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cached_datetime_module));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cached_statements));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cadata));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cafile));
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index aa66b20859a472..e1808c85acfb2d 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -318,6 +318,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(c_call)
STRUCT_FOR_ID(c_exception)
STRUCT_FOR_ID(c_return)
+ STRUCT_FOR_ID(cached_datetime_module)
STRUCT_FOR_ID(cached_statements)
STRUCT_FOR_ID(cadata)
STRUCT_FOR_ID(cafile)
diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h
index b27720e9ff6ecf..2dde6febc2cae4 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -827,6 +827,7 @@ extern "C" {
INIT_ID(c_call), \
INIT_ID(c_exception), \
INIT_ID(c_return), \
+ INIT_ID(cached_datetime_module), \
INIT_ID(cached_statements), \
INIT_ID(cadata), \
INIT_ID(cafile), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h
index c61c556b758769..b00119a1bad7ff 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -795,6 +795,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(c_return);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
+ string = &_Py_ID(cached_datetime_module);
+ assert(_PyUnicode_CheckConsistency(string, 1));
+ _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(cached_statements);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 466382b5148509..16bb4c6980aa08 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -25,17 +25,18 @@
# include <winsock2.h> /* struct timeval */
#endif
+
+/* forward declarations */
+static PyTypeObject PyDateTime_DateType;
+static PyTypeObject PyDateTime_DateTimeType;
+static PyTypeObject PyDateTime_TimeType;
+static PyTypeObject PyDateTime_DeltaType;
+static PyTypeObject PyDateTime_TZInfoType;
+static PyTypeObject PyDateTime_TimeZoneType;
+
+
typedef struct {
- /* Static types exposed by the datetime C-API. */
- PyTypeObject *date_type;
- PyTypeObject *datetime_type;
- PyTypeObject *delta_type;
- PyTypeObject *time_type;
- PyTypeObject *tzinfo_type;
- /* Exposed indirectly via TimeZone_UTC. */
- PyTypeObject *timezone_type;
-
- /* Other module classes. */
+ /* Module heap types. */
PyTypeObject *isocalendar_date_type;
/* Conversion factors. */
@@ -47,39 +48,182 @@ typedef struct {
PyObject *us_per_week; // 1e6 * 3600 * 24 * 7 as Python int
PyObject *seconds_per_day; // 3600 * 24 as Python int
- /* The interned UTC timezone instance */
- PyObject *utc;
-
/* The interned Unix epoch datetime instance */
PyObject *epoch;
-
- /* While we use a global state, we ensure it's only initialized once */
- int initialized;
} datetime_state;
-static datetime_state _datetime_global_state;
+/* The module has a fixed number of static objects, due to being exposed
+ * through the datetime C-API. There are five types exposed directly,
+ * one type exposed indirectly, and one singleton constant (UTC).
+ *
+ * Each of these objects is hidden behind a macro in the same way as
+ * the per-module objects stored in module state. The macros for the
+ * static objects don't need to be passed a state, but the consistency
+ * of doing so is more clear. We use a dedicated noop macro, NO_STATE,
+ * to make the special case obvious. */
+
+#define NO_STATE NULL
+
+#define DATE_TYPE(st) &PyDateTime_DateType
+#define DATETIME_TYPE(st) &PyDateTime_DateTimeType
+#define TIME_TYPE(st) &PyDateTime_TimeType
+#define DELTA_TYPE(st) &PyDateTime_DeltaType
+#define TZINFO_TYPE(st) &PyDateTime_TZInfoType
+#define TIMEZONE_TYPE(st) &PyDateTime_TimeZoneType
+#define ISOCALENDAR_DATE_TYPE(st) st->isocalendar_date_type
+
+#define PyDate_Check(op) PyObject_TypeCheck(op, DATE_TYPE(NO_STATE))
+#define PyDate_CheckExact(op) Py_IS_TYPE(op, DATE_TYPE(NO_STATE))
+
+#define PyDateTime_Check(op) PyObject_TypeCheck(op, DATETIME_TYPE(NO_STATE))
+#define PyDateTime_CheckExact(op) Py_IS_TYPE(op, DATETIME_TYPE(NO_STATE))
+
+#define PyTime_Check(op) PyObject_TypeCheck(op, TIME_TYPE(NO_STATE))
+#define PyTime_CheckExact(op) Py_IS_TYPE(op, TIME_TYPE(NO_STATE))
+
+#define PyDelta_Check(op) PyObject_TypeCheck(op, DELTA_TYPE(NO_STATE))
+#define PyDelta_CheckExact(op) Py_IS_TYPE(op, DELTA_TYPE(NO_STATE))
+
+#define PyTZInfo_Check(op) PyObject_TypeCheck(op, TZINFO_TYPE(NO_STATE))
+#define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, TZINFO_TYPE(NO_STATE))
+
+#define PyTimezone_Check(op) PyObject_TypeCheck(op, TIMEZONE_TYPE(NO_STATE))
+
+#define CONST_US_PER_MS(st) st->us_per_ms
+#define CONST_US_PER_SECOND(st) st->us_per_second
+#define CONST_US_PER_MINUTE(st) st->us_per_minute
+#define CONST_US_PER_HOUR(st) st->us_per_hour
+#define CONST_US_PER_DAY(st) st->us_per_day
+#define CONST_US_PER_WEEK(st) st->us_per_week
+#define CONST_SEC_PER_DAY(st) st->seconds_per_day
+#define CONST_EPOCH(st) st->epoch
+#define CONST_UTC(st) ((PyObject *)&utc_timezone)
+
+static datetime_state *
+get_module_state(PyObject *module)
+{
+ void *state = _PyModule_GetState(module);
+ assert(state != NULL);
+ return (datetime_state *)state;
+}
+
+
+#define INTERP_KEY ((PyObject *)&_Py_ID(cached_datetime_module))
+
+static PyObject *
+get_current_module(PyInterpreterState *interp)
+{
+ PyObject *dict = PyInterpreterState_GetDict(interp);
+ if (dict == NULL) {
+ return NULL;
+ }
+ PyObject *ref = NULL;
+ if (PyDict_GetItemRef(dict, INTERP_KEY, &ref) < 0) {
+ return NULL;
+ }
+ if (ref == NULL) {
+ return NULL;
+ }
+ PyObject *mod = NULL;
+ (void)PyWeakref_GetRef(ref, &mod);
+ if (mod == Py_None) {
+ Py_CLEAR(mod);
+ }
+ Py_DECREF(ref);
+ return mod;
+}
+
+static PyModuleDef datetimemodule;
+
+static datetime_state *
+_get_current_state(PyObject **p_mod)
+{
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ PyObject *mod = get_current_module(interp);
+ if (mod == NULL) {
+ assert(!PyErr_Occurred());
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+ /* The static types can outlive the module,
+ * so we must re-import the module. */
+ mod = PyImport_ImportModule("_datetime");
+ if (mod == NULL) {
+ return NULL;
+ }
+ }
+ datetime_state *st = get_module_state(mod);
+ *p_mod = mod;
+ return st;
+}
+
+#define GET_CURRENT_STATE(MOD_VAR) \
+ _get_current_state(&MOD_VAR)
+#define RELEASE_CURRENT_STATE(ST_VAR, MOD_VAR) \
+ Py_DECREF(MOD_VAR)
-static inline datetime_state* get_datetime_state(void)
+static int
+set_current_module(PyInterpreterState *interp, PyObject *mod)
{
- return &_datetime_global_state;
+ assert(mod != NULL);
+ PyObject *dict = PyInterpreterState_GetDict(interp);
+ if (dict == NULL) {
+ return -1;
+ }
+ PyObject *ref = PyWeakref_NewRef(mod, NULL);
+ if (ref == NULL) {
+ return -1;
+ }
+ int rc = PyDict_SetItem(dict, INTERP_KEY, ref);
+ Py_DECREF(ref);
+ return rc;
}
-#define PyDate_Check(op) PyObject_TypeCheck(op, get_datetime_state()->date_type)
-#define PyDate_CheckExact(op) Py_IS_TYPE(op, get_datetime_state()->date_type)
+static void
+clear_current_module(PyInterpreterState *interp, PyObject *expected)
+{
+ PyObject *exc = PyErr_GetRaisedException();
+
+ PyObject *current = NULL;
+
+ PyObject *dict = PyInterpreterState_GetDict(interp);
+ if (dict == NULL) {
+ goto error;
+ }
+
+ if (expected != NULL) {
+ PyObject *ref = NULL;
+ if (PyDict_GetItemRef(dict, INTERP_KEY, &ref) < 0) {
+ goto error;
+ }
+ if (ref != NULL) {
+ int rc = PyWeakref_GetRef(ref, ¤t);
+ Py_DECREF(ref);
+ if (rc < 0) {
+ goto error;
+ }
+ if (current != expected) {
+ goto finally;
+ }
+ }
+ }
-#define PyDateTime_Check(op) PyObject_TypeCheck(op, get_datetime_state()->datetime_type)
-#define PyDateTime_CheckExact(op) Py_IS_TYPE(op, get_datetime_state()->datetime_type)
+ if (PyDict_DelItem(dict, INTERP_KEY) < 0) {
+ if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
+ goto error;
+ }
+ }
-#define PyTime_Check(op) PyObject_TypeCheck(op, get_datetime_state()->time_type)
-#define PyTime_CheckExact(op) Py_IS_TYPE(op, get_datetime_state()->time_type)
+ goto finally;
-#define PyDelta_Check(op) PyObject_TypeCheck(op, get_datetime_state()->delta_type)
-#define PyDelta_CheckExact(op) Py_IS_TYPE(op, get_datetime_state()->delta_type)
+error:
+ PyErr_Print();
-#define PyTZInfo_Check(op) PyObject_TypeCheck(op, get_datetime_state()->tzinfo_type)
-#define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, get_datetime_state()->tzinfo_type)
+finally:
+ Py_XDECREF(current);
+ PyErr_SetRaisedException(exc);
+}
-#define PyTimezone_Check(op) PyObject_TypeCheck(op, get_datetime_state()->timezone_type)
/* We require that C int be at least 32 bits, and use int virtually
* everywhere. In just a few cases we use a temp long, where a Python
@@ -988,7 +1132,7 @@ new_date_ex(int year, int month, int day, PyTypeObject *type)
}
#define new_date(year, month, day) \
- new_date_ex(year, month, day, get_datetime_state()->date_type)
+ new_date_ex(year, month, day, DATE_TYPE(NO_STATE))
// Forward declaration
static PyObject *
@@ -998,13 +1142,12 @@ new_datetime_ex(int, int, int, int, int, int, int, PyObject *, PyTypeObject *);
static PyObject *
new_date_subclass_ex(int year, int month, int day, PyObject *cls)
{
- datetime_state *st = get_datetime_state();
PyObject *result;
// We have "fast path" constructors for two subclasses: date and datetime
- if ((PyTypeObject *)cls == st->date_type) {
+ if ((PyTypeObject *)cls == DATE_TYPE(NO_STATE)) {
result = new_date_ex(year, month, day, (PyTypeObject *)cls);
}
- else if ((PyTypeObject *)cls == st->datetime_type) {
+ else if ((PyTypeObject *)cls == DATETIME_TYPE(NO_STATE)) {
result = new_datetime_ex(year, month, day, 0, 0, 0, 0, Py_None,
(PyTypeObject *)cls);
}
@@ -1058,8 +1201,7 @@ new_datetime_ex(int year, int month, int day, int hour, int minute,
}
#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo, fold) \
- new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
- get_datetime_state()->datetime_type)
+ new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, DATETIME_TYPE(NO_STATE))
static PyObject *
call_subclass_fold(PyObject *cls, int fold, const char *format, ...)
@@ -1100,9 +1242,8 @@ new_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute
int second, int usecond, PyObject *tzinfo,
int fold, PyObject *cls)
{
- datetime_state *st = get_datetime_state();
PyObject* dt;
- if ((PyTypeObject*)cls == st->datetime_type) {
+ if ((PyTypeObject*)cls == DATETIME_TYPE(NO_STATE)) {
// Use the fast path constructor
dt = new_datetime(year, month, day, hour, minute, second, usecond,
tzinfo, fold);
@@ -1163,16 +1304,15 @@ new_time_ex(int hour, int minute, int second, int usecond,
return new_time_ex2(hour, minute, second, usecond, tzinfo, 0, type);
}
-#define new_time(hh, mm, ss, us, tzinfo, fold) \
- new_time_ex2(hh, mm, ss, us, tzinfo, fold, get_datetime_state()->time_type)
+#define new_time(hh, mm, ss, us, tzinfo, fold) \
+ new_time_ex2(hh, mm, ss, us, tzinfo, fold, TIME_TYPE(NO_STATE))
static PyObject *
new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
PyObject *tzinfo, int fold, PyObject *cls)
{
PyObject *t;
- datetime_state *st = get_datetime_state();
- if ((PyTypeObject*)cls == st->time_type) {
+ if ((PyTypeObject*)cls == TIME_TYPE(NO_STATE)) {
// Use the fast path constructor
t = new_time(hour, minute, second, usecond, tzinfo, fold);
}
@@ -1224,7 +1364,7 @@ new_delta_ex(int days, int seconds, int microseconds, int normalize,
}
#define new_delta(d, s, us, normalize) \
- new_delta_ex(d, s, us, normalize, get_datetime_state()->delta_type)
+ new_delta_ex(d, s, us, normalize, DELTA_TYPE(NO_STATE))
typedef struct
@@ -1244,8 +1384,7 @@ static PyObject *
create_timezone(PyObject *offset, PyObject *name)
{
PyDateTime_TimeZone *self;
- datetime_state *st = get_datetime_state();
- PyTypeObject *type = st->timezone_type;
+ PyTypeObject *type = TIMEZONE_TYPE(NO_STATE);
assert(offset != NULL);
assert(PyDelta_Check(offset));
@@ -1267,6 +1406,7 @@ create_timezone(PyObject *offset, PyObject *name)
}
static int delta_bool(PyDateTime_Delta *self);
+static PyDateTime_TimeZone utc_timezone;
static PyObject *
new_timezone(PyObject *offset, PyObject *name)
@@ -1276,8 +1416,7 @@ new_timezone(PyObject *offset, PyObject *name)
assert(name == NULL || PyUnicode_Check(name));
if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) {
- datetime_state *st = get_datetime_state();
- return Py_NewRef(st->utc);
+ return Py_NewRef(CONST_UTC(NO_STATE));
}
if ((GET_TD_DAYS(offset) == -1 &&
GET_TD_SECONDS(offset) == 0 &&
@@ -1490,8 +1629,7 @@ tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds)
if (rv == 1) {
// Create a timezone from offset in seconds (0 returns UTC)
if (tzoffset == 0) {
- datetime_state *st = get_datetime_state();
- return Py_NewRef(st->utc);
+ return Py_NewRef(CONST_UTC(NO_STATE));
}
PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1);
@@ -1920,11 +2058,13 @@ delta_to_microseconds(PyDateTime_Delta *self)
PyObject *x3 = NULL;
PyObject *result = NULL;
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
x1 = PyLong_FromLong(GET_TD_DAYS(self));
if (x1 == NULL)
goto Done;
- datetime_state *st = get_datetime_state();
- x2 = PyNumber_Multiply(x1, st->seconds_per_day); /* days in seconds */
+ x2 = PyNumber_Multiply(x1, CONST_SEC_PER_DAY(st)); /* days in seconds */
if (x2 == NULL)
goto Done;
Py_SETREF(x1, NULL);
@@ -1941,7 +2081,7 @@ delta_to_microseconds(PyDateTime_Delta *self)
/* x1 = */ x2 = NULL;
/* x3 has days+seconds in seconds */
- x1 = PyNumber_Multiply(x3, st->us_per_second); /* us */
+ x1 = PyNumber_Multiply(x3, CONST_US_PER_SECOND(st)); /* us */
if (x1 == NULL)
goto Done;
Py_SETREF(x3, NULL);
@@ -1957,6 +2097,7 @@ delta_to_microseconds(PyDateTime_Delta *self)
Py_XDECREF(x1);
Py_XDECREF(x2);
Py_XDECREF(x3);
+ RELEASE_CURRENT_STATE(st, current_mod);
return result;
}
@@ -1996,8 +2137,10 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
PyObject *num = NULL;
PyObject *result = NULL;
- datetime_state *st = get_datetime_state();
- tuple = checked_divmod(pyus, st->us_per_second);
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
+ tuple = checked_divmod(pyus, CONST_US_PER_SECOND(st));
if (tuple == NULL) {
goto Done;
}
@@ -2015,7 +2158,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
num = Py_NewRef(PyTuple_GET_ITEM(tuple, 0)); /* leftover seconds */
Py_DECREF(tuple);
- tuple = checked_divmod(num, st->seconds_per_day);
+ tuple = checked_divmod(num, CONST_SEC_PER_DAY(st));
if (tuple == NULL)
goto Done;
Py_DECREF(num);
@@ -2040,6 +2183,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
Done:
Py_XDECREF(tuple);
Py_XDECREF(num);
+ RELEASE_CURRENT_STATE(st, current_mod);
return result;
BadDivmod:
@@ -2049,7 +2193,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
}
#define microseconds_to_delta(pymicros) \
- microseconds_to_delta_ex(pymicros, get_datetime_state()->delta_type)
+ microseconds_to_delta_ex(pymicros, DELTA_TYPE(NO_STATE))
static PyObject *
multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
@@ -2577,6 +2721,9 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *self = NULL;
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
/* Argument objects. */
PyObject *day = NULL;
PyObject *second = NULL;
@@ -2615,29 +2762,28 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
y = accum("microseconds", x, us, _PyLong_GetOne(), &leftover_us);
CLEANUP;
}
- datetime_state *st = get_datetime_state();
if (ms) {
- y = accum("milliseconds", x, ms, st->us_per_ms, &leftover_us);
+ y = accum("milliseconds", x, ms, CONST_US_PER_MS(st), &leftover_us);
CLEANUP;
}
if (second) {
- y = accum("seconds", x, second, st->us_per_second, &leftover_us);
+ y = accum("seconds", x, second, CONST_US_PER_SECOND(st), &leftover_us);
CLEANUP;
}
if (minute) {
- y = accum("minutes", x, minute, st->us_per_minute, &leftover_us);
+ y = accum("minutes", x, minute, CONST_US_PER_MINUTE(st), &leftover_us);
CLEANUP;
}
if (hour) {
- y = accum("hours", x, hour, st->us_per_hour, &leftover_us);
+ y = accum("hours", x, hour, CONST_US_PER_HOUR(st), &leftover_us);
CLEANUP;
}
if (day) {
- y = accum("days", x, day, st->us_per_day, &leftover_us);
+ y = accum("days", x, day, CONST_US_PER_DAY(st), &leftover_us);
CLEANUP;
}
if (week) {
- y = accum("weeks", x, week, st->us_per_week, &leftover_us);
+ y = accum("weeks", x, week, CONST_US_PER_WEEK(st), &leftover_us);
CLEANUP;
}
if (leftover_us) {
@@ -2679,7 +2825,9 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
self = microseconds_to_delta_ex(x, type);
Py_DECREF(x);
+
Done:
+ RELEASE_CURRENT_STATE(st, current_mod);
return self;
#undef CLEANUP
@@ -2792,9 +2940,12 @@ delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored))
if (total_microseconds == NULL)
return NULL;
- datetime_state *st = get_datetime_state();
- total_seconds = PyNumber_TrueDivide(total_microseconds, st->us_per_second);
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
+ total_seconds = PyNumber_TrueDivide(total_microseconds, CONST_US_PER_SECOND(st));
+ RELEASE_CURRENT_STATE(st, current_mod);
Py_DECREF(total_microseconds);
return total_seconds;
}
@@ -3547,9 +3698,12 @@ date_isocalendar(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
week = 0;
}
- datetime_state *st = get_datetime_state();
- PyObject *v = iso_calendar_date_new_impl(st->isocalendar_date_type,
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
+ PyObject *v = iso_calendar_date_new_impl(ISOCALENDAR_DATE_TYPE(st),
year, week + 1, day + 1);
+ RELEASE_CURRENT_STATE(st, current_mod);
if (v == NULL) {
return NULL;
}
@@ -4018,9 +4172,8 @@ timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *offset;
PyObject *name = NULL;
- datetime_state *st = get_datetime_state();
if (PyArg_ParseTupleAndKeywords(args, kw, "O!|U:timezone", timezone_kws,
- st->delta_type, &offset, &name))
+ DELTA_TYPE(NO_STATE), &offset, &name))
return new_timezone(offset, name);
return NULL;
@@ -4073,8 +4226,7 @@ timezone_repr(PyDateTime_TimeZone *self)
to use Py_TYPE(self)->tp_name here. */
const char *type_name = Py_TYPE(self)->tp_name;
- datetime_state *st = get_datetime_state();
- if (((PyObject *)self) == st->utc) {
+ if ((PyObject *)self == CONST_UTC(NO_STATE)) {
return PyUnicode_FromFormat("%s.utc", type_name);
}
@@ -4096,8 +4248,7 @@ timezone_str(PyDateTime_TimeZone *self)
if (self->name != NULL) {
return Py_NewRef(self->name);
}
- datetime_state *st = get_datetime_state();
- if ((PyObject *)self == st->utc ||
+ if ((PyObject *)self == CONST_UTC(NO_STATE) ||
(GET_TD_DAYS(self->offset) == 0 &&
GET_TD_SECONDS(self->offset) == 0 &&
GET_TD_MICROSECONDS(self->offset) == 0))
@@ -4260,7 +4411,7 @@ static PyDateTime_TimeZone *
look_up_timezone(PyObject *offset, PyObject *name)
{
if (offset == utc_timezone.offset && name == NULL) {
- return &utc_timezone;
+ return (PyDateTime_TimeZone *)CONST_UTC(NO_STATE);
}
return NULL;
}
@@ -4777,8 +4928,7 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) {
}
PyObject *t;
- datetime_state *st = get_datetime_state();
- if ( (PyTypeObject *)cls == st->time_type) {
+ if ( (PyTypeObject *)cls == TIME_TYPE(NO_STATE)) {
t = new_time(hour, minute, second, microsecond, tzinfo, 0);
} else {
t = PyObject_CallFunction(cls, "iiiiO",
@@ -5376,10 +5526,9 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
PyObject *tzinfo = NULL;
PyObject *result = NULL;
- datetime_state *st = get_datetime_state();
if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine", keywords,
- st->date_type, &date,
- st->time_type, &time, &tzinfo)) {
+ DATE_TYPE(NO_STATE), &date,
+ TIME_TYPE(NO_STATE), &time, &tzinfo)) {
if (tzinfo == NULL) {
if (HASTZINFO(time))
tzinfo = ((PyDateTime_Time *)time)->tzinfo;
@@ -6209,7 +6358,6 @@ local_timezone_from_timestamp(time_t timestamp)
delta = new_delta(0, local_time_tm.tm_gmtoff, 0, 1);
#else /* HAVE_STRUCT_TM_TM_ZONE */
{
- datetime_state *st = get_datetime_state();
PyObject *local_time, *utc_time;
struct tm utc_time_tm;
char buf[100];
@@ -6264,8 +6412,11 @@ local_timezone(PyDateTime_DateTime *utc_time)
PyObject *one_second;
PyObject *seconds;
- datetime_state *st = get_datetime_state();
- delta = datetime_subtract((PyObject *)utc_time, st->epoch);
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
+ delta = datetime_subtract((PyObject *)utc_time, CONST_EPOCH(st));
+ RELEASE_CURRENT_STATE(st, current_mod);
if (delta == NULL)
return NULL;
@@ -6378,7 +6529,6 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
if (result == NULL)
return NULL;
- datetime_state *st = get_datetime_state();
/* Make sure result is aware and UTC. */
if (!HASTZINFO(result)) {
temp = (PyObject *)result;
@@ -6390,7 +6540,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
DATE_GET_MINUTE(result),
DATE_GET_SECOND(result),
DATE_GET_MICROSECOND(result),
- st->utc,
+ CONST_UTC(NO_STATE),
DATE_GET_FOLD(result),
Py_TYPE(result));
Py_DECREF(temp);
@@ -6399,7 +6549,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
}
else {
/* Result is already aware - just replace tzinfo. */
- Py_SETREF(result->tzinfo, Py_NewRef(st->utc));
+ Py_SETREF(result->tzinfo, Py_NewRef(CONST_UTC(NO_STATE)));
}
/* Attach new tzinfo and let fromutc() do the rest. */
@@ -6503,9 +6653,12 @@ datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
PyObject *result;
if (HASTZINFO(self) && self->tzinfo != Py_None) {
- datetime_state *st = get_datetime_state();
+ PyObject *current_mod = NULL;
+ datetime_state *st = GET_CURRENT_STATE(current_mod);
+
PyObject *delta;
- delta = datetime_subtract((PyObject *)self, st->epoch);
+ delta = datetime_subtract((PyObject *)self, CONST_EPOCH(st));
+ RELEASE_CURRENT_STATE(st, current_mod);
if (delta == NULL)
return NULL;
result = delta_total_seconds(delta, NULL);
@@ -6839,23 +6992,6 @@ get_datetime_capi(void)
return &capi;
}
-static int
-datetime_clear(PyObject *module)
-{
- datetime_state *st = get_datetime_state();
-
- Py_CLEAR(st->us_per_ms);
- Py_CLEAR(st->us_per_second);
- Py_CLEAR(st->us_per_minute);
- Py_CLEAR(st->us_per_hour);
- Py_CLEAR(st->us_per_day);
- Py_CLEAR(st->us_per_week);
- Py_CLEAR(st->seconds_per_day);
- Py_CLEAR(st->utc);
- Py_CLEAR(st->epoch);
- return 0;
-}
-
static PyObject *
create_timezone_from_delta(int days, int sec, int ms, int normalize)
{
@@ -6869,25 +7005,39 @@ create_timezone_from_delta(int days, int sec, int ms, int normalize)
}
static int
-init_state(datetime_state *st, PyTypeObject *PyDateTime_IsoCalendarDateType)
-{
- // While datetime uses global module "state", we unly initialize it once.
- // The PyLong objects created here (once per process) are not decref'd.
- if (st->initialized) {
+init_state(datetime_state *st, PyObject *module, PyObject *old_module)
+{
+ /* Each module gets its own heap types. */
+#define ADD_TYPE(FIELD, SPEC, BASE) \
+ do { \
+ PyObject *cls = PyType_FromModuleAndSpec( \
+ module, SPEC, (PyObject *)BASE); \
+ if (cls == NULL) { \
+ return -1; \
+ } \
+ st->FIELD = (PyTypeObject *)cls; \
+ } while (0)
+
+ ADD_TYPE(isocalendar_date_type, &isocal_spec, &PyTuple_Type);
+#undef ADD_TYPE
+
+ if (old_module != NULL) {
+ assert(old_module != module);
+ datetime_state *st_old = get_module_state(old_module);
+ *st = (datetime_state){
+ .isocalendar_date_type = st->isocalendar_date_type,
+ .us_per_ms = Py_NewRef(st_old->us_per_ms),
+ .us_per_second = Py_NewRef(st_old->us_per_second),
+ .us_per_minute = Py_NewRef(st_old->us_per_minute),
+ .us_per_hour = Py_NewRef(st_old->us_per_hour),
+ .us_per_day = Py_NewRef(st_old->us_per_day),
+ .us_per_week = Py_NewRef(st_old->us_per_week),
+ .seconds_per_day = Py_NewRef(st_old->seconds_per_day),
+ .epoch = Py_NewRef(st_old->epoch),
+ };
return 0;
}
- /* Static types exposed by the C-API. */
- st->date_type = &PyDateTime_DateType;
- st->datetime_type = &PyDateTime_DateTimeType;
- st->delta_type = &PyDateTime_DeltaType;
- st->time_type = &PyDateTime_TimeType;
- st->tzinfo_type = &PyDateTime_TZInfoType;
- st->timezone_type = &PyDateTime_TimeZoneType;
-
- /* Per-module heap types. */
- st->isocalendar_date_type = PyDateTime_IsoCalendarDateType;
-
st->us_per_ms = PyLong_FromLong(1000);
if (st->us_per_ms == NULL) {
return -1;
@@ -6921,26 +7071,54 @@ init_state(datetime_state *st, PyTypeObject *PyDateTime_IsoCalendarDateType)
return -1;
}
- /* Init UTC timezone */
- st->utc = create_timezone_from_delta(0, 0, 0, 0);
- if (st->utc == NULL) {
- return -1;
- }
-
/* Init Unix epoch */
- st->epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, st->utc, 0);
+ st->epoch = new_datetime(
+ 1970, 1, 1, 0, 0, 0, 0, (PyObject *)&utc_timezone, 0);
if (st->epoch == NULL) {
return -1;
}
- st->initialized = 1;
+ return 0;
+}
+
+static int
+traverse_state(datetime_state *st, visitproc visit, void *arg)
+{
+ /* heap types */
+ Py_VISIT(st->isocalendar_date_type);
return 0;
}
+static int
+clear_state(datetime_state *st)
+{
+ Py_CLEAR(st->isocalendar_date_type);
+ Py_CLEAR(st->us_per_ms);
+ Py_CLEAR(st->us_per_second);
+ Py_CLEAR(st->us_per_minute);
+ Py_CLEAR(st->us_per_hour);
+ Py_CLEAR(st->us_per_day);
+ Py_CLEAR(st->us_per_week);
+ Py_CLEAR(st->seconds_per_day);
+ Py_CLEAR(st->epoch);
+ return 0;
+}
+
static int
_datetime_exec(PyObject *module)
{
+ int rc = -1;
+ datetime_state *st = get_module_state(module);
+
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ PyObject *old_module = get_current_module(interp);
+ if (PyErr_Occurred()) {
+ assert(old_module == NULL);
+ goto error;
+ }
+ /* We actually set the "current" module right before a successful return. */
+
// `&...` is not a constant expression according to a strict reading
// of C standards. Fill tp_base at run-time rather than statically.
// See https://bugs.python.org/issue40777
@@ -6953,6 +7131,7 @@ _datetime_exec(PyObject *module)
&PyDateTime_TimeType,
&PyDateTime_DeltaType,
&PyDateTime_TZInfoType,
+ /* Indirectly, via the utc object. */
&PyDateTime_TimeZoneType,
};
@@ -6962,29 +7141,16 @@ _datetime_exec(PyObject *module)
}
}
-#define CREATE_TYPE(VAR, SPEC, BASE) \
- do { \
- VAR = (PyTypeObject *)PyType_FromModuleAndSpec( \
- module, SPEC, (PyObject *)BASE); \
- if (VAR == NULL) { \
- goto error; \
- } \
- } while (0)
-
- PyTypeObject *PyDateTime_IsoCalendarDateType = NULL;
- datetime_state *st = get_datetime_state();
-
- if (!st->initialized) {
- CREATE_TYPE(PyDateTime_IsoCalendarDateType, &isocal_spec, &PyTuple_Type);
- }
-#undef CREATE_TYPE
-
- if (init_state(st, PyDateTime_IsoCalendarDateType) < 0) {
+ if (init_state(st, module, old_module) < 0) {
goto error;
}
+ /* For now we only set the objects on the static types once.
+ * We will relax that once each types __dict__ is per-interpreter. */
#define DATETIME_ADD_MACRO(dict, c, value_expr) \
do { \
+ if (PyDict_GetItemString(dict, c) == NULL) { \
+ assert(!PyErr_Occurred()); \
PyObject *value = (value_expr); \
if (value == NULL) { \
goto error; \
@@ -6994,29 +7160,30 @@ _datetime_exec(PyObject *module)
goto error; \
} \
Py_DECREF(value); \
+ } \
} while(0)
/* timedelta values */
- PyObject *d = st->delta_type->tp_dict;
+ PyObject *d = PyDateTime_DeltaType.tp_dict;
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0));
DATETIME_ADD_MACRO(d, "max",
new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0));
/* date values */
- d = st->date_type->tp_dict;
+ d = PyDateTime_DateType.tp_dict;
DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1));
DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31));
DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0));
/* time values */
- d = st->time_type->tp_dict;
+ d = PyDateTime_TimeType.tp_dict;
DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0));
DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0));
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
/* datetime values */
- d = st->datetime_type->tp_dict;
+ d = PyDateTime_DateTimeType.tp_dict;
DATETIME_ADD_MACRO(d, "min",
new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0));
DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59,
@@ -7024,8 +7191,8 @@ _datetime_exec(PyObject *module)
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
/* timezone values */
- d = st->timezone_type->tp_dict;
- if (PyDict_SetItemString(d, "utc", st->utc) < 0) {
+ d = PyDateTime_TimeZoneType.tp_dict;
+ if (PyDict_SetItemString(d, "utc", (PyObject *)&utc_timezone) < 0) {
goto error;
}
@@ -7034,12 +7201,13 @@ _datetime_exec(PyObject *module)
* values. This may change in the future.*/
/* -23:59 */
- PyObject *min = create_timezone_from_delta(-1, 60, 0, 1);
- DATETIME_ADD_MACRO(d, "min", min);
+ DATETIME_ADD_MACRO(d, "min", create_timezone_from_delta(-1, 60, 0, 1));
/* +23:59 */
- PyObject *max = create_timezone_from_delta(0, (23 * 60 + 59) * 60, 0, 0);
- DATETIME_ADD_MACRO(d, "max", max);
+ DATETIME_ADD_MACRO(
+ d, "max", create_timezone_from_delta(0, (23 * 60 + 59) * 60, 0, 0));
+
+#undef DATETIME_ADD_MACRO
/* Add module level attributes */
if (PyModule_AddIntMacro(module, MINYEAR) < 0) {
@@ -7048,7 +7216,7 @@ _datetime_exec(PyObject *module)
if (PyModule_AddIntMacro(module, MAXYEAR) < 0) {
goto error;
}
- if (PyModule_AddObjectRef(module, "UTC", st->utc) < 0) {
+ if (PyModule_AddObjectRef(module, "UTC", (PyObject *)&utc_timezone) < 0) {
goto error;
}
@@ -7081,13 +7249,20 @@ _datetime_exec(PyObject *module)
static_assert(DI100Y == 25 * DI4Y - 1, "DI100Y");
assert(DI100Y == days_before_year(100+1));
- return 0;
+ if (set_current_module(interp, module) < 0) {
+ goto error;
+ }
+
+ rc = 0;
+ goto finally;
error:
- datetime_clear(module);
- return -1;
+ clear_state(st);
+
+finally:
+ Py_XDECREF(old_module);
+ return rc;
}
-#undef DATETIME_ADD_MACRO
static PyModuleDef_Slot module_slots[] = {
{Py_mod_exec, _datetime_exec},
@@ -7096,13 +7271,46 @@ static PyModuleDef_Slot module_slots[] = {
{0, NULL},
};
+static int
+module_traverse(PyObject *mod, visitproc visit, void *arg)
+{
+ datetime_state *st = get_module_state(mod);
+ traverse_state(st, visit, arg);
+ return 0;
+}
+
+static int
+module_clear(PyObject *mod)
+{
+ datetime_state *st = get_module_state(mod);
+ clear_state(st);
+
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ clear_current_module(interp, mod);
+
+ return 0;
+}
+
+static void
+module_free(void *mod)
+{
+ datetime_state *st = get_module_state((PyObject *)mod);
+ clear_state(st);
+
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ clear_current_module(interp, (PyObject *)mod);
+}
+
static PyModuleDef datetimemodule = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "_datetime",
.m_doc = "Fast implementation of the datetime type.",
- .m_size = 0,
+ .m_size = sizeof(datetime_state),
.m_methods = module_methods,
.m_slots = module_slots,
+ .m_traverse = module_traverse,
+ .m_clear = module_clear,
+ .m_free = module_free,
};
PyMODINIT_FUNC
1
0
https://github.com/python/cpython/commit/47fb4327b5c405da6df066dcaa01b7c1ae…
commit: 47fb4327b5c405da6df066dcaa01b7c1aefab313
branch: main
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-03T20:58:41Z
summary:
gh-117657: Fix race involving immortalizing objects (#119927)
The free-threaded build currently immortalizes objects that use deferred
reference counting (see gh-117783). This typically happens once the
first non-main thread is created, but the behavior can be suppressed for
tests, in subinterpreters, or during a compile() call.
This fixes a race condition involving the tracking of whether the
behavior is suppressed.
files:
M Include/internal/pycore_gc.h
M Lib/test/support/__init__.py
M Modules/_testinternalcapi.c
M Objects/codeobject.c
M Objects/object.c
M Python/bltinmodule.c
M Python/gc_free_threading.c
M Python/pystate.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index 60582521db5bd7..ba8b8e1903f307 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -347,15 +347,11 @@ struct _gc_runtime_state {
/* gh-117783: Deferred reference counting is not fully implemented yet, so
as a temporary measure we treat objects using deferred referenence
- counting as immortal. */
- struct {
- /* Immortalize objects instead of marking them as using deferred
- reference counting. */
- int enabled;
-
- /* Set enabled=1 when the first background thread is created. */
- int enable_on_thread_created;
- } immortalize;
+ counting as immortal. The value may be zero, one, or a negative number:
+ 0: immortalize deferred RC objects once the first thread is created
+ 1: immortalize all deferred RC objects immediately
+ <0: suppressed; don't immortalize objects */
+ int immortalize;
#endif
};
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 5825efadffcb29..4b320b494bb8dd 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -529,11 +529,11 @@ def suppress_immortalization(suppress=True):
yield
return
- old_values = _testinternalcapi.set_immortalize_deferred(False)
+ _testinternalcapi.suppress_immortalization(True)
try:
yield
finally:
- _testinternalcapi.set_immortalize_deferred(*old_values)
+ _testinternalcapi.suppress_immortalization(False)
def skip_if_suppress_immortalization():
try:
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index d9b9c999603d5a..6d4a00c06ca9de 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1966,24 +1966,18 @@ get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored))
#endif
static PyObject *
-set_immortalize_deferred(PyObject *self, PyObject *value)
+suppress_immortalization(PyObject *self, PyObject *value)
{
#ifdef Py_GIL_DISABLED
- PyInterpreterState *interp = PyInterpreterState_Get();
- int old_enabled = interp->gc.immortalize.enabled;
- int old_enabled_on_thread = interp->gc.immortalize.enable_on_thread_created;
- int enabled_on_thread = 0;
- if (!PyArg_ParseTuple(value, "i|i",
- &interp->gc.immortalize.enabled,
- &enabled_on_thread))
- {
+ int suppress = PyObject_IsTrue(value);
+ if (suppress < 0) {
return NULL;
}
- interp->gc.immortalize.enable_on_thread_created = enabled_on_thread;
- return Py_BuildValue("ii", old_enabled, old_enabled_on_thread);
-#else
- return Py_BuildValue("OO", Py_False, Py_False);
+ PyInterpreterState *interp = PyInterpreterState_Get();
+ // Subtract two to suppress immortalization (so that 1 -> -1)
+ _Py_atomic_add_int(&interp->gc.immortalize, suppress ? -2 : 2);
#endif
+ Py_RETURN_NONE;
}
static PyObject *
@@ -1991,7 +1985,7 @@ get_immortalize_deferred(PyObject *self, PyObject *Py_UNUSED(ignored))
{
#ifdef Py_GIL_DISABLED
PyInterpreterState *interp = PyInterpreterState_Get();
- return PyBool_FromLong(interp->gc.immortalize.enable_on_thread_created);
+ return PyBool_FromLong(_Py_atomic_load_int(&interp->gc.immortalize) >= 0);
#else
Py_RETURN_FALSE;
#endif
@@ -2111,7 +2105,7 @@ static PyMethodDef module_functions[] = {
#ifdef Py_GIL_DISABLED
{"py_thread_id", get_py_thread_id, METH_NOARGS},
#endif
- {"set_immortalize_deferred", set_immortalize_deferred, METH_VARARGS},
+ {"suppress_immortalization", suppress_immortalization, METH_O},
{"get_immortalize_deferred", get_immortalize_deferred, METH_NOARGS},
#ifdef _Py_TIER2
{"uop_symbols_test", _Py_uop_symbols_test, METH_NOARGS},
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 2ffda8dee07c90..e3e306bfe810c4 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -110,7 +110,7 @@ should_intern_string(PyObject *o)
// unless we've disabled immortalizing objects that use deferred reference
// counting.
PyInterpreterState *interp = _PyInterpreterState_GET();
- if (interp->gc.immortalize.enable_on_thread_created) {
+ if (_Py_atomic_load_int(&interp->gc.immortalize) < 0) {
return 1;
}
#endif
@@ -240,7 +240,7 @@ intern_constants(PyObject *tuple, int *modified)
PyThreadState *tstate = PyThreadState_GET();
if (!_Py_IsImmortal(v) && !PyCode_Check(v) &&
!PyUnicode_CheckExact(v) &&
- tstate->interp->gc.immortalize.enable_on_thread_created)
+ _Py_atomic_load_int(&tstate->interp->gc.immortalize) >= 0)
{
PyObject *interned = intern_one_constant(v);
if (interned == NULL) {
diff --git a/Objects/object.c b/Objects/object.c
index d4fe14c5b3d1aa..5d53e9e5eaba4e 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -2429,7 +2429,7 @@ _PyObject_SetDeferredRefcount(PyObject *op)
assert(op->ob_ref_shared == 0);
_PyObject_SET_GC_BITS(op, _PyGC_BITS_DEFERRED);
PyInterpreterState *interp = _PyInterpreterState_GET();
- if (interp->gc.immortalize.enabled) {
+ if (_Py_atomic_load_int_relaxed(&interp->gc.immortalize) == 1) {
// gh-117696: immortalize objects instead of using deferred reference
// counting for now.
_Py_SetImmortal(op);
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 2a02d8161591c6..c4d3ecbeeff0e6 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -870,15 +870,15 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
// gh-118527: Disable immortalization of code constants for explicit
// compile() calls to get consistent frozen outputs between the default
// and free-threaded builds.
+ // Subtract two to suppress immortalization (so that 1 -> -1)
PyInterpreterState *interp = _PyInterpreterState_GET();
- int old_value = interp->gc.immortalize.enable_on_thread_created;
- interp->gc.immortalize.enable_on_thread_created = 0;
+ _Py_atomic_add_int(&interp->gc.immortalize, -2);
#endif
result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize);
#ifdef Py_GIL_DISABLED
- interp->gc.immortalize.enable_on_thread_created = old_value;
+ _Py_atomic_add_int(&interp->gc.immortalize, 2);
#endif
Py_XDECREF(source_copy);
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index e6bd012c40ee82..d005b79ff40dbf 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -703,11 +703,9 @@ _PyGC_Init(PyInterpreterState *interp)
{
GCState *gcstate = &interp->gc;
- if (_Py_IsMainInterpreter(interp)) {
- // gh-117783: immortalize objects that would use deferred refcounting
- // once the first non-main thread is created.
- gcstate->immortalize.enable_on_thread_created = 1;
- }
+ // gh-117783: immortalize objects that would use deferred refcounting
+ // once the first non-main thread is created (but not in subinterpreters).
+ gcstate->immortalize = _Py_IsMainInterpreter(interp) ? 0 : -1;
gcstate->garbage = PyList_New(0);
if (gcstate->garbage == NULL) {
@@ -1808,8 +1806,10 @@ _PyGC_ImmortalizeDeferredObjects(PyInterpreterState *interp)
{
struct visitor_args args;
_PyEval_StopTheWorld(interp);
- gc_visit_heaps(interp, &immortalize_visitor, &args);
- interp->gc.immortalize.enabled = 1;
+ if (interp->gc.immortalize == 0) {
+ gc_visit_heaps(interp, &immortalize_visitor, &args);
+ interp->gc.immortalize = 1;
+ }
_PyEval_StartTheWorld(interp);
}
diff --git a/Python/pystate.c b/Python/pystate.c
index 36e4206b4a282e..d0293915db7689 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1583,9 +1583,7 @@ new_threadstate(PyInterpreterState *interp, int whence)
}
else {
#ifdef Py_GIL_DISABLED
- if (interp->gc.immortalize.enable_on_thread_created &&
- !interp->gc.immortalize.enabled)
- {
+ if (_Py_atomic_load_int(&interp->gc.immortalize) == 0) {
// Immortalize objects marked as using deferred reference counting
// the first time a non-main thread is created.
_PyGC_ImmortalizeDeferredObjects(interp);
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index 39cc5b080c8703..d5fcac61f0db04 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -47,7 +47,6 @@ race_top:_PyImport_AcquireLock
race_top:_Py_dict_lookup_threadsafe
race_top:_imp_release_lock
race_top:_multiprocessing_SemLock_acquire_impl
-race_top:builtin_compile_impl
race_top:dictiter_new
race_top:dictresize
race_top:insert_to_emptydict
@@ -55,7 +54,6 @@ race_top:insertdict
race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
-race_top:should_intern_string
race_top:_Py_slot_tp_getattr_hook
race_top:add_threadstate
race_top:dump_traceback
1
0
https://github.com/python/cpython/commit/b8fde5db86334690da23343f5f4326adcd…
commit: b8fde5db86334690da23343f5f4326adcd8160fb
branch: main
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2024-06-03T20:44:36Z
summary:
update CODEOWNERS (#120003)
files:
M .github/CODEOWNERS
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index e08d6cc5719737..ca5c8aaa3a0bef 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -34,6 +34,7 @@ Python/ceval*.h @markshannon
Python/compile.c @markshannon @iritkatriel
Python/assemble.c @markshannon @iritkatriel
Python/flowgraph.c @markshannon @iritkatriel
+Python/instruction_sequence.c @iritkatriel
Python/ast_opt.c @isidentical
Python/bytecodes.c @markshannon
Python/optimizer*.c @markshannon
@@ -74,11 +75,8 @@ Programs/python.c @ericsnowcurrently
Tools/build/generate_global_objects.py @ericsnowcurrently
# Exceptions
-Lib/traceback.py @iritkatriel
Lib/test/test_except*.py @iritkatriel
-Lib/test/test_traceback.py @iritkatriel
Objects/exceptions.c @iritkatriel
-Python/traceback.c @iritkatriel
# Hashing
**/*hashlib* @gpshead @tiran
1
0

03 Jun '24
https://github.com/python/cpython/commit/3bf7a5079c8d1845af98c145056e7ae1e1…
commit: 3bf7a5079c8d1845af98c145056e7ae1e102be43
branch: 3.12
author: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2024-06-03T12:26:25-07:00
summary:
[3.12] gh-119821: Fix refleak in LOAD_FROM_DICT_OR_GLOBALS (#119975)
files:
M Python/bytecodes.c
M Python/generated_cases.c.h
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 18061b692641f2..e17b2294c24d50 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1209,6 +1209,7 @@ dummy_func(
format_exc_check_arg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
+ Py_DECREF(mod_or_class_dict);
ERROR_IF(true, error);
}
Py_INCREF(v);
@@ -1230,6 +1231,7 @@ dummy_func(
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
+ Py_DECREF(mod_or_class_dict);
ERROR_IF(true, error);
}
}
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 31f37ec4cdd943..a23cbd52ec3cc9 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1671,6 +1671,7 @@
format_exc_check_arg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
+ Py_DECREF(mod_or_class_dict);
if (true) goto pop_1_error;
}
Py_INCREF(v);
@@ -1692,12 +1693,13 @@
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
+ Py_DECREF(mod_or_class_dict);
if (true) goto pop_1_error;
}
}
}
}
- #line 1701 "Python/generated_cases.c.h"
+ #line 1703 "Python/generated_cases.c.h"
Py_DECREF(mod_or_class_dict);
stack_pointer[-1] = v;
DISPATCH();
@@ -1705,7 +1707,7 @@
TARGET(LOAD_NAME) {
PyObject *v;
- #line 1242 "Python/bytecodes.c"
+ #line 1244 "Python/bytecodes.c"
PyObject *mod_or_class_dict = LOCALS();
if (mod_or_class_dict == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -1765,7 +1767,7 @@
}
}
}
- #line 1769 "Python/generated_cases.c.h"
+ #line 1771 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = v;
DISPATCH();
@@ -1776,7 +1778,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
PyObject *null = NULL;
PyObject *v;
- #line 1310 "Python/bytecodes.c"
+ #line 1312 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -1828,7 +1830,7 @@
}
}
null = NULL;
- #line 1832 "Python/generated_cases.c.h"
+ #line 1834 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = v;
@@ -1842,7 +1844,7 @@
PyObject *res;
uint16_t index = read_u16(&next_instr[1].cache);
uint16_t version = read_u16(&next_instr[2].cache);
- #line 1364 "Python/bytecodes.c"
+ #line 1366 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS();
DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
@@ -1853,7 +1855,7 @@
Py_INCREF(res);
STAT_INC(LOAD_GLOBAL, hit);
null = NULL;
- #line 1857 "Python/generated_cases.c.h"
+ #line 1859 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -1868,7 +1870,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 1377 "Python/bytecodes.c"
+ #line 1379 "Python/bytecodes.c"
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
PyDictObject *mdict = (PyDictObject *)GLOBALS();
@@ -1883,7 +1885,7 @@
Py_INCREF(res);
STAT_INC(LOAD_GLOBAL, hit);
null = NULL;
- #line 1887 "Python/generated_cases.c.h"
+ #line 1889 "Python/generated_cases.c.h"
STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -1893,16 +1895,16 @@
}
TARGET(DELETE_FAST) {
- #line 1394 "Python/bytecodes.c"
+ #line 1396 "Python/bytecodes.c"
PyObject *v = GETLOCAL(oparg);
if (v == NULL) goto unbound_local_error;
SETLOCAL(oparg, NULL);
- #line 1901 "Python/generated_cases.c.h"
+ #line 1903 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(MAKE_CELL) {
- #line 1400 "Python/bytecodes.c"
+ #line 1402 "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);
@@ -1911,12 +1913,12 @@
goto resume_with_error;
}
SETLOCAL(oparg, cell);
- #line 1915 "Python/generated_cases.c.h"
+ #line 1917 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(DELETE_DEREF) {
- #line 1411 "Python/bytecodes.c"
+ #line 1413 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
// Can't use ERROR_IF here.
@@ -1927,14 +1929,14 @@
}
PyCell_SET(cell, NULL);
Py_DECREF(oldobj);
- #line 1931 "Python/generated_cases.c.h"
+ #line 1933 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(LOAD_FROM_DICT_OR_DEREF) {
PyObject *class_dict = stack_pointer[-1];
PyObject *value;
- #line 1424 "Python/bytecodes.c"
+ #line 1426 "Python/bytecodes.c"
PyObject *name;
assert(class_dict);
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
@@ -1967,14 +1969,14 @@
Py_INCREF(value);
}
Py_DECREF(class_dict);
- #line 1971 "Python/generated_cases.c.h"
+ #line 1973 "Python/generated_cases.c.h"
stack_pointer[-1] = value;
DISPATCH();
}
TARGET(LOAD_DEREF) {
PyObject *value;
- #line 1459 "Python/bytecodes.c"
+ #line 1461 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
@@ -1982,7 +1984,7 @@
if (true) goto error;
}
Py_INCREF(value);
- #line 1986 "Python/generated_cases.c.h"
+ #line 1988 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = value;
DISPATCH();
@@ -1990,18 +1992,18 @@
TARGET(STORE_DEREF) {
PyObject *v = stack_pointer[-1];
- #line 1469 "Python/bytecodes.c"
+ #line 1471 "Python/bytecodes.c"
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
PyCell_SET(cell, v);
Py_XDECREF(oldobj);
- #line 1999 "Python/generated_cases.c.h"
+ #line 2001 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(COPY_FREE_VARS) {
- #line 1476 "Python/bytecodes.c"
+ #line 1478 "Python/bytecodes.c"
/* Copy closure variables to free variables */
PyCodeObject *co = frame->f_code;
assert(PyFunction_Check(frame->f_funcobj));
@@ -2012,22 +2014,22 @@
PyObject *o = PyTuple_GET_ITEM(closure, i);
frame->localsplus[offset + i] = Py_NewRef(o);
}
- #line 2016 "Python/generated_cases.c.h"
+ #line 2018 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(BUILD_STRING) {
PyObject **pieces = (stack_pointer - oparg);
PyObject *str;
- #line 1489 "Python/bytecodes.c"
+ #line 1491 "Python/bytecodes.c"
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
- #line 2025 "Python/generated_cases.c.h"
+ #line 2027 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(pieces[_i]);
}
- #line 1491 "Python/bytecodes.c"
+ #line 1493 "Python/bytecodes.c"
if (str == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2031 "Python/generated_cases.c.h"
+ #line 2033 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = str;
@@ -2037,10 +2039,10 @@
TARGET(BUILD_TUPLE) {
PyObject **values = (stack_pointer - oparg);
PyObject *tup;
- #line 1495 "Python/bytecodes.c"
+ #line 1497 "Python/bytecodes.c"
tup = _PyTuple_FromArraySteal(values, oparg);
if (tup == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2044 "Python/generated_cases.c.h"
+ #line 2046 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = tup;
@@ -2050,10 +2052,10 @@
TARGET(BUILD_LIST) {
PyObject **values = (stack_pointer - oparg);
PyObject *list;
- #line 1500 "Python/bytecodes.c"
+ #line 1502 "Python/bytecodes.c"
list = _PyList_FromArraySteal(values, oparg);
if (list == NULL) { STACK_SHRINK(oparg); goto error; }
- #line 2057 "Python/generated_cases.c.h"
+ #line 2059 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = list;
@@ -2063,7 +2065,7 @@
TARGET(LIST_EXTEND) {
PyObject *iterable = stack_pointer[-1];
PyObject *list = stack_pointer[-(2 + (oparg-1))];
- #line 1505 "Python/bytecodes.c"
+ #line 1507 "Python/bytecodes.c"
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
if (none_val == NULL) {
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -2074,13 +2076,13 @@
"Value after * must be an iterable, not %.200s",
Py_TYPE(iterable)->tp_name);
}
- #line 2078 "Python/generated_cases.c.h"
+ #line 2080 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1516 "Python/bytecodes.c"
+ #line 1518 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
assert(Py_IsNone(none_val));
- #line 2084 "Python/generated_cases.c.h"
+ #line 2086 "Python/generated_cases.c.h"
Py_DECREF(iterable);
STACK_SHRINK(1);
DISPATCH();
@@ -2089,13 +2091,13 @@
TARGET(SET_UPDATE) {
PyObject *iterable = stack_pointer[-1];
PyObject *set = stack_pointer[-(2 + (oparg-1))];
- #line 1523 "Python/bytecodes.c"
+ #line 1525 "Python/bytecodes.c"
int err = _PySet_Update(set, iterable);
- #line 2095 "Python/generated_cases.c.h"
+ #line 2097 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 1525 "Python/bytecodes.c"
+ #line 1527 "Python/bytecodes.c"
if (err < 0) goto pop_1_error;
- #line 2099 "Python/generated_cases.c.h"
+ #line 2101 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
@@ -2103,7 +2105,7 @@
TARGET(BUILD_SET) {
PyObject **values = (stack_pointer - oparg);
PyObject *set;
- #line 1529 "Python/bytecodes.c"
+ #line 1531 "Python/bytecodes.c"
set = PySet_New(NULL);
if (set == NULL)
goto error;
@@ -2118,7 +2120,7 @@
Py_DECREF(set);
if (true) { STACK_SHRINK(oparg); goto error; }
}
- #line 2122 "Python/generated_cases.c.h"
+ #line 2124 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_GROW(1);
stack_pointer[-1] = set;
@@ -2128,18 +2130,18 @@
TARGET(BUILD_MAP) {
PyObject **values = (stack_pointer - oparg*2);
PyObject *map;
- #line 1546 "Python/bytecodes.c"
+ #line 1548 "Python/bytecodes.c"
map = _PyDict_FromItems(
values, 2,
values+1, 2,
oparg);
- #line 2137 "Python/generated_cases.c.h"
+ #line 2139 "Python/generated_cases.c.h"
for (int _i = oparg*2; --_i >= 0;) {
Py_DECREF(values[_i]);
}
- #line 1551 "Python/bytecodes.c"
+ #line 1553 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }
- #line 2143 "Python/generated_cases.c.h"
+ #line 2145 "Python/generated_cases.c.h"
STACK_SHRINK(oparg*2);
STACK_GROW(1);
stack_pointer[-1] = map;
@@ -2147,7 +2149,7 @@
}
TARGET(SETUP_ANNOTATIONS) {
- #line 1555 "Python/bytecodes.c"
+ #line 1557 "Python/bytecodes.c"
int err;
PyObject *ann_dict;
if (LOCALS() == NULL) {
@@ -2187,7 +2189,7 @@
Py_DECREF(ann_dict);
}
}
- #line 2191 "Python/generated_cases.c.h"
+ #line 2193 "Python/generated_cases.c.h"
DISPATCH();
}
@@ -2195,7 +2197,7 @@
PyObject *keys = stack_pointer[-1];
PyObject **values = (stack_pointer - (1 + oparg));
PyObject *map;
- #line 1597 "Python/bytecodes.c"
+ #line 1599 "Python/bytecodes.c"
if (!PyTuple_CheckExact(keys) ||
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
_PyErr_SetString(tstate, PyExc_SystemError,
@@ -2205,14 +2207,14 @@
map = _PyDict_FromItems(
&PyTuple_GET_ITEM(keys, 0), 1,
values, 1, oparg);
- #line 2209 "Python/generated_cases.c.h"
+ #line 2211 "Python/generated_cases.c.h"
for (int _i = oparg; --_i >= 0;) {
Py_DECREF(values[_i]);
}
Py_DECREF(keys);
- #line 1607 "Python/bytecodes.c"
+ #line 1609 "Python/bytecodes.c"
if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }
- #line 2216 "Python/generated_cases.c.h"
+ #line 2218 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
stack_pointer[-1] = map;
DISPATCH();
@@ -2220,7 +2222,7 @@
TARGET(DICT_UPDATE) {
PyObject *update = stack_pointer[-1];
- #line 1611 "Python/bytecodes.c"
+ #line 1613 "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)) {
@@ -2228,12 +2230,12 @@
"'%.200s' object is not a mapping",
Py_TYPE(update)->tp_name);
}
- #line 2232 "Python/generated_cases.c.h"
+ #line 2234 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1619 "Python/bytecodes.c"
+ #line 1621 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2237 "Python/generated_cases.c.h"
+ #line 2239 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
DISPATCH();
@@ -2241,17 +2243,17 @@
TARGET(DICT_MERGE) {
PyObject *update = stack_pointer[-1];
- #line 1625 "Python/bytecodes.c"
+ #line 1627 "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 2250 "Python/generated_cases.c.h"
+ #line 2252 "Python/generated_cases.c.h"
Py_DECREF(update);
- #line 1630 "Python/bytecodes.c"
+ #line 1632 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
- #line 2255 "Python/generated_cases.c.h"
+ #line 2257 "Python/generated_cases.c.h"
Py_DECREF(update);
STACK_SHRINK(1);
PREDICT(CALL_FUNCTION_EX);
@@ -2261,26 +2263,26 @@
TARGET(MAP_ADD) {
PyObject *value = stack_pointer[-1];
PyObject *key = stack_pointer[-2];
- #line 1637 "Python/bytecodes.c"
+ #line 1639 "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 2271 "Python/generated_cases.c.h"
+ #line 2273 "Python/generated_cases.c.h"
STACK_SHRINK(2);
PREDICT(JUMP_BACKWARD);
DISPATCH();
}
TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) {
- #line 1646 "Python/bytecodes.c"
+ #line 1648 "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 2284 "Python/generated_cases.c.h"
+ #line 2286 "Python/generated_cases.c.h"
}
TARGET(LOAD_SUPER_ATTR) {
@@ -2291,7 +2293,7 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1660 "Python/bytecodes.c"
+ #line 1662 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
int load_method = oparg & 1;
#if ENABLE_SPECIALIZATION
@@ -2333,16 +2335,16 @@
}
}
}
- #line 2337 "Python/generated_cases.c.h"
+ #line 2339 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1702 "Python/bytecodes.c"
+ #line 1704 "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 2346 "Python/generated_cases.c.h"
+ #line 2348 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2357,20 +2359,20 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2 = NULL;
PyObject *res;
- #line 1709 "Python/bytecodes.c"
+ #line 1711 "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 2368 "Python/generated_cases.c.h"
+ #line 2370 "Python/generated_cases.c.h"
Py_DECREF(global_super);
Py_DECREF(class);
Py_DECREF(self);
- #line 1716 "Python/bytecodes.c"
+ #line 1718 "Python/bytecodes.c"
if (res == NULL) goto pop_3_error;
- #line 2374 "Python/generated_cases.c.h"
+ #line 2376 "Python/generated_cases.c.h"
STACK_SHRINK(2);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2385,7 +2387,7 @@
PyObject *global_super = stack_pointer[-3];
PyObject *res2;
PyObject *res;
- #line 1720 "Python/bytecodes.c"
+ #line 1722 "Python/bytecodes.c"
assert(oparg & 1);
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
@@ -2408,7 +2410,7 @@
res = res2;
res2 = NULL;
}
- #line 2412 "Python/generated_cases.c.h"
+ #line 2414 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
stack_pointer[-2] = res2;
@@ -2422,7 +2424,7 @@
PyObject *owner = stack_pointer[-1];
PyObject *res2 = NULL;
PyObject *res;
- #line 1759 "Python/bytecodes.c"
+ #line 1761 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2456,9 +2458,9 @@
NULL | meth | arg1 | ... | argN
*/
- #line 2460 "Python/generated_cases.c.h"
+ #line 2462 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1793 "Python/bytecodes.c"
+ #line 1795 "Python/bytecodes.c"
if (meth == NULL) goto pop_1_error;
res2 = NULL;
res = meth;
@@ -2467,12 +2469,12 @@
else {
/* Classic, pushes one value. */
res = PyObject_GetAttr(owner, name);
- #line 2471 "Python/generated_cases.c.h"
+ #line 2473 "Python/generated_cases.c.h"
Py_DECREF(owner);
- #line 1802 "Python/bytecodes.c"
+ #line 1804 "Python/bytecodes.c"
if (res == NULL) goto pop_1_error;
}
- #line 2476 "Python/generated_cases.c.h"
+ #line 2478 "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; }
@@ -2486,7 +2488,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1807 "Python/bytecodes.c"
+ #line 1809 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2499,7 +2501,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2503 "Python/generated_cases.c.h"
+ #line 2505 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2514,7 +2516,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1823 "Python/bytecodes.c"
+ #line 1825 "Python/bytecodes.c"
DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
@@ -2527,7 +2529,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2531 "Python/generated_cases.c.h"
+ #line 2533 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2542,7 +2544,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1839 "Python/bytecodes.c"
+ #line 1841 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2569,7 +2571,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2573 "Python/generated_cases.c.h"
+ #line 2575 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2584,7 +2586,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
uint16_t index = read_u16(&next_instr[3].cache);
- #line 1869 "Python/bytecodes.c"
+ #line 1871 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
@@ -2594,7 +2596,7 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(res);
res2 = NULL;
- #line 2598 "Python/generated_cases.c.h"
+ #line 2600 "Python/generated_cases.c.h"
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2609,7 +2611,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 1882 "Python/bytecodes.c"
+ #line 1884 "Python/bytecodes.c"
DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);
DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,
@@ -2621,7 +2623,7 @@
res = descr;
assert(res != NULL);
Py_INCREF(res);
- #line 2625 "Python/generated_cases.c.h"
+ #line 2627 "Python/generated_cases.c.h"
Py_DECREF(cls);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1] = res;
@@ -2635,7 +2637,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 1897 "Python/bytecodes.c"
+ #line 1899 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
PyTypeObject *cls = Py_TYPE(owner);
@@ -2659,7 +2661,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2663 "Python/generated_cases.c.h"
+ #line 2665 "Python/generated_cases.c.h"
}
TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) {
@@ -2667,7 +2669,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 1923 "Python/bytecodes.c"
+ #line 1925 "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);
@@ -2693,7 +2695,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 2697 "Python/generated_cases.c.h"
+ #line 2699 "Python/generated_cases.c.h"
}
TARGET(STORE_ATTR_INSTANCE_VALUE) {
@@ -2701,7 +2703,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 1951 "Python/bytecodes.c"
+ #line 1953 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2719,7 +2721,7 @@
Py_DECREF(old_value);
}
Py_DECREF(owner);
- #line 2723 "Python/generated_cases.c.h"
+ #line 2725 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2730,7 +2732,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 1971 "Python/bytecodes.c"
+ #line 1973 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2769,7 +2771,7 @@
/* PEP 509 */
dict->ma_version_tag = new_version;
Py_DECREF(owner);
- #line 2773 "Python/generated_cases.c.h"
+ #line 2775 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2780,7 +2782,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 2012 "Python/bytecodes.c"
+ #line 2014 "Python/bytecodes.c"
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
@@ -2790,7 +2792,7 @@
*(PyObject **)addr = value;
Py_XDECREF(old_value);
Py_DECREF(owner);
- #line 2794 "Python/generated_cases.c.h"
+ #line 2796 "Python/generated_cases.c.h"
STACK_SHRINK(2);
next_instr += 4;
DISPATCH();
@@ -2802,7 +2804,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2031 "Python/bytecodes.c"
+ #line 2033 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2815,12 +2817,12 @@
#endif /* ENABLE_SPECIALIZATION */
assert((oparg >> 4) <= Py_GE);
res = PyObject_RichCompare(left, right, oparg>>4);
- #line 2819 "Python/generated_cases.c.h"
+ #line 2821 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2044 "Python/bytecodes.c"
+ #line 2046 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 2824 "Python/generated_cases.c.h"
+ #line 2826 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2831,7 +2833,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2048 "Python/bytecodes.c"
+ #line 2050 "Python/bytecodes.c"
DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
@@ -2842,7 +2844,7 @@
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2846 "Python/generated_cases.c.h"
+ #line 2848 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2853,7 +2855,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2062 "Python/bytecodes.c"
+ #line 2064 "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);
@@ -2868,7 +2870,7 @@
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
res = (sign_ish & oparg) ? Py_True : Py_False;
- #line 2872 "Python/generated_cases.c.h"
+ #line 2874 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2879,7 +2881,7 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *res;
- #line 2080 "Python/bytecodes.c"
+ #line 2082 "Python/bytecodes.c"
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
@@ -2891,7 +2893,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 2895 "Python/generated_cases.c.h"
+ #line 2897 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -2902,14 +2904,14 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2094 "Python/bytecodes.c"
+ #line 2096 "Python/bytecodes.c"
int res = Py_Is(left, right) ^ oparg;
- #line 2908 "Python/generated_cases.c.h"
+ #line 2910 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2096 "Python/bytecodes.c"
+ #line 2098 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 2913 "Python/generated_cases.c.h"
+ #line 2915 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2919,15 +2921,15 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2100 "Python/bytecodes.c"
+ #line 2102 "Python/bytecodes.c"
int res = PySequence_Contains(right, left);
- #line 2925 "Python/generated_cases.c.h"
+ #line 2927 "Python/generated_cases.c.h"
Py_DECREF(left);
Py_DECREF(right);
- #line 2102 "Python/bytecodes.c"
+ #line 2104 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
b = (res ^ oparg) ? Py_True : Py_False;
- #line 2931 "Python/generated_cases.c.h"
+ #line 2933 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = b;
DISPATCH();
@@ -2938,12 +2940,12 @@
PyObject *exc_value = stack_pointer[-2];
PyObject *rest;
PyObject *match;
- #line 2107 "Python/bytecodes.c"
+ #line 2109 "Python/bytecodes.c"
if (check_except_star_type_valid(tstate, match_type) < 0) {
- #line 2944 "Python/generated_cases.c.h"
+ #line 2946 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2109 "Python/bytecodes.c"
+ #line 2111 "Python/bytecodes.c"
if (true) goto pop_2_error;
}
@@ -2951,10 +2953,10 @@
rest = NULL;
int res = exception_group_match(exc_value, match_type,
&match, &rest);
- #line 2955 "Python/generated_cases.c.h"
+ #line 2957 "Python/generated_cases.c.h"
Py_DECREF(exc_value);
Py_DECREF(match_type);
- #line 2117 "Python/bytecodes.c"
+ #line 2119 "Python/bytecodes.c"
if (res < 0) goto pop_2_error;
assert((match == NULL) == (rest == NULL));
@@ -2963,7 +2965,7 @@
if (!Py_IsNone(match)) {
PyErr_SetHandledException(match);
}
- #line 2967 "Python/generated_cases.c.h"
+ #line 2969 "Python/generated_cases.c.h"
stack_pointer[-1] = match;
stack_pointer[-2] = rest;
DISPATCH();
@@ -2973,21 +2975,21 @@
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *b;
- #line 2128 "Python/bytecodes.c"
+ #line 2130 "Python/bytecodes.c"
assert(PyExceptionInstance_Check(left));
if (check_except_type_valid(tstate, right) < 0) {
- #line 2980 "Python/generated_cases.c.h"
+ #line 2982 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2131 "Python/bytecodes.c"
+ #line 2133 "Python/bytecodes.c"
if (true) goto pop_1_error;
}
int res = PyErr_GivenExceptionMatches(left, right);
- #line 2987 "Python/generated_cases.c.h"
+ #line 2989 "Python/generated_cases.c.h"
Py_DECREF(right);
- #line 2136 "Python/bytecodes.c"
+ #line 2138 "Python/bytecodes.c"
b = res ? Py_True : Py_False;
- #line 2991 "Python/generated_cases.c.h"
+ #line 2993 "Python/generated_cases.c.h"
stack_pointer[-1] = b;
DISPATCH();
}
@@ -2996,15 +2998,15 @@
PyObject *fromlist = stack_pointer[-1];
PyObject *level = stack_pointer[-2];
PyObject *res;
- #line 2140 "Python/bytecodes.c"
+ #line 2142 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
res = import_name(tstate, frame, name, fromlist, level);
- #line 3003 "Python/generated_cases.c.h"
+ #line 3005 "Python/generated_cases.c.h"
Py_DECREF(level);
Py_DECREF(fromlist);
- #line 2143 "Python/bytecodes.c"
+ #line 2145 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 3008 "Python/generated_cases.c.h"
+ #line 3010 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3013,29 +3015,29 @@
TARGET(IMPORT_FROM) {
PyObject *from = stack_pointer[-1];
PyObject *res;
- #line 2147 "Python/bytecodes.c"
+ #line 2149 "Python/bytecodes.c"
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
res = import_from(tstate, from, name);
if (res == NULL) goto error;
- #line 3021 "Python/generated_cases.c.h"
+ #line 3023 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
}
TARGET(JUMP_FORWARD) {
- #line 2153 "Python/bytecodes.c"
+ #line 2155 "Python/bytecodes.c"
JUMPBY(oparg);
- #line 3030 "Python/generated_cases.c.h"
+ #line 3032 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(JUMP_BACKWARD) {
PREDICTED(JUMP_BACKWARD);
- #line 2157 "Python/bytecodes.c"
+ #line 2159 "Python/bytecodes.c"
assert(oparg < INSTR_OFFSET());
JUMPBY(-oparg);
- #line 3039 "Python/generated_cases.c.h"
+ #line 3041 "Python/generated_cases.c.h"
CHECK_EVAL_BREAKER();
DISPATCH();
}
@@ -3043,15 +3045,15 @@
TARGET(POP_JUMP_IF_FALSE) {
PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = stack_pointer[-1];
- #line 2163 "Python/bytecodes.c"
+ #line 2165 "Python/bytecodes.c"
if (Py_IsFalse(cond)) {
JUMPBY(oparg);
}
else if (!Py_IsTrue(cond)) {
int err = PyObject_IsTrue(cond);
- #line 3053 "Python/generated_cases.c.h"
+ #line 3055 "Python/generated_cases.c.h"
Py_DECREF(cond);
- #line 2169 "Python/bytecodes.c"
+ #line 2171 "Python/bytecodes.c"
if (err == 0) {
JUMPBY(oparg);
}
@@ -3059,22 +3061,22 @@
if (err < 0) goto pop_1_error;
}
}
- #line 3063 "Python/generated_cases.c.h"
+ #line 3065 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_TRUE) {
PyObject *cond = stack_pointer[-1];
- #line 2179 "Python/bytecodes.c"
+ #line 2181 "Python/bytecodes.c"
if (Py_IsTrue(cond)) {
JUMPBY(oparg);
}
else if (!Py_IsFalse(cond)) {
int err = PyObject_IsTrue(cond);
- #line 3076 "Python/generated_cases.c.h"
+ #line 3078 "Python/generated_cases.c.h"
Py_DECREF(cond);
- #line 2185 "Python/bytecodes.c"
+ #line 2187 "Python/bytecodes.c"
if (err > 0) {
JUMPBY(oparg);
}
@@ -3082,63 +3084,63 @@
if (err < 0) goto pop_1_error;
}
}
- #line 3086 "Python/generated_cases.c.h"
+ #line 3088 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_NOT_NONE) {
PyObject *value = stack_pointer[-1];
- #line 2195 "Python/bytecodes.c"
+ #line 2197 "Python/bytecodes.c"
if (!Py_IsNone(value)) {
- #line 3095 "Python/generated_cases.c.h"
+ #line 3097 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 2197 "Python/bytecodes.c"
+ #line 2199 "Python/bytecodes.c"
JUMPBY(oparg);
}
- #line 3100 "Python/generated_cases.c.h"
+ #line 3102 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(POP_JUMP_IF_NONE) {
PyObject *value = stack_pointer[-1];
- #line 2202 "Python/bytecodes.c"
+ #line 2204 "Python/bytecodes.c"
if (Py_IsNone(value)) {
JUMPBY(oparg);
}
else {
- #line 3112 "Python/generated_cases.c.h"
+ #line 3114 "Python/generated_cases.c.h"
Py_DECREF(value);
- #line 2207 "Python/bytecodes.c"
+ #line 2209 "Python/bytecodes.c"
}
- #line 3116 "Python/generated_cases.c.h"
+ #line 3118 "Python/generated_cases.c.h"
STACK_SHRINK(1);
DISPATCH();
}
TARGET(JUMP_BACKWARD_NO_INTERRUPT) {
- #line 2211 "Python/bytecodes.c"
+ #line 2213 "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 3129 "Python/generated_cases.c.h"
+ #line 3131 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(GET_LEN) {
PyObject *obj = stack_pointer[-1];
PyObject *len_o;
- #line 2220 "Python/bytecodes.c"
+ #line 2222 "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 3142 "Python/generated_cases.c.h"
+ #line 3144 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = len_o;
DISPATCH();
@@ -3149,16 +3151,16 @@
PyObject *type = stack_pointer[-2];
PyObject *subject = stack_pointer[-3];
PyObject *attrs;
- #line 2228 "Python/bytecodes.c"
+ #line 2230 "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 3158 "Python/generated_cases.c.h"
+ #line 3160 "Python/generated_cases.c.h"
Py_DECREF(subject);
Py_DECREF(type);
Py_DECREF(names);
- #line 2233 "Python/bytecodes.c"
+ #line 2235 "Python/bytecodes.c"
if (attrs) {
assert(PyTuple_CheckExact(attrs)); // Success!
}
@@ -3166,7 +3168,7 @@
if (_PyErr_Occurred(tstate)) goto pop_3_error;
attrs = Py_None; // Failure!
}
- #line 3170 "Python/generated_cases.c.h"
+ #line 3172 "Python/generated_cases.c.h"
STACK_SHRINK(2);
stack_pointer[-1] = attrs;
DISPATCH();
@@ -3175,10 +3177,10 @@
TARGET(MATCH_MAPPING) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2243 "Python/bytecodes.c"
+ #line 2245 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
res = match ? Py_True : Py_False;
- #line 3182 "Python/generated_cases.c.h"
+ #line 3184 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
PREDICT(POP_JUMP_IF_FALSE);
@@ -3188,10 +3190,10 @@
TARGET(MATCH_SEQUENCE) {
PyObject *subject = stack_pointer[-1];
PyObject *res;
- #line 2249 "Python/bytecodes.c"
+ #line 2251 "Python/bytecodes.c"
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
res = match ? Py_True : Py_False;
- #line 3195 "Python/generated_cases.c.h"
+ #line 3197 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
PREDICT(POP_JUMP_IF_FALSE);
@@ -3202,11 +3204,11 @@
PyObject *keys = stack_pointer[-1];
PyObject *subject = stack_pointer[-2];
PyObject *values_or_none;
- #line 2255 "Python/bytecodes.c"
+ #line 2257 "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 3210 "Python/generated_cases.c.h"
+ #line 3212 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = values_or_none;
DISPATCH();
@@ -3215,14 +3217,14 @@
TARGET(GET_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2261 "Python/bytecodes.c"
+ #line 2263 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
iter = PyObject_GetIter(iterable);
- #line 3222 "Python/generated_cases.c.h"
+ #line 3224 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2264 "Python/bytecodes.c"
+ #line 2266 "Python/bytecodes.c"
if (iter == NULL) goto pop_1_error;
- #line 3226 "Python/generated_cases.c.h"
+ #line 3228 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
DISPATCH();
}
@@ -3230,7 +3232,7 @@
TARGET(GET_YIELD_FROM_ITER) {
PyObject *iterable = stack_pointer[-1];
PyObject *iter;
- #line 2268 "Python/bytecodes.c"
+ #line 2270 "Python/bytecodes.c"
/* before: [obj]; after [getiter(obj)] */
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
@@ -3253,11 +3255,11 @@
if (iter == NULL) {
goto error;
}
- #line 3257 "Python/generated_cases.c.h"
+ #line 3259 "Python/generated_cases.c.h"
Py_DECREF(iterable);
- #line 2291 "Python/bytecodes.c"
+ #line 2293 "Python/bytecodes.c"
}
- #line 3261 "Python/generated_cases.c.h"
+ #line 3263 "Python/generated_cases.c.h"
stack_pointer[-1] = iter;
PREDICT(LOAD_CONST);
DISPATCH();
@@ -3268,7 +3270,7 @@
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2310 "Python/bytecodes.c"
+ #line 2312 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyForIterCache *cache = (_PyForIterCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -3299,7 +3301,7 @@
DISPATCH();
}
// Common case: no jump, leave it to the code generator
- #line 3303 "Python/generated_cases.c.h"
+ #line 3305 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3307,7 +3309,7 @@
}
TARGET(INSTRUMENTED_FOR_ITER) {
- #line 2343 "Python/bytecodes.c"
+ #line 2345 "Python/bytecodes.c"
_Py_CODEUNIT *here = next_instr-1;
_Py_CODEUNIT *target;
PyObject *iter = TOP();
@@ -3333,14 +3335,14 @@
target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;
}
INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);
- #line 3337 "Python/generated_cases.c.h"
+ #line 3339 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(FOR_ITER_LIST) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2371 "Python/bytecodes.c"
+ #line 2373 "Python/bytecodes.c"
DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);
_PyListIterObject *it = (_PyListIterObject *)iter;
STAT_INC(FOR_ITER, hit);
@@ -3360,7 +3362,7 @@
DISPATCH();
end_for_iter_list:
// Common case: no jump, leave it to the code generator
- #line 3364 "Python/generated_cases.c.h"
+ #line 3366 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3370,7 +3372,7 @@
TARGET(FOR_ITER_TUPLE) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2393 "Python/bytecodes.c"
+ #line 2395 "Python/bytecodes.c"
_PyTupleIterObject *it = (_PyTupleIterObject *)iter;
DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);
STAT_INC(FOR_ITER, hit);
@@ -3390,7 +3392,7 @@
DISPATCH();
end_for_iter_tuple:
// Common case: no jump, leave it to the code generator
- #line 3394 "Python/generated_cases.c.h"
+ #line 3396 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3400,7 +3402,7 @@
TARGET(FOR_ITER_RANGE) {
PyObject *iter = stack_pointer[-1];
PyObject *next;
- #line 2415 "Python/bytecodes.c"
+ #line 2417 "Python/bytecodes.c"
_PyRangeIterObject *r = (_PyRangeIterObject *)iter;
DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
STAT_INC(FOR_ITER, hit);
@@ -3418,7 +3420,7 @@
if (next == NULL) {
goto error;
}
- #line 3422 "Python/generated_cases.c.h"
+ #line 3424 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = next;
next_instr += 1;
@@ -3427,7 +3429,7 @@
TARGET(FOR_ITER_GEN) {
PyObject *iter = stack_pointer[-1];
- #line 2435 "Python/bytecodes.c"
+ #line 2437 "Python/bytecodes.c"
DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);
PyGenObject *gen = (PyGenObject *)iter;
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER);
@@ -3443,14 +3445,14 @@
assert(next_instr[oparg].op.code == END_FOR ||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
DISPATCH_INLINED(gen_frame);
- #line 3447 "Python/generated_cases.c.h"
+ #line 3449 "Python/generated_cases.c.h"
}
TARGET(BEFORE_ASYNC_WITH) {
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2453 "Python/bytecodes.c"
+ #line 2455 "Python/bytecodes.c"
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
if (enter == NULL) {
if (!_PyErr_Occurred(tstate)) {
@@ -3473,16 +3475,16 @@
Py_DECREF(enter);
goto error;
}
- #line 3477 "Python/generated_cases.c.h"
+ #line 3479 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2476 "Python/bytecodes.c"
+ #line 2478 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3486 "Python/generated_cases.c.h"
+ #line 3488 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3494,7 +3496,7 @@
PyObject *mgr = stack_pointer[-1];
PyObject *exit;
PyObject *res;
- #line 2486 "Python/bytecodes.c"
+ #line 2488 "Python/bytecodes.c"
/* pop the context manager, push its __exit__ and the
* value returned from calling its __enter__
*/
@@ -3520,16 +3522,16 @@
Py_DECREF(enter);
goto error;
}
- #line 3524 "Python/generated_cases.c.h"
+ #line 3526 "Python/generated_cases.c.h"
Py_DECREF(mgr);
- #line 2512 "Python/bytecodes.c"
+ #line 2514 "Python/bytecodes.c"
res = _PyObject_CallNoArgs(enter);
Py_DECREF(enter);
if (res == NULL) {
Py_DECREF(exit);
if (true) goto pop_1_error;
}
- #line 3533 "Python/generated_cases.c.h"
+ #line 3535 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
stack_pointer[-2] = exit;
@@ -3541,7 +3543,7 @@
PyObject *lasti = stack_pointer[-3];
PyObject *exit_func = stack_pointer[-4];
PyObject *res;
- #line 2521 "Python/bytecodes.c"
+ #line 2523 "Python/bytecodes.c"
/* At the top of the stack are 4 values:
- val: TOP = exc_info()
- unused: SECOND = previous exception
@@ -3567,7 +3569,7 @@
res = PyObject_Vectorcall(exit_func, stack + 1,
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
if (res == NULL) goto error;
- #line 3571 "Python/generated_cases.c.h"
+ #line 3573 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = res;
DISPATCH();
@@ -3576,7 +3578,7 @@
TARGET(PUSH_EXC_INFO) {
PyObject *new_exc = stack_pointer[-1];
PyObject *prev_exc;
- #line 2549 "Python/bytecodes.c"
+ #line 2551 "Python/bytecodes.c"
_PyErr_StackItem *exc_info = tstate->exc_info;
if (exc_info->exc_value != NULL) {
prev_exc = exc_info->exc_value;
@@ -3586,7 +3588,7 @@
}
assert(PyExceptionInstance_Check(new_exc));
exc_info->exc_value = Py_NewRef(new_exc);
- #line 3590 "Python/generated_cases.c.h"
+ #line 3592 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = new_exc;
stack_pointer[-2] = prev_exc;
@@ -3600,7 +3602,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 2561 "Python/bytecodes.c"
+ #line 2563 "Python/bytecodes.c"
/* Cached method object */
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
@@ -3617,7 +3619,7 @@
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
res = self;
assert(oparg & 1);
- #line 3621 "Python/generated_cases.c.h"
+ #line 3623 "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; }
@@ -3631,7 +3633,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2580 "Python/bytecodes.c"
+ #line 2582 "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);
@@ -3641,7 +3643,7 @@
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
- #line 3645 "Python/generated_cases.c.h"
+ #line 3647 "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; }
@@ -3655,7 +3657,7 @@
PyObject *res;
uint32_t type_version = read_u32(&next_instr[1].cache);
PyObject *descr = read_obj(&next_instr[5].cache);
- #line 2592 "Python/bytecodes.c"
+ #line 2594 "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;
@@ -3669,7 +3671,7 @@
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
- #line 3673 "Python/generated_cases.c.h"
+ #line 3675 "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; }
@@ -3678,16 +3680,16 @@
}
TARGET(KW_NAMES) {
- #line 2608 "Python/bytecodes.c"
+ #line 2610 "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 3686 "Python/generated_cases.c.h"
+ #line 3688 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_CALL) {
- #line 2614 "Python/bytecodes.c"
+ #line 2616 "Python/bytecodes.c"
int is_meth = PEEK(oparg+2) != NULL;
int total_args = oparg + is_meth;
PyObject *function = PEEK(total_args + 1);
@@ -3700,7 +3702,7 @@
_PyCallCache *cache = (_PyCallCache *)next_instr;
INCREMENT_ADAPTIVE_COUNTER(cache->counter);
GO_TO_INSTRUCTION(CALL);
- #line 3704 "Python/generated_cases.c.h"
+ #line 3706 "Python/generated_cases.c.h"
}
TARGET(CALL) {
@@ -3710,7 +3712,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2659 "Python/bytecodes.c"
+ #line 2661 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -3792,7 +3794,7 @@
Py_DECREF(args[i]);
}
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3796 "Python/generated_cases.c.h"
+ #line 3798 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3804,7 +3806,7 @@
TARGET(CALL_BOUND_METHOD_EXACT_ARGS) {
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 2747 "Python/bytecodes.c"
+ #line 2749 "Python/bytecodes.c"
DEOPT_IF(method != NULL, CALL);
DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);
STAT_INC(CALL, hit);
@@ -3814,7 +3816,7 @@
PEEK(oparg + 2) = Py_NewRef(meth); // method
Py_DECREF(callable);
GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);
- #line 3818 "Python/generated_cases.c.h"
+ #line 3820 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_EXACT_ARGS) {
@@ -3823,7 +3825,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2759 "Python/bytecodes.c"
+ #line 2761 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3849,7 +3851,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3853 "Python/generated_cases.c.h"
+ #line 3855 "Python/generated_cases.c.h"
}
TARGET(CALL_PY_WITH_DEFAULTS) {
@@ -3857,7 +3859,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
uint32_t func_version = read_u32(&next_instr[1].cache);
- #line 2787 "Python/bytecodes.c"
+ #line 2789 "Python/bytecodes.c"
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
@@ -3893,7 +3895,7 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
frame->return_offset = 0;
DISPATCH_INLINED(new_frame);
- #line 3897 "Python/generated_cases.c.h"
+ #line 3899 "Python/generated_cases.c.h"
}
TARGET(CALL_NO_KW_TYPE_1) {
@@ -3901,7 +3903,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2825 "Python/bytecodes.c"
+ #line 2827 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3911,7 +3913,7 @@
res = Py_NewRef(Py_TYPE(obj));
Py_DECREF(obj);
Py_DECREF(&PyType_Type); // I.e., callable
- #line 3915 "Python/generated_cases.c.h"
+ #line 3917 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3924,7 +3926,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2837 "Python/bytecodes.c"
+ #line 2839 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3935,7 +3937,7 @@
Py_DECREF(arg);
Py_DECREF(&PyUnicode_Type); // I.e., callable
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3939 "Python/generated_cases.c.h"
+ #line 3941 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3949,7 +3951,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *null = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2851 "Python/bytecodes.c"
+ #line 2853 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
@@ -3960,7 +3962,7 @@
Py_DECREF(arg);
Py_DECREF(&PyTuple_Type); // I.e., tuple
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 3964 "Python/generated_cases.c.h"
+ #line 3966 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -3974,7 +3976,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2865 "Python/bytecodes.c"
+ #line 2867 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -3996,7 +3998,7 @@
}
Py_DECREF(tp);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4000 "Python/generated_cases.c.h"
+ #line 4002 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4010,7 +4012,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2890 "Python/bytecodes.c"
+ #line 2892 "Python/bytecodes.c"
/* Builtin METH_O functions */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4038,7 +4040,7 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4042 "Python/generated_cases.c.h"
+ #line 4044 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4052,7 +4054,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2921 "Python/bytecodes.c"
+ #line 2923 "Python/bytecodes.c"
/* Builtin METH_FASTCALL functions, without keywords */
assert(kwnames == NULL);
int is_meth = method != NULL;
@@ -4084,7 +4086,7 @@
'invalid'). In those cases an exception is set, so we must
handle it.
*/
- #line 4088 "Python/generated_cases.c.h"
+ #line 4090 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4098,7 +4100,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2956 "Python/bytecodes.c"
+ #line 2958 "Python/bytecodes.c"
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
int is_meth = method != NULL;
int total_args = oparg;
@@ -4130,7 +4132,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4134 "Python/generated_cases.c.h"
+ #line 4136 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4144,7 +4146,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 2991 "Python/bytecodes.c"
+ #line 2993 "Python/bytecodes.c"
assert(kwnames == NULL);
/* len(o) */
int is_meth = method != NULL;
@@ -4169,7 +4171,7 @@
Py_DECREF(callable);
Py_DECREF(arg);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4173 "Python/generated_cases.c.h"
+ #line 4175 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4182,7 +4184,7 @@
PyObject *callable = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3018 "Python/bytecodes.c"
+ #line 3020 "Python/bytecodes.c"
assert(kwnames == NULL);
/* isinstance(o, o2) */
int is_meth = method != NULL;
@@ -4209,7 +4211,7 @@
Py_DECREF(cls);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4213 "Python/generated_cases.c.h"
+ #line 4215 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4221,7 +4223,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *self = stack_pointer[-(1 + oparg)];
PyObject *method = stack_pointer[-(2 + oparg)];
- #line 3048 "Python/bytecodes.c"
+ #line 3050 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 1);
PyInterpreterState *interp = _PyInterpreterState_GET();
@@ -4239,14 +4241,14 @@
JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
assert(next_instr[-1].op.code == POP_TOP);
DISPATCH();
- #line 4243 "Python/generated_cases.c.h"
+ #line 4245 "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 3068 "Python/bytecodes.c"
+ #line 3070 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4277,7 +4279,7 @@
Py_DECREF(arg);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4281 "Python/generated_cases.c.h"
+ #line 4283 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4290,7 +4292,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3102 "Python/bytecodes.c"
+ #line 3104 "Python/bytecodes.c"
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
@@ -4319,7 +4321,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4323 "Python/generated_cases.c.h"
+ #line 4325 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4332,7 +4334,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3134 "Python/bytecodes.c"
+ #line 3136 "Python/bytecodes.c"
assert(kwnames == NULL);
assert(oparg == 0 || oparg == 1);
int is_meth = method != NULL;
@@ -4361,7 +4363,7 @@
Py_DECREF(self);
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4365 "Python/generated_cases.c.h"
+ #line 4367 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4374,7 +4376,7 @@
PyObject **args = (stack_pointer - oparg);
PyObject *method = stack_pointer[-(2 + oparg)];
PyObject *res;
- #line 3166 "Python/bytecodes.c"
+ #line 3168 "Python/bytecodes.c"
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
@@ -4402,7 +4404,7 @@
}
Py_DECREF(callable);
if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
- #line 4406 "Python/generated_cases.c.h"
+ #line 4408 "Python/generated_cases.c.h"
STACK_SHRINK(oparg);
STACK_SHRINK(1);
stack_pointer[-1] = res;
@@ -4412,9 +4414,9 @@
}
TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {
- #line 3197 "Python/bytecodes.c"
+ #line 3199 "Python/bytecodes.c"
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
- #line 4418 "Python/generated_cases.c.h"
+ #line 4420 "Python/generated_cases.c.h"
}
TARGET(CALL_FUNCTION_EX) {
@@ -4423,7 +4425,7 @@
PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))];
PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))];
PyObject *result;
- #line 3201 "Python/bytecodes.c"
+ #line 3203 "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));
@@ -4485,14 +4487,14 @@
}
result = PyObject_Call(func, callargs, kwargs);
}
- #line 4489 "Python/generated_cases.c.h"
+ #line 4491 "Python/generated_cases.c.h"
Py_DECREF(func);
Py_DECREF(callargs);
Py_XDECREF(kwargs);
- #line 3263 "Python/bytecodes.c"
+ #line 3265 "Python/bytecodes.c"
assert(PEEK(3 + (oparg & 1)) == NULL);
if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; }
- #line 4496 "Python/generated_cases.c.h"
+ #line 4498 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg & 1) ? 1 : 0));
STACK_SHRINK(2);
stack_pointer[-1] = result;
@@ -4507,7 +4509,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 3273 "Python/bytecodes.c"
+ #line 3275 "Python/bytecodes.c"
PyFunctionObject *func_obj = (PyFunctionObject *)
PyFunction_New(codeobj, GLOBALS());
@@ -4536,14 +4538,14 @@
func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;
func = (PyObject *)func_obj;
- #line 4540 "Python/generated_cases.c.h"
+ #line 4542 "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 3304 "Python/bytecodes.c"
+ #line 3306 "Python/bytecodes.c"
assert(PyFunction_Check(frame->f_funcobj));
PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
@@ -4564,7 +4566,7 @@
frame = cframe.current_frame = prev;
_PyFrame_StackPush(frame, (PyObject *)gen);
goto resume_frame;
- #line 4568 "Python/generated_cases.c.h"
+ #line 4570 "Python/generated_cases.c.h"
}
TARGET(BUILD_SLICE) {
@@ -4572,15 +4574,15 @@
PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))];
PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))];
PyObject *slice;
- #line 3327 "Python/bytecodes.c"
+ #line 3329 "Python/bytecodes.c"
slice = PySlice_New(start, stop, step);
- #line 4578 "Python/generated_cases.c.h"
+ #line 4580 "Python/generated_cases.c.h"
Py_DECREF(start);
Py_DECREF(stop);
Py_XDECREF(step);
- #line 3329 "Python/bytecodes.c"
+ #line 3331 "Python/bytecodes.c"
if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; }
- #line 4584 "Python/generated_cases.c.h"
+ #line 4586 "Python/generated_cases.c.h"
STACK_SHRINK(((oparg == 3) ? 1 : 0));
STACK_SHRINK(1);
stack_pointer[-1] = slice;
@@ -4591,7 +4593,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 3333 "Python/bytecodes.c"
+ #line 3335 "Python/bytecodes.c"
/* Handles f-string value formatting. */
PyObject *(*conv_fn)(PyObject *);
int which_conversion = oparg & FVC_MASK;
@@ -4626,7 +4628,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 4630 "Python/generated_cases.c.h"
+ #line 4632 "Python/generated_cases.c.h"
STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));
stack_pointer[-1] = result;
DISPATCH();
@@ -4635,10 +4637,10 @@
TARGET(COPY) {
PyObject *bottom = stack_pointer[-(1 + (oparg-1))];
PyObject *top;
- #line 3370 "Python/bytecodes.c"
+ #line 3372 "Python/bytecodes.c"
assert(oparg > 0);
top = Py_NewRef(bottom);
- #line 4642 "Python/generated_cases.c.h"
+ #line 4644 "Python/generated_cases.c.h"
STACK_GROW(1);
stack_pointer[-1] = top;
DISPATCH();
@@ -4650,7 +4652,7 @@
PyObject *rhs = stack_pointer[-1];
PyObject *lhs = stack_pointer[-2];
PyObject *res;
- #line 3375 "Python/bytecodes.c"
+ #line 3377 "Python/bytecodes.c"
#if ENABLE_SPECIALIZATION
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -4665,12 +4667,12 @@
assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
assert(binary_ops[oparg]);
res = binary_ops[oparg](lhs, rhs);
- #line 4669 "Python/generated_cases.c.h"
+ #line 4671 "Python/generated_cases.c.h"
Py_DECREF(lhs);
Py_DECREF(rhs);
- #line 3390 "Python/bytecodes.c"
+ #line 3392 "Python/bytecodes.c"
if (res == NULL) goto pop_2_error;
- #line 4674 "Python/generated_cases.c.h"
+ #line 4676 "Python/generated_cases.c.h"
STACK_SHRINK(1);
stack_pointer[-1] = res;
next_instr += 1;
@@ -4680,16 +4682,16 @@
TARGET(SWAP) {
PyObject *top = stack_pointer[-1];
PyObject *bottom = stack_pointer[-(2 + (oparg-2))];
- #line 3395 "Python/bytecodes.c"
+ #line 3397 "Python/bytecodes.c"
assert(oparg >= 2);
- #line 4686 "Python/generated_cases.c.h"
+ #line 4688 "Python/generated_cases.c.h"
stack_pointer[-1] = bottom;
stack_pointer[-(2 + (oparg-2))] = top;
DISPATCH();
}
TARGET(INSTRUMENTED_INSTRUCTION) {
- #line 3399 "Python/bytecodes.c"
+ #line 3401 "Python/bytecodes.c"
int next_opcode = _Py_call_instrumentation_instruction(
tstate, frame, next_instr-1);
if (next_opcode < 0) goto error;
@@ -4701,26 +4703,26 @@
assert(next_opcode > 0 && next_opcode < 256);
opcode = next_opcode;
DISPATCH_GOTO();
- #line 4705 "Python/generated_cases.c.h"
+ #line 4707 "Python/generated_cases.c.h"
}
TARGET(INSTRUMENTED_JUMP_FORWARD) {
- #line 3413 "Python/bytecodes.c"
+ #line 3415 "Python/bytecodes.c"
INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP);
- #line 4711 "Python/generated_cases.c.h"
+ #line 4713 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_JUMP_BACKWARD) {
- #line 3417 "Python/bytecodes.c"
+ #line 3419 "Python/bytecodes.c"
INSTRUMENTED_JUMP(next_instr-1, next_instr-oparg, PY_MONITORING_EVENT_JUMP);
- #line 4718 "Python/generated_cases.c.h"
+ #line 4720 "Python/generated_cases.c.h"
CHECK_EVAL_BREAKER();
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) {
- #line 3422 "Python/bytecodes.c"
+ #line 3424 "Python/bytecodes.c"
PyObject *cond = POP();
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
@@ -4729,12 +4731,12 @@
assert(err == 0 || err == 1);
int offset = err*oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4733 "Python/generated_cases.c.h"
+ #line 4735 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) {
- #line 3433 "Python/bytecodes.c"
+ #line 3435 "Python/bytecodes.c"
PyObject *cond = POP();
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
@@ -4743,12 +4745,12 @@
assert(err == 0 || err == 1);
int offset = (1-err)*oparg;
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4747 "Python/generated_cases.c.h"
+ #line 4749 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) {
- #line 3444 "Python/bytecodes.c"
+ #line 3446 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4760,12 +4762,12 @@
offset = 0;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4764 "Python/generated_cases.c.h"
+ #line 4766 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) {
- #line 3458 "Python/bytecodes.c"
+ #line 3460 "Python/bytecodes.c"
PyObject *value = POP();
_Py_CODEUNIT *here = next_instr-1;
int offset;
@@ -4777,30 +4779,30 @@
offset = oparg;
}
INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);
- #line 4781 "Python/generated_cases.c.h"
+ #line 4783 "Python/generated_cases.c.h"
DISPATCH();
}
TARGET(EXTENDED_ARG) {
- #line 3472 "Python/bytecodes.c"
+ #line 3474 "Python/bytecodes.c"
assert(oparg);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
PRE_DISPATCH_GOTO();
DISPATCH_GOTO();
- #line 4792 "Python/generated_cases.c.h"
+ #line 4794 "Python/generated_cases.c.h"
}
TARGET(CACHE) {
- #line 3480 "Python/bytecodes.c"
+ #line 3482 "Python/bytecodes.c"
assert(0 && "Executing a cache.");
Py_UNREACHABLE();
- #line 4799 "Python/generated_cases.c.h"
+ #line 4801 "Python/generated_cases.c.h"
}
TARGET(RESERVED) {
- #line 3485 "Python/bytecodes.c"
+ #line 3487 "Python/bytecodes.c"
assert(0 && "Executing RESERVED instruction.");
Py_UNREACHABLE();
- #line 4806 "Python/generated_cases.c.h"
+ #line 4808 "Python/generated_cases.c.h"
}
1
0

03 Jun '24
https://github.com/python/cpython/commit/ca37034baa2909722df58c02dfd13e1d66…
commit: ca37034baa2909722df58c02dfd13e1d667252ce
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-03T18:07:22Z
summary:
[3.13] gh-117657: Avoid `sem_clockwait` in TSAN (GH-119915) (#119992)
The `sem_clockwait` function is not currently instrumented, which leads
to false positives.
(cherry picked from commit 41c1cefbae71d687d1a935233b086473df65e15c)
Co-authored-by: Sam Gross <colesbury(a)gmail.com>
files:
M Python/parking_lot.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Python/parking_lot.c b/Python/parking_lot.c
index e2def9e249cd56..841b1d71ea16cb 100644
--- a/Python/parking_lot.c
+++ b/Python/parking_lot.c
@@ -119,7 +119,7 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
if (timeout >= 0) {
struct timespec ts;
-#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT)
+#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT) && !defined(_Py_THREAD_SANITIZER)
PyTime_t now;
// silently ignore error: cannot report error to the caller
(void)PyTime_MonotonicRaw(&now);
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index 60839e636a654c..d150e901945073 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -15,14 +15,10 @@ race:set_allocator_unlocked
# These entries are for warnings that trigger in a library function, as called
# by a CPython function.
-# https://gist.github.com/swtaarrs/9d41251e603fa6dedd604191a6da820d
-race:park_detached_threads
# https://gist.github.com/swtaarrs/8e0e365e1d9cecece3269a2fb2f2b8b8
race:sock_recv_impl
# https://gist.github.com/swtaarrs/08dfe7883b4c975c31ecb39388987a67
race:free_threadstate
-# https://gist.github.com/swtaarrs/cd6aec2006e0c1b561b68d65e9f1a872
-race:_PyParkingLot_Park
# These warnings trigger directly in a CPython function.
@@ -33,8 +29,6 @@ race_top:_mi_heap_delayed_free_partial
race_top:_PyEval_EvalFrameDefault
race_top:_PyImport_AcquireLock
race_top:_PyImport_ReleaseLock
-# https://gist.github.com/mpage/0a24eb2dd458441ededb498e9b0e5de8
-race_top:_PyParkingLot_Park
race_top:_PyType_HasFeature
race_top:assign_version_tag
race_top:insertdict
@@ -47,8 +41,6 @@ race_top:set_contains_key
# https://gist.github.com/colesbury/d13d033f413b4ad07929d044bed86c35
race_top:set_discard_entry
race_top:set_inheritable
-race_top:start_the_world
-race_top:tstate_set_detached
race_top:Py_SET_TYPE
race_top:_PyDict_CheckConsistency
race_top:_PyImport_AcquireLock
@@ -65,7 +57,6 @@ race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
race_top:should_intern_string
-race_top:llist_insert_tail
race_top:_Py_slot_tp_getattr_hook
race_top:add_threadstate
race_top:dump_traceback
1
0
https://github.com/python/cpython/commit/41c1cefbae71d687d1a935233b086473df…
commit: 41c1cefbae71d687d1a935233b086473df65e15c
branch: main
author: Sam Gross <colesbury(a)gmail.com>
committer: colesbury <colesbury(a)gmail.com>
date: 2024-06-03T13:42:27-04:00
summary:
gh-117657: Avoid `sem_clockwait` in TSAN (#119915)
The `sem_clockwait` function is not currently instrumented, which leads
to false positives.
files:
M Python/parking_lot.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Python/parking_lot.c b/Python/parking_lot.c
index e2def9e249cd56..841b1d71ea16cb 100644
--- a/Python/parking_lot.c
+++ b/Python/parking_lot.c
@@ -119,7 +119,7 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
if (timeout >= 0) {
struct timespec ts;
-#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT)
+#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT) && !defined(_Py_THREAD_SANITIZER)
PyTime_t now;
// silently ignore error: cannot report error to the caller
(void)PyTime_MonotonicRaw(&now);
diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt
index ff9c8036e92fe7..39cc5b080c8703 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -15,14 +15,10 @@ race:set_allocator_unlocked
# These entries are for warnings that trigger in a library function, as called
# by a CPython function.
-# https://gist.github.com/swtaarrs/9d41251e603fa6dedd604191a6da820d
-race:park_detached_threads
# https://gist.github.com/swtaarrs/8e0e365e1d9cecece3269a2fb2f2b8b8
race:sock_recv_impl
# https://gist.github.com/swtaarrs/08dfe7883b4c975c31ecb39388987a67
race:free_threadstate
-# https://gist.github.com/swtaarrs/cd6aec2006e0c1b561b68d65e9f1a872
-race:_PyParkingLot_Park
# These warnings trigger directly in a CPython function.
@@ -33,8 +29,6 @@ race_top:_mi_heap_delayed_free_partial
race_top:_PyEval_EvalFrameDefault
race_top:_PyImport_AcquireLock
race_top:_PyImport_ReleaseLock
-# https://gist.github.com/mpage/0a24eb2dd458441ededb498e9b0e5de8
-race_top:_PyParkingLot_Park
race_top:_PyType_HasFeature
race_top:assign_version_tag
race_top:insertdict
@@ -47,8 +41,6 @@ race_top:set_contains_key
# https://gist.github.com/colesbury/d13d033f413b4ad07929d044bed86c35
race_top:set_discard_entry
race_top:set_inheritable
-race_top:start_the_world
-race_top:tstate_set_detached
race_top:Py_SET_TYPE
race_top:_PyDict_CheckConsistency
race_top:_PyImport_AcquireLock
@@ -64,7 +56,6 @@ race_top:list_get_item_ref
race_top:make_pending_calls
race_top:set_add_entry
race_top:should_intern_string
-race_top:llist_insert_tail
race_top:_Py_slot_tp_getattr_hook
race_top:add_threadstate
race_top:dump_traceback
1
0