diff options
author | Mark Shannon <mark@hotpy.org> | 2024-03-06 13:12:23 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-06 13:12:23 (GMT) |
commit | 27858e2a17924dfac9a10efc17caee1f5126ea19 (patch) | |
tree | 2af07baa6bdc4bed313b95a25ff224dbd0fdf0e7 /Python | |
parent | 33c0aa3bb9b334593e27fe4b2b0fe912117a1ee1 (diff) | |
download | cpython-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.c | 8 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 12 | ||||
-rw-r--r-- | Python/optimizer_analysis.c | 37 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 6 |
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; } |