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-105848: Replace KW_NAMES + CALL with LOAD_CONST + CALL_KW #109300

Merged
merged 14 commits into from
Sep 13, 2023

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Sep 12, 2023

Get rid of the magic kwnames side-channel and split out calls with a tuple of keyword names on the stack (CALL_KW) from those with no keyword arguments (the existing CALL family). Stats on an earlier version of this branch suggested that specializing CALL_KW just isn't worth it.

Other cleanup:

The new CALL_KW instruction is mostly copied and lightly modified from the existing CALL instruction. They can probably share code using uops, but that's a project for another day.


📚 Documentation preview 📚: https://cpython-previews--109300.org.readthedocs.build/

@brandtbucher brandtbucher added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Sep 12, 2023
@brandtbucher brandtbucher self-assigned this Sep 12, 2023
@brandtbucher brandtbucher added 🔨 test-with-buildbots Test PR w/ buildbots; report in status section 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section labels Sep 12, 2023
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @brandtbucher for commit 53917a5 🤖

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @brandtbucher for commit 53917a5 🤖

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Sep 12, 2023
@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 12, 2023
@brandtbucher
Copy link
Member Author

1% faster.

@markshannon
Copy link
Member

Can you add CALL_KW to the list of specializable instructions that we don't specialize for the stats. https://github.com/python/cpython/blob/main/Python/specialize.c#L135

@brettcannon brettcannon removed their request for review September 12, 2023 17:25
Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

I just love seeing this! Mostly some docs nits.

Comment on lines +2 to +3
arguments. Also, fix a possible crash when jumping over method calls in a
debugger.
Copy link
Member

Choose a reason for hiding this comment

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

Is the crash fix inseparable from the new opcode? Is there no issue for it?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's just bugs in mark_stacks left over from #107788. So same issue number, unrelated to the new opcode though.

@@ -1122,7 +1122,7 @@ iterations of the loop.
This bytecode distinguishes two cases: if ``STACK[-1]`` has a method with the
correct name, the bytecode pushes the unbound method and ``STACK[-1]``.
``STACK[-1]`` will be used as the first argument (``self``) by :opcode:`CALL`
when calling the unbound method. Otherwise, ``NULL`` and the object returned by
or :opcode:`CALL_KW` when calling the unbound method. Otherwise, ``NULL`` and the object returned by
Copy link
Member

Choose a reason for hiding this comment

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

Break long line

Suggested change
or :opcode:`CALL_KW` when calling the unbound method. Otherwise, ``NULL`` and the object returned by
or :opcode:`CALL_KW` when calling the unbound method.
Otherwise, ``NULL`` and the object returned by

* The callable
* The positional arguments
* The named arguments
* ``self`` (or ``NULL``)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* ``self`` (or ``NULL``)
* ``self`` or ``NULL``

Comment on lines 1427 to 1428
``argc`` is the total of the positional and named arguments, excluding
``self`` when a ``NULL`` is not present.
Copy link
Member

Choose a reason for hiding this comment

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

(Same thing about whether "not" should be removed.)

Make explicit that if there are N positional and M keyword arguments, oparg is N+M, and len(tuple) must be == M.

@@ -473,7 +474,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3561).to_bytes(2, 'little') + b'\r\n'
Copy link
Member

Choose a reason for hiding this comment

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

This is already a merge conflict. :-) Might need to manually merge #109269.

// or
// [method, self, arg1, arg2, ...]
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
// [callable, self, arg1, arg2, ...]
Copy link
Member

Choose a reason for hiding this comment

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

Maybe add (here too) that oparg counts arg1 etc., but not self? (It has to be this way, of course, but still bears repeating IMO.)

Comment on lines 1400 to 1401
``argc`` is the total of the positional arguments, excluding
``self`` when a ``NULL`` is not present.
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 it's clearer to just say "excluding self":

Suggested change
``argc`` is the total of the positional arguments, excluding
``self`` when a ``NULL`` is not present.
``argc`` is the total of the positional arguments, excluding ``self``.


* The callable
* ``self``
* ``self`` (or ``NULL``)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* ``self`` (or ``NULL``)
* ``self`` or ``NULL``

Comment on lines 1427 to 1428
``argc`` is the total of the positional and named arguments, excluding
``self`` when a ``NULL`` is not present.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
``argc`` is the total of the positional and named arguments, excluding
``self`` when a ``NULL`` is not present.
``argc`` is the total of the positional and named arguments, excluding ``self``.

GO_TO_INSTRUCTION(CALL_KW);
}

inst(CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this deserves a comment (like CALL) about the stack contents on entry and exit? Or if not, maybe CALL doesn't need it either? (Because it should be clear from the DSL.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'd rather just remove it from both. It's not that complex anymore.

@brandtbucher
Copy link
Member Author

Ignoring the buildbot failures since they're all either failing on main or on other PRs also. Not a very informative run... :(

@brandtbucher
Copy link
Member Author

Can you add CALL_KW to the list of specializable instructions that we don't specialize for the stats. https://github.com/python/cpython/blob/main/Python/specialize.c#L135

That's only useful if we're recording failure kinds, right? We're not in this case, so I don't think it would actually add anything other than an empty section.

Comment on lines -1395 to +1401
:opcode:`KW_NAMES`, if any.
On the stack are (in ascending order), either:
Calls a callable object with the number of arguments specified by ``argc``.
On the stack are (in ascending order):

* NULL
* The callable
* The positional arguments
* The named arguments

or:

* The callable
* ``self``
* ``self`` or ``NULL``
* The remaining positional arguments
* The named arguments

``argc`` is the total of the positional and named arguments, excluding
``self`` when a ``NULL`` is not present.
``argc`` is the total of the positional arguments, excluding ``self``.
Copy link
Member

Choose a reason for hiding this comment

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

That is definitely easier to follow. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants