diff options
Diffstat (limited to 'Python/optimizer.c')
-rw-r--r-- | Python/optimizer.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/Python/optimizer.c b/Python/optimizer.c index f8d0aa04b9e..8d01d605ef4 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -204,16 +204,74 @@ get_oparg(PyObject *self, PyObject *Py_UNUSED(ignored)) static int executor_clear(PyObject *executor); static void unlink_executor(_PyExecutorObject *executor); + +static void +free_executor(_PyExecutorObject *self) +{ +#ifdef _Py_JIT + _PyJIT_Free(self); +#endif + PyObject_GC_Del(self); +} + +void +_Py_ClearExecutorDeletionList(PyInterpreterState *interp) +{ + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); + PyThreadState* ts = PyInterpreterState_ThreadHead(interp); + HEAD_UNLOCK(runtime); + while (ts) { + _PyExecutorObject *current = (_PyExecutorObject *)ts->current_executor; + if (current != NULL) { + /* Anything in this list will be unlinked, so we can reuse the + * linked field as a reachability marker. */ + current->vm_data.linked = 1; + } + HEAD_LOCK(runtime); + ts = PyThreadState_Next(ts); + HEAD_UNLOCK(runtime); + } + _PyExecutorObject **prev_to_next_ptr = &interp->executor_deletion_list_head; + _PyExecutorObject *exec = *prev_to_next_ptr; + while (exec != NULL) { + if (exec->vm_data.linked) { + // This executor is currently executing + exec->vm_data.linked = 0; + prev_to_next_ptr = &exec->vm_data.links.next; + } + else { + *prev_to_next_ptr = exec->vm_data.links.next; + free_executor(exec); + } + exec = *prev_to_next_ptr; + } + interp->executor_deletion_list_remaining_capacity = EXECUTOR_DELETE_LIST_MAX; +} + +static void +add_to_pending_deletion_list(_PyExecutorObject *self) +{ + PyInterpreterState *interp = PyInterpreterState_Get(); + self->vm_data.links.next = interp->executor_deletion_list_head; + interp->executor_deletion_list_head = self; + if (interp->executor_deletion_list_remaining_capacity > 0) { + interp->executor_deletion_list_remaining_capacity--; + } + else { + _Py_ClearExecutorDeletionList(interp); + } +} + static void uop_dealloc(PyObject *op) { _PyExecutorObject *self = _PyExecutorObject_CAST(op); _PyObject_GC_UNTRACK(self); assert(self->vm_data.code == NULL); unlink_executor(self); -#ifdef _Py_JIT - _PyJIT_Free(self); -#endif - PyObject_GC_Del(self); + // Once unlinked it becomes impossible to invalidate an executor, so do it here. + self->vm_data.valid = 0; + add_to_pending_deletion_list(self); } const char * @@ -1234,8 +1292,8 @@ uop_optimize( for (int pc = 0; pc < length; pc++) { int opcode = buffer[pc].opcode; int oparg = buffer[pc].oparg; - if (oparg < _PyUop_Replication[opcode]) { - buffer[pc].opcode = opcode + oparg + 1; + if (oparg < _PyUop_Replication[opcode].stop && oparg >= _PyUop_Replication[opcode].start) { + buffer[pc].opcode = opcode + oparg + 1 - _PyUop_Replication[opcode].start; assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode], _PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0); } else if (is_terminator(&buffer[pc])) { |