mirror of
https://github.com/python/cpython.git
synced 2025-08-27 12:16:04 +00:00
GH-114695: Add sys._clear_internal_caches
(GH-115152)
This commit is contained in:
parent
54bde5dcc3
commit
235cacff81
12 changed files with 130 additions and 84 deletions
|
@ -2370,23 +2370,12 @@ dummy_func(
|
|||
CHECK_EVAL_BREAKER();
|
||||
|
||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
|
||||
if (executor->vm_data.valid) {
|
||||
Py_INCREF(executor);
|
||||
current_executor = executor;
|
||||
GOTO_TIER_TWO();
|
||||
}
|
||||
else {
|
||||
/* ENTER_EXECUTOR will be the first code unit of the instruction */
|
||||
assert(oparg < 256);
|
||||
code->co_executors->executors[oparg] = NULL;
|
||||
opcode = this_instr->op.code = executor->vm_data.opcode;
|
||||
this_instr->op.arg = executor->vm_data.oparg;
|
||||
oparg = executor->vm_data.oparg;
|
||||
Py_DECREF(executor);
|
||||
next_instr = this_instr;
|
||||
DISPATCH_GOTO();
|
||||
}
|
||||
current_executor = code->co_executors->executors[oparg & 255];
|
||||
assert(current_executor->vm_data.index == INSTR_OFFSET() - 1);
|
||||
assert(current_executor->vm_data.code == code);
|
||||
assert(current_executor->vm_data.valid);
|
||||
Py_INCREF(current_executor);
|
||||
GOTO_TIER_TWO();
|
||||
}
|
||||
|
||||
replaced op(_POP_JUMP_IF_FALSE, (cond -- )) {
|
||||
|
|
20
Python/clinic/sysmodule.c.h
generated
20
Python/clinic/sysmodule.c.h
generated
|
@ -1131,6 +1131,24 @@ sys__clear_type_cache(PyObject *module, PyObject *Py_UNUSED(ignored))
|
|||
return sys__clear_type_cache_impl(module);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(sys__clear_internal_caches__doc__,
|
||||
"_clear_internal_caches($module, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Clear all internal performance-related caches.");
|
||||
|
||||
#define SYS__CLEAR_INTERNAL_CACHES_METHODDEF \
|
||||
{"_clear_internal_caches", (PyCFunction)sys__clear_internal_caches, METH_NOARGS, sys__clear_internal_caches__doc__},
|
||||
|
||||
static PyObject *
|
||||
sys__clear_internal_caches_impl(PyObject *module);
|
||||
|
||||
static PyObject *
|
||||
sys__clear_internal_caches(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
return sys__clear_internal_caches_impl(module);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(sys_is_finalizing__doc__,
|
||||
"is_finalizing($module, /)\n"
|
||||
"--\n"
|
||||
|
@ -1486,4 +1504,4 @@ exit:
|
|||
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
|
||||
#define SYS_GETANDROIDAPILEVEL_METHODDEF
|
||||
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
|
||||
/*[clinic end generated code: output=3dc3b2cb0ce38ebb input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=b8b1c53e04c3b20c input=a9049054013a1b77]*/
|
||||
|
|
25
Python/generated_cases.c.h
generated
25
Python/generated_cases.c.h
generated
|
@ -2363,29 +2363,18 @@
|
|||
}
|
||||
|
||||
TARGET(ENTER_EXECUTOR) {
|
||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(ENTER_EXECUTOR);
|
||||
TIER_ONE_ONLY
|
||||
CHECK_EVAL_BREAKER();
|
||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
|
||||
if (executor->vm_data.valid) {
|
||||
Py_INCREF(executor);
|
||||
current_executor = executor;
|
||||
GOTO_TIER_TWO();
|
||||
}
|
||||
else {
|
||||
/* ENTER_EXECUTOR will be the first code unit of the instruction */
|
||||
assert(oparg < 256);
|
||||
code->co_executors->executors[oparg] = NULL;
|
||||
opcode = this_instr->op.code = executor->vm_data.opcode;
|
||||
this_instr->op.arg = executor->vm_data.oparg;
|
||||
oparg = executor->vm_data.oparg;
|
||||
Py_DECREF(executor);
|
||||
next_instr = this_instr;
|
||||
DISPATCH_GOTO();
|
||||
}
|
||||
current_executor = code->co_executors->executors[oparg & 255];
|
||||
assert(current_executor->vm_data.index == INSTR_OFFSET() - 1);
|
||||
assert(current_executor->vm_data.code == code);
|
||||
assert(current_executor->vm_data.valid);
|
||||
Py_INCREF(current_executor);
|
||||
GOTO_TIER_TWO();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -73,25 +73,21 @@ insert_executor(PyCodeObject *code, _Py_CODEUNIT *instr, int index, _PyExecutorO
|
|||
Py_INCREF(executor);
|
||||
if (instr->op.code == ENTER_EXECUTOR) {
|
||||
assert(index == instr->op.arg);
|
||||
_PyExecutorObject *old = code->co_executors->executors[index];
|
||||
executor->vm_data.opcode = old->vm_data.opcode;
|
||||
executor->vm_data.oparg = old->vm_data.oparg;
|
||||
old->vm_data.opcode = 0;
|
||||
code->co_executors->executors[index] = executor;
|
||||
Py_DECREF(old);
|
||||
_Py_ExecutorClear(code->co_executors->executors[index]);
|
||||
}
|
||||
else {
|
||||
assert(code->co_executors->size == index);
|
||||
assert(code->co_executors->capacity > index);
|
||||
executor->vm_data.opcode = instr->op.code;
|
||||
executor->vm_data.oparg = instr->op.arg;
|
||||
code->co_executors->executors[index] = executor;
|
||||
assert(index < MAX_EXECUTORS_SIZE);
|
||||
instr->op.code = ENTER_EXECUTOR;
|
||||
instr->op.arg = index;
|
||||
code->co_executors->size++;
|
||||
}
|
||||
return;
|
||||
executor->vm_data.opcode = instr->op.code;
|
||||
executor->vm_data.oparg = instr->op.arg;
|
||||
executor->vm_data.code = code;
|
||||
executor->vm_data.index = (int)(instr - _PyCode_CODE(code));
|
||||
code->co_executors->executors[index] = executor;
|
||||
assert(index < MAX_EXECUTORS_SIZE);
|
||||
instr->op.code = ENTER_EXECUTOR;
|
||||
instr->op.arg = index;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1071,7 +1067,7 @@ link_executor(_PyExecutorObject *executor)
|
|||
}
|
||||
head->vm_data.links.next = executor;
|
||||
}
|
||||
executor->vm_data.linked = true;
|
||||
executor->vm_data.valid = true;
|
||||
/* executor_list_head must be first in list */
|
||||
assert(interp->executor_list_head->vm_data.links.previous == NULL);
|
||||
}
|
||||
|
@ -1079,7 +1075,7 @@ link_executor(_PyExecutorObject *executor)
|
|||
static void
|
||||
unlink_executor(_PyExecutorObject *executor)
|
||||
{
|
||||
if (!executor->vm_data.linked) {
|
||||
if (!executor->vm_data.valid) {
|
||||
return;
|
||||
}
|
||||
_PyExecutorLinkListNode *links = &executor->vm_data.links;
|
||||
|
@ -1097,7 +1093,7 @@ unlink_executor(_PyExecutorObject *executor)
|
|||
assert(interp->executor_list_head == executor);
|
||||
interp->executor_list_head = next;
|
||||
}
|
||||
executor->vm_data.linked = false;
|
||||
executor->vm_data.valid = false;
|
||||
}
|
||||
|
||||
/* This must be called by optimizers before using the executor */
|
||||
|
@ -1116,12 +1112,24 @@ void
|
|||
_Py_ExecutorClear(_PyExecutorObject *executor)
|
||||
{
|
||||
unlink_executor(executor);
|
||||
PyCodeObject *code = executor->vm_data.code;
|
||||
if (code == NULL) {
|
||||
return;
|
||||
}
|
||||
_Py_CODEUNIT *instruction = &_PyCode_CODE(code)[executor->vm_data.index];
|
||||
assert(instruction->op.code == ENTER_EXECUTOR);
|
||||
int index = instruction->op.arg;
|
||||
assert(code->co_executors->executors[index] == executor);
|
||||
instruction->op.code = executor->vm_data.opcode;
|
||||
instruction->op.arg = executor->vm_data.oparg;
|
||||
executor->vm_data.code = NULL;
|
||||
Py_CLEAR(code->co_executors->executors[index]);
|
||||
}
|
||||
|
||||
void
|
||||
_Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj)
|
||||
{
|
||||
assert(executor->vm_data.valid = true);
|
||||
assert(executor->vm_data.valid);
|
||||
_Py_BloomFilter_Add(&executor->vm_data.bloom, obj);
|
||||
}
|
||||
|
||||
|
@ -1140,8 +1148,7 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj)
|
|||
assert(exec->vm_data.valid);
|
||||
_PyExecutorObject *next = exec->vm_data.links.next;
|
||||
if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter)) {
|
||||
exec->vm_data.valid = false;
|
||||
unlink_executor(exec);
|
||||
_Py_ExecutorClear(exec);
|
||||
}
|
||||
exec = next;
|
||||
}
|
||||
|
@ -1151,15 +1158,14 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj)
|
|||
void
|
||||
_Py_Executors_InvalidateAll(PyInterpreterState *interp)
|
||||
{
|
||||
/* Walk the list of executors */
|
||||
for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) {
|
||||
assert(exec->vm_data.valid);
|
||||
_PyExecutorObject *next = exec->vm_data.links.next;
|
||||
exec->vm_data.links.next = NULL;
|
||||
exec->vm_data.links.previous = NULL;
|
||||
exec->vm_data.valid = false;
|
||||
exec->vm_data.linked = false;
|
||||
exec = next;
|
||||
while (interp->executor_list_head) {
|
||||
_PyExecutorObject *executor = interp->executor_list_head;
|
||||
if (executor->vm_data.code) {
|
||||
// Clear the entire code object so its co_executors array be freed:
|
||||
_PyCode_Clear_Executors(executor->vm_data.code);
|
||||
}
|
||||
else {
|
||||
_Py_ExecutorClear(executor);
|
||||
}
|
||||
}
|
||||
interp->executor_list_head = NULL;
|
||||
}
|
||||
|
|
|
@ -2127,6 +2127,22 @@ sys__clear_type_cache_impl(PyObject *module)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
sys._clear_internal_caches
|
||||
|
||||
Clear all internal performance-related caches.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
sys__clear_internal_caches_impl(PyObject *module)
|
||||
/*[clinic end generated code: output=0ee128670a4966d6 input=253e741ca744f6e8]*/
|
||||
{
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
_Py_Executors_InvalidateAll(interp);
|
||||
PyType_ClearCache();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* Note that, for now, we do not have a per-interpreter equivalent
|
||||
for sys.is_finalizing(). */
|
||||
|
||||
|
@ -2461,6 +2477,7 @@ static PyMethodDef sys_methods[] = {
|
|||
{"audit", _PyCFunction_CAST(sys_audit), METH_FASTCALL, audit_doc },
|
||||
{"breakpointhook", _PyCFunction_CAST(sys_breakpointhook),
|
||||
METH_FASTCALL | METH_KEYWORDS, breakpointhook_doc},
|
||||
SYS__CLEAR_INTERNAL_CACHES_METHODDEF
|
||||
SYS__CLEAR_TYPE_CACHE_METHODDEF
|
||||
SYS__CURRENT_FRAMES_METHODDEF
|
||||
SYS__CURRENT_EXCEPTIONS_METHODDEF
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue