Skip to content

Commit aada168

Browse files
fix exception bug
1 parent 2e3ddc1 commit aada168

File tree

12 files changed

+1207
-342
lines changed

12 files changed

+1207
-342
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ typedef struct {
3737
typedef struct _PyExitData {
3838
uint32_t target;
3939
uint16_t index;
40+
char is_dynamic;
4041
_Py_BackoffCounter temperature;
4142
struct _PyExecutorObject *executor;
4243
} _PyExitData;
4344

4445
typedef struct _PyExecutorObject {
4546
PyObject_VAR_HEAD
4647
const _PyUOpInstruction *trace;
48+
_Py_CODEUNIT *expected_entrypoint;
4749
_PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */
4850
uint32_t exit_count;
4951
uint32_t code_size;

Include/internal/pycore_uop_metadata.h

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

Python/bytecodes.c

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5414,6 +5414,7 @@ dummy_func(
54145414
}
54155415

54165416
tier2 op(_ERROR_POP_N, (target/2 --)) {
5417+
assert(target != 0);
54175418
assert(oparg == 0);
54185419
frame->instr_ptr = _PyFrame_GetBytecode(frame) + target;
54195420
SYNC_SP();
@@ -5435,28 +5436,35 @@ dummy_func(
54355436
tier2 op(_COLD_EXIT, ( -- )) {
54365437
_PyExitData *exit = tstate->jit_exit;
54375438
assert(exit != NULL);
5438-
_Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target;
5439-
_Py_BackoffCounter temperature = exit->temperature;
5440-
if (!backoff_counter_triggers(temperature)) {
5441-
exit->temperature = advance_backoff_counter(temperature);
5442-
GOTO_TIER_ONE(target, 0);
5443-
}
5444-
_PyExecutorObject *executor;
5445-
if (target->op.code == ENTER_EXECUTOR) {
5446-
PyCodeObject *code = _PyFrame_GetCode(frame);
5447-
executor = code->co_executors->executors[target->op.arg];
5448-
Py_INCREF(executor);
5449-
}
5450-
else {
5451-
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
5452-
assert(tstate->current_executor == (PyObject *)previous_executor);
5453-
int chain_depth = previous_executor->vm_data.chain_depth + 1;
5454-
_PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth);
5455-
GOTO_TIER_ONE(target, 1);
5456-
}
5457-
assert(tstate->jit_exit == exit);
5458-
exit->executor = executor;
5459-
TIER2_TO_TIER2(exit->executor);
5439+
bool is_dynamic = exit->is_dynamic;
5440+
_Py_CODEUNIT *target = is_dynamic ? frame->instr_ptr : (_PyFrame_GetBytecode(frame) + exit->target);
5441+
GOTO_TIER_ONE(target, 0);
5442+
// _Py_BackoffCounter temperature = exit->temperature;
5443+
// if (target->op.code == ENTER_EXECUTOR) {
5444+
// PyCodeObject *code = _PyFrame_GetCode(frame);
5445+
// _PyExecutorObject *executor = code->co_executors->executors[target->op.arg];
5446+
// if (is_dynamic && executor->expected_entrypoint != target) {
5447+
// GOTO_TIER_ONE(target, 0);
5448+
// }
5449+
// Py_INCREF(executor);
5450+
// assert(tstate->jit_exit == exit);
5451+
// exit->executor = executor;
5452+
// TIER2_TO_TIER2(exit->executor);
5453+
// }
5454+
// else {
5455+
// if (!backoff_counter_triggers(temperature)) {
5456+
// exit->temperature = advance_backoff_counter(temperature);
5457+
// GOTO_TIER_ONE(target, 0);
5458+
// }
5459+
// if (is_dynamic) {
5460+
// GOTO_TIER_ONE(target, 0);
5461+
// }
5462+
// _PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
5463+
// assert(tstate->current_executor == (PyObject *)previous_executor);
5464+
// int chain_depth = 0;
5465+
// _PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth);
5466+
// GOTO_TIER_ONE(target, 1);
5467+
// }
54605468
}
54615469

54625470
tier2 op(_GUARD_IP, (ip/4 --)) {
@@ -5465,36 +5473,20 @@ dummy_func(
54655473

54665474
tier2 op(_DYNAMIC_EXIT, (exit_p/4 --)) {
54675475
_Py_CODEUNIT *target = frame->instr_ptr;
5476+
_PyExitData *exit = (_PyExitData *)exit_p;
54685477
#if defined(Py_DEBUG) && !defined(_Py_JIT)
5478+
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
54695479
if (frame->lltrace >= 2) {
5470-
printf("GUARD IP EXIT: [UOp ");
5480+
printf("DYNAMIC EXIT: [UOp ");
54715481
_PyUOpPrint(&next_uop[-1]);
5472-
printf(", target %d -> %s]\n",
5482+
printf(", exit %tu, temp %d, target %d -> %s]\n",
5483+
exit - current_executor->exits, exit->temperature.value_and_backoff,
54735484
(int)(target - _PyFrame_GetBytecode(frame)),
54745485
_PyOpcode_OpName[target->op.code]);
54755486
}
54765487
#endif
5477-
_PyExitData *exit = (_PyExitData *)exit_p;
5478-
tstate->jit_exit = exit_p;
5479-
_Py_BackoffCounter temperature = exit->temperature;
5480-
_PyExecutorObject *executor;
5481-
if (target->op.code == ENTER_EXECUTOR) {
5482-
PyCodeObject *code = _PyFrame_GetCode(frame);
5483-
executor = code->co_executors->executors[target->op.arg];
5484-
Py_INCREF(executor);
5485-
}
5486-
else {
5487-
if (!backoff_counter_triggers(temperature)) {
5488-
exit->temperature = advance_backoff_counter(temperature);
5489-
GOTO_TIER_ONE(frame->instr_ptr, 0);
5490-
}
5491-
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
5492-
assert(tstate->current_executor == (PyObject *)previous_executor);
5493-
// Set chain_depth to 0 because we want to keep tracing whatever we see next.
5494-
_PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), 0);
5495-
GOTO_TIER_ONE(target, 1);
5496-
}
5497-
exit->executor = executor;
5488+
assert(exit->is_dynamic);
5489+
tstate->jit_exit = exit;
54985490
TIER2_TO_TIER2(exit->executor);
54995491
}
55005492

Python/ceval.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -975,12 +975,11 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
975975

976976
// 1 for trace full, 0 for successful write.
977977
static int
978-
add_to_code_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, PyCodeObject *old_code, _Py_CODEUNIT *this_instr, _Py_CODEUNIT *next_instr, int opcode, int oparg, int jump_taken)
978+
add_to_code_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, PyCodeObject *old_code, PyFunctionObject *old_func, _Py_CODEUNIT *this_instr, _Py_CODEUNIT *next_instr, int opcode, int oparg, int jump_taken)
979979
{
980980
assert(frame != NULL);
981981
assert(tstate->interp->jit_tracer_code_curr_size < UOP_MAX_TRACE_LENGTH);
982-
PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
983-
return !_PyJIT_translate_single_bytecode_to_trace(tstate, frame, this_instr, next_instr, old_code, func, opcode, oparg, jump_taken);
982+
return !_PyJIT_translate_single_bytecode_to_trace(tstate, frame, this_instr, next_instr, old_code, old_func, opcode, oparg, jump_taken);
984983
}
985984

986985
/* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on MSVC.
@@ -1195,14 +1194,15 @@ _PyTier2Interpreter(
11951194
for (;;) {
11961195
uopcode = next_uop->opcode;
11971196
#ifdef Py_DEBUG
1198-
if (frame->lltrace >= 4 &&
1199-
next_uop->opcode != _YIELD_VALUE &&
1197+
if (frame->lltrace >= 4) {
1198+
if (next_uop->opcode != _YIELD_VALUE &&
12001199
next_uop->opcode != _FOR_ITER_GEN_FRAME &&
12011200
next_uop->opcode != _PUSH_FRAME &&
12021201
next_uop->opcode != _PY_FRAME_KW &&
12031202
next_uop->opcode != _SAVE_RETURN_OFFSET &&
12041203
next_uop->opcode != _SAVE_RETURN_OFFSET) {
1205-
dump_stack(frame, stack_pointer);
1204+
dump_stack(frame, stack_pointer);
1205+
}
12061206
if (next_uop->opcode == _START_EXECUTOR) {
12071207
printf("%4d uop: ", 0);
12081208
}

Python/ceval_macros.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,28 +130,34 @@
130130
# define LABEL(name) name:
131131
#endif
132132

133+
#define TRACING_JUMP_TO_LABEL(label) \
134+
RECORD_JUMP_TAKEN() \
135+
RECORD_TRACE() \
136+
BAIL_TRACING_NO_DISPATCH() \
137+
JUMP_TO_LABEL(label);
138+
133139
#if _Py_TAIL_CALL_INTERP || USE_COMPUTED_GOTOS
134140
# define IS_JIT_TRACING() (DISPATCH_TABLE_VAR == TRACING_DISPATCH_TABLE)
135141
# define ENTER_TRACING() DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE;
136142
# define LEAVE_TRACING() DISPATCH_TABLE_VAR = DISPATCH_TABLE;
137143
# define BAIL_TRACING_NO_DISPATCH() \
138144
LEAVE_TRACING(); \
139-
int err = _PyOptimizer_Optimize(frame, tstate); \
140-
if (err < 0) { \
145+
int _err = _PyOptimizer_Optimize(frame, tstate); \
146+
if (_err < 0) { \
141147
JUMP_TO_LABEL(error); \
142148
}
143149
# define BAIL_TRACING() \
144150
BAIL_TRACING_NO_DISPATCH() \
145151
DISPATCH();
146152
# define RECORD_TRACE() do { \
147153
frame->instr_ptr = next_instr; \
148-
if (add_to_code_trace(tstate, frame, old_code, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
154+
if (add_to_code_trace(tstate, frame, old_code, old_func, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
149155
BAIL_TRACING(); \
150156
} \
151157
} while (0);
152158
# define RECORD_TRACE_NO_DISPATCH() do { \
153159
frame->instr_ptr = next_instr; \
154-
if (add_to_code_trace(tstate, frame, old_code, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
160+
if (add_to_code_trace(tstate, frame, old_code, old_func, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
155161
BAIL_TRACING_NO_DISPATCH(); \
156162
} \
157163
} while (0);
@@ -415,7 +421,9 @@ do { \
415421
JUMP_TO_LABEL(error); \
416422
} \
417423
if (keep_tracing_bit) { \
424+
assert(next_instr == frame->instr_ptr); \
418425
assert(next_instr->op.code != ENTER_EXECUTOR); \
426+
assert(tstate->interp->jit_tracer_code_curr_size == 2); \
419427
ENTER_TRACING(); \
420428
} \
421429
else { \

Python/executor_cases.c.h

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

0 commit comments

Comments
 (0)