Specialization is mostly performed when generating the superblock, but there will still be redundancy.
E.g. in the example above, the final CHECK_GLOBALS_DICT_KEY_VERSION can be removed the global's dict key has already been checked.
We can also remove some checks by moving from inline checks to global checks.
E.g. we can remove the CHECK_BUILTINS_DICT_KEY_VERSION and deoptimization (discard) the superblock should the builtins dict ever change. We can also remove the function version check and replace the CHECK_MODULE_DICT_VERSION; LOAD_ATTR_MODULE_UNCHECKED with LOAD_CONST by adding a global check on the module's dictionary.
Applying these optimizations we get something like:
LOAD_CONST (typing)
POP_TOP
LOAD_CONST (typing.cast)
LOAD_CONST (int)
LOAD_FAST 0 (x)
PUSH_FRAME 2
CHECK_EVAL_BREAKER
LOAD_FAST 1 (val)
RETURN_VALUE
STORE_FAST 0 (x)
LOAD_GLOBAL_MODULE_UNCHECKED (unpredicable)
EXIT # Can't predict where we are going
The resulting superblock is invalidated if any of the following occur:
Taking the example superblock (removing the SAVE_IP for clarity, they are removed properly by a later pass)
Specialization is mostly performed when generating the superblock, but there will still be redundancy. E.g. in the example above, the final
CHECK_GLOBALS_DICT_KEY_VERSION
can be removed the global's dict key has already been checked. We can also remove some checks by moving from inline checks to global checks. E.g. we can remove theCHECK_BUILTINS_DICT_KEY_VERSION
and deoptimization (discard) the superblock should the builtins dict ever change. We can also remove the function version check and replace theCHECK_MODULE_DICT_VERSION; LOAD_ATTR_MODULE_UNCHECKED
withLOAD_CONST
by adding a global check on the module's dictionary.Applying these optimizations we get something like:
The resulting superblock is invalidated if any of the following occur:
typing
module's__dict__
is modified.typing.cast
changes