[DELETE_SUBSCR] = { .nuops = 1, .uops = { { DELETE_SUBSCR, 0, 0 } } },
[CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { CALL_INTRINSIC_1, 0, 0 } } },
[CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { CALL_INTRINSIC_2, 0, 0 } } },
- [RETURN_VALUE] = { .nuops = 2, .uops = { { _SAVE_CURRENT_IP, 7, -1 }, { _POP_FRAME, 0, 0 } } },
- [RETURN_CONST] = { .nuops = 3, .uops = { { LOAD_CONST, 0, 0 }, { _SAVE_CURRENT_IP, 7, -1 }, { _POP_FRAME, 0, 0 } } },
+ [RETURN_VALUE] = { .nuops = 1, .uops = { { _POP_FRAME, 0, 0 } } },
+ [RETURN_CONST] = { .nuops = 2, .uops = { { LOAD_CONST, 0, 0 }, { _POP_FRAME, 0, 0 } } },
[GET_AITER] = { .nuops = 1, .uops = { { GET_AITER, 0, 0 } } },
[GET_ANEXT] = { .nuops = 1, .uops = { { GET_ANEXT, 0, 0 } } },
[GET_AWAITABLE] = { .nuops = 1, .uops = { { GET_AWAITABLE, 0, 0 } } },
--- /dev/null
+Remove unnecessary instruction pointer updates before returning from frames.
}
macro(RETURN_VALUE) =
- _SAVE_CURRENT_IP + // Sets frame->prev_instr
_POP_FRAME;
inst(INSTRUMENTED_RETURN_VALUE, (retval --)) {
macro(RETURN_CONST) =
LOAD_CONST +
- _SAVE_CURRENT_IP + // Sets frame->prev_instr
_POP_FRAME;
inst(INSTRUMENTED_RETURN_CONST, (--)) {
TARGET(RETURN_VALUE) {
PyObject *retval;
- // _SAVE_CURRENT_IP
- {
- TIER_ONE_ONLY
- frame->prev_instr = next_instr - 1;
- }
- // _POP_FRAME
retval = stack_pointer[-1];
STACK_SHRINK(1);
- {
- assert(EMPTY());
- #if TIER_ONE
- assert(frame != &entry_frame);
- #endif
- STORE_SP();
- _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);
- frame->prev_instr += frame->return_offset;
- _PyFrame_StackPush(frame, retval);
- LOAD_SP();
- LOAD_IP();
- #if LLTRACE && TIER_ONE
- lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
- if (lltrace < 0) {
- goto exit_unwind;
- }
- #endif
+ assert(EMPTY());
+ #if TIER_ONE
+ assert(frame != &entry_frame);
+ #endif
+ STORE_SP();
+ _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);
+ frame->prev_instr += frame->return_offset;
+ _PyFrame_StackPush(frame, retval);
+ LOAD_SP();
+ LOAD_IP();
+#if LLTRACE && TIER_ONE
+ lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
+ if (lltrace < 0) {
+ goto exit_unwind;
}
+#endif
DISPATCH();
}
value = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(value);
}
- // _SAVE_CURRENT_IP
- {
- TIER_ONE_ONLY
- frame->prev_instr = next_instr - 1;
- }
// _POP_FRAME
retval = value;
{
case OPARG_BOTTOM: // Second half of super-instr
oparg = orig_oparg & 0xF;
break;
- case OPARG_SET_IP: // op==_SET_IP; oparg=next instr
+ case OPARG_SET_IP: // uop=_SET_IP; oparg=next_instr-1
+ // The number of caches is smuggled in via offset:
+ assert(offset == _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]);
oparg = INSTR_IP(instr + offset, code);
uop = _SET_IP;
break;
bool need_ip = true;
for (int pc = 0; pc < trace_length; pc++) {
int opcode = trace[pc].opcode;
- if (opcode == _SAVE_CURRENT_IP) {
- // Special case: never remove preceding _SET_IP
- last_set_ip = -1;
- }
- else if (opcode == _SET_IP) {
+ if (opcode == _SET_IP) {
if (!need_ip && last_set_ip >= 0) {
trace[last_set_ip].opcode = NOP;
}
break;
}
else {
- // If opcode has ERROR or DEOPT, set need_up to true
- if (_PyOpcode_opcode_metadata[opcode].flags & (HAS_ERROR_FLAG | HAS_DEOPT_FLAG)) {
+ // If opcode has ERROR or DEOPT, set need_ip to true
+ if (_PyOpcode_opcode_metadata[opcode].flags & (HAS_ERROR_FLAG | HAS_DEOPT_FLAG) || opcode == _PUSH_FRAME) {
need_ip = true;
}
}