GH-96803: Add three C-API functions to make _PyInterpreterFrame less opaque for users of PEP 523. (GH-96849)

This commit is contained in:
Mark Shannon 2023-05-05 17:53:07 +01:00 committed by GitHub
parent 45a9e3834a
commit a0df9ee8fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 48 additions and 8 deletions

View File

@ -4,6 +4,8 @@
# error "this header file must not be included directly" # error "this header file must not be included directly"
#endif #endif
struct _PyInterpreterFrame;
/* Standard object interface */ /* Standard object interface */
PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
@ -27,3 +29,18 @@ PyAPI_FUNC(int) _PyFrame_IsEntryFrame(PyFrameObject *frame);
PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f); PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f);
PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *); PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
/* The following functions are for use by debuggers and other tools
* implementing custom frame evaluators with PEP 523. */
/* Returns the code object of the frame (strong reference).
* Does not raise an exception. */
PyAPI_FUNC(PyCodeObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
/* Returns a byte ofsset into the last executed instruction.
* Does not raise an exception. */
PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame);
/* Returns the currently executing line number, or -1 if there is no line number.
* Does not raise an exception. */
PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame);

View File

@ -265,8 +265,6 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_l
return new_frame; return new_frame;
} }
int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
static inline static inline
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame) PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
{ {

View File

@ -0,0 +1,6 @@
Add unstable C-API functions to get the code object, lasti and line number from
the internal ``_PyInterpreterFrame`` in the limited API. The functions are:
* ``PyCodeObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)``
* ``int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)``
* ``int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame)``

View File

@ -7,6 +7,7 @@
#include "pycore_runtime.h" // _Py_ID() #include "pycore_runtime.h" // _Py_ID()
#include "pycore_traceback.h" #include "pycore_traceback.h"
#include <pycore_frame.h> #include <pycore_frame.h>
#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include <stdlib.h> // malloc() #include <stdlib.h> // malloc()
@ -257,7 +258,7 @@ static void
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame) tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
{ {
frame->filename = &_Py_STR(anon_unknown); frame->filename = &_Py_STR(anon_unknown);
int lineno = _PyInterpreterFrame_GetLine(pyframe); int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
if (lineno < 0) { if (lineno < 0) {
lineno = 0; lineno = 0;
} }

View File

@ -38,7 +38,7 @@ PyFrame_GetLineNumber(PyFrameObject *f)
return f->f_lineno; return f->f_lineno;
} }
else { else {
return _PyInterpreterFrame_GetLine(f->f_frame); return PyUnstable_InterpreterFrame_GetLine(f->f_frame);
} }
} }

View File

@ -12,6 +12,7 @@
#include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystate.h" // _PyThreadState_GET()
#include "structmember.h" // PyMemberDef #include "structmember.h" // PyMemberDef
#include "opcode.h" // SEND #include "opcode.h" // SEND
#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include "pystats.h" #include "pystats.h"
static PyObject *gen_close(PyGenObject *, PyObject *); static PyObject *gen_close(PyGenObject *, PyObject *);
@ -1322,7 +1323,7 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
frame = current_frame; frame = current_frame;
for (int i = 0; i < frame_count; ++i) { for (int i = 0; i < frame_count; ++i) {
PyCodeObject *code = frame->f_code; PyCodeObject *code = frame->f_code;
int line = _PyInterpreterFrame_GetLine(frame); int line = PyUnstable_InterpreterFrame_GetLine(frame);
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line, PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
code->co_name); code->co_name);
if (!frameinfo) { if (!frameinfo) {

View File

@ -27,6 +27,7 @@
#include "pycore_dict.h" #include "pycore_dict.h"
#include "dictobject.h" #include "dictobject.h"
#include "pycore_frame.h" #include "pycore_frame.h"
#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include "opcode.h" #include "opcode.h"
#include "pydtrace.h" #include "pydtrace.h"
#include "setobject.h" #include "setobject.h"
@ -785,7 +786,7 @@ handle_eval_breaker:
_PyErr_Format(tstate, PyExc_SystemError, _PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d", "%U:%d: unknown opcode %d",
frame->f_code->co_filename, frame->f_code->co_filename,
_PyInterpreterFrame_GetLine(frame), PyUnstable_InterpreterFrame_GetLine(frame),
opcode); opcode);
goto error; goto error;

View File

@ -144,8 +144,24 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
Py_DECREF(frame->f_funcobj); Py_DECREF(frame->f_funcobj);
} }
/* Unstable API functions */
PyCodeObject *
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
{
PyCodeObject *code = frame->f_code;
Py_INCREF(code);
return code;
}
int int
_PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame) PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)
{
return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
}
int
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
{ {
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
return PyCode_Addr2Line(frame->f_code, addr); return PyCode_Addr2Line(frame->f_code, addr);

View File

@ -1180,7 +1180,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
PUTS(fd, "???"); PUTS(fd, "???");
} }
int lineno = _PyInterpreterFrame_GetLine(frame); int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
PUTS(fd, ", line "); PUTS(fd, ", line ");
if (lineno >= 0) { if (lineno >= 0) {
_Py_DumpDecimal(fd, (size_t)lineno); _Py_DumpDecimal(fd, (size_t)lineno);