]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-122320: Limit dict key versions used by test_opcache. (gh-132961)
authorNeil Schemenauer <nas-github@arctrix.com>
Mon, 28 Apr 2025 19:54:55 +0000 (12:54 -0700)
committerGitHub <noreply@github.com>
Mon, 28 Apr 2025 19:54:55 +0000 (12:54 -0700)
The `test_load_global_module()` test consumes a lot of dict key versions.
Skip the test if we have consumed half of the available versions that can be
used for the "load global" cache.

Lib/test/test_opcache.py
Modules/_testinternalcapi.c
Modules/clinic/_testinternalcapi.c.h

index ac132465b227ad8b00924d8dc6ee518c10d51d9d..21d7e62833c061b99af261539c30e695045b284a 100644 (file)
@@ -16,6 +16,16 @@ if check_impl_detail(cpython=False):
 _testinternalcapi = import_module("_testinternalcapi")
 
 
+def have_dict_key_versions():
+    # max version value that can be stored in the load global cache. This is
+    # determined by the type of module_keys_version and builtin_keys_version
+    # in _PyLoadGlobalCache, uint16_t.
+    max_version = 1<<16
+    # use a wide safety margin (use only half of what's available)
+    limit = max_version // 2
+    return _testinternalcapi.get_next_dict_keys_version() < limit
+
+
 class TestBase(unittest.TestCase):
     def assert_specialized(self, f, opname):
         instructions = dis.get_instructions(f, adaptive=True)
@@ -1029,6 +1039,8 @@ class TestRacesDoNotCrash(TestBase):
 
     @requires_specialization_ft
     def test_load_global_module(self):
+        if not have_dict_key_versions():
+            raise unittest.SkipTest("Low on dict key versions")
         def get_items():
             items = []
             for _ in range(self.ITEMS):
index 99dca9f77df6becc2473ec3cd0aa7610aebda588..353cb630513abc322fca6fb579d54bfc8d4850c9 100644 (file)
@@ -1985,6 +1985,18 @@ gh_119213_getargs_impl(PyObject *module, PyObject *spam)
     return Py_NewRef(spam);
 }
 
+/*[clinic input]
+get_next_dict_keys_version
+[clinic start generated code]*/
+
+static PyObject *
+get_next_dict_keys_version_impl(PyObject *module)
+/*[clinic end generated code: output=e5405a509cf9d423 input=bd1cee7c6b9d3a3c]*/
+{
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    uint32_t keys_version = interp->dict_state.next_keys_version;
+    return PyLong_FromLong(keys_version);
+}
 
 static PyObject *
 get_static_builtin_types(PyObject *self, PyObject *Py_UNUSED(ignored))
@@ -2124,6 +2136,7 @@ static PyMethodDef module_functions[] = {
     {"get_tracked_heap_size", get_tracked_heap_size, METH_NOARGS},
     {"is_static_immortal", is_static_immortal, METH_O},
     {"incref_decref_delayed", incref_decref_delayed, METH_O},
+    GET_NEXT_DICT_KEYS_VERSION_METHODDEF
     {NULL, NULL} /* sentinel */
 };
 
index 7dfc16965cc0d881e7e151a8da8d2e2989f793db..21f4ee3201e5bf3c33fe47d28f6c3fc4f9ab9605 100644 (file)
@@ -375,4 +375,21 @@ skip_optional_pos:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=da34166d2c147e7a input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(get_next_dict_keys_version__doc__,
+"get_next_dict_keys_version($module, /)\n"
+"--\n"
+"\n");
+
+#define GET_NEXT_DICT_KEYS_VERSION_METHODDEF    \
+    {"get_next_dict_keys_version", (PyCFunction)get_next_dict_keys_version, METH_NOARGS, get_next_dict_keys_version__doc__},
+
+static PyObject *
+get_next_dict_keys_version_impl(PyObject *module);
+
+static PyObject *
+get_next_dict_keys_version(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return get_next_dict_keys_version_impl(module);
+}
+/*[clinic end generated code: output=fbd8b7e0cae8bac7 input=a9049054013a1b77]*/