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

Commit cbeb1b4

Browse files
author
Anselm Kruis
committed
Stackless issue #254: simplify Stackless mods of interpreter main loop
Eliminate duplicated code to prepare for merging the changes introduced by bpo-17611.
1 parent 9de60fd commit cbeb1b4

File tree

1 file changed

+74
-108
lines changed

1 file changed

+74
-108
lines changed

Python/ceval.c

Lines changed: 74 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
556556
(!((x) >> 24) ? 2 : 3 ))))
557557
#ifdef LLTRACE
558558
#define LLTRACE_HANDLE_UNWINDING(obj__, msg__) \
559-
lltrace && prtrace((obj__), (msg__))
559+
(void)(lltrace && prtrace((obj__), (msg__)))
560560
#else
561-
#define LLTRACE_HANDLE_UNWINDING(obj__, msg__) 1
561+
#define LLTRACE_HANDLE_UNWINDING(obj__, msg__) (void)1
562562
#endif
563563

564564
#define HANDLE_UNWINDING(frame_func, has_opcode, retval__) \
@@ -616,6 +616,20 @@ do { \
616616
next_instr += 1 + EXTENDED_ARG_OFFSET(oparg); \
617617
LLTRACE_HANDLE_UNWINDING((retval__), "handle_unwinding end:");\
618618
} while(0)
619+
620+
/* To be called in the slp_continue_<xxxx> block, if
621+
* HANDLE_UNWINDING is used with has_opcode==1
622+
*/
623+
#define SLP_SET_OPCODE_AND_OPARG() \
624+
do { \
625+
NEXTOPARG(); \
626+
while (opcode == EXTENDED_ARG) { \
627+
int oldoparg = oparg; \
628+
NEXTOPARG(); \
629+
oparg |= oldoparg << 8; \
630+
} \
631+
} while(0)
632+
619633
#endif
620634

621635
PyObject* _Py_HOT_FUNCTION
@@ -1036,118 +1050,38 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
10361050
/* this is a return */
10371051
PUSH(retval); /* we are back from a function call */
10381052
}
1039-
else {
1040-
if (f->f_execute == slp_eval_frame_noval) {
1041-
/* don't push it, frame ignores value */
1042-
Py_XDECREF(retval);
1043-
}
1044-
else if (f->f_execute == slp_eval_frame_iter) {
1045-
/* finalise the for_iter operation */
1046-
NEXTOPARG();
1047-
if (opcode == EXTENDED_ARG) {
1048-
int oldoparg = oparg;
1049-
NEXTOPARG();
1050-
oparg |= oldoparg << 8;
1051-
}
1052-
assert(opcode == FOR_ITER);
1053-
1054-
if (retval != NULL) {
1055-
PUSH(retval);
1056-
}
1057-
else if (!PyErr_Occurred()) {
1058-
/* iterator ended normally */
1059-
assert(retval == NULL); /* to prevent reference leaks */
1060-
retval = POP();
1061-
Py_DECREF(retval);
1062-
/* perform the delayed block jump */
1063-
JUMPBY(oparg);
1064-
}
1065-
else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
1066-
/* we need to check for stopiteration because
1067-
* somebody might inject this as a real
1068-
* exception.
1069-
*/
1070-
if (tstate->c_tracefunc != NULL)
1071-
call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f);
1072-
PyErr_Clear();
1073-
assert(retval == NULL); /* to prevent reference leaks */
1074-
retval = POP();
1075-
Py_DECREF(retval);
1076-
JUMPBY(oparg);
1077-
}
1078-
}
1079-
else if (f->f_execute == slp_eval_frame_setup_with) {
1080-
/* finalise the SETUP_WITH operation */
1081-
NEXTOPARG();
1082-
if (opcode == EXTENDED_ARG) {
1083-
int oldoparg = oparg;
1084-
NEXTOPARG();
1085-
oparg |= oldoparg << 8;
1086-
}
1087-
assert(opcode == SETUP_WITH);
1088-
1089-
if (retval) {
1090-
/* Setup a finally block before pushing the result of
1091-
__enter__ on the stack. */
1092-
PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg,
1093-
STACK_LEVEL());
1094-
1095-
PUSH(retval);
1096-
}
1097-
}
1098-
else if (f->f_execute == slp_eval_frame_with_cleanup) {
1099-
/* finalise the WITH_CLEANUP_START operation */
1100-
if (retval) {
1101-
/* recompute exc */
1102-
PyObject *exc = TOP();
1103-
if (PyLong_Check(exc))
1104-
exc = Py_None;
1105-
Py_INCREF(exc); /* Duplicating the exception on the stack */
1106-
PUSH(exc);
1107-
PUSH(retval);
1108-
/* XXX: The main loop contains a PREDICT(WITH_CLEANUP_FINISH);
1109-
* I wonder, if we must use it here?
1110-
* If so, then set f_execute too.
1111-
*/
1112-
/*f->f_execute = PyEval_EvalFrame_value;
1113-
PREDICT(WITH_CLEANUP_FINISH); */
1114-
}
1115-
}
1116-
else if (f->f_execute == slp_eval_frame_yield_from) {
1117-
/* finalise the YIELD_FROM operation */
1118-
PyObject *receiver = TOP();
1119-
if (retval == NULL) {
1120-
int err;
1121-
if (tstate->c_tracefunc != NULL
1122-
&& PyErr_ExceptionMatches(PyExc_StopIteration))
1123-
call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f);
1124-
err = _PyGen_FetchStopIterationValue(&retval);
1125-
if (err < 0) {
1126-
retval = NULL;
1127-
}
1128-
else {
1129-
Py_DECREF(receiver);
1130-
SET_TOP(retval);
1131-
}
1132-
}
1133-
else {
1134-
/* receiver remains on stack, retval is value to be yielded */
1135-
f->f_stacktop = stack_pointer;
1136-
why = WHY_YIELD;
1137-
/* and repeat... */
1138-
assert(f->f_lasti >= (int)sizeof(_Py_CODEUNIT));
1139-
f->f_lasti -= sizeof(_Py_CODEUNIT);
1140-
goto fast_yield;
1141-
}
1142-
}
1143-
else
1144-
Py_FatalError("invalid frame function");
1053+
else if (f->f_execute == slp_eval_frame_noval) {
1054+
f->f_execute = slp_eval_frame_value;
1055+
/* don't push it, frame ignores value */
1056+
Py_XDECREF(retval);
1057+
}
1058+
else if (f->f_execute == slp_eval_frame_iter) {
1059+
f->f_execute = slp_eval_frame_value;
1060+
goto slp_continue_slp_eval_frame_iter;
1061+
}
1062+
else if (f->f_execute == slp_eval_frame_setup_with) {
1063+
f->f_execute = slp_eval_frame_value;
1064+
goto slp_continue_slp_eval_frame_setup_with;
1065+
}
1066+
else if (f->f_execute == slp_eval_frame_with_cleanup) {
1067+
f->f_execute = slp_eval_frame_value;
1068+
goto slp_continue_slp_eval_frame_with_cleanup;
1069+
}
1070+
else if (f->f_execute == slp_eval_frame_yield_from) {
11451071
f->f_execute = slp_eval_frame_value;
1072+
goto slp_continue_slp_eval_frame_yield_from;
11461073
}
1074+
else
1075+
Py_FatalError("invalid frame function");
11471076

11481077
/* always check for an error flag */
11491078
if (retval == NULL)
11501079
goto error;
1080+
/* At this point retval contains an uncounted reference.
1081+
* We set it to NULL, to match C-Python code, which initializes
1082+
* retval to NULL;
1083+
*/
1084+
retval = NULL;
11511085
#endif
11521086

11531087
#ifdef Py_DEBUG
@@ -2033,6 +1967,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
20331967
if (STACKLESS_UNWINDING(retval)) {
20341968
HANDLE_UNWINDING(slp_eval_frame_yield_from, 0, retval);
20351969
}
1970+
if (0) {
1971+
slp_continue_slp_eval_frame_yield_from:
1972+
/* Initialize variables */
1973+
receiver = TOP();
1974+
}
20361975
#endif
20371976
if (retval == NULL) {
20381977
PyObject *val;
@@ -3057,6 +2996,16 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
30572996
if (STACKLESS_UNWINDING(next)) {
30582997
HANDLE_UNWINDING(slp_eval_frame_iter, 1, next);
30592998
}
2999+
if (0) {
3000+
slp_continue_slp_eval_frame_iter:
3001+
SLP_SET_OPCODE_AND_OPARG();
3002+
assert(opcode == FOR_ITER);
3003+
3004+
/* Initialize variables */
3005+
iter = TOP();
3006+
next = retval;
3007+
retval = NULL;
3008+
}
30603009
#else
30613010
next = (*iter->ob_type->tp_iternext)(iter);
30623011
#endif
@@ -3164,6 +3113,14 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
31643113
if (STACKLESS_UNWINDING(res)) {
31653114
HANDLE_UNWINDING(slp_eval_frame_setup_with, 1, res);
31663115
}
3116+
if(0) {
3117+
slp_continue_slp_eval_frame_setup_with:
3118+
SLP_SET_OPCODE_AND_OPARG();
3119+
assert(opcode == SETUP_WITH);
3120+
/* Initialize variables */
3121+
res = retval;
3122+
retval = NULL;
3123+
}
31673124
#endif
31683125
if (res == NULL)
31693126
goto error;
@@ -3263,6 +3220,15 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
32633220
if (STACKLESS_UNWINDING(res)) {
32643221
HANDLE_UNWINDING(slp_eval_frame_with_cleanup, 0, res);
32653222
}
3223+
if (0) {
3224+
slp_continue_slp_eval_frame_with_cleanup:
3225+
/* Initialize variables */
3226+
exc = TOP();
3227+
if (PyLong_Check(exc))
3228+
exc = Py_None;
3229+
res = retval;
3230+
retval = NULL;
3231+
}
32663232
#endif
32673233
if (res == NULL)
32683234
goto error;

0 commit comments

Comments
 (0)