bpo-40429: PyFrame_GetCode() result cannot be NULL (GH-19772)
Add frame_nslots() to factorize duplicate code.
This commit is contained in:
parent
521c8d6806
commit
6d86a2331e
|
@ -34,6 +34,7 @@ Reflection
|
||||||
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
|
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
|
||||||
|
|
||||||
Return a borrowed reference to the *frame* code.
|
Return a borrowed reference to the *frame* code.
|
||||||
|
The frame code cannot be ``NULL``.
|
||||||
|
|
||||||
*frame* must not be ``NULL``.
|
*frame* must not be ``NULL``.
|
||||||
|
|
||||||
|
|
|
@ -347,13 +347,6 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
|
||||||
frame->lineno = (unsigned int)lineno;
|
frame->lineno = (unsigned int)lineno;
|
||||||
|
|
||||||
code = PyFrame_GetCode(pyframe);
|
code = PyFrame_GetCode(pyframe);
|
||||||
if (code == NULL) {
|
|
||||||
#ifdef TRACE_DEBUG
|
|
||||||
tracemalloc_error("failed to get the code object of the frame");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code->co_filename == NULL) {
|
if (code->co_filename == NULL) {
|
||||||
#ifdef TRACE_DEBUG
|
#ifdef TRACE_DEBUG
|
||||||
tracemalloc_error("failed to get the filename of the code object");
|
tracemalloc_error("failed to get the filename of the code object");
|
||||||
|
|
|
@ -665,12 +665,18 @@ frame_dealloc(PyFrameObject *f)
|
||||||
Py_TRASHCAN_SAFE_END(f)
|
Py_TRASHCAN_SAFE_END(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Py_ssize_t
|
||||||
|
frame_nslots(PyFrameObject *frame)
|
||||||
|
{
|
||||||
|
PyCodeObject *code = frame->f_code;
|
||||||
|
return (code->co_nlocals
|
||||||
|
+ PyTuple_GET_SIZE(code->co_cellvars)
|
||||||
|
+ PyTuple_GET_SIZE(code->co_freevars));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
|
frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
PyObject **fastlocals, **p;
|
|
||||||
Py_ssize_t i, slots;
|
|
||||||
|
|
||||||
Py_VISIT(f->f_back);
|
Py_VISIT(f->f_back);
|
||||||
Py_VISIT(f->f_code);
|
Py_VISIT(f->f_code);
|
||||||
Py_VISIT(f->f_builtins);
|
Py_VISIT(f->f_builtins);
|
||||||
|
@ -679,15 +685,16 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
|
||||||
Py_VISIT(f->f_trace);
|
Py_VISIT(f->f_trace);
|
||||||
|
|
||||||
/* locals */
|
/* locals */
|
||||||
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
|
PyObject **fastlocals = f->f_localsplus;
|
||||||
fastlocals = f->f_localsplus;
|
for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) {
|
||||||
for (i = slots; --i >= 0; ++fastlocals)
|
|
||||||
Py_VISIT(*fastlocals);
|
Py_VISIT(*fastlocals);
|
||||||
|
}
|
||||||
|
|
||||||
/* stack */
|
/* stack */
|
||||||
if (f->f_stacktop != NULL) {
|
if (f->f_stacktop != NULL) {
|
||||||
for (p = f->f_valuestack; p < f->f_stacktop; p++)
|
for (PyObject **p = f->f_valuestack; p < f->f_stacktop; p++) {
|
||||||
Py_VISIT(*p);
|
Py_VISIT(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -695,30 +702,28 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
|
||||||
static int
|
static int
|
||||||
frame_tp_clear(PyFrameObject *f)
|
frame_tp_clear(PyFrameObject *f)
|
||||||
{
|
{
|
||||||
PyObject **fastlocals, **p, **oldtop;
|
|
||||||
Py_ssize_t i, slots;
|
|
||||||
|
|
||||||
/* Before anything else, make sure that this frame is clearly marked
|
/* Before anything else, make sure that this frame is clearly marked
|
||||||
* as being defunct! Else, e.g., a generator reachable from this
|
* as being defunct! Else, e.g., a generator reachable from this
|
||||||
* frame may also point to this frame, believe itself to still be
|
* frame may also point to this frame, believe itself to still be
|
||||||
* active, and try cleaning up this frame again.
|
* active, and try cleaning up this frame again.
|
||||||
*/
|
*/
|
||||||
oldtop = f->f_stacktop;
|
PyObject **oldtop = f->f_stacktop;
|
||||||
f->f_stacktop = NULL;
|
f->f_stacktop = NULL;
|
||||||
f->f_executing = 0;
|
f->f_executing = 0;
|
||||||
|
|
||||||
Py_CLEAR(f->f_trace);
|
Py_CLEAR(f->f_trace);
|
||||||
|
|
||||||
/* locals */
|
/* locals */
|
||||||
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
|
PyObject **fastlocals = f->f_localsplus;
|
||||||
fastlocals = f->f_localsplus;
|
for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) {
|
||||||
for (i = slots; --i >= 0; ++fastlocals)
|
|
||||||
Py_CLEAR(*fastlocals);
|
Py_CLEAR(*fastlocals);
|
||||||
|
}
|
||||||
|
|
||||||
/* stack */
|
/* stack */
|
||||||
if (oldtop != NULL) {
|
if (oldtop != NULL) {
|
||||||
for (p = f->f_valuestack; p < oldtop; p++)
|
for (PyObject **p = f->f_valuestack; p < oldtop; p++) {
|
||||||
Py_CLEAR(*p);
|
Py_CLEAR(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -747,10 +752,10 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
Py_ssize_t res, extras, ncells, nfrees;
|
Py_ssize_t res, extras, ncells, nfrees;
|
||||||
|
|
||||||
ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars);
|
PyCodeObject *code = f->f_code;
|
||||||
nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars);
|
ncells = PyTuple_GET_SIZE(code->co_cellvars);
|
||||||
extras = f->f_code->co_stacksize + f->f_code->co_nlocals +
|
nfrees = PyTuple_GET_SIZE(code->co_freevars);
|
||||||
ncells + nfrees;
|
extras = code->co_stacksize + code->co_nlocals + ncells + nfrees;
|
||||||
/* subtract one as it is already included in PyFrameObject */
|
/* subtract one as it is already included in PyFrameObject */
|
||||||
res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
|
res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
|
||||||
|
|
||||||
|
@ -764,9 +769,10 @@ static PyObject *
|
||||||
frame_repr(PyFrameObject *f)
|
frame_repr(PyFrameObject *f)
|
||||||
{
|
{
|
||||||
int lineno = PyFrame_GetLineNumber(f);
|
int lineno = PyFrame_GetLineNumber(f);
|
||||||
|
PyCodeObject *code = f->f_code;
|
||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"<frame at %p, file %R, line %d, code %S>",
|
"<frame at %p, file %R, line %d, code %S>",
|
||||||
f, f->f_code->co_filename, lineno, f->f_code->co_name);
|
f, code->co_filename, lineno, code->co_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef frame_methods[] = {
|
static PyMethodDef frame_methods[] = {
|
||||||
|
@ -940,6 +946,8 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code,
|
||||||
f->f_trace_opcodes = 0;
|
f->f_trace_opcodes = 0;
|
||||||
f->f_trace_lines = 1;
|
f->f_trace_lines = 1;
|
||||||
|
|
||||||
|
assert(f->f_code != NULL);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,5 +1235,7 @@ PyCodeObject *
|
||||||
PyFrame_GetCode(PyFrameObject *frame)
|
PyFrame_GetCode(PyFrameObject *frame)
|
||||||
{
|
{
|
||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
return frame->f_code;
|
PyCodeObject *code = frame->f_code;
|
||||||
|
assert(code != NULL);
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1117,11 +1117,11 @@ compute_cr_origin(int origin_depth)
|
||||||
}
|
}
|
||||||
frame = PyEval_GetFrame();
|
frame = PyEval_GetFrame();
|
||||||
for (int i = 0; i < frame_count; ++i) {
|
for (int i = 0; i < frame_count; ++i) {
|
||||||
PyObject *frameinfo = Py_BuildValue(
|
PyCodeObject *code = frame->f_code;
|
||||||
"OiO",
|
PyObject *frameinfo = Py_BuildValue("OiO",
|
||||||
frame->f_code->co_filename,
|
code->co_filename,
|
||||||
PyFrame_GetLineNumber(frame),
|
PyFrame_GetLineNumber(frame),
|
||||||
frame->f_code->co_name);
|
code->co_name);
|
||||||
if (!frameinfo) {
|
if (!frameinfo) {
|
||||||
Py_DECREF(cr_origin);
|
Py_DECREF(cr_origin);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -8040,11 +8040,6 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
co = PyFrame_GetCode(f);
|
co = PyFrame_GetCode(f);
|
||||||
if (co == NULL) {
|
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
|
||||||
"super(): no code object");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (co->co_argcount == 0) {
|
if (co->co_argcount == 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"super(): no arguments");
|
"super(): no arguments");
|
||||||
|
|
|
@ -784,10 +784,6 @@ is_internal_frame(PyFrameObject *frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyCodeObject *code = PyFrame_GetCode(frame);
|
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||||
if (code == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *filename = code->co_filename;
|
PyObject *filename = code->co_filename;
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5580,9 +5580,10 @@ dtrace_function_entry(PyFrameObject *f)
|
||||||
const char *funcname;
|
const char *funcname;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
filename = PyUnicode_AsUTF8(f->f_code->co_filename);
|
PyCodeObject *code = f->f_code;
|
||||||
funcname = PyUnicode_AsUTF8(f->f_code->co_name);
|
filename = PyUnicode_AsUTF8(code->co_filename);
|
||||||
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
funcname = PyUnicode_AsUTF8(code->co_name);
|
||||||
|
lineno = PyCode_Addr2Line(code, f->f_lasti);
|
||||||
|
|
||||||
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
|
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
|
||||||
}
|
}
|
||||||
|
@ -5594,9 +5595,10 @@ dtrace_function_return(PyFrameObject *f)
|
||||||
const char *funcname;
|
const char *funcname;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
filename = PyUnicode_AsUTF8(f->f_code->co_filename);
|
PyCodeObject *code = f->f_code;
|
||||||
funcname = PyUnicode_AsUTF8(f->f_code->co_name);
|
filename = PyUnicode_AsUTF8(code->co_filename);
|
||||||
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
funcname = PyUnicode_AsUTF8(code->co_name);
|
||||||
|
lineno = PyCode_Addr2Line(code, f->f_lasti);
|
||||||
|
|
||||||
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
|
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue