mirror of
https://github.com/python/cpython.git
synced 2025-07-10 04:45:36 +00:00
GH-121131: Clean up and fix some instrumented instructions. (GH-121132)
* Add support for 'prev_instr' to code generator and refactor some INSTRUMENTED instructions
This commit is contained in:
parent
d9efa45d74
commit
afb0aa6ed2
15 changed files with 277 additions and 215 deletions
222
Python/generated_cases.c.h
generated
222
Python/generated_cases.c.h
generated
|
@ -3657,6 +3657,41 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(INSTRUMENTED_LINE) {
|
||||
_Py_CODEUNIT *prev_instr = frame->instr_ptr;
|
||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||
(void)this_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_LINE);
|
||||
int original_opcode = 0;
|
||||
if (tstate->tracing) {
|
||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||
original_opcode = code->_co_monitoring->lines[(int)(this_instr - _PyCode_CODE(code))].original_opcode;
|
||||
next_instr = this_instr;
|
||||
} else {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
original_opcode = _Py_call_instrumentation_line(
|
||||
tstate, frame, this_instr, prev_instr);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (original_opcode < 0) {
|
||||
next_instr = this_instr+1;
|
||||
goto error;
|
||||
}
|
||||
next_instr = frame->instr_ptr;
|
||||
if (next_instr != this_instr) {
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
if (_PyOpcode_Caches[original_opcode]) {
|
||||
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
||||
/* Prevent the underlying instruction from specializing
|
||||
* and overwriting the instrumentation. */
|
||||
PAUSE_ADAPTIVE_COUNTER(cache->counter);
|
||||
}
|
||||
opcode = original_opcode;
|
||||
DISPATCH_GOTO();
|
||||
}
|
||||
|
||||
TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) {
|
||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||
(void)this_instr;
|
||||
|
@ -3785,23 +3820,44 @@
|
|||
(void)this_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_RETURN_CONST);
|
||||
PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_RETURN,
|
||||
frame, this_instr, retval);
|
||||
if (err) goto error;
|
||||
Py_INCREF(retval);
|
||||
assert(EMPTY());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
assert(frame != &entry_frame);
|
||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
_PyEval_FrameClearAndPop(tstate, dying);
|
||||
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(retval));
|
||||
LOAD_IP(frame->return_offset);
|
||||
goto resume_frame;
|
||||
_PyStackRef value;
|
||||
_PyStackRef val;
|
||||
_PyStackRef retval;
|
||||
_PyStackRef res;
|
||||
// _LOAD_CONST
|
||||
{
|
||||
value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
|
||||
}
|
||||
// _RETURN_VALUE_EVENT
|
||||
val = value;
|
||||
{
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_RETURN,
|
||||
frame, this_instr, PyStackRef_AsPyObjectBorrow(val));
|
||||
if (err) goto error;
|
||||
}
|
||||
// _RETURN_VALUE
|
||||
retval = val;
|
||||
{
|
||||
#if TIER_ONE
|
||||
assert(frame != &entry_frame);
|
||||
#endif
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(EMPTY());
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
_PyEval_FrameClearAndPop(tstate, dying);
|
||||
LOAD_SP();
|
||||
LOAD_IP(frame->return_offset);
|
||||
res = retval;
|
||||
LLTRACE_RESUME_FRAME();
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(INSTRUMENTED_RETURN_VALUE) {
|
||||
|
@ -3809,24 +3865,41 @@
|
|||
(void)this_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE);
|
||||
_PyStackRef val;
|
||||
_PyStackRef retval;
|
||||
retval = stack_pointer[-1];
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_RETURN,
|
||||
frame, this_instr, PyStackRef_AsPyObjectBorrow(retval));
|
||||
if (err) goto error;
|
||||
STACK_SHRINK(1);
|
||||
assert(EMPTY());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
assert(frame != &entry_frame);
|
||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
_PyEval_FrameClearAndPop(tstate, dying);
|
||||
_PyFrame_StackPush(frame, retval);
|
||||
LOAD_IP(frame->return_offset);
|
||||
goto resume_frame;
|
||||
_PyStackRef res;
|
||||
// _RETURN_VALUE_EVENT
|
||||
val = stack_pointer[-1];
|
||||
{
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_RETURN,
|
||||
frame, this_instr, PyStackRef_AsPyObjectBorrow(val));
|
||||
if (err) goto error;
|
||||
}
|
||||
// _RETURN_VALUE
|
||||
retval = val;
|
||||
{
|
||||
#if TIER_ONE
|
||||
assert(frame != &entry_frame);
|
||||
#endif
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(EMPTY());
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
_PyEval_FrameClearAndPop(tstate, dying);
|
||||
LOAD_SP();
|
||||
LOAD_IP(frame->return_offset);
|
||||
res = retval;
|
||||
LLTRACE_RESUME_FRAME();
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(INSTRUMENTED_YIELD_VALUE) {
|
||||
|
@ -3834,30 +3907,65 @@
|
|||
(void)this_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE);
|
||||
_PyStackRef val;
|
||||
_PyStackRef retval;
|
||||
retval = stack_pointer[-1];
|
||||
assert(frame != &entry_frame);
|
||||
frame->instr_ptr = next_instr;
|
||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||
assert(oparg == 0 || oparg == 1);
|
||||
gen->gi_frame_state = FRAME_SUSPENDED + oparg;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer - 1);
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_YIELD,
|
||||
frame, this_instr, PyStackRef_AsPyObjectBorrow(retval));
|
||||
if (err) goto error;
|
||||
tstate->exc_info = gen->gi_exc_state.previous_item;
|
||||
gen->gi_exc_state.previous_item = NULL;
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
_PyInterpreterFrame *gen_frame = frame;
|
||||
frame = tstate->current_frame = frame->previous;
|
||||
gen_frame->previous = NULL;
|
||||
_PyFrame_StackPush(frame, retval);
|
||||
/* We don't know which of these is relevant here, so keep them equal */
|
||||
assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
|
||||
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
|
||||
goto resume_frame;
|
||||
_PyStackRef value;
|
||||
// _YIELD_VALUE_EVENT
|
||||
val = stack_pointer[-1];
|
||||
{
|
||||
SAVE_SP();
|
||||
int err = _Py_call_instrumentation_arg(
|
||||
tstate, PY_MONITORING_EVENT_PY_YIELD,
|
||||
frame, this_instr, PyStackRef_AsPyObjectBorrow(val));
|
||||
LOAD_SP();
|
||||
if (err) goto error;
|
||||
if (frame->instr_ptr != this_instr) {
|
||||
next_instr = frame->instr_ptr;
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
// _YIELD_VALUE
|
||||
retval = val;
|
||||
{
|
||||
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
||||
// The compiler treats any exception raised here as a failed close()
|
||||
// or throw() call.
|
||||
#if TIER_ONE
|
||||
assert(frame != &entry_frame);
|
||||
#endif
|
||||
frame->instr_ptr++;
|
||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||
assert(oparg == 0 || oparg == 1);
|
||||
gen->gi_frame_state = FRAME_SUSPENDED + oparg;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
tstate->exc_info = gen->gi_exc_state.previous_item;
|
||||
gen->gi_exc_state.previous_item = NULL;
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
_PyInterpreterFrame *gen_frame = frame;
|
||||
frame = tstate->current_frame = frame->previous;
|
||||
gen_frame->previous = NULL;
|
||||
/* We don't know which of these is relevant here, so keep them equal */
|
||||
assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
|
||||
#if TIER_ONE
|
||||
assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE ||
|
||||
frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION ||
|
||||
_PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND ||
|
||||
_PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER ||
|
||||
_PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT ||
|
||||
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
|
||||
#endif
|
||||
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
|
||||
LOAD_SP();
|
||||
value = retval;
|
||||
LLTRACE_RESUME_FRAME();
|
||||
}
|
||||
stack_pointer[0] = value;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(INTERPRETER_EXIT) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue