typedef struct _PyInterpreterFrame {
/* "Specials" section */
- PyFunctionObject *f_func; /* Strong reference */
+ PyObject *f_funcobj; /* Strong reference */
PyObject *f_globals; /* Borrowed reference */
PyObject *f_builtins; /* Borrowed reference */
PyObject *f_locals; /* Strong reference, may be NULL */
_PyInterpreterFrame *frame, PyFunctionObject *func,
PyObject *locals, PyCodeObject *code)
{
- frame->f_func = func;
+ frame->f_funcobj = (PyObject *)func;
frame->f_code = (PyCodeObject *)Py_NewRef(code);
frame->f_builtins = func->func_builtins;
frame->f_globals = func->func_globals;
--- /dev/null
+The internal field ``_PyInterpreterFrame.f_func`` is renamed to
+``_PyInterpreterFrame.f_funcobj`` and may be any object. The ``f_globals``
+and ``f_builtin`` fields may hold junk values.
+
+It is safest to treat the ``_PyInterpreterFrame`` struct as opaque.
static PyObject *
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
{
- PyList_Append(record_list, f->f_func->func_name);
+ if (PyFunction_Check(f->f_funcobj)) {
+ PyList_Append(record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
+ }
return _PyEval_EvalFrameDefault(tstate, f, exc);
}
/* Don't clear code object until the end */
co = frame->f_code;
frame->f_code = NULL;
- Py_CLEAR(frame->f_func);
+ Py_CLEAR(frame->f_funcobj);
Py_CLEAR(frame->f_locals);
PyObject **locals = _PyFrame_GetLocalsArray(frame);
for (int i = 0; i < frame->stacktop; i++) {
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
// here:
int lasti = _PyInterpreterFrame_LASTI(frame);
- if (lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS) {
+ if (lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS
+ && PyFunction_Check(frame->f_funcobj))
+ {
/* Free vars have not been initialized -- Do that */
PyCodeObject *co = frame->f_code;
- PyObject *closure = frame->f_func->func_closure;
+ PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
int offset = co->co_nlocals + co->co_nplaincellvars;
for (int i = 0; i < co->co_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
- PyFunctionObject *f = frame->f_func;
- if (f == NULL) {
+ PyObject *fobj = frame->f_funcobj;
+ if (fobj == NULL || !PyFunction_Check(fobj)) {
printf("\nResuming frame.");
return;
}
+ PyFunctionObject *f = (PyFunctionObject *)fobj;
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
PyObject *name = f->func_qualname;
TARGET(COPY_FREE_VARS) {
/* Copy closure variables to free variables */
PyCodeObject *co = frame->f_code;
- PyObject *closure = frame->f_func->func_closure;
+ assert(PyFunction_Check(frame->f_funcobj));
+ PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
int offset = co->co_nlocals + co->co_nplaincellvars;
assert(oparg == co->co_nfreevars);
for (int i = 0; i < oparg; ++i) {
}
TARGET(RETURN_GENERATOR) {
- PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(frame->f_func);
+ assert(PyFunction_Check(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
if (gen == NULL) {
goto error;
}
/* Make sure that frame is in a valid state */
frame->stacktop = 0;
frame->f_locals = NULL;
- Py_INCREF(frame->f_func);
+ Py_INCREF(frame->f_funcobj);
Py_INCREF(frame->f_code);
/* Restore previous cframe and return. */
tstate->cframe = cframe.previous;
{
Py_VISIT(frame->frame_obj);
Py_VISIT(frame->f_locals);
- Py_VISIT(frame->f_func);
+ Py_VISIT(frame->f_funcobj);
Py_VISIT(frame->f_code);
/* locals */
PyObject **locals = _PyFrame_GetLocalsArray(frame);
}
Py_XDECREF(frame->frame_obj);
Py_XDECREF(frame->f_locals);
- Py_DECREF(frame->f_func);
+ Py_DECREF(frame->f_funcobj);
Py_DECREF(frame->f_code);
}