8000 GH-121131: Clean up and fix some instrumented instructions. (GH-121132) · python/cpython@afb0aa6 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit afb0aa6

Browse files
authored
GH-121131: Clean up and fix some instrumented instructions. (GH-121132)
* Add support for 'prev_instr' to code generator and refactor some INSTRUMENTED instructions
1 parent d9efa45 commit afb0aa6

15 files changed

+277
-215
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_ids.h

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/opcode_ids.h

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/_opcode_metadata.py

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_sys_settrace.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2857,7 +2857,7 @@ def test_no_jump_from_exception_event(output):
28572857
output.append(1)
28582858
1 / 0
28592859

2860-
@jump_test(3, 2, [2, 5], event='return')
2860+
@jump_test(3, 2, [2, 2, 5], event='return')
28612861
def test_jump_from_yield(output):
28622862
def gen():
28632863
output.append(2)

Python/bytecodes.c

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -945,48 +945,25 @@ dummy_func(
945945
LLTRACE_RESUME_FRAME();
946946
}
947947

948-
inst(INSTRUMENTED_RETURN_VALUE, (retval --)) {
948+
tier1 op(_RETURN_VALUE_EVENT, (val -- val)) {
949949
int err = _Py_call_instrumentation_arg(
950950
tstate, PY_MONITORING_EVENT_PY_RETURN,
951-
frame, this_instr, PyStackRef_AsPyObjectBorrow(retval));
951+
frame, this_instr, PyStackRef_AsPyObjectBorrow(val));
952952
if (err) ERROR_NO_POP();
953-
STACK_SHRINK(1);
954-
assert(EMPTY());
955-
_PyFrame_SetStackPointer(frame, stack_pointer);
956-
_Py_LeaveRecursiveCallPy(tstate);
957-
assert(frame != &entry_frame);
958-
// GH-99729: We need to unlink the frame *before* clearing it:
959-
_PyInterpreterFrame *dying = frame;
960-
frame = tstate->current_frame = dying->previous;
961-
_PyEval_FrameClearAndPop(tstate, dying);
962-
_PyFrame_StackPush(frame, retval);
963-
LOAD_IP(frame->return_offset);
964-
goto resume_frame;
965953
}
966954

955+
macro(INSTRUMENTED_RETURN_VALUE) =
956+
_RETURN_VALUE_EVENT +
957+
RETURN_VALUE;
958+
967959
macro(RETURN_CONST) =
968960
LOAD_CONST +
969961
RETURN_VALUE;
970962

971-
inst(INSTRUMENTED_RETURN_CONST, (--)) {
972-
PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg);
973-
int err = _Py_call_instrumentation_arg(
974-
tstate, PY_MONITORING_EVENT_PY_RETURN,
975-
frame, this_instr, retval);
976-
if (err) ERROR_NO_POP();
977-
Py_INCREF(retval);
978-
assert(EMPTY());
979-
_PyFrame_SetStackPointer(frame, stack_pointer);
980-
_Py_LeaveRecursiveCallPy(tstate);
981-
assert(frame != &entry_frame);
982-
// GH-99729: We need to unlink the frame *before* clearing it:
983-
_PyInterpreterFrame *dying = frame;
984-
frame = tstate->current_frame = dying->previous;
985-
_PyEval_FrameClearAndPop(tstate, dying);
986-
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(retval));
987-
LOAD_IP(frame->return_offset);
988-
goto resume_frame;
989-
}
963+
macro(INSTRUMENTED_RETURN_CONST) =
964+
LOAD_CONST +
965+
_RETURN_VALUE_EVENT +
966+
RETURN_VALUE;
990967

991968
inst(GET_AITER, (obj -- iter)) {
992969
unaryfunc getter = NULL;
@@ -1183,31 +1160,6 @@ dummy_func(
11831160
_SEND_GEN_FRAME +
11841161
_PUSH_FRAME;
11851162

1186-
inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) {
1187-
assert(frame != &entry_frame);
1188-
frame->instr_ptr = next_instr;
1189-
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
1190-
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
1191-
assert(oparg == 0 || oparg == 1);
1192-
gen->gi_frame_state = FRAME_SUSPENDED + oparg;
1193-
_PyFrame_SetStackPointer(frame, stack_pointer - 1);
1194-
int err = _Py_call_instrumentation_arg(
1195-
tstate, PY_MONITORING_EVENT_PY_YIELD,
1196-
frame, this_instr, PyStackRef_AsPyObjectBorrow(retval));
1197-
if (err) ERROR_NO_POP();
1198-
tstate->exc_info = gen->gi_exc_state.previous_item;
1199-
gen->gi_exc_state.previous_item = NULL;
1200-
_Py_LeaveRecursiveCallPy(tstate);
1201-
_PyInterpreterFrame *gen_frame = frame;
1202-
frame = tstate->current_frame = frame->previous;
1203-
gen_frame->previous = NULL;
1204-
_PyFrame_StackPush(frame, retval);
1205-
/* We don't know which of these is relevant here, so keep them equal */
1206-
assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
1207-
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
1208-
goto resume_frame;
1209-
}
1210-
12111163
inst(YIELD_VALUE, (retval -- value)) {
12121164
// NOTE: It's important that YIELD_VALUE never raises an exception!
12131165
// The compiler treats any exception raised here as a failed close()
@@ -1244,6 +1196,23 @@ dummy_func(
12441196
LLTRACE_RESUME_FRAME();
12451197
}
12461198

1199+
tier1 op(_YIELD_VALUE_EVENT, (val -- val)) {
1200+
SAVE_SP();
1201+
int err = _Py_call_instrumentation_arg(
1202+
tstate, PY_MONITORING_EVENT_PY_YIELD,
1203+
frame, this_instr, PyStackRef_AsPyObjectBorrow(val));
1204+
LOAD_SP();
1205+
if (err) ERROR_NO_POP();
1206+
if (frame->instr_ptr != this_instr) {
1207+
next_instr = frame->instr_ptr;
1208+
DISPATCH();
1209+
}
1210+
}
1211+
1212+
macro(INSTRUMENTED_YIELD_VALUE) =
1213+
_YIELD_VALUE_EVENT +
1214+
YIELD_VALUE;
1215+
12471216
inst(POP_EXCEPT, (exc_value -- )) {
12481217
_PyErr_StackItem *exc_info = tstate->exc_info;
12491218
Py_XSETREF(exc_info->exc_value,
@@ -4450,6 +4419,36 @@ dummy_func(
44504419
assert(oparg >= 2);
44514420
}
44524421

4422+
inst(INSTRUMENTED_LINE, ( -- )) {
4423+
int original_opcode = 0;
4424+
if (tstate->tracing) {
4425+
PyCodeObject *code = _PyFrame_GetCode(frame);
4426+
original_opcode = code->_co_monitoring->lines[(int)(this_instr - _PyCode_CODE(code))].original_opcode;
4427+
next_instr = this_instr;
4428+
} else {
4429+
_PyFrame_SetStackPointer(frame, stack_pointer);
4430+
original_opcode = _Py_call_instrumentation_line(
4431+
tstate, frame, this_instr, prev_instr);
4432+
stack_pointer = _PyFrame_GetStackPointer(frame);
4433+
if (original_opcode < 0) {
4434+
next_instr = this_instr+1;
4435+
goto error;
4436+
}
4437+
next_instr = frame->instr_ptr;
4438+
if (next_instr != this_instr) {
4439+
DISPATCH();
4440+
}
4441+
}
4442+
if (_PyOpcode_Caches[original_opcode]) {
4443+
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
4444+
/* Prevent the underlying instruction from specializing
4445+
* and overwriting the instrumentation. */
4446+
PAUSE_ADAPTIVE_COUNTER(cache->counter);
4447+
}
4448+
opcode = original_opcode;
4449+
DISPATCH_GOTO();
4450+
}
4451+
44534452
inst(INSTRUMENTED_INSTRUCTION, ( -- )) {
44544453
int next_opcode = _Py_call_instrumentation_instruction(
44554454
tstate, frame, this_instr);

Python/ceval.c

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -835,46 +835,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
835835

836836
#include "generated_cases.c.h"
837837

838-
/* INSTRUMENTED_LINE has to be here, rather than in bytecodes.c,
839-
* because it needs to capture frame->instr_ptr before it is updated,
840-
* as happens in the standard instruction prologue.
841-
*/
842-
#if USE_COMPUTED_GOTOS
843-
TARGET_INSTRUMENTED_LINE:
844-
#else
845-
case INSTRUMENTED_LINE:
846-
#endif
847-
{
848-
_Py_CODEUNIT *prev = frame->instr_ptr;
849-
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
850-
int original_opcode = 0;
851-
if (tstate->tracing) {
852-
PyCodeObject *code = _PyFrame_GetCode(frame);
853-
original_opcode = code->_co_monitoring->lines[(int)(here - _PyCode_CODE(code))].original_opcode;
854-
} else {
855-
_PyFrame_SetStackPointer(frame, stack_pointer);
856-
original_opcode = _Py_call_instrumentation_line(
857-
tstate, frame, here, prev);
858-
stack_pointer = _PyFrame_GetStackPointer(frame);
859-
if (original_opcode < 0) {
860-
next_instr = here+1;
861-
goto error;
862-
}
863-
next_instr = frame->instr_ptr;
864-
if (next_instr != here) {
865-
DISPATCH();
866-
}
867-
}
868-
if (_PyOpcode_Caches[original_opcode]) {
869-
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
870-
/* Prevent the underlying instruction from specializing
871-
* and overwriting the instrumentation. */
872-
PAUSE_ADAPTIVE_COUNTER(cache->counter);
873-
}
874-
opcode = original_opcode;
875-
DISPATCH_GOTO();
876-
}
877-
878838

879839
#if USE_COMPUTED_GOTOS
880840
_unknown_opcode:

Python/ceval_macros.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,10 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
402402
/* There's no STORE_IP(), it's inlined by the code generator. */
403403

404404
#define LOAD_SP() \
405-
stack_pointer = _PyFrame_GetStackPointer(frame);
405+
stack_pointer = _PyFrame_GetStackPointer(frame)
406+
407+
#define SAVE_SP() \
408+
_PyFrame_SetStackPointer(frame, stack_pointer)
406409

407410
/* Tier-switching macros. */
408411

Python/executor_cases.c.h

Lines changed: 2 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
0