Skip to content

Commit 085e172

Browse files
committed
"Specialize" JUMP_BACKWARD for JIT on/off
1 parent 07500fd commit 085e172

File tree

8 files changed

+273
-138
lines changed

8 files changed

+273
-138
lines changed

Include/internal/pycore_opcode_metadata.h

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

Include/opcode_ids.h

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

Lib/_opcode_metadata.py

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

Lib/test/test_dis.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import unittest
1616
from test.support import (captured_stdout, requires_debug_ranges,
1717
requires_specialization, cpython_only,
18-
os_helper)
18+
os_helper, import_helper)
1919
from test.support.bytecode_helper import BytecodeTestCase
2020

2121

@@ -912,7 +912,7 @@ def loop_test():
912912
LOAD_FAST 0 (i)
913913
CALL_PY_GENERAL 1
914914
POP_TOP
915-
JUMP_BACKWARD 17 (to L1)
915+
JUMP_BACKWARD_{: <6} 17 (to L1)
916916
917917
%3d L2: END_FOR
918918
POP_ITER
@@ -1316,7 +1316,8 @@ def test_loop_quicken(self):
13161316
# Loop can trigger a quicken where the loop is located
13171317
self.code_quicken(loop_test, 4)
13181318
got = self.get_disassembly(loop_test, adaptive=True)
1319-
expected = dis_loop_test_quickened_code
1319+
jit = import_helper.import_module("_testinternalcapi").jit_enabled()
1320+
expected = dis_loop_test_quickened_code.format("JIT" if jit else "NO_JIT")
13201321
self.do_disassembly_compare(got, expected)
13211322

13221323
@cpython_only

Python/bytecodes.c

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2797,44 +2797,69 @@ dummy_func(
27972797
JUMPBY(oparg);
27982798
}
27992799

2800-
tier1 op(_JUMP_BACKWARD, (the_counter/1 --)) {
2801-
assert(oparg <= INSTR_OFFSET());
2802-
JUMPBY(-oparg);
2800+
family(JUMP_BACKWARD, 1) = {
2801+
JUMP_BACKWARD_NO_JIT,
2802+
JUMP_BACKWARD_JIT,
2803+
};
2804+
2805+
tier1 op(_SPECIALIZE_JUMP_BACKWARD, (--)) {
2806+
#if ENABLE_SPECIALIZATION
2807+
if (this_instr->op.code == JUMP_BACKWARD) {
2808+
if (tstate->interp->jit) {
2809+
this_instr->op.code = JUMP_BACKWARD_JIT;
2810+
next_instr = this_instr;
2811+
DISPATCH_SAME_OPARG();
2812+
}
2813+
this_instr->op.code = JUMP_BACKWARD_NO_JIT;
2814+
}
2815+
#endif
2816+
}
2817+
2818+
tier1 op(_JIT, (--)) {
28032819
#ifdef _Py_TIER2
2804-
#if ENABLE_SPECIALIZATION
2805-
if (tstate->interp->jit) {
2806-
_Py_BackoffCounter counter = this_instr[1].counter;
2807-
if (backoff_counter_triggers(counter) && this_instr->op.code == JUMP_BACKWARD) {
2808-
_Py_CODEUNIT *start = this_instr;
2809-
/* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */
2810-
while (oparg > 255) {
2811-
oparg >>= 8;
2812-
start--;
2813-
}
2814-
_PyExecutorObject *executor;
2815-
int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer, &executor, 0);
2816-
if (optimized <= 0) {
2817-
this_instr[1].counter = restart_backoff_counter(counter);
2818-
ERROR_IF(optimized < 0, error);
2819-
}
2820-
else {
2821-
this_instr[1].counter = initial_jump_backoff_counter();
2822-
assert(tstate->previous_executor == NULL);
2823-
tstate->previous_executor = Py_None;
2824-
GOTO_TIER_TWO(executor);
2825-
}
2820+
_Py_BackoffCounter counter = this_instr[1].counter;
2821+
if (backoff_counter_triggers(counter)) {
2822+
_Py_CODEUNIT *start = this_instr;
2823+
/* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */
2824+
while (oparg > 255) {
2825+
oparg >>= 8;
2826+
start--;
2827+
}
2828+
_PyExecutorObject *executor;
2829+
int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer, &executor, 0);
2830+
if (optimized <= 0) {
2831+
this_instr[1].counter = restart_backoff_counter(counter);
2832+
ERROR_IF(optimized < 0, error);
28262833
}
28272834
else {
2828-
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
2835+
this_instr[1].counter = initial_jump_backoff_counter();
2836+
assert(tstate->previous_executor == NULL);
2837+
tstate->previous_executor = Py_None;
2838+
GOTO_TIER_TWO(executor);
28292839
}
28302840
}
2831-
#endif /* ENABLE_SPECIALIZATION */
2841+
else {
2842+
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
2843+
}
28322844
#endif /* _Py_TIER2 */
28332845
}
28342846

28352847
macro(JUMP_BACKWARD) =
2848+
unused/1 +
2849+
_SPECIALIZE_JUMP_BACKWARD +
28362850
_CHECK_PERIODIC +
2837-
_JUMP_BACKWARD;
2851+
JUMP_BACKWARD_NO_INTERRUPT;
2852+
2853+
macro(JUMP_BACKWARD_NO_JIT) =
2854+
unused/1 +
2855+
_CHECK_PERIODIC +
2856+
JUMP_BACKWARD_NO_INTERRUPT;
2857+
2858+
macro(JUMP_BACKWARD_JIT) =
2859+
unused/1 +
2860+
_CHECK_PERIODIC +
2861+
JUMP_BACKWARD_NO_INTERRUPT +
2862+
_JIT;
28382863

28392864
pseudo(JUMP, (--)) = {
28402865
JUMP_FORWARD,
@@ -2923,6 +2948,7 @@ dummy_func(
29232948
* generator or coroutine, so we deliberately do not check it here.
29242949
* (see bpo-30039).
29252950
*/
2951+
assert(oparg <= INSTR_OFFSET());
29262952
JUMPBY(-oparg);
29272953
}
29282954

0 commit comments

Comments
 (0)