Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-98831: Modernize the FOR_ITER family of instructions #101626

Merged
merged 7 commits into from
Feb 7, 2023

Conversation

gvanrossum
Copy link
Member

@gvanrossum gvanrossum commented Feb 7, 2023

This is somewhat tricky because most of the family members (with the exception of FOR_ITER_GEN) are actually super-instructions that jump over the END_FOR instruction that is the target of the jump (which pops two stack items). In addition, FOR_ITER_RANGE also jumps over the STORE_FAST that follows it when the range is not exhausted.

The cache and stack effects documented in the DSL don't acknowledge the existence of these optimizations. (This will bite us when we try to incorporate these instructions in a level 2 interpreter, we'll have to deal with it then.)

Copy link
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good. Just one question

STAT_INC(FOR_ITER, hit);
PyListObject *seq = it->it_seq;
if (seq) {
if (it->it_index < PyList_GET_SIZE(seq)) {
PyObject *next = PyList_GET_ITEM(seq, it->it_index++);
PUSH(Py_NewRef(next));
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused, why do we not need to JUMPBY INLINE_CACHE_ENTRIES_FOR_ITER anymore?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the JUMPBY(1); in line 2688.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh right. I forgot that the inline cache entries for FOR_ITER is just the counter. Thanks Irit!

FOR_ITER_GEN,
};

inst(FOR_ITER, (unused/1, iter -- iter, next)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be counter/1 instead of unused/1, and then the counter used in the body?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all cases where the counter is manipulated using ADAPTIVE_COUNTER_IS_ZERO / DECREMENT_ADAPTIVE_COUNTER I'm leaving this idiom unchanged -- the generator won't let you write back to cache entries, so it would become asymmetrical, and the common case is DECREMENT_ADAPTIVE_COUNTER anyway.

Python/bytecodes.c Outdated Show resolved Hide resolved
gvanrossum and others added 2 commits February 7, 2023 07:11
Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
@gvanrossum gvanrossum merged commit d54b8d8 into python:main Feb 7, 2023
@gvanrossum gvanrossum deleted the for-iter-family branch February 7, 2023 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants