2021-07-26 18:22:16 +08:00
|
|
|
|
2022-05-18 21:38:43 +08:00
|
|
|
#define _PY_INTERPRETER
|
|
|
|
|
2021-07-26 18:22:16 +08:00
|
|
|
#include "Python.h"
|
|
|
|
#include "frameobject.h"
|
2022-06-19 18:02:33 +08:00
|
|
|
#include "pycore_code.h" // stats
|
2021-07-26 18:22:16 +08:00
|
|
|
#include "pycore_frame.h"
|
|
|
|
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
2022-01-20 19:46:39 +08:00
|
|
|
#include "opcode.h"
|
2021-07-26 18:22:16 +08:00
|
|
|
|
|
|
|
int
|
2022-02-25 23:22:00 +08:00
|
|
|
_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
|
2021-07-26 18:22:16 +08:00
|
|
|
{
|
|
|
|
Py_VISIT(frame->frame_obj);
|
|
|
|
Py_VISIT(frame->f_locals);
|
2024-09-25 04:08:18 +08:00
|
|
|
_Py_VISIT_STACKREF(frame->f_funcobj);
|
|
|
|
_Py_VISIT_STACKREF(frame->f_executable);
|
2024-08-16 00:09:11 +08:00
|
|
|
return _PyGC_VisitFrameStack(frame, visit, arg);
|
2021-07-26 18:22:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyFrameObject *
|
2022-02-25 23:22:00 +08:00
|
|
|
_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
|
2021-07-26 18:22:16 +08:00
|
|
|
{
|
|
|
|
assert(frame->frame_obj == NULL);
|
2023-02-28 19:50:52 +08:00
|
|
|
PyObject *exc = PyErr_GetRaisedException();
|
2021-11-29 20:34:59 +08:00
|
|
|
|
2023-06-14 20:46:37 +08:00
|
|
|
PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame));
|
2021-07-26 18:22:16 +08:00
|
|
|
if (f == NULL) {
|
2023-02-28 19:50:52 +08:00
|
|
|
Py_XDECREF(exc);
|
2022-10-07 07:20:01 +08:00
|
|
|
return NULL;
|
2021-07-26 18:22:16 +08:00
|
|
|
}
|
2023-02-28 19:50:52 +08:00
|
|
|
PyErr_SetRaisedException(exc);
|
2024-03-13 07:35:28 +08:00
|
|
|
|
|
|
|
// GH-97002: There was a time when a frame object could be created when we
|
|
|
|
// are allocating the new frame object f above, so frame->frame_obj would
|
|
|
|
// be assigned already. That path does not exist anymore. We won't call any
|
|
|
|
// Python code in this function and garbage collection will not run.
|
|
|
|
// Notice that _PyFrame_New_NoTrack() can potentially raise a MemoryError,
|
|
|
|
// but it won't allocate a traceback until the frame unwinds, so we are safe
|
|
|
|
// here.
|
|
|
|
assert(frame->frame_obj == NULL);
|
2022-10-07 07:20:01 +08:00
|
|
|
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
|
|
|
|
assert(frame->owner != FRAME_CLEARED);
|
|
|
|
f->f_frame = frame;
|
|
|
|
frame->frame_obj = f;
|
2021-07-26 18:22:16 +08:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-02-25 23:22:00 +08:00
|
|
|
take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
|
2021-07-26 18:22:16 +08:00
|
|
|
{
|
2022-11-10 20:34:57 +08:00
|
|
|
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
|
2022-03-22 20:57:19 +08:00
|
|
|
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
|
|
|
|
assert(frame->owner != FRAME_CLEARED);
|
2024-07-18 19:47:21 +08:00
|
|
|
Py_ssize_t size = ((char*)frame->stackpointer) - (char *)frame;
|
2022-02-25 23:22:00 +08:00
|
|
|
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
|
|
|
|
frame = (_PyInterpreterFrame *)f->_f_frame_data;
|
2024-07-18 19:47:21 +08:00
|
|
|
frame->stackpointer = (_PyStackRef *)(((char *)frame) + size);
|
2024-09-13 00:37:06 +08:00
|
|
|
frame->f_executable = PyStackRef_DUP(frame->f_executable);
|
2021-07-26 18:22:16 +08:00
|
|
|
f->f_frame = frame;
|
2022-03-22 20:57:19 +08:00
|
|
|
frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
|
2022-10-05 08:30:03 +08:00
|
|
|
if (_PyFrame_IsIncomplete(frame)) {
|
|
|
|
// This may be a newly-created generator or coroutine frame. Since it's
|
|
|
|
// dead anyways, just pretend that the first RESUME ran:
|
2023-06-14 20:46:37 +08:00
|
|
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
2024-11-05 03:13:32 +08:00
|
|
|
frame->instr_ptr =
|
|
|
|
_PyFrame_GetBytecode(frame) + code->_co_firsttraceable + 1;
|
2022-10-05 08:30:03 +08:00
|
|
|
}
|
|
|
|
assert(!_PyFrame_IsIncomplete(frame));
|
2021-07-26 18:22:16 +08:00
|
|
|
assert(f->f_back == NULL);
|
2023-01-10 04:20:04 +08:00
|
|
|
_PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous);
|
2022-11-10 20:34:57 +08:00
|
|
|
frame->previous = NULL;
|
2022-07-01 18:08:20 +08:00
|
|
|
if (prev) {
|
2022-11-10 20:34:57 +08:00
|
|
|
assert(prev->owner != FRAME_OWNED_BY_CSTACK);
|
2022-02-25 23:22:00 +08:00
|
|
|
/* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */
|
2022-07-01 18:08:20 +08:00
|
|
|
PyFrameObject *back = _PyFrame_GetFrameObject(prev);
|
2021-07-26 18:22:16 +08:00
|
|
|
if (back == NULL) {
|
|
|
|
/* Memory error here. */
|
|
|
|
assert(PyErr_ExceptionMatches(PyExc_MemoryError));
|
|
|
|
/* Nothing we can do about it */
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
f->f_back = (PyFrameObject *)Py_NewRef(back);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) {
|
|
|
|
_PyObject_GC_TRACK((PyObject *)f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-01 02:32:25 +08:00
|
|
|
void
|
|
|
|
_PyFrame_ClearLocals(_PyInterpreterFrame *frame)
|
|
|
|
{
|
2024-07-18 19:47:21 +08:00
|
|
|
assert(frame->stackpointer != NULL);
|
|
|
|
_PyStackRef *sp = frame->stackpointer;
|
|
|
|
_PyStackRef *locals = frame->localsplus;
|
|
|
|
frame->stackpointer = locals;
|
|
|
|
while (sp > locals) {
|
|
|
|
sp--;
|
|
|
|
PyStackRef_XCLOSE(*sp);
|
2024-05-01 02:32:25 +08:00
|
|
|
}
|
|
|
|
Py_CLEAR(frame->f_locals);
|
|
|
|
}
|
|
|
|
|
2021-11-29 20:34:59 +08:00
|
|
|
void
|
2023-02-23 18:19:01 +08:00
|
|
|
_PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
|
2021-07-26 18:22:16 +08:00
|
|
|
{
|
2021-11-22 22:01:23 +08:00
|
|
|
/* It is the responsibility of the owning generator/coroutine
|
2022-01-20 19:46:39 +08:00
|
|
|
* to have cleared the enclosing generator, if any. */
|
2022-03-22 20:57:19 +08:00
|
|
|
assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
|
2024-06-24 17:23:38 +08:00
|
|
|
_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state == FRAME_CLEARED);
|
2022-12-06 22:01:38 +08:00
|
|
|
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
|
|
|
|
// crucial that this frame has been unlinked, and is no longer visible:
|
2023-08-17 18:16:03 +08:00
|
|
|
assert(_PyThreadState_GET()->current_frame != frame);
|
2021-07-26 18:22:16 +08:00
|
|
|
if (frame->frame_obj) {
|
|
|
|
PyFrameObject *f = frame->frame_obj;
|
|
|
|
frame->frame_obj = NULL;
|
|
|
|
if (Py_REFCNT(f) > 1) {
|
|
|
|
take_ownership(f, frame);
|
|
|
|
Py_DECREF(f);
|
2021-11-29 20:34:59 +08:00
|
|
|
return;
|
2021-07-26 18:22:16 +08:00
|
|
|
}
|
|
|
|
Py_DECREF(f);
|
|
|
|
}
|
2024-05-01 02:32:25 +08:00
|
|
|
_PyFrame_ClearLocals(frame);
|
2024-09-25 04:08:18 +08:00
|
|
|
PyStackRef_CLEAR(frame->f_funcobj);
|
2021-07-26 18:22:16 +08:00
|
|
|
}
|
2022-01-28 20:42:30 +08:00
|
|
|
|
2023-05-06 00:53:07 +08:00
|
|
|
/* Unstable API functions */
|
|
|
|
|
2023-05-18 17:10:15 +08:00
|
|
|
PyObject *
|
2023-05-06 00:53:07 +08:00
|
|
|
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
|
|
|
|
{
|
2024-09-13 00:37:06 +08:00
|
|
|
return PyStackRef_AsPyObjectNew(frame->f_executable);
|
2023-05-06 00:53:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)
|
|
|
|
{
|
|
|
|
return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
|
|
|
}
|
|
|
|
|
2022-04-08 03:31:01 +08:00
|
|
|
int
|
2023-05-06 00:53:07 +08:00
|
|
|
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
|
2022-04-08 03:31:01 +08:00
|
|
|
{
|
|
|
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
2023-06-14 20:46:37 +08:00
|
|
|
return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
|
2022-04-08 03:31:01 +08:00
|
|
|
}
|
2023-06-14 20:46:37 +08:00
|
|
|
|
2023-08-31 15:56:06 +08:00
|
|
|
const PyTypeObject *const PyUnstable_ExecutableKinds[PyUnstable_EXECUTABLE_KINDS+1] = {
|
|
|
|
[PyUnstable_EXECUTABLE_KIND_SKIP] = &_PyNone_Type,
|
|
|
|
[PyUnstable_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type,
|
|
|
|
[PyUnstable_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type,
|
|
|
|
[PyUnstable_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
|
|
|
|
[PyUnstable_EXECUTABLE_KINDS] = NULL,
|
2023-06-14 20:46:37 +08:00
|
|
|
};
|