Skip to content

Commit ed73c90

Browse files
gh-139109: JIT _EXIT_TRACE to ENTER_EXECUTOR rather than _DEOPT (GH-141573)
1 parent 85f3009 commit ed73c90

File tree

5 files changed

+44
-8
lines changed

5 files changed

+44
-8
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ PyAPI_FUNC(int) _PyDumpExecutors(FILE *out);
362362
extern void _Py_ClearExecutorDeletionList(PyInterpreterState *interp);
363363
#endif
364364

365-
int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, bool stop_tracing);
365+
int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);
366366

367367
int
368368
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,

Lib/test/test_capi/test_opt.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ def get_first_executor(func):
4040
pass
4141
return None
4242

43+
def get_all_executors(func):
44+
code = func.__code__
45+
co_code = code.co_code
46+
executors = []
47+
for i in range(0, len(co_code), 2):
48+
try:
49+
executors.append(_opcode.get_executor(code, i))
50+
except ValueError:
51+
pass
52+
return executors
53+
4354

4455
def iter_opnames(ex):
4556
for item in ex:
@@ -2629,6 +2640,31 @@ def gen():
26292640
next(g)
26302641
""" % _testinternalcapi.SPECIALIZATION_THRESHOLD))
26312642

2643+
def test_executor_side_exits_create_another_executor(self):
2644+
def f():
2645+
for x in range(TIER2_THRESHOLD + 3):
2646+
for y in range(TIER2_THRESHOLD + 3):
2647+
z = x + y
2648+
2649+
f()
2650+
all_executors = get_all_executors(f)
2651+
# Inner loop warms up first.
2652+
# Outer loop warms up later, linking to the inner one.
2653+
# Therefore, we have at least two executors.
2654+
self.assertGreaterEqual(len(all_executors), 2)
2655+
for executor in all_executors:
2656+
opnames = list(get_opnames(executor))
2657+
# Assert all executors first terminator ends in
2658+
# _EXIT_TRACE or _JUMP_TO_TOP, not _DEOPT
2659+
for idx, op in enumerate(opnames):
2660+
if op == "_EXIT_TRACE" or op == "_JUMP_TO_TOP":
2661+
break
2662+
elif op == "_DEOPT":
2663+
self.fail(f"_DEOPT encountered first at executor"
2664+
f" {executor} at offset {idx} rather"
2665+
f" than expected _EXIT_TRACE")
2666+
2667+
26322668

26332669
def global_identity(x):
26342670
return x

Python/bytecodes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5643,7 +5643,7 @@ dummy_func(
56435643
bool stop_tracing = (opcode == WITH_EXCEPT_START ||
56445644
opcode == RERAISE || opcode == CLEANUP_THROW ||
56455645
opcode == PUSH_EXC_INFO || opcode == INTERPRETER_EXIT);
5646-
int full = !_PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr, stop_tracing);
5646+
int full = !_PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr, stop_tracing ? _DEOPT : 0);
56475647
if (full) {
56485648
LEAVE_TRACING();
56495649
int err = stop_tracing_and_jit(tstate, frame);
@@ -5683,7 +5683,7 @@ dummy_func(
56835683
#if _Py_TIER2
56845684
assert(IS_JIT_TRACING());
56855685
int opcode = next_instr->op.code;
5686-
_PyJit_translate_single_bytecode_to_trace(tstate, frame, NULL, true);
5686+
_PyJit_translate_single_bytecode_to_trace(tstate, frame, NULL, _EXIT_TRACE);
56875687
LEAVE_TRACING();
56885688
int err = stop_tracing_and_jit(tstate, frame);
56895689
ERROR_IF(err < 0);

Python/generated_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ _PyJit_translate_single_bytecode_to_trace(
574574
PyThreadState *tstate,
575575
_PyInterpreterFrame *frame,
576576
_Py_CODEUNIT *next_instr,
577-
bool stop_tracing)
577+
int stop_tracing_opcode)
578578
{
579579

580580
#ifdef Py_DEBUG
@@ -637,8 +637,8 @@ _PyJit_translate_single_bytecode_to_trace(
637637
goto full;
638638
}
639639

640-
if (stop_tracing) {
641-
ADD_TO_TRACE(_DEOPT, 0, 0, target);
640+
if (stop_tracing_opcode != 0) {
641+
ADD_TO_TRACE(stop_tracing_opcode, 0, 0, target);
642642
goto done;
643643
}
644644

0 commit comments

Comments
 (0)