Skip to content

Commit 5234a8f

Browse files
author
Anselm Kruis
committed
Stackless issue python#187: refactor the Stackless ceval.c patch
Replace jumping around with gotos by a quite large macro.
1 parent 57ca0f4 commit 5234a8f

File tree

1 file changed

+68
-96
lines changed

1 file changed

+68
-96
lines changed

Python/ceval.c

Lines changed: 68 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,64 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
548548
return tstate->interp->eval_frame(f, throwflag);
549549
}
550550

551+
#ifdef STACKLESS
552+
#define EXTENDED_ARG_OFFSET(x) \
553+
(assert(sizeof(x) == 4), \
554+
(!((x) >> 8) ? 0 : \
555+
(!((x) >> 16) ? 1 : \
556+
(!((x) >> 24) ? 2 : 3 ))))
557+
558+
#define HANDLE_UNWINDING(frame_func, has_opcode, retval__) \
559+
do { \
560+
if (has_opcode) \
561+
next_instr -= 1 + EXTENDED_ARG_OFFSET(oparg); \
562+
SLP_DISABLE_GCC_W_ADDRESS /* suppress warning, if frame_func is a function */ \
563+
if (frame_func != NULL) { \
564+
SLP_RESTORE_WARNINGS \
565+
f->f_execute = (frame_func); \
566+
} \
567+
/* keep the reference to the frame to be called. */ \
568+
f->f_stacktop = stack_pointer; \
569+
/* Set f->f_lasti to the instruction before the current one or to the */ \
570+
/* first instruction (-1). See "f->f_lasti refers to ..." above. */ \
571+
f->f_lasti = INSTR_OFFSET() != 0 ? \
572+
assert(INSTR_OFFSET() >= sizeof(_Py_CODEUNIT)), \
573+
(int)(INSTR_OFFSET() - sizeof(_Py_CODEUNIT)) : -1; \
574+
if (SLP_PEEK_NEXT_FRAME(tstate)->f_back != f) \
575+
return (retval__); \
576+
STACKLESS_UNPACK(tstate, (retval__)); \
577+
{ \
578+
PyFrameObject *f2 = SLP_CLAIM_NEXT_FRAME(tstate); \
579+
(retval__) = CALL_FRAME_FUNCTION(f2, 0, (retval__)); \
580+
Py_DECREF(f2); \
581+
if (SLP_PEEK_NEXT_FRAME(tstate) != f) { \
582+
assert(f->f_execute == slp_eval_frame_value || f->f_execute == slp_eval_frame_noval || \
583+
f->f_execute == slp_eval_frame_setup_with || f->f_execute == slp_eval_frame_with_cleanup); \
584+
if (f->f_execute == slp_eval_frame_noval) \
585+
f->f_execute = slp_eval_frame_value; \
586+
return (retval__); \
587+
} \
588+
f2 = SLP_CLAIM_NEXT_FRAME(tstate); \
589+
assert(f == f2); \
590+
Py_DECREF(f2); \
591+
} \
592+
if (STACKLESS_UNWINDING(retval__)) \
593+
STACKLESS_UNPACK(tstate, (retval__)); \
594+
f->f_stacktop = NULL; \
595+
SLP_DISABLE_GCC_W_ADDRESS /* suppress warning, if frame_func is a function */ \
596+
if (frame_func != NULL) { \
597+
SLP_RESTORE_WARNINGS \
598+
assert(f->f_execute == (frame_func)); \
599+
} \
600+
else { \
601+
assert(f->f_execute == slp_eval_frame_value || f->f_execute == slp_eval_frame_noval); \
602+
} \
603+
f->f_execute = slp_eval_frame_value; \
604+
if (has_opcode) \
605+
next_instr += 1 + EXTENDED_ARG_OFFSET(oparg); \
606+
} while(0)
607+
#endif
608+
551609
PyObject* _Py_HOT_FUNCTION
552610
#ifdef STACKLESS
553611
slp_eval_frame_value(PyFrameObject *f, int throwflag, PyObject *retval)
@@ -2945,10 +3003,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
29453003
STACKLESS_ASSERT();
29463004
}
29473005
if (STACKLESS_UNWINDING(next)) {
2948-
retval = next;
2949-
goto stackless_iter;
2950-
stackless_iter_return:
2951-
next = retval;
3006+
HANDLE_UNWINDING(slp_eval_frame_iter, 1, next);
29523007
iter = TOP();
29533008
}
29543009
#else
@@ -3056,10 +3111,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
30563111
Py_DECREF(enter);
30573112
#ifdef STACKLESS
30583113
if (STACKLESS_UNWINDING(res)) {
3059-
retval = res;
3060-
goto stackless_setup_with;
3061-
stackless_setup_with_return:
3062-
res = retval;
3114+
HANDLE_UNWINDING(slp_eval_frame_setup_with, 1, res);
30633115
}
30643116
#endif
30653117
if (res == NULL)
@@ -3158,10 +3210,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
31583210
Py_DECREF(exit_func);
31593211
#ifdef STACKLESS
31603212
if (STACKLESS_UNWINDING(res)) {
3161-
retval = res;
3162-
goto stackless_with_cleanup;
3163-
stackless_with_cleanup_return:
3164-
res = retval;
3213+
HANDLE_UNWINDING(slp_eval_frame_with_cleanup, 0, res);
31653214
/* recompute exc after the goto */
31663215
exc = TOP();
31673216
if (PyLong_Check(exc))
@@ -3283,8 +3332,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
32833332
}
32843333
#ifdef STACKLESS
32853334
if (STACKLESS_UNWINDING(res)) {
3286-
retval = res;
3287-
goto stackless_call;
3335+
HANDLE_UNWINDING(NULL, 0, res);
32883336
}
32893337
#endif
32903338

@@ -3302,10 +3350,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
33023350
stack_pointer = sp;
33033351
#ifdef STACKLESS
33043352
if (STACKLESS_UNWINDING(res)) {
3305-
retval = res;
3306-
goto stackless_call;
3307-
stackless_call_return:
3308-
res = retval;
3353+
HANDLE_UNWINDING(NULL, 0, res);
33093354
}
33103355
#endif
33113356
PUSH(res);
@@ -3326,8 +3371,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
33263371
Py_DECREF(names);
33273372
#ifdef STACKLESS
33283373
if (STACKLESS_UNWINDING(res)) {
3329-
retval = res;
3330-
goto stackless_call;
3374+
HANDLE_UNWINDING(NULL, 0, res);
33313375
}
33323376
#endif
33333377
PUSH(res);
@@ -3387,12 +3431,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
33873431
Py_XDECREF(kwargs);
33883432
#ifdef STACKLESS
33893433
if (STACKLESS_UNWINDING(result)) {
3390-
retval = result;
3391-
(void) POP(); /* compensate for the PUSH(res) after label stackless_call_return: */
3392-
goto stackless_call;
3393-
}
3434+
(void) POP(); /* top of stack causes a GC related assertion error */
3435+
HANDLE_UNWINDING(NULL, 0, result);
3436+
PUSH(result)
3437+
} else
33943438
#endif
3395-
33963439
SET_TOP(result);
33973440
if (result == NULL) {
33983441
goto error;
@@ -3710,77 +3753,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
37103753

37113754
return _Py_CheckFunctionResult(NULL, retval, "PyEval_EvalFrameEx");
37123755

3713-
stackless_setup_with:
3714-
f->f_execute = slp_eval_frame_setup_with;
3715-
goto stackless_call_with_opcode;
3716-
3717-
stackless_with_cleanup:
3718-
f->f_execute = slp_eval_frame_with_cleanup;
3719-
goto stackless_call;
3720-
3721-
stackless_iter:
3722-
/* restore this opcode and enable frame to handle it */
3723-
f->f_execute = slp_eval_frame_iter;
3724-
stackless_call_with_opcode:
3725-
3726-
#define EXTENDED_ARG_OFFSET(x) \
3727-
(assert(sizeof(x) == 4), \
3728-
(!((x) >> 8) ? 0 : \
3729-
(!((x) >> 16) ? 1 : \
3730-
(!((x) >> 24) ? 2 : 3 ))))
3731-
3732-
next_instr -= 1 + EXTENDED_ARG_OFFSET(oparg);
3733-
3734-
stackless_call:
3735-
/*
3736-
* keep the reference to the frame to be called.
3737-
*/
3738-
f->f_stacktop = stack_pointer;
3739-
3740-
/* Set f->f_lasti to the instruction before the current one or to the
3741-
* first instruction (-1). See "f->f_lasti refers to ..." above.
3742-
*/
3743-
f->f_lasti = INSTR_OFFSET() != 0 ?
3744-
assert(INSTR_OFFSET() >= sizeof(_Py_CODEUNIT)),
3745-
(int)(INSTR_OFFSET() - sizeof(_Py_CODEUNIT)) : -1;
3746-
if (SLP_PEEK_NEXT_FRAME(tstate)->f_back != f)
3747-
return retval;
3748-
STACKLESS_UNPACK(tstate, retval);
3749-
{
3750-
PyFrameObject *f2 = SLP_CLAIM_NEXT_FRAME(tstate);
3751-
retval = CALL_FRAME_FUNCTION(f2, 0, retval);
3752-
Py_DECREF(f2);
3753-
if (SLP_PEEK_NEXT_FRAME(tstate) != f) {
3754-
assert(f->f_execute == slp_eval_frame_value || f->f_execute == slp_eval_frame_noval ||
3755-
f->f_execute == slp_eval_frame_setup_with || f->f_execute == slp_eval_frame_with_cleanup);
3756-
if (f->f_execute == slp_eval_frame_noval)
3757-
f->f_execute = slp_eval_frame_value;
3758-
return retval;
3759-
}
3760-
f2 = SLP_CLAIM_NEXT_FRAME(tstate);
3761-
assert(f == f2);
3762-
Py_DECREF(f2);
3763-
}
3764-
if (STACKLESS_UNWINDING(retval))
3765-
STACKLESS_UNPACK(tstate, retval);
3766-
3767-
f->f_stacktop = NULL;
3768-
if (f->f_execute == slp_eval_frame_iter) {
3769-
next_instr += 1 + EXTENDED_ARG_OFFSET(oparg);;
3770-
f->f_execute = slp_eval_frame_value;
3771-
goto stackless_iter_return;
3772-
}
3773-
else if (f->f_execute == slp_eval_frame_setup_with) {
3774-
next_instr += 1 + EXTENDED_ARG_OFFSET(oparg);
3775-
f->f_execute = slp_eval_frame_value;
3776-
goto stackless_setup_with_return;
3777-
}
3778-
else if (f->f_execute == slp_eval_frame_with_cleanup) {
3779-
f->f_execute = slp_eval_frame_value;
3780-
goto stackless_with_cleanup_return;
3781-
}
3782-
3783-
goto stackless_call_return;
37843756

37853757
stackless_interrupt_call:
37863758
/* interrupted during unwinding */

0 commit comments

Comments
 (0)