mirror of https://github.com/python/cpython
gh-107674: Improve performance of `sys.settrace` (GH-114986)
This commit is contained in:
parent
9578288a3e
commit
0a61e23700
|
@ -0,0 +1 @@
|
|||
Improved the performance of :func:`sys.settrace` significantly
|
|
@ -143,6 +143,7 @@ dummy_func(
|
|||
|
||||
tier1 inst(RESUME, (--)) {
|
||||
assert(frame == tstate->current_frame);
|
||||
if (tstate->tracing == 0) {
|
||||
uintptr_t global_version =
|
||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||
~_PY_EVAL_EVENTS_MASK;
|
||||
|
@ -152,14 +153,14 @@ dummy_func(
|
|||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||
ERROR_IF(err, error);
|
||||
next_instr = this_instr;
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
this_instr->op.code = RESUME_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
inst(RESUME_CHECK, (--)) {
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
|
@ -169,13 +170,13 @@ dummy_func(
|
|||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||
DEOPT_IF(eval_breaker != version);
|
||||
DEOPT_IF(eval_breaker != version && tstate->tracing == 0);
|
||||
}
|
||||
|
||||
inst(INSTRUMENTED_RESUME, (--)) {
|
||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
||||
uintptr_t code_version = _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)) {
|
||||
GOTO_ERROR(error);
|
||||
}
|
||||
|
|
|
@ -800,8 +800,13 @@ resume_frame:
|
|||
{
|
||||
_Py_CODEUNIT *prev = frame->instr_ptr;
|
||||
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
|
||||
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);
|
||||
int original_opcode = _Py_call_instrumentation_line(
|
||||
original_opcode = _Py_call_instrumentation_line(
|
||||
tstate, frame, here, prev);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (original_opcode < 0) {
|
||||
|
@ -812,6 +817,7 @@ resume_frame:
|
|||
if (next_instr != here) {
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
if (_PyOpcode_Caches[original_opcode]) {
|
||||
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
||||
/* Prevent the underlying instruction from specializing
|
||||
|
|
|
@ -339,6 +339,9 @@ do { \
|
|||
// for an exception handler, displaying the traceback, and so on
|
||||
#define INSTRUMENTED_JUMP(src, dest, event) \
|
||||
do { \
|
||||
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); \
|
||||
|
@ -346,6 +349,7 @@ do { \
|
|||
next_instr = (dest)+1; \
|
||||
goto error; \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
typedef PyObject *(*convertion_func_ptr)(PyObject *);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||
if (eval_breaker != version) goto deoptimize;
|
||||
if (eval_breaker != version && tstate->tracing == 0) goto deoptimize;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -3125,7 +3125,7 @@
|
|||
INSTRUCTION_STATS(INSTRUMENTED_RESUME);
|
||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
||||
uintptr_t code_version = _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)) {
|
||||
GOTO_ERROR(error);
|
||||
}
|
||||
|
@ -4780,6 +4780,7 @@
|
|||
PREDICTED(RESUME);
|
||||
_Py_CODEUNIT *this_instr = next_instr - 1;
|
||||
assert(frame == tstate->current_frame);
|
||||
if (tstate->tracing == 0) {
|
||||
uintptr_t global_version =
|
||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||
~_PY_EVAL_EVENTS_MASK;
|
||||
|
@ -4789,13 +4790,13 @@
|
|||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||
if (err) goto error;
|
||||
next_instr = this_instr;
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
this_instr->op.code = RESUME_CHECK;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -4811,7 +4812,7 @@
|
|||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||
DEOPT_IF(eval_breaker != version, RESUME);
|
||||
DEOPT_IF(eval_breaker != version && tstate->tracing == 0, RESUME);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -1156,15 +1156,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 = compute_line(code, i, line_delta);
|
||||
|
|
Loading…
Reference in New Issue