Skip to content

Commit

Permalink
Switch back to linked frame traversal
Browse files Browse the repository at this point in the history
Traverse from the top (newest) of stack to oldest, as a linked
reference, instead of linking every frame against rootstate. This
behavior is expected by the tests.

Also fix f_back processing because Py 3.11 only tracks f_back
when FRAME_OWNED_BY_FRAME_OBJECT, i.e. the frame finished executing.
We don't always have this luxary.

For #41
  • Loading branch information
zhuyifei1999 committed May 13, 2023
1 parent 6f91e4c commit 435b5d5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
20 changes: 5 additions & 15 deletions src/heapy/rootstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,27 +435,17 @@ rootstate_traverse(NyHeapTraverse *ta)
ts = is->tstate_head;
#endif
for (; ts; ts = ts->next) {
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 11
PyFrameObject *frame;
if (ts == bts && hv->limitframe) {
frame = (PyFrameObject *)Py_NewRef(hv->limitframe);
Py_VISIT(hv->limitframe);
} else if (!hv->limitframe) {
frame = PyThreadState_GetFrame(ts);
}

while (frame) {
PyFrameObject *next_frame = PyFrame_GetBack(frame);
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 11
PyFrameObject *frame = PyThreadState_GetFrame(ts);
Py_VISIT(frame);
Py_DECREF(frame);
frame = next_frame;
}
Py_XDECREF(frame);
#else
if (ts == bts && hv->limitframe) {
Py_VISIT(hv->limitframe);
} else if (!hv->limitframe) {
Py_VISIT(ts->frame);
}
#endif
}
Py_VISIT(ts->c_profileobj);
Py_VISIT(ts->c_traceobj);

Expand Down
15 changes: 14 additions & 1 deletion src/heapy/stdtypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ frame_relate(NyHeapRelate *r)
Py_ssize_t ncells = PyTuple_GET_SIZE(co->co_cellvars);
Py_ssize_t nlocals = co->co_nlocals;;
Py_ssize_t nfreevars = PyTuple_GET_SIZE(co->co_freevars);
#endif
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 11
// Py 3.11 only holds f_back when FRAME_OWNED_BY_FRAME_OBJECT
PyFrameObject *next_frame = PyFrame_GetBack(v);
if ((PyObject *)next_frame == r->tgt && r->visit(
NYHR_ATTRIBUTE, PyUnicode_FromString("f_back"), r)) {
Py_XDECREF(next_frame);
return 1;
}
Py_XDECREF(next_frame);
#endif
ATTR(f_back)
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 11
Expand Down Expand Up @@ -335,7 +345,10 @@ frame_traverse(NyHeapTraverse *ta) {
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 11
/* _PyFrame_Traverse is not exposed and CPython's frame_traverse only
calls it when FRAME_OWNED_BY_FRAME_OBJECT :( */
Py_VISIT(v->f_back);
PyFrameObject *next_frame = PyFrame_GetBack(v);
Py_VISIT(next_frame);
Py_XDECREF(next_frame);

Py_VISIT(v->f_trace);
Py_VISIT(iv->f_func);
Py_VISIT(iv->f_code);
Expand Down

0 comments on commit 435b5d5

Please sign in to comment.