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

bpo-44338: Port LOAD_GLOBAL to PEP 659 adaptive interpreter #26638

Merged
merged 11 commits into from
Jun 14, 2021

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Jun 10, 2021

  • Adds two specializations of LOAD_GLOBAL:

    • LOAD_GLOBAL_MODULE for module variables
    • LOAD_GLOBAL_BUILTIN for builtins.
  • Removes the old "opcache" mechanism.

  • Adds a few more stats (hidden behind a compile-time flag).

https://bugs.python.org/issue44338

@markshannon markshannon added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jun 10, 2021
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @markshannon for commit 8ad3e55 🤖

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

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jun 10, 2021
Copy link
Member

@ericsnowcurrently ericsnowcurrently left a comment

Choose a reason for hiding this comment

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

There are a few spots where things are a little unclear but mostly I was able to follow the change.

Python/ceval.c Outdated Show resolved Hide resolved
Python/ceval.c Outdated
Comment on lines 2923 to 2926
STAT_INC(loadglobal_deferred);
cache->adaptive.counter--;
oparg = cache->adaptive.original_oparg;
JUMP_TO_INSTRUCTION(LOAD_GLOBAL);
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 also virtual identical, right? Will that be the case for all the XXXX_ADAPTIVE opcodes?

Python/ceval.c Show resolved Hide resolved
goto fail;
}
cache1->module_keys_version = keys_version;
cache0->index = index;
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was going to ask about this (Py_ssize_t -> uint16_t) but looks like GHA beat me to it. :) Does this limit us on the size of the builtins/globals dicts or are dicts already constrained to 2^16 entries?

Copy link
Member Author

Choose a reason for hiding this comment

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

We just can't optimize access to variables with index > 64k.
If your module has more than 64k variables, then you have plenty of other problems 🙂

Python/ceval.c Show resolved Hide resolved
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
_PyLoadGlobalCache *cache1 = &caches[-1].load_global;
DEOPT_IF(dict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL);
Copy link
Member

Choose a reason for hiding this comment

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

Do we also need to check the case where it's a different globals dict? It can't be done from Python (except if someone creates a new function using the code object from another function, or passes the code object to exec()) but can easily be done from C. There is the remote chance that (in that already unlikely case) the keys version is the same.

Copy link
Member Author

Choose a reason for hiding this comment

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

If the keys version is the same, then it has the same keys in the same order and is the same kind of dict.
In which case it doesn't matter if it is a different dictionary, because we cache the index, not the value.

As an aside, you can get different dictionaries with the same keys as module dicts at different times.

class C: pass
d1 = C().__dict__
d2 = C().__dict__
# d1 and d2 should share keys
m = ModuleType()
m.__dict__ = d1
# Specialize
m.__dict__ = d2
# globals in m would see same keys as when specialized

Python/ceval.c Show resolved Hide resolved
Python/specialize.c Show resolved Hide resolved
@markshannon markshannon merged commit eecbc7c into python:main Jun 14, 2021
jdevries3133 pushed a commit to jdevries3133/cpython that referenced this pull request Jun 19, 2021
…-26638)

* Add specializations of LOAD_GLOBAL.

* Add more stats.

* Remove old opcache; it is no longer used.

* Add NEWS
@markshannon markshannon deleted the specialize-load-global branch January 6, 2022 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants