Skip to content
Merged
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Improved the performance of :func:`sys.settrace` significantly
33 changes: 17 additions & 16 deletions Python/bytecodes.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -148,20 +148,18 @@ dummy_func(

tier1 inst(RESUME, (--)){
assert(frame == tstate->current_frame);
uintptr_t global_version =
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
~_PY_EVAL_EVENTS_MASK;
PyCodeObject *code = _PyFrame_GetCode(frame);
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
assert((code_version & 255) == 0);
if (code_version != global_version){
int err = _Py_Instrument(code, tstate->interp);
ERROR_IF(err, error);
next_instr = this_instr;
}
else{
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM){
CHECK_EVAL_BREAKER();
if (tstate->tracing == 0){
uintptr_t global_version =
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
~_PY_EVAL_EVENTS_MASK;
PyCodeObject* code = _PyFrame_GetCode(frame);
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
assert((code_version & 255) == 0);
if (code_version != global_version){
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
ERROR_IF(err, error);
next_instr = this_instr;
DISPATCH();
}
assert(this_instr->op.code == RESUME ||
this_instr->op.code == RESUME_CHECK ||
Expand All@@ -173,6 +171,9 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION */
}
}
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM){
CHECK_EVAL_BREAKER();
}
}

inst(RESUME_CHECK, (--)){
Expand All@@ -189,7 +190,7 @@ dummy_func(
inst(INSTRUMENTED_RESUME, (--)){
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
if (code_version != global_version){
if (code_version != global_version && tstate->tracing == 0){
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)){
ERROR_NO_POP();
}
Expand DownExpand Up@@ -4284,7 +4285,7 @@ dummy_func(
#endif
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
DEOPT_IF(eval_breaker & _PY_EVAL_EVENTS_MASK);
assert(eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
}

// END BYTECODES //
Expand Down
28 changes: 17 additions & 11 deletions Python/ceval.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -808,17 +808,23 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
{
_Py_CODEUNIT *prev = frame->instr_ptr;
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
_PyFrame_SetStackPointer(frame, stack_pointer);
int original_opcode = _Py_call_instrumentation_line(
tstate, frame, here, prev);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (original_opcode < 0){
next_instr = here+1;
goto error;
}
next_instr = frame->instr_ptr;
if (next_instr != here){
DISPATCH();
int original_opcode = 0;
if (tstate->tracing){
PyCodeObject *code = _PyFrame_GetCode(frame);
original_opcode = code->_co_monitoring->lines[(int)(here - _PyCode_CODE(code))].original_opcode;
} else{
_PyFrame_SetStackPointer(frame, stack_pointer);
original_opcode = _Py_call_instrumentation_line(
tstate, frame, here, prev);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (original_opcode < 0){
next_instr = here+1;
goto error;
}
next_instr = frame->instr_ptr;
if (next_instr != here){
DISPATCH();
}
}
if (_PyOpcode_Caches[original_opcode]){
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
Expand Down
16 changes: 10 additions & 6 deletions Python/ceval_macros.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -358,12 +358,16 @@ do{\
// for an exception handler, displaying the traceback, and so on
#define INSTRUMENTED_JUMP(src, dest, event) \
do{\
_PyFrame_SetStackPointer(frame, stack_pointer); \
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
stack_pointer = _PyFrame_GetStackPointer(frame); \
if (next_instr == NULL){\
next_instr = (dest)+1; \
goto error; \
if (tstate->tracing){\
next_instr = dest; \
} else{\
_PyFrame_SetStackPointer(frame, stack_pointer); \
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
stack_pointer = _PyFrame_GetStackPointer(frame); \
if (next_instr == NULL){\
next_instr = (dest)+1; \
goto error; \
} \
} \
} while (0);

Expand Down
2 changes: 1 addition & 1 deletion Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 16 additions & 15 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Python/instrumentation.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -1217,15 +1217,13 @@ int
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
{
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(tstate->tracing == 0);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
int i = (int)(instr - _PyCode_CODE(code));

_PyCoMonitoringData *monitoring = code->_co_monitoring;
_PyCoLineInstrumentationData *line_data = &monitoring->lines[i];
if (tstate->tracing){
goto done;
}
PyInterpreterState *interp = tstate->interp;
int8_t line_delta = line_data->line_delta;
int line = 0;
Expand Down