]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-96803: Add three C-API functions to make _PyInterpreterFrame less opaque for users...
authorMark Shannon <mark@hotpy.org>
Fri, 5 May 2023 16:53:07 +0000 (17:53 +0100)
committerGitHub <noreply@github.com>
Fri, 5 May 2023 16:53:07 +0000 (17:53 +0100)
Include/cpython/frameobject.h
Include/internal/pycore_frame.h
Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst [new file with mode: 0644]
Modules/_tracemalloc.c
Objects/frameobject.c
Objects/genobject.c
Python/ceval.c
Python/frame.c
Python/traceback.c

index 4e19535c656f2cbef34238143c61aa120d6c9c5e..6f3efe36ede5d80edaa2774239696878ccf885a9 100644 (file)
@@ -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);
index d8d7fe9ef2ebde0fe8ffc8ab9e1a16e56360082d..3d3cbbff7aae813570dd8e023bae02b3853ab504 100644 (file)
@@ -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 (file)
index 0000000..6fc56d2
--- /dev/null
@@ -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)``
index d69c5636486da9fa50c16e8458793499672cf4f0..c5714d5e7d5a0f8d4547913380ef8698dd490c89 100644 (file)
@@ -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;
     }
index ef0070199ab2c000e5eb2450088da0f95dd64102..d0eca447c012ea5fb88e88603658dcb7d0bd41d9 100644 (file)
@@ -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);
     }
 }
 
index 6316fa9865fe6517b83487e3b3f10a78a296f3b1..937d497753e970c250c1140999cc4e5e81ad5a26 100644 (file)
@@ -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) {
index 958689debc87f8c0ad3a153135d10ce81d4ff93d..56a3b123f463315eba0c59b33a1d8ae08ecbcde4 100644 (file)
@@ -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;
 
index c2c0be301139128a6e6b8faa2657eb2338b6356c..d792b92fa57560bc8d4ca195cc293c243372f257 100644 (file)
@@ -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);
index 097f69c76abfe1b109d2df389559a0d8168ab5fd..b2479542047308cba71aab004716e0aa1631d81b 100644 (file)
@@ -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);