Skip to content

Commit c381903

Browse files
Address review
1 parent 97d5f2b commit c381903

File tree

5 files changed

+34
-27
lines changed

5 files changed

+34
-27
lines changed

Objects/codeobject.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,9 +2434,7 @@ code_dealloc(PyObject *self)
24342434
#ifdef _Py_TIER2
24352435
_Py_Executors_InvalidateDependency(tstate->interp, self, 1);
24362436
if (co->co_executors != NULL) {
2437-
Py_BEGIN_CRITICAL_SECTION(co);
24382437
clear_executors(co);
2439-
Py_END_CRITICAL_SECTION();
24402438
}
24412439
#endif
24422440

Objects/funcobject.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,9 @@ uint32_t
411411
_PyFunction_GetVersionForCurrentState(PyFunctionObject *func)
412412
{
413413
// This function does not need locking/atomics as it can only be
414-
// called from the optimizer, which is currently disabled
415-
// when there are multiple threads.
414+
// called from the specializing interpreter or optimizer.
415+
// The specializing interpreter holds a strong reference to the function.
416+
// The optimizer is currently disabled when there are multiple threads.
416417
return func->func_version;
417418
}
418419

Python/optimizer.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,9 @@ get_oparg(PyObject *self, PyObject *Py_UNUSED(ignored))
241241

242242
///////////////////// Experimental UOp Optimizer /////////////////////
243243

244-
static int executor_clear(PyObject *executor);
245-
static void unlink_executor(_PyExecutorObject *executor);
244+
static int executor_clear(PyInterpreterState *interp, PyObject *executor);
245+
static int executor_clear_implicit_interp(PyObject *executor);
246+
static void unlink_executor(PyInterpreterState *interp, _PyExecutorObject *executor);
246247

247248

248249
void
@@ -308,7 +309,7 @@ uop_dealloc(PyObject *op) {
308309
_PyExecutorObject *self = _PyExecutorObject_CAST(op);
309310
_PyObject_GC_UNTRACK(self);
310311
assert(self->vm_data.code == NULL);
311-
unlink_executor(self);
312+
unlink_executor(_PyInterpreterState_GET(), self);
312313
// Once unlinked it becomes impossible to invalidate an executor, so do it here.
313314
self->vm_data.valid = 0;
314315
add_to_pending_deletion_list(self);
@@ -464,7 +465,7 @@ PyTypeObject _PyUOpExecutor_Type = {
464465
.tp_as_sequence = &uop_as_sequence,
465466
.tp_methods = uop_executor_methods,
466467
.tp_traverse = executor_traverse,
467-
.tp_clear = executor_clear,
468+
.tp_clear = executor_clear_implicit_interp,
468469
.tp_is_gc = executor_is_gc,
469470
};
470471

@@ -1525,7 +1526,7 @@ link_executor(_PyExecutorObject *executor)
15251526
}
15261527

15271528
static void
1528-
unlink_executor(_PyExecutorObject *executor)
1529+
unlink_executor(PyInterpreterState *interp, _PyExecutorObject *executor)
15291530
{
15301531
if (!executor->vm_data.linked) {
15311532
return;
@@ -1542,7 +1543,6 @@ unlink_executor(_PyExecutorObject *executor)
15421543
}
15431544
else {
15441545
// prev == NULL implies that executor is the list head
1545-
PyInterpreterState *interp = PyInterpreterState_Get();
15461546
assert(interp->executor_list_head == executor);
15471547
interp->executor_list_head = next;
15481548
}
@@ -1653,15 +1653,19 @@ _Py_ExecutorDetach(_PyExecutorObject *executor)
16531653
Py_DECREF(executor);
16541654
}
16551655

1656+
// Note: we must use the interp state supplied and pass it to
1657+
// unlink_executor. This function might be called when a new
1658+
// interpreter is being created/removed. Thus the interpreter
1659+
// state is inconsistent with where the executor actually belongs.
16561660
static int
1657-
executor_clear(PyObject *op)
1661+
executor_clear(PyInterpreterState *interp, PyObject *op)
16581662
{
16591663
_PyExecutorObject *executor = _PyExecutorObject_CAST(op);
16601664
if (!executor->vm_data.valid) {
16611665
return 0;
16621666
}
16631667
assert(executor->vm_data.valid == 1);
1664-
unlink_executor(executor);
1668+
unlink_executor(interp, executor);
16651669
executor->vm_data.valid = 0;
16661670

16671671
/* It is possible for an executor to form a reference
@@ -1675,15 +1679,21 @@ executor_clear(PyObject *op)
16751679
executor->exits[i].temperature = initial_unreachable_backoff_counter();
16761680
_PyExecutorObject *e = executor->exits[i].executor;
16771681
executor->exits[i].executor = NULL;
1678-
if (e != cold && e != cold_dynamic) {
1679-
executor_clear((PyObject *)e);
1682+
if (e != cold && e != cold_dynamic && e->vm_data.code == NULL) {
1683+
executor_clear(interp, (PyObject *)e);
16801684
}
16811685
}
16821686
_Py_ExecutorDetach(executor);
16831687
Py_DECREF(executor);
16841688
return 0;
16851689
}
16861690

1691+
static int
1692+
executor_clear_implicit_interp(PyObject *op)
1693+
{
1694+
return executor_clear(_PyInterpreterState_GET(), op);
1695+
}
1696+
16871697
void
16881698
_Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj)
16891699
{
@@ -1728,7 +1738,7 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
17281738
}
17291739
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
17301740
PyObject *exec = PyList_GET_ITEM(invalidate, i);
1731-
executor_clear(exec);
1741+
executor_clear(interp, exec);
17321742
if (is_invalidation) {
17331743
OPT_STAT_INC(executors_invalidated);
17341744
}
@@ -1766,7 +1776,7 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)
17661776
_PyCode_Clear_Executors(executor->vm_data.code);
17671777
}
17681778
else {
1769-
executor_clear((PyObject *)executor);
1779+
executor_clear(interp, (PyObject *)executor);
17701780
}
17711781
if (is_invalidation) {
17721782
OPT_STAT_INC(executors_invalidated);
@@ -1801,7 +1811,7 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp)
18011811
}
18021812
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
18031813
PyObject *exec = PyList_GET_ITEM(invalidate, i);
1804-
executor_clear(exec);
1814+
executor_clear(interp, exec);
18051815
}
18061816
Py_DECREF(invalidate);
18071817
return;

Python/optimizer_analysis.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,14 @@ eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit)
226226

227227
static JitOptRef
228228
lookup_attr(JitOptContext *ctx, _PyUOpInstruction *this_instr,
229-
PyTypeObject *type, PyObject *name, uint16_t immortal,
229+
PyTypeObject *type, PyObject *name, uint16_t deferred_refcount,
230230
uint16_t mortal)
231231
{
232232
// The cached value may be dead, so we need to do the lookup again... :(
233233
if (type && PyType_Check(type)) {
234234
PyObject *lookup = _PyType_Lookup(type, name);
235235
if (lookup) {
236-
int opcode = _Py_IsImmortal(lookup) || _PyObject_HasDeferredRefcount(lookup) ? immortal : mortal;
236+
int opcode = _Py_IsImmortal(lookup) || _PyObject_HasDeferredRefcount(lookup) ? deferred_refcount : mortal;
237237
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)lookup);
238238
return sym_new_const(ctx, lookup);
239239
}

Python/pystate.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,20 +1522,18 @@ add_threadstate(PyInterpreterState *interp, PyThreadState *tstate,
15221522
{
15231523
assert(interp->threads.head != tstate);
15241524
if (next != NULL) {
1525+
#if defined(_Py_TIER2) && defined(Py_GIL_DISABLED)
1526+
FT_ATOMIC_STORE_UINT8(interp->jit, 0);
1527+
// There's more than one thread. In FT mode,
1528+
// disable the JIT completely for now.
1529+
_Py_Executors_InvalidateAll(interp, 1);
1530+
#endif
15251531
assert(next->prev == NULL || next->prev == tstate);
15261532
next->prev = tstate;
15271533
}
15281534
tstate->next = next;
15291535
assert(tstate->prev == NULL);
15301536
interp->threads.head = tstate;
1531-
#if defined(_Py_TIER2) && defined(Py_GIL_DISABLED)
1532-
// There's more than one thread. In FT mode,
1533-
// disable the JIT completely for now.
1534-
if (next != NULL) {
1535-
_Py_Executors_InvalidateAll(interp, 1);
1536-
FT_ATOMIC_STORE_UINT8(interp->jit, 0);
1537-
}
1538-
#endif
15391537
}
15401538

15411539
static PyThreadState *

0 commit comments

Comments
 (0)