Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 47 additions & 39 deletions Stackless/core/stacklesseval.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ slp_eval_frame(PyFrameObject *f)
PyThreadState *ts = _PyThreadState_GET();
PyFrameObject *fprev = f->f_back;
intptr_t * stackref;
int set_cstack_base;
PyObject *retval;

if (fprev == NULL && ts->st.main == NULL) {
Expand Down Expand Up @@ -345,51 +346,58 @@ slp_eval_frame(PyFrameObject *f)

/* mark the stack base */
stackref = SLP_STACK_REFPLUS + (intptr_t *) &f;
if (ts->st.cstack_base == NULL)
set_cstack_base = ts->st.cstack_base == NULL;
if (set_cstack_base)
ts->st.cstack_base = stackref - SLP_CSTACK_GOODGAP;
if (stackref > ts->st.cstack_base) {
PyCStackObject *initial_stub;
retval = climb_stack_and_eval_frame(f);
initial_stub = ts->st.initial_stub;
/* cst might be NULL in OOM conditions */
if (ts->interp != _PyRuntime.interpreters.main && initial_stub != NULL) {
PyCStackObject *cst;
register int found = 0;
assert(initial_stub->startaddr == ts->st.cstack_base);
for (cst = initial_stub->next; cst != initial_stub; cst = cst->next) {
if (Py_SIZE(cst) != 0 && cst->task != NULL &&
cst->tstate == ts) {
assert(cst->startaddr == ts->st.cstack_base);
found = 1;
break;
}
}
if (!found) {
Py_CLEAR(ts->st.initial_stub);
ts->st.cstack_base = NULL;
ts->st.cstack_root = NULL;
}
retval = climb_stack_and_eval_frame(f); /* recursively calls slp_eval_frame(f) */
} else {
assert(SLP_CURRENT_FRAME(ts) == NULL); /* else we would change the current frame */
SLP_STORE_NEXT_FRAME(ts, f);
returning = make_initial_stub();
if (returning < 0)
return NULL;
/* returning will be 1 if we "switched back" to this stub, and 0
* if this is the original call that just created the stub.
* If the stub is being reused, the argument, i.e. the frame,
* is in ts->frame
*/
SLP_ASSERT_FRAME_IN_TRANSFER(ts);
if (returning != 1) {
assert(f == SLP_PEEK_NEXT_FRAME(ts));
}
return retval;
assert(ts->interp->st.initial_tstate != NULL);
assert(ts->interp->st.mem_bomb != NULL);

retval = slp_run_tasklet();
}

assert(SLP_CURRENT_FRAME(ts) == NULL); /* else we would change the current frame */
SLP_STORE_NEXT_FRAME(ts, f);
returning = make_initial_stub();
if (returning < 0)
return NULL;
/* returning will be 1 if we "switched back" to this stub, and 0
* if this is the original call that just created the stub.
* If the stub is being reused, the argument, i.e. the frame,
* is in ts->frame
*/
SLP_ASSERT_FRAME_IN_TRANSFER(ts);
if (returning != 1) {
assert(f == SLP_PEEK_NEXT_FRAME(ts));
/* Clear the initial stub, except for the main interpreter.
* Without this code, terminating sub-interpreters would leak references. */
if (set_cstack_base /* only for the outermost call */
&& ts->interp != _PyRuntime.interpreters.main /* not for the main interpreter */
&& ts->st.initial_stub != NULL) /* not yet cleared */
{
PyCStackObject *initial_stub = ts->st.initial_stub;
PyCStackObject *cst;
register int found = 0;
assert(initial_stub->startaddr == ts->st.cstack_base);
for (cst = initial_stub->next; cst != initial_stub; cst = cst->next) {
if (Py_SIZE(cst) != 0 && cst->task != NULL &&
cst->tstate == ts) {
assert(cst->startaddr == ts->st.cstack_base);
found = 1; /* Initial stub is still in use. */
break;
}
}
if (!found) {
/* This initial stub is no longer in use, free it */
Py_CLEAR(ts->st.initial_stub);
ts->st.cstack_base = NULL;
ts->st.cstack_root = NULL;
}
}
assert(ts->interp->st.initial_tstate != NULL);
assert(ts->interp->st.mem_bomb != NULL);
return slp_run_tasklet();
return retval;
}
assert(ts->interp->st.initial_tstate != NULL);
assert(ts->interp->st.mem_bomb != NULL); /* see above */
Expand Down