Skip to content

Commit 358199a

Browse files
committed
Address reviewer comments, and drop test_iteration_deopt.
1 parent 1781cad commit 358199a

File tree

10 files changed

+37
-180
lines changed

10 files changed

+37
-180
lines changed

Include/internal/pycore_list.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
#ifdef Py_GIL_DISABLED
12+
#include "pycore_stackref.h"
13+
#endif
14+
1115
PyAPI_FUNC(PyObject*) _PyList_Extend(PyListObject *, PyObject *);
1216
extern void _PyList_DebugMallocStats(FILE *out);
1317
// _PyList_GetItemRef should be used only when the object is known as a list
1418
// because it doesn't raise TypeError when the object is not a list, whereas PyList_GetItemRef does.
1519
extern PyObject* _PyList_GetItemRef(PyListObject *, Py_ssize_t i);
1620
#ifdef Py_GIL_DISABLED
1721
// Returns -1 in case of races with other threads.
18-
extern int _PyList_GetItemRefNoLock(PyListObject *, Py_ssize_t, PyObject **);
22+
extern int _PyList_GetItemRefNoLock(PyListObject *, Py_ssize_t, _PyStackRef *);
1923
#endif
2024

2125
#define _PyList_ITEMS(op) _Py_RVALUE(_PyList_CAST(op)->ob_item)

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/libregrtest/tsan.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
'test_threadsignals',
2727
'test_weakref',
2828
'test_free_threading.test_slots',
29-
'test_free_threading.test_iteration',
3029
]
3130

3231

Lib/test/test_free_threading/test_iteration_deopt.py

Lines changed: 0 additions & 154 deletions
This file was deleted.

Objects/listobject.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ _PyList_GetItemRef(PyListObject *list, Py_ssize_t i)
417417

418418
#ifdef Py_GIL_DISABLED
419419
int
420-
_PyList_GetItemRefNoLock(PyListObject *list, Py_ssize_t i, PyObject **result)
420+
_PyList_GetItemRefNoLock(PyListObject *list, Py_ssize_t i, _PyStackRef *result)
421421
{
422422
assert(_Py_IsOwnedByCurrentThread((PyObject *)list) ||
423423
_PyObject_GC_IS_SHARED(list));
@@ -433,8 +433,8 @@ _PyList_GetItemRefNoLock(PyListObject *list, Py_ssize_t i, PyObject **result)
433433
if (!valid_index(i, cap)) {
434434
return 0;
435435
}
436-
*result = _Py_TryXGetRef(&ob_item[i]);
437-
if (*result == NULL) {
436+
PyObject *obj = _Py_atomic_load_ptr(&ob_item[i]);
437+
if (obj == NULL || !_Py_TryIncrefCompareStackRef(&ob_item[i], obj, result)) {
438438
return -1;
439439
}
440440
return 1;

Python/bytecodes.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,8 +3028,10 @@ dummy_func(
30283028
replaced op(_ITER_JUMP_LIST, (iter -- iter)) {
30293029
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
30303030
assert(Py_TYPE(iter_o) == &PyListIter_Type);
3031-
// For free-threaded Python, the loop exit can happen at any point during item
3032-
// retrieval, so separate ops don't make much sense.
3031+
// For free-threaded Python, the loop exit can happen at any point during
3032+
// item retrieval, so it doesn't make much sense to check and jump
3033+
// separately before item retrieval. Any length check we do here can be
3034+
// invalid by the time we actually try to fetch the item.
30333035
#ifdef Py_GIL_DISABLED
30343036
assert(_PyObject_IsUniquelyReferenced(iter_o));
30353037
#else
@@ -3075,19 +3077,17 @@ dummy_func(
30753077
assert(_Py_IsOwnedByCurrentThread((PyObject *)seq) ||
30763078
_PyObject_GC_IS_SHARED(seq));
30773079
STAT_INC(FOR_ITER, hit);
3078-
PyObject *item;
3079-
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &item);
3080+
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next);
30803081
// A negative result means we lost a race with another thread
30813082
// and we need to take the slow path.
3082-
EXIT_IF(result < 0);
3083+
DEOPT_IF(result < 0);
30833084
if (result == 0) {
30843085
it->it_index = -1;
30853086
/* Jump forward oparg, then skip following END_FOR instruction */
30863087
JUMPBY(oparg + 1);
30873088
DISPATCH();
30883089
}
30893090
it->it_index++;
3090-
next = PyStackRef_FromPyObjectSteal(item);
30913091
#else
30923092
assert(it->it_index < PyList_GET_SIZE(seq));
30933093
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
@@ -3110,9 +3110,8 @@ dummy_func(
31103110

31113111
replaced op(_ITER_JUMP_TUPLE, (iter -- iter)) {
31123112
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
3113+
(void)iter_o;
31133114
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
3114-
// For free-threaded Python, the loop exit can happen at any point during item
3115-
// retrieval, so separate ops don't make much sense.
31163115
#ifdef Py_GIL_DISABLED
31173116
assert(_PyObject_IsUniquelyReferenced(iter_o));
31183117
#endif
@@ -3218,6 +3217,10 @@ dummy_func(
32183217
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
32193218
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
32203219
#ifdef Py_GIL_DISABLED
3220+
// Since generators can't be used by multiple threads anyway we
3221+
// don't need to deopt here, but this lets us work on making
3222+
// generators thread-safe without necessarily having to
3223+
// specialize them thread-safely as well.
32213224
DEOPT_IF(!_PyObject_IsUniquelyReferenced((PyObject *)gen));
32223225
#endif
32233226
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);

Python/executor_cases.c.h

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 10 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2654,7 +2654,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int oparg)
26542654
#ifdef Py_GIL_DISABLED
26552655
// Only specialize for uniquely referenced iterators, so that we know
26562656
// they're only referenced by this one thread. This is more limiting
2657-
// than we need (event `it = iter(mylist); for item in it:` won't get
2657+
// than we need (even `it = iter(mylist); for item in it:` won't get
26582658
// specialized) but we don't have a way to check whether we're the only
26592659
// _thread_ who has access to the object.
26602660
if (!_PyObject_IsUniquelyReferenced(iter_o))

0 commit comments

Comments
 (0)