GH-145668: Add FOR_ITER specialization for virtual iterators. Specialize GET_ITER. (GH-147967)

* Add FOR_ITER_VIRTUAL to specialize FOR_ITER for virtual iterators
* Add GET_ITER_SELF to specialize GET_ITER for iterators (including generators)
* Add GET_ITER_VIRTUAL to specialize GET_ITER for iterables as virtual iterators
* Add new (internal) _tp_iteritem function slot to PyTypeObject
* Put limited RESUME at start of genexpr for free-threading. Fix up exception handling in genexpr
This commit is contained in:
Mark Shannon 2026-04-16 15:22:22 +01:00 committed by GitHub
parent 0fcf2b72d3
commit 600f4dbd54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 2987 additions and 1534 deletions

View file

@ -2715,20 +2715,24 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT
}
}
else {
if (tp == &PyList_Type) {
#ifdef Py_GIL_DISABLED
// Only specialize for lists owned by this thread or shared
if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
goto failure;
if (tp->_tp_iteritem != NULL) {
if (tp == &PyList_Type) {
#ifdef Py_GIL_DISABLED
// Only specialize for lists owned by this thread or shared
if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
goto failure;
}
#endif
specialize(instr, FOR_ITER_LIST);
return;
}
else if (tp == &PyTuple_Type) {
specialize(instr, FOR_ITER_TUPLE);
return;
}
#endif
specialize(instr, FOR_ITER_LIST);
return;
}
else if (tp == &PyTuple_Type) {
specialize(instr, FOR_ITER_TUPLE);
return;
}
specialize(instr, FOR_ITER_VIRTUAL);
return;
}
failure:
SPECIALIZATION_FAIL(FOR_ITER,
@ -2923,6 +2927,23 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr)
return;
}
void
_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr)
{
assert(ENABLE_SPECIALIZATION);
PyTypeObject *tp = PyStackRef_TYPE(iterable);
if (tp->_tp_iteritem != NULL) {
specialize(instr, GET_ITER_VIRTUAL);
return;
}
if (tp->tp_iter == PyObject_SelfIter) {
specialize(instr, GET_ITER_SELF);
return;
}
SPECIALIZATION_FAIL(GET_ITER,
tp == &PyCoro_Type ? SPEC_FAIL_ITER_COROUTINE : SPEC_FAIL_OTHER);
unspecialize(instr);
}
void
_Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame)