GH-113710: Tier 2 optimizer: check the function instead of checking globals. (GH-116410)

This commit is contained in:
Mark Shannon 2024-03-06 13:12:23 +00:00 committed by GitHub
parent 33c0aa3bb9
commit 27858e2a17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 137 additions and 149 deletions

View file

@ -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;