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,22 +143,23 @@ dummy_func(
|
||||||
|
|
||||||
tier1 inst(RESUME, (--)) {
|
tier1 inst(RESUME, (--)) {
|
||||||
assert(frame == tstate->current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
uintptr_t global_version =
|
if (tstate->tracing == 0) {
|
||||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
uintptr_t global_version =
|
||||||
~_PY_EVAL_EVENTS_MASK;
|
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||||
uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
~_PY_EVAL_EVENTS_MASK;
|
||||||
assert((code_version & 255) == 0);
|
uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||||
if (code_version != global_version) {
|
assert((code_version & 255) == 0);
|
||||||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
if (code_version != global_version) {
|
||||||
ERROR_IF(err, error);
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
next_instr = this_instr;
|
ERROR_IF(err, error);
|
||||||
}
|
next_instr = this_instr;
|
||||||
else {
|
DISPATCH();
|
||||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
|
||||||
CHECK_EVAL_BREAKER();
|
|
||||||
}
|
}
|
||||||
this_instr->op.code = RESUME_CHECK;
|
|
||||||
}
|
}
|
||||||
|
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
}
|
||||||
|
this_instr->op.code = RESUME_CHECK;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(RESUME_CHECK, (--)) {
|
inst(RESUME_CHECK, (--)) {
|
||||||
|
@ -169,13 +170,13 @@ dummy_func(
|
||||||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||||
DEOPT_IF(eval_breaker != version);
|
DEOPT_IF(eval_breaker != version && tstate->tracing == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(INSTRUMENTED_RESUME, (--)) {
|
inst(INSTRUMENTED_RESUME, (--)) {
|
||||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
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;
|
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)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
||||||
GOTO_ERROR(error);
|
GOTO_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -800,17 +800,23 @@ resume_frame:
|
||||||
{
|
{
|
||||||
_Py_CODEUNIT *prev = frame->instr_ptr;
|
_Py_CODEUNIT *prev = frame->instr_ptr;
|
||||||
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
|
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
int original_opcode = 0;
|
||||||
int original_opcode = _Py_call_instrumentation_line(
|
if (tstate->tracing) {
|
||||||
tstate, frame, here, prev);
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
original_opcode = code->_co_monitoring->lines[(int)(here - _PyCode_CODE(code))].original_opcode;
|
||||||
if (original_opcode < 0) {
|
} else {
|
||||||
next_instr = here+1;
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
goto error;
|
original_opcode = _Py_call_instrumentation_line(
|
||||||
}
|
tstate, frame, here, prev);
|
||||||
next_instr = frame->instr_ptr;
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (next_instr != here) {
|
if (original_opcode < 0) {
|
||||||
DISPATCH();
|
next_instr = here+1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
next_instr = frame->instr_ptr;
|
||||||
|
if (next_instr != here) {
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (_PyOpcode_Caches[original_opcode]) {
|
if (_PyOpcode_Caches[original_opcode]) {
|
||||||
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
||||||
|
|
|
@ -339,12 +339,16 @@ do { \
|
||||||
// for an exception handler, displaying the traceback, and so on
|
// for an exception handler, displaying the traceback, and so on
|
||||||
#define INSTRUMENTED_JUMP(src, dest, event) \
|
#define INSTRUMENTED_JUMP(src, dest, event) \
|
||||||
do { \
|
do { \
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
if (tstate->tracing) {\
|
||||||
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
|
next_instr = dest; \
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
} else { \
|
||||||
if (next_instr == NULL) { \
|
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
||||||
next_instr = (dest)+1; \
|
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
|
||||||
goto error; \
|
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||||
|
if (next_instr == NULL) { \
|
||||||
|
next_instr = (dest)+1; \
|
||||||
|
goto error; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||||
if (eval_breaker != version) goto deoptimize;
|
if (eval_breaker != version && tstate->tracing == 0) goto deoptimize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3125,7 +3125,7 @@
|
||||||
INSTRUCTION_STATS(INSTRUMENTED_RESUME);
|
INSTRUCTION_STATS(INSTRUMENTED_RESUME);
|
||||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
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;
|
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)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
||||||
GOTO_ERROR(error);
|
GOTO_ERROR(error);
|
||||||
}
|
}
|
||||||
|
@ -4780,22 +4780,23 @@
|
||||||
PREDICTED(RESUME);
|
PREDICTED(RESUME);
|
||||||
_Py_CODEUNIT *this_instr = next_instr - 1;
|
_Py_CODEUNIT *this_instr = next_instr - 1;
|
||||||
assert(frame == tstate->current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
uintptr_t global_version =
|
if (tstate->tracing == 0) {
|
||||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
uintptr_t global_version =
|
||||||
~_PY_EVAL_EVENTS_MASK;
|
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||||
uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
~_PY_EVAL_EVENTS_MASK;
|
||||||
assert((code_version & 255) == 0);
|
uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||||
if (code_version != global_version) {
|
assert((code_version & 255) == 0);
|
||||||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
if (code_version != global_version) {
|
||||||
if (err) goto error;
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
next_instr = this_instr;
|
if (err) goto error;
|
||||||
}
|
next_instr = this_instr;
|
||||||
else {
|
DISPATCH();
|
||||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
|
||||||
CHECK_EVAL_BREAKER();
|
|
||||||
}
|
}
|
||||||
this_instr->op.code = RESUME_CHECK;
|
|
||||||
}
|
}
|
||||||
|
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
}
|
||||||
|
this_instr->op.code = RESUME_CHECK;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4811,7 +4812,7 @@
|
||||||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||||
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
|
||||||
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
assert((version & _PY_EVAL_EVENTS_MASK) == 0);
|
||||||
DEOPT_IF(eval_breaker != version, RESUME);
|
DEOPT_IF(eval_breaker != version && tstate->tracing == 0, RESUME);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1156,15 +1156,13 @@ int
|
||||||
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
|
assert(tstate->tracing == 0);
|
||||||
assert(is_version_up_to_date(code, tstate->interp));
|
assert(is_version_up_to_date(code, tstate->interp));
|
||||||
assert(instrumentation_cross_checks(tstate->interp, code));
|
assert(instrumentation_cross_checks(tstate->interp, code));
|
||||||
int i = (int)(instr - _PyCode_CODE(code));
|
int i = (int)(instr - _PyCode_CODE(code));
|
||||||
|
|
||||||
_PyCoMonitoringData *monitoring = code->_co_monitoring;
|
_PyCoMonitoringData *monitoring = code->_co_monitoring;
|
||||||
_PyCoLineInstrumentationData *line_data = &monitoring->lines[i];
|
_PyCoLineInstrumentationData *line_data = &monitoring->lines[i];
|
||||||
if (tstate->tracing) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
int8_t line_delta = line_data->line_delta;
|
int8_t line_delta = line_data->line_delta;
|
||||||
int line = compute_line(code, i, line_delta);
|
int line = compute_line(code, i, line_delta);
|
||||||
|
|
Loading…
Reference in New Issue