aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/generated_cases.c.h
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-07-26 12:24:12 +0100
committerGitHub <noreply@github.com>2024-07-26 12:24:12 +0100
commitafb0aa6ed20bd8e982ecb307f12923cf8dbccd8c (patch)
tree222f3075796f8167442bcc744c52efe3c7c8eaa5 /Python/generated_cases.c.h
parentd9efa45d7457b0dfea467bb1c2d22c69056ffc73 (diff)
downloadcpython-afb0aa6ed20bd8e982ecb307f12923cf8dbccd8c.tar.gz
cpython-afb0aa6ed20bd8e982ecb307f12923cf8dbccd8c.zip
GH-121131: Clean up and fix some instrumented instructions. (GH-121132)
* Add support for 'prev_instr' to code generator and refactor some INSTRUMENTED instructions
Diffstat (limited to 'Python/generated_cases.c.h')
-rw-r--r--Python/generated_cases.c.h222
1 files changed, 165 insertions, 57 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index c9907438ddc..634053a9383 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -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) {