From 1eb68125786974bf1f4f89e8a675fad408ced730 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 28 Apr 2020 17:07:25 +0200 Subject: [PATCH] bpo-40421: Add PyFrame_GetLastInstr() function New PyFrame_GetLastInstr() function: get the index of last attempted instruction in bytecode of a frame. Replace frame->f_lasti with PyFrame_GetLastInstr(frame). --- Doc/c-api/reflection.rst | 11 +++++++++++ Doc/whatsnew/3.9.rst | 2 ++ Include/cpython/frameobject.h | 2 ++ .../C API/2020-04-28-19-25-20.bpo-40421.iHT9OE.rst | 2 ++ Objects/frameobject.c | 8 ++++++++ Python/traceback.c | 6 +++--- 6 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-04-28-19-25-20.bpo-40421.iHT9OE.rst diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst index b313ea302598e6c..976d5f641a71c7f 100644 --- a/Doc/c-api/reflection.rst +++ b/Doc/c-api/reflection.rst @@ -40,6 +40,17 @@ Reflection .. versionadded:: 3.9 +.. c:function:: int PyFrame_GetLastInstr(PyFrameObject *frame) + + Get the index of last attempted instruction in bytecode of *frame*. + + Return ``-1`` for new frame (not run yet). + + *frame* must not be ``NULL``. + + .. versionadded:: 3.9 + + .. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame) Return the line number that *frame* is currently executing. diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index e3751fa1680117b..696714a8c647ff1 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -539,6 +539,8 @@ Build and C API Changes * New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the frame code. + New :c:func:`PyFrame_GetLastInstr` function: get the index of last attempted + instruction in bytecode of a frame. (Contributed by Victor Stinner in :issue:`40421`.) * Add :c:func:`PyFrame_GetLineNumber` to the limited C API. diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h index e819cefd13cbeb1..536b7e7159f35f2 100644 --- a/Include/cpython/frameobject.h +++ b/Include/cpython/frameobject.h @@ -79,6 +79,8 @@ PyAPI_FUNC(int) PyFrame_ClearFreeList(void); PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out); +PyAPI_FUNC(int) PyFrame_GetLastInstr(PyFrameObject *frame); + #ifdef __cplusplus } #endif diff --git a/Misc/NEWS.d/next/C API/2020-04-28-19-25-20.bpo-40421.iHT9OE.rst b/Misc/NEWS.d/next/C API/2020-04-28-19-25-20.bpo-40421.iHT9OE.rst new file mode 100644 index 000000000000000..e28c8ac455a1a83 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-04-28-19-25-20.bpo-40421.iHT9OE.rst @@ -0,0 +1,2 @@ +New :c:func:`PyFrame_GetLastInstr` function: get the index of last attempted +instruction in bytecode of a frame. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 92206c5f521086d..74d42e7db255062 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1229,3 +1229,11 @@ PyFrame_GetCode(PyFrameObject *frame) assert(frame != NULL); return frame->f_code; } + + +int +PyFrame_GetLastInstr(PyFrameObject *frame) +{ + assert(frame != NULL); + return frame->f_lasti; +} diff --git a/Python/traceback.c b/Python/traceback.c index 1ea6cbada964f53..476dc3e6e475564 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -233,7 +233,8 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame) assert(tb_next == NULL || PyTraceBack_Check(tb_next)); assert(frame != NULL); - return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_lasti, + return tb_create_raw((PyTracebackObject *)tb_next, frame, + PyFrame_GetLastInstr(frame), PyFrame_GetLineNumber(frame)); } @@ -767,8 +768,7 @@ dump_frame(int fd, PyFrameObject *frame) PUTS(fd, "???"); } - /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ - lineno = PyCode_Addr2Line(code, frame->f_lasti); + lineno = PyCode_Addr2Line(code, PyFrame_GetLastInstr(frame)); PUTS(fd, ", line "); if (lineno >= 0) { _Py_DumpDecimal(fd, (unsigned long)lineno);