summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-03-06 13:12:23 (GMT)
committerGitHub <noreply@github.com>2024-03-06 13:12:23 (GMT)
commit27858e2a17924dfac9a10efc17caee1f5126ea19 (patch)
tree2af07baa6bdc4bed313b95a25ff224dbd0fdf0e7 /Python
parent33c0aa3bb9b334593e27fe4b2b0fe912117a1ee1 (diff)
downloadcpython-27858e2a17924dfac9a10efc17caee1f5126ea19.zip
cpython-27858e2a17924dfac9a10efc17caee1f5126ea19.tar.gz
cpython-27858e2a17924dfac9a10efc17caee1f5126ea19.tar.bz2
GH-113710: Tier 2 optimizer: check the function instead of checking globals. (GH-116410)
Diffstat (limited to 'Python')
-rw-r--r--Python/bytecodes.c8
-rw-r--r--Python/executor_cases.c.h12
-rw-r--r--Python/optimizer_analysis.c37
-rw-r--r--Python/optimizer_cases.c.h6
4 files changed, 27 insertions, 36 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 15794cb..ad4ea4e 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4058,12 +4058,8 @@ dummy_func(
null = NULL;
}
- tier2 op(_CHECK_GLOBALS, (dict/4 -- )) {
- DEOPT_IF(GLOBALS() != dict);
- }
-
- tier2 op(_CHECK_BUILTINS, (dict/4 -- )) {
- DEOPT_IF(BUILTINS() != dict);
+ tier2 op(_CHECK_FUNCTION, (func/4 -- )) {
+ DEOPT_IF(frame->f_funcobj != func);
}
/* Internal -- for testing executors */
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 806f748..a057466 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3789,15 +3789,9 @@
break;
}
- case _CHECK_GLOBALS: {
- PyObject *dict = (PyObject *)CURRENT_OPERAND();
- if (GLOBALS() != dict) goto deoptimize;
- break;
- }
-
- case _CHECK_BUILTINS: {
- PyObject *dict = (PyObject *)CURRENT_OPERAND();
- if (BUILTINS() != dict) goto deoptimize;
+ case _CHECK_FUNCTION: {
+ PyObject *func = (PyObject *)CURRENT_OPERAND();
+ if (frame->f_funcobj != func) goto deoptimize;
break;
}
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 18e3382..0f25527 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -154,10 +154,10 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
/* These values represent stacks of booleans (one bool per bit).
* Pushing a frame shifts left, popping a frame shifts right. */
- uint32_t builtins_checked = 0;
+ uint32_t function_checked = 0;
uint32_t builtins_watched = 0;
- uint32_t globals_checked = 0;
uint32_t globals_watched = 0;
+ uint32_t prechecked_function_version = 0;
if (interp->dict_state.watchers[GLOBALS_WATCHER_ID] == NULL) {
interp->dict_state.watchers[GLOBALS_WATCHER_ID] = globals_watcher_callback;
}
@@ -176,13 +176,13 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
PyDict_Watch(BUILTINS_WATCHER_ID, builtins);
builtins_watched |= 1;
}
- if (builtins_checked & 1) {
+ if (function_checked & 1) {
buffer[pc].opcode = NOP;
}
else {
- buffer[pc].opcode = _CHECK_BUILTINS;
+ buffer[pc].opcode = _CHECK_FUNCTION;
buffer[pc].operand = (uintptr_t)builtins;
- builtins_checked |= 1;
+ function_checked |= 1;
}
break;
case _GUARD_GLOBALS_VERSION:
@@ -198,36 +198,39 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
_Py_BloomFilter_Add(dependencies, globals);
globals_watched |= 1;
}
- if (globals_checked & 1) {
+ if (function_checked & 1) {
buffer[pc].opcode = NOP;
}
else {
- buffer[pc].opcode = _CHECK_GLOBALS;
+ buffer[pc].opcode = _CHECK_FUNCTION;
buffer[pc].operand = (uintptr_t)globals;
- globals_checked |= 1;
+ function_checked |= 1;
}
break;
case _LOAD_GLOBAL_BUILTINS:
- if (globals_checked & builtins_checked & globals_watched & builtins_watched & 1) {
+ if (function_checked & globals_watched & builtins_watched & 1) {
convert_global_to_const(inst, builtins);
}
break;
case _LOAD_GLOBAL_MODULE:
- if (globals_checked & globals_watched & 1) {
+ if (function_checked & globals_watched & 1) {
convert_global_to_const(inst, globals);
}
break;
case _PUSH_FRAME:
{
- globals_checked <<= 1;
- globals_watched <<= 1;
- builtins_checked <<= 1;
builtins_watched <<= 1;
+ globals_watched <<= 1;
+ function_checked <<= 1;
PyFunctionObject *func = (PyFunctionObject *)buffer[pc].operand;
if (func == NULL) {
return 1;
}
assert(PyFunction_Check(func));
+ if (prechecked_function_version == func->func_version) {
+ function_checked |= 1;
+ }
+ prechecked_function_version = 0;
globals = func->func_globals;
builtins = func->func_builtins;
if (builtins != interp->builtins) {
@@ -237,16 +240,18 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
}
case _POP_FRAME:
{
- globals_checked >>= 1;
- globals_watched >>= 1;
- builtins_checked >>= 1;
builtins_watched >>= 1;
+ globals_watched >>= 1;
+ function_checked >>= 1;
PyFunctionObject *func = (PyFunctionObject *)buffer[pc].operand;
assert(PyFunction_Check(func));
globals = func->func_globals;
builtins = func->func_builtins;
break;
}
+ case _CHECK_FUNCTION_EXACT_ARGS:
+ prechecked_function_version = (uint32_t)buffer[pc].operand;
+ break;
default:
if (op_is_end(opcode)) {
return 1;
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 32dfca9..a114b03 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1951,11 +1951,7 @@
break;
}
- case _CHECK_GLOBALS: {
- break;
- }
-
- case _CHECK_BUILTINS: {
+ case _CHECK_FUNCTION: {
break;
}