Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Stackless issue #272: convert macro HANDLE_UNWINDING to a function #273

Merged
63 changes: 63 additions & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#define LLTRACE_HANDLE_UNWINDING(obj__, msg__) (void)1
#endif

#if 1
static inline int
handle_unwinding(int lineno, PyFrameObject *f,
PyObject **stack_pointer, int oparg, PyThreadState *tstate,
const _Py_CODEUNIT *first_instr, const _Py_CODEUNIT *next_instr,
char frame_func, int has_opcode, PyObject **pretval);
#define HANDLE_UNWINDING(frame_func, has_opcode, retval__) \
if (handle_unwinding(__LINE__, f, stack_pointer, oparg, tstate, \
first_instr, next_instr, (frame_func), (has_opcode), &(retval__)))\
return (retval__)
#else
/* keep the old macro in case of performance problems */
#define HANDLE_UNWINDING(frame_func, has_opcode, retval__) \
do { \
if (has_opcode) \
Expand Down Expand Up @@ -642,6 +654,7 @@ do { \
next_instr += 1 + EXTENDED_ARG_OFFSET(oparg); \
LLTRACE_HANDLE_UNWINDING((retval__), "handle_unwinding end:");\
} while(0)
#endif

/* To be called in the slp_continue_<xxxx> block, if
* HANDLE_UNWINDING is used with has_opcode==1
Expand Down Expand Up @@ -3824,6 +3837,56 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)


#ifdef STACKLESS
static inline int
handle_unwinding(int lineno, PyFrameObject *f,
PyObject **stack_pointer, int oparg, PyThreadState *tstate,
const _Py_CODEUNIT *first_instr, const _Py_CODEUNIT *next_instr,
char frame_func, int has_opcode, PyObject **pretval)
{
assert(*pretval); /* check argument */
if (has_opcode)
next_instr -= 1 + EXTENDED_ARG_OFFSET(oparg);
assert(SLP_FRAME_EXECUTING_VALUE == f->f_executing);
if (frame_func != SLP_FRAME_EXECUTING_VALUE) {
f->f_executing = frame_func;
/* check argument: must be an executing frame with retval */
assert(frame_func != SLP_FRAME_EXECUTING_NOVAL);
assert(SLP_FRAME_IS_EXECUTING(f));
}
/* keep the reference to the frame to be called. */
f->f_stacktop = stack_pointer;
/* Set f->f_lasti to the instruction before the current one or to the */
/* first instruction (-1). See "f->f_lasti refers to ..." above. */
f->f_lasti = INSTR_OFFSET() != 0 ?
assert(INSTR_OFFSET() >= sizeof(_Py_CODEUNIT)),
(int)(INSTR_OFFSET() - sizeof(_Py_CODEUNIT)) : -1;
if (SLP_PEEK_NEXT_FRAME(tstate)->f_back != f) {
LLTRACE_HANDLE_UNWINDING(STACKLESS_RETVAL(tstate, *pretval), "handle_unwinding return:");
return 1;
}
STACKLESS_UNPACK(tstate, *pretval);
{
LLTRACE_HANDLE_UNWINDING(*pretval, "handle_unwinding call next frame:");
PyFrameObject *f2 = SLP_CLAIM_NEXT_FRAME(tstate);
*pretval = CALL_FRAME_FUNCTION(f2, 0, *pretval);
Py_DECREF(f2);
if (SLP_PEEK_NEXT_FRAME(tstate) != f) {
assert(f->f_executing == (frame_func));
LLTRACE_HANDLE_UNWINDING(STACKLESS_RETVAL(tstate, *pretval), "handle_unwinding return from next frame:");
return 1;
}
f2 = SLP_CLAIM_NEXT_FRAME(tstate);
assert(f == f2);
Py_DECREF(f2);
}
if (STACKLESS_UNWINDING(*pretval))
STACKLESS_UNPACK(tstate, *pretval);
f->f_stacktop = NULL;
assert(f->f_executing == frame_func);
f->f_executing = SLP_FRAME_EXECUTING_VALUE;
LLTRACE_HANDLE_UNWINDING(*pretval, "handle_unwinding end:");
return 0;
}

static PyObject *
run_frame_dispatch(PyCFrameObject *cf, int exc, PyObject *retval)
Expand Down