Skip to content

Commit 4caa222

Browse files
committed
address review: thread safe, parameterize test
1 parent a7e785b commit 4caa222

2 files changed

Lines changed: 44 additions & 22 deletions

File tree

‎Lib/test/test_listcomps.py‎

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -948,18 +948,29 @@ def test_frame_locals_dedup_learned_before_cell_is_bound(self):
948948
# Reading f_locals before the comprehension cell is bound must not
949949
# cache "names are unique": the repeated name is still on the code
950950
# object, and dict(**f_locals) inside the comprehension has to work.
951-
code = """
952-
def outer(x):
953-
def inner():
954-
list(sys._getframe().f_locals)
955-
return [dict(**sys._getframe().f_locals)['x'] for x in x]
956-
return inner()
957-
result = outer([7, 8])
958-
"""
951+
# Each API initializes the cache on its own code object. list(proxy)
952+
# goes through keys() first, so it does not cover the others.
953+
probes = {
954+
"keys": "list(sys._getframe().f_locals.keys())",
955+
"values": "list(sys._getframe().f_locals.values())",
956+
"items": "list(sys._getframe().f_locals.items())",
957+
"len": "len(sys._getframe().f_locals)",
958+
}
959959
import sys
960-
self._check_in_scopes(
961-
code, {"result": [7, 8]},
962-
ns={"sys": sys}, scopes=["module", "function"])
960+
for name, probe in probes.items():
961+
with self.subTest(probe=name):
962+
code = f"""
963+
def outer(x):
964+
def inner():
965+
{probe}
966+
return [dict(**sys._getframe().f_locals)['x']
967+
for x in x]
968+
return inner()
969+
result = outer([7, 8])
970+
"""
971+
self._check_in_scopes(
972+
code, {"result": [7, 8]},
973+
ns={"sys": sys}, scopes=["module", "function"])
963974

964975
def test_frame_locals_nested_comp_cell_and_enclosing_free(self):
965976
# Stress a nested inlined shape where a comp cell and enclosing free

‎Objects/frameobject.c‎

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ static int
104104
framelocalsproxy_prepare_dedup(PyCodeObject *co, PyObject **seen)
105105
{
106106
*seen = NULL;
107-
if (co->_co_localsplus_dedup == _PYCODE_LOCALSPLUS_DEDUP_UNIQUE) {
107+
if (FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) ==
108+
_PYCODE_LOCALSPLUS_DEDUP_UNIQUE) {
108109
return 0;
109110
}
110111
*seen = PyDict_New();
@@ -126,7 +127,8 @@ framelocalsproxy_visit_name(PyCodeObject *co, int i, PyObject *seen,
126127
return has_value;
127128
}
128129
if (!has_value &&
129-
co->_co_localsplus_dedup != _PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
130+
FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) !=
131+
_PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
130132
return 0;
131133
}
132134
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
@@ -141,7 +143,8 @@ framelocalsproxy_visit_name(PyCodeObject *co, int i, PyObject *seen,
141143
return has_value;
142144
}
143145
else {
144-
co->_co_localsplus_dedup = _PYCODE_LOCALSPLUS_DEDUP_NEEDED;
146+
FT_ATOMIC_STORE_CHAR_RELAXED(co->_co_localsplus_dedup,
147+
_PYCODE_LOCALSPLUS_DEDUP_NEEDED);
145148
if (!has_value || prev == Py_True) {
146149
return 0;
147150
}
@@ -459,8 +462,10 @@ framelocalsproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored))
459462
}
460463
}
461464
}
462-
if (co->_co_localsplus_dedup == _PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
463-
co->_co_localsplus_dedup = _PYCODE_LOCALSPLUS_DEDUP_UNIQUE;
465+
if (FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) ==
466+
_PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
467+
FT_ATOMIC_STORE_CHAR_RELAXED(co->_co_localsplus_dedup,
468+
_PYCODE_LOCALSPLUS_DEDUP_UNIQUE);
464469
}
465470
Py_XDECREF(seen);
466471

@@ -687,8 +692,10 @@ framelocalsproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored))
687692
}
688693
Py_XDECREF(value);
689694
}
690-
if (co->_co_localsplus_dedup == _PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
691-
co->_co_localsplus_dedup = _PYCODE_LOCALSPLUS_DEDUP_UNIQUE;
695+
if (FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) ==
696+
_PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
697+
FT_ATOMIC_STORE_CHAR_RELAXED(co->_co_localsplus_dedup,
698+
_PYCODE_LOCALSPLUS_DEDUP_UNIQUE);
692699
}
693700
Py_XDECREF(seen);
694701

@@ -749,8 +756,10 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
749756
goto error;
750757
}
751758
}
752-
if (co->_co_localsplus_dedup == _PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
753-
co->_co_localsplus_dedup = _PYCODE_LOCALSPLUS_DEDUP_UNIQUE;
759+
if (FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) ==
760+
_PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
761+
FT_ATOMIC_STORE_CHAR_RELAXED(co->_co_localsplus_dedup,
762+
_PYCODE_LOCALSPLUS_DEDUP_UNIQUE);
754763
}
755764
Py_XDECREF(seen);
756765
seen = NULL;
@@ -807,8 +816,10 @@ framelocalsproxy_length(PyObject *self)
807816
size++;
808817
}
809818
}
810-
if (co->_co_localsplus_dedup == _PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
811-
co->_co_localsplus_dedup = _PYCODE_LOCALSPLUS_DEDUP_UNIQUE;
819+
if (FT_ATOMIC_LOAD_CHAR_RELAXED(co->_co_localsplus_dedup) ==
820+
_PYCODE_LOCALSPLUS_DEDUP_UNKNOWN) {
821+
FT_ATOMIC_STORE_CHAR_RELAXED(co->_co_localsplus_dedup,
822+
_PYCODE_LOCALSPLUS_DEDUP_UNIQUE);
812823
}
813824
Py_XDECREF(seen);
814825
return size;

0 commit comments

Comments
 (0)