summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-05-05 17:53:07 +0100
committerGitHub <noreply@github.com>2023-05-05 17:53:07 +0100
commita0df9ee8fc77443510ab7e9ba8fd830f255a8fec (patch)
tree2af48b491e6dcd471fd16f04e6ae87a85b1097cd
parent45a9e3834a6ed20ee250e2e5a8583dffcef0eb73 (diff)
downloadcpython-git-a0df9ee8fc77443510ab7e9ba8fd830f255a8fec.tar.gz
GH-96803: Add three C-API functions to make _PyInterpreterFrame less opaque for users of PEP 523. (GH-96849)
-rw-r--r--Include/cpython/frameobject.h17
-rw-r--r--Include/internal/pycore_frame.h2
-rw-r--r--Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst6
-rw-r--r--Modules/_tracemalloc.c3
-rw-r--r--Objects/frameobject.c2
-rw-r--r--Objects/genobject.c3
-rw-r--r--Python/ceval.c3
-rw-r--r--Python/frame.c18
-rw-r--r--Python/traceback.c2
9 files changed, 48 insertions, 8 deletions
diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h
index 4e19535c65..6f3efe36ed 100644
--- a/Include/cpython/frameobject.h
+++ b/Include/cpython/frameobject.h
@@ -4,6 +4,8 @@
# error "this header file must not be included directly"
#endif
+struct _PyInterpreterFrame;
+
/* Standard object interface */
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(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);
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index d8d7fe9ef2..3d3cbbff7a 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -265,8 +265,6 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_l
return new_frame;
}
-int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
-
static inline
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
{
diff --git a/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst b/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst
new file mode 100644
index 0000000000..6fc56d2249
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst
@@ -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)``
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index d69c563648..c5714d5e7d 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -7,6 +7,7 @@
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_traceback.h"
#include <pycore_frame.h>
+#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include <stdlib.h> // malloc()
@@ -257,7 +258,7 @@ static void
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
{
frame->filename = &_Py_STR(anon_unknown);
- int lineno = _PyInterpreterFrame_GetLine(pyframe);
+ int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
if (lineno < 0) {
lineno = 0;
}
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index ef0070199a..d0eca447c0 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -38,7 +38,7 @@ PyFrame_GetLineNumber(PyFrameObject *f)
return f->f_lineno;
}
else {
- return _PyInterpreterFrame_GetLine(f->f_frame);
+ return PyUnstable_InterpreterFrame_GetLine(f->f_frame);
}
}
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 6316fa9865..937d497753 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -12,6 +12,7 @@
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "structmember.h" // PyMemberDef
#include "opcode.h" // SEND
+#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include "pystats.h"
static PyObject *gen_close(PyGenObject *, PyObject *);
@@ -1322,7 +1323,7 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
frame = current_frame;
for (int i = 0; i < frame_count; ++i) {
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,
code->co_name);
if (!frameinfo) {
diff --git a/Python/ceval.c b/Python/ceval.c
index 958689debc..56a3b123f4 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -27,6 +27,7 @@
#include "pycore_dict.h"
#include "dictobject.h"
#include "pycore_frame.h"
+#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include "opcode.h"
#include "pydtrace.h"
#include "setobject.h"
@@ -785,7 +786,7 @@ handle_eval_breaker:
_PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d",
frame->f_code->co_filename,
- _PyInterpreterFrame_GetLine(frame),
+ PyUnstable_InterpreterFrame_GetLine(frame),
opcode);
goto error;
diff --git a/Python/frame.c b/Python/frame.c
index c2c0be3011..d792b92fa5 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -144,8 +144,24 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
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
+PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)
+{
+ return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
+}
+
int
-_PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame)
+PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
{
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
return PyCode_Addr2Line(frame->f_code, addr);
diff --git a/Python/traceback.c b/Python/traceback.c
index 097f69c76a..b247954204 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -1180,7 +1180,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
PUTS(fd, "???");
}
- int lineno = _PyInterpreterFrame_GetLine(frame);
+ int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
PUTS(fd, ", line ");
if (lineno >= 0) {
_Py_DumpDecimal(fd, (size_t)lineno);