Skip to content

Commit 08ec600

Browse files
Remove specialize_counter
1 parent 251e19e commit 08ec600

File tree

13 files changed

+44
-101
lines changed

13 files changed

+44
-101
lines changed

Include/internal/pycore_backoff.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ backoff_counter_triggers(_Py_BackoffCounter counter)
9595
return counter.value_and_backoff < UNREACHABLE_BACKOFF;
9696
}
9797

98+
static inline _Py_BackoffCounter
99+
trigger_backoff_counter(void)
100+
{
101+
_Py_BackoffCounter result;
102+
result.value_and_backoff = 0;
103+
return result;
104+
}
105+
98106
// Initial JUMP_BACKWARD counter.
99107
// Must be larger than ADAPTIVE_COOLDOWN_VALUE, otherwise when JIT code is
100108
// invalidated we may construct a new trace before the bytecode has properly
@@ -134,14 +142,6 @@ initial_unreachable_backoff_counter(void)
134142
return make_backoff_counter(0, UNREACHABLE_BACKOFF);
135143
}
136144

137-
// Required to not get stuck in infinite specialization loops due to specialization failure.
138-
// We use 2 here as there are a few scenarios:
139-
// 1. Freshly specialized from unspecialized, in which case the counter will be 1.
140-
// 2. Re-specialized from deopt, in which case the counter will be 1.
141-
// 3. Deopt -> Specialize -> Deopt -> Specialize, in which case the counter will be 2.
142-
// We do not want the 3rd case.
143-
#define MAX_SPECIALIZATION_TRIES 2
144-
145145
#ifdef __cplusplus
146146
}
147147
#endif

Include/internal/pycore_tstate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ typedef struct _PyJitTracerPreviousState {
4141
int code_curr_size;
4242
int instr_oparg;
4343
int instr_stacklevel;
44-
int specialize_counter;
4544
_Py_CODEUNIT *instr;
4645
PyCodeObject *instr_code; // Strong
4746
struct _PyInterpreterFrame *instr_frame;

Python/bytecodes.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5249,7 +5249,7 @@ dummy_func(
52495249
? _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR : _PyFrame_GetBytecode(frame))
52505250
+ exit->target;
52515251
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
5252-
if (frame->lltrace >= 2) {
5252+
if (frame->lltrace >= 3) {
52535253
printf("SIDE EXIT: [UOp ");
52545254
_PyUOpPrint(&next_uop[-1]);
52555255
printf(", exit %tu, temp %d, target %d -> %s, is_control_flow %d]\n",
@@ -5267,7 +5267,7 @@ dummy_func(
52675267
_PyExitData *exit = (_PyExitData *)exit_p;
52685268
_Py_CODEUNIT *target = frame->instr_ptr;
52695269
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
5270-
if (frame->lltrace >= 2) {
5270+
if (frame->lltrace >= 3) {
52715271
printf("DYNAMIC EXIT: [UOp ");
52725272
_PyUOpPrint(&next_uop[-1]);
52735273
printf(", exit %tu, temp %d, target %d -> %s]\n",
@@ -5663,7 +5663,6 @@ dummy_func(
56635663
else {
56645664
_tstate->jit_state.prev_state.instr = next_instr;
56655665
}
5666-
_tstate->jit_state.prev_state.specialize_counter = 0;
56675666
PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
56685667
if (_tstate->jit_state.prev_state.instr_code != (PyCodeObject *)prev_code) {
56695668
Py_SETREF(_tstate->jit_state.prev_state.instr_code, (PyCodeObject*)Py_NewRef((prev_code)));
@@ -5672,6 +5671,9 @@ dummy_func(
56725671
_tstate->jit_state.prev_state.instr_frame = frame;
56735672
_tstate->jit_state.prev_state.instr_oparg = oparg;
56745673
_tstate->jit_state.prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL();
5674+
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
5675+
(&next_instr[1])->counter = trigger_backoff_counter();
5676+
}
56755677
DISPATCH_GOTO_NON_TRACING();
56765678
#else
56775679
Py_FatalError("JIT label executed in non-jit build.");

Python/ceval_macros.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,12 @@
134134

135135
#if (_Py_TAIL_CALL_INTERP || USE_COMPUTED_GOTOS) && _Py_TIER2
136136
# define IS_JIT_TRACING() (DISPATCH_TABLE_VAR == TRACING_DISPATCH_TABLE)
137-
# define IS_JIT_TRACING_MAKING_PROGRESS() (IS_JIT_TRACING() && ((_PyThreadStateImpl *)tstate)->jit_state.prev_state.specialize_counter < MAX_SPECIALIZATION_TRIES)
138137
# define ENTER_TRACING() \
139138
DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE;
140139
# define LEAVE_TRACING() \
141140
DISPATCH_TABLE_VAR = DISPATCH_TABLE;
142141
#else
143142
# define IS_JIT_TRACING() (0)
144-
# define IS_JIT_TRACING_MAKING_PROGRESS() (0)
145143
# define ENTER_TRACING()
146144
# define LEAVE_TRACING()
147145
#endif
@@ -308,7 +306,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
308306
* which is always an integral type. */
309307
// Force re-specialization when tracing a side exit to get good side exits.
310308
#define ADAPTIVE_COUNTER_TRIGGERS(COUNTER) \
311-
backoff_counter_triggers(forge_backoff_counter((COUNTER))) || IS_JIT_TRACING_MAKING_PROGRESS()
309+
backoff_counter_triggers(forge_backoff_counter((COUNTER)))
312310

313311
#define ADVANCE_ADAPTIVE_COUNTER(COUNTER) \
314312
do { \

Python/executor_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/generated_cases.c.h

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

Python/optimizer.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ _PyOptimizer_Optimize(
129129
if (_tstate->jit_state.initial_state.func == NULL) {
130130
return 0;
131131
}
132+
assert(_tstate->jit_state.initial_state.func != NULL);
132133
interp->compiling = true;
133134
// The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must*
134135
// make progress in order to avoid infinite loops or excessively-long
@@ -584,10 +585,6 @@ _PyJit_translate_single_bytecode_to_trace(
584585
// We must point to the first EXTENDED_ARG when deopting.
585586
int oparg = _tstate->jit_state.prev_state.instr_oparg;
586587
int opcode = this_instr->op.code;
587-
// Failed specialization many times. Deopt!
588-
if (_tstate->jit_state.prev_state.specialize_counter >= MAX_SPECIALIZATION_TRIES) {
589-
opcode = _PyOpcode_Deopt[opcode];
590-
}
591588
int rewind_oparg = oparg;
592589
while (rewind_oparg > 255) {
593590
rewind_oparg >>= 8;
@@ -736,6 +733,7 @@ _PyJit_translate_single_bytecode_to_trace(
736733
_Py_CODEUNIT *computed_jump_instr = computed_next_instr_without_modifiers + oparg;
737734
assert(next_instr == computed_next_instr || next_instr == computed_jump_instr);
738735
int jump_happened = computed_jump_instr == next_instr;
736+
assert(jump_happened == (target_instr[1].cache & 1));
739737
uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened];
740738
ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code));
741739
break;
@@ -974,7 +972,10 @@ _PyJit_TryInitializeTracing(
974972
return 0;
975973
}
976974
}
977-
975+
PyObject *func = PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
976+
if (func == NULL) {
977+
return 0;
978+
}
978979
PyCodeObject *code = _PyFrame_GetCode(frame);
979980
#ifdef Py_DEBUG
980981
char *python_lltrace = Py_GETENV("PYTHON_LLTRACE");
@@ -999,13 +1000,12 @@ _PyJit_TryInitializeTracing(
9991000
_tstate->jit_state.initial_state.start_instr = start_instr;
10001001
_tstate->jit_state.initial_state.close_loop_instr = close_loop_instr;
10011002
_tstate->jit_state.initial_state.code = (PyCodeObject *)Py_NewRef(code);
1002-
_tstate->jit_state.initial_state.func = (PyFunctionObject *)Py_XNewRef(PyStackRef_AsPyObjectBorrow(frame->f_funcobj));
1003+
_tstate->jit_state.initial_state.func = (PyFunctionObject *)Py_NewRef(func);
10031004
_tstate->jit_state.initial_state.exit = exit;
10041005
_tstate->jit_state.initial_state.stack_depth = curr_stackdepth;
10051006
_tstate->jit_state.initial_state.chain_depth = chain_depth;
10061007
_tstate->jit_state.prev_state.instr_frame = frame;
10071008
_tstate->jit_state.prev_state.dependencies_still_valid = true;
1008-
_tstate->jit_state.prev_state.specialize_counter = 0;
10091009
_tstate->jit_state.prev_state.instr_code = (PyCodeObject *)Py_NewRef(_PyFrame_GetCode(frame));
10101010
_tstate->jit_state.prev_state.instr = curr_instr;
10111011
_tstate->jit_state.prev_state.instr_frame = frame;
@@ -1014,7 +1014,10 @@ _PyJit_TryInitializeTracing(
10141014
_tstate->jit_state.prev_state.instr_is_super = false;
10151015
assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (exit != NULL));
10161016
_tstate->jit_state.initial_state.jump_backward_instr = curr_instr;
1017-
assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (exit != NULL));
1017+
1018+
if (_PyOpcode_Caches[_PyOpcode_Deopt[close_loop_instr->op.code]]) {
1019+
close_loop_instr[1].counter = trigger_backoff_counter();
1020+
}
10181021
_Py_BloomFilter_Init(&_tstate->jit_state.prev_state.dependencies);
10191022
return 1;
10201023
}
@@ -1366,9 +1369,10 @@ uop_optimize(
13661369
assert(length < UOP_MAX_TRACE_LENGTH);
13671370
OPT_STAT_INC(traces_created);
13681371
if (!is_noopt) {
1369-
length = _Py_uop_analyze_and_optimize(_tstate->jit_state.initial_state.func, buffer,
1370-
length,
1371-
curr_stackentries, &new_dependencies);
1372+
length = _Py_uop_analyze_and_optimize(
1373+
_tstate->jit_state.initial_state.func,
1374+
buffer,length,
1375+
curr_stackentries, &new_dependencies);
13721376
if (length <= 0) {
13731377
return length;
13741378
}

Python/optimizer_analysis.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,10 @@ optimize_uops(
360360
}
361361
if (ctx->contradiction) {
362362
// Attempted to push a "bottom" (contradiction) symbol onto the stack.
363-
// This means that the abstract interpreter has hit unreachable code.
363+
// This means that the abstract interpreter has optimized to trace
364+
// to an unreachable estate.
364365
// We *could* generate an _EXIT_TRACE or _FATAL_ERROR here, but hitting
365-
// bottom indicates type instability, so we are probably better off
366+
// bottom usually indicates an optimizer bug, so we are probably better off
366367
// retrying later.
367368
DPRINTF(3, "\n");
368369
DPRINTF(1, "Hit bottom in abstract interpreter\n");

Python/optimizer_bytecodes.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ dummy_func(void) {
342342
int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
343343
if (!already_bool) {
344344
sym_set_type(value, &PyBool_Type);
345-
value = sym_new_truthiness(ctx, value, true);
346345
}
347346
}
348347

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)