mirror of
https://github.com/python/cpython.git
synced 2025-09-10 18:58:35 +00:00
GH-132554: "Virtual" iterators (GH-132555)
* FOR_ITER now pushes either the iterator and NULL or leaves the iterable and pushes tagged zero * NEXT_ITER uses the tagged int as the index into the sequence or, if TOS is NULL, iterates as before.
This commit is contained in:
parent
9300a596d3
commit
f6f4e8a662
25 changed files with 713 additions and 618 deletions
|
@ -2904,53 +2904,57 @@ int
|
|||
#endif // Py_STATS
|
||||
|
||||
Py_NO_INLINE void
|
||||
_Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int oparg)
|
||||
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
|
||||
{
|
||||
assert(ENABLE_SPECIALIZATION_FT);
|
||||
assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
|
||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||
PyTypeObject *tp = Py_TYPE(iter_o);
|
||||
|
||||
if (PyStackRef_IsNull(null_or_index)) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// Only specialize for uniquely referenced iterators, so that we know
|
||||
// they're only referenced by this one thread. This is more limiting
|
||||
// than we need (even `it = iter(mylist); for item in it:` won't get
|
||||
// specialized) but we don't have a way to check whether we're the only
|
||||
// _thread_ who has access to the object.
|
||||
if (!_PyObject_IsUniquelyReferenced(iter_o))
|
||||
goto failure;
|
||||
#endif
|
||||
if (tp == &PyListIter_Type) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
||||
if (!_Py_IsOwnedByCurrentThread((PyObject *)it->it_seq) &&
|
||||
!_PyObject_GC_IS_SHARED(it->it_seq)) {
|
||||
// Maybe this should just set GC_IS_SHARED in a critical
|
||||
// section, instead of leaving it to the first iteration?
|
||||
// Only specialize for uniquely referenced iterators, so that we know
|
||||
// they're only referenced by this one thread. This is more limiting
|
||||
// than we need (even `it = iter(mylist); for item in it:` won't get
|
||||
// specialized) but we don't have a way to check whether we're the only
|
||||
// _thread_ who has access to the object.
|
||||
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
||||
goto failure;
|
||||
}
|
||||
#endif
|
||||
specialize(instr, FOR_ITER_LIST);
|
||||
return;
|
||||
if (tp == &PyRangeIter_Type) {
|
||||
specialize(instr, FOR_ITER_RANGE);
|
||||
return;
|
||||
}
|
||||
else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
|
||||
// Generators are very much not thread-safe, so don't worry about
|
||||
// the specialization not being thread-safe.
|
||||
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
||||
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
||||
);
|
||||
/* Don't specialize if PEP 523 is active */
|
||||
if (_PyInterpreterState_GET()->eval_frame) {
|
||||
goto failure;
|
||||
}
|
||||
specialize(instr, FOR_ITER_GEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (tp == &PyTupleIter_Type) {
|
||||
specialize(instr, FOR_ITER_TUPLE);
|
||||
return;
|
||||
}
|
||||
else if (tp == &PyRangeIter_Type) {
|
||||
specialize(instr, FOR_ITER_RANGE);
|
||||
return;
|
||||
}
|
||||
else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
|
||||
// Generators are very much not thread-safe, so don't worry about
|
||||
// the specialization not being thread-safe.
|
||||
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
||||
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
||||
);
|
||||
/* Don't specialize if PEP 523 is active */
|
||||
if (_PyInterpreterState_GET()->eval_frame)
|
||||
goto failure;
|
||||
specialize(instr, FOR_ITER_GEN);
|
||||
return;
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
specialize(instr, FOR_ITER_LIST);
|
||||
return;
|
||||
}
|
||||
else if (tp == &PyTuple_Type) {
|
||||
specialize(instr, FOR_ITER_TUPLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
failure:
|
||||
SPECIALIZATION_FAIL(FOR_ITER,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue