diff --git a/Objects/clinic/frameobject.c.h b/Objects/clinic/frameobject.c.h new file mode 100644 index 00000000000000..327896f4b97c68 --- /dev/null +++ b/Objects/clinic/frameobject.c.h @@ -0,0 +1,436 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() + +PyDoc_STRVAR(frame_locals__doc__, +"Return the mapping used by the frame to look up local variables."); +#if defined(frame_locals_DOCSTR) +# undef frame_locals_DOCSTR +#endif +#define frame_locals_DOCSTR frame_locals__doc__ + +#if !defined(frame_locals_DOCSTR) +# define frame_locals_DOCSTR NULL +#endif +#if defined(FRAME_LOCALS_GETSETDEF) +# undef FRAME_LOCALS_GETSETDEF +# define FRAME_LOCALS_GETSETDEF {"f_locals", (getter)frame_locals_get, (setter)frame_locals_set, frame_locals_DOCSTR}, +#else +# define FRAME_LOCALS_GETSETDEF {"f_locals", (getter)frame_locals_get, NULL, frame_locals_DOCSTR}, +#endif + +static PyObject * +frame_locals_get_impl(PyFrameObject *self); + +static PyObject * +frame_locals_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_locals_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_lineno__doc__, +"Return the current line number in the frame."); +#if defined(frame_lineno_DOCSTR) +# undef frame_lineno_DOCSTR +#endif +#define frame_lineno_DOCSTR frame_lineno__doc__ + +#if !defined(frame_lineno_DOCSTR) +# define frame_lineno_DOCSTR NULL +#endif +#if defined(FRAME_LINENO_GETSETDEF) +# undef FRAME_LINENO_GETSETDEF +# define FRAME_LINENO_GETSETDEF {"f_lineno", (getter)frame_lineno_get, (setter)frame_lineno_set, frame_lineno_DOCSTR}, +#else +# define FRAME_LINENO_GETSETDEF {"f_lineno", (getter)frame_lineno_get, NULL, frame_lineno_DOCSTR}, +#endif + +static PyObject * +frame_lineno_get_impl(PyFrameObject *self); + +static PyObject * +frame_lineno_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_lineno_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_lasti__doc__, +"Return the index of the last attempted instruction in the frame."); +#if defined(frame_lasti_DOCSTR) +# undef frame_lasti_DOCSTR +#endif +#define frame_lasti_DOCSTR frame_lasti__doc__ + +#if !defined(frame_lasti_DOCSTR) +# define frame_lasti_DOCSTR NULL +#endif +#if defined(FRAME_LASTI_GETSETDEF) +# undef FRAME_LASTI_GETSETDEF +# define FRAME_LASTI_GETSETDEF {"f_lasti", (getter)frame_lasti_get, (setter)frame_lasti_set, frame_lasti_DOCSTR}, +#else +# define FRAME_LASTI_GETSETDEF {"f_lasti", (getter)frame_lasti_get, NULL, frame_lasti_DOCSTR}, +#endif + +static PyObject * +frame_lasti_get_impl(PyFrameObject *self); + +static PyObject * +frame_lasti_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_lasti_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_globals__doc__, +"Return the global variables in the frame."); +#if defined(frame_globals_DOCSTR) +# undef frame_globals_DOCSTR +#endif +#define frame_globals_DOCSTR frame_globals__doc__ + +#if !defined(frame_globals_DOCSTR) +# define frame_globals_DOCSTR NULL +#endif +#if defined(FRAME_GLOBALS_GETSETDEF) +# undef FRAME_GLOBALS_GETSETDEF +# define FRAME_GLOBALS_GETSETDEF {"f_globals", (getter)frame_globals_get, (setter)frame_globals_set, frame_globals_DOCSTR}, +#else +# define FRAME_GLOBALS_GETSETDEF {"f_globals", (getter)frame_globals_get, NULL, frame_globals_DOCSTR}, +#endif + +static PyObject * +frame_globals_get_impl(PyFrameObject *self); + +static PyObject * +frame_globals_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_globals_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_builtins__doc__, +"Return the built-in variables in the frame."); +#if defined(frame_builtins_DOCSTR) +# undef frame_builtins_DOCSTR +#endif +#define frame_builtins_DOCSTR frame_builtins__doc__ + +#if !defined(frame_builtins_DOCSTR) +# define frame_builtins_DOCSTR NULL +#endif +#if defined(FRAME_BUILTINS_GETSETDEF) +# undef FRAME_BUILTINS_GETSETDEF +# define FRAME_BUILTINS_GETSETDEF {"f_builtins", (getter)frame_builtins_get, (setter)frame_builtins_set, frame_builtins_DOCSTR}, +#else +# define FRAME_BUILTINS_GETSETDEF {"f_builtins", (getter)frame_builtins_get, NULL, frame_builtins_DOCSTR}, +#endif + +static PyObject * +frame_builtins_get_impl(PyFrameObject *self); + +static PyObject * +frame_builtins_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_builtins_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_code__doc__, +"Return the code object being executed in this frame."); +#if defined(frame_code_DOCSTR) +# undef frame_code_DOCSTR +#endif +#define frame_code_DOCSTR frame_code__doc__ + +#if !defined(frame_code_DOCSTR) +# define frame_code_DOCSTR NULL +#endif +#if defined(FRAME_CODE_GETSETDEF) +# undef FRAME_CODE_GETSETDEF +# define FRAME_CODE_GETSETDEF {"f_code", (getter)frame_code_get, (setter)frame_code_set, frame_code_DOCSTR}, +#else +# define FRAME_CODE_GETSETDEF {"f_code", (getter)frame_code_get, NULL, frame_code_DOCSTR}, +#endif + +static PyObject * +frame_code_get_impl(PyFrameObject *self); + +static PyObject * +frame_code_get(PyObject *self, void *Py_UNUSED(context)) +{ + return frame_code_get_impl((PyFrameObject *)self); +} + +#if !defined(frame_back_DOCSTR) +# define frame_back_DOCSTR NULL +#endif +#if defined(FRAME_BACK_GETSETDEF) +# undef FRAME_BACK_GETSETDEF +# define FRAME_BACK_GETSETDEF {"f_back", (getter)frame_back_get, (setter)frame_back_set, frame_back_DOCSTR}, +#else +# define FRAME_BACK_GETSETDEF {"f_back", (getter)frame_back_get, NULL, frame_back_DOCSTR}, +#endif + +static PyObject * +frame_back_get_impl(PyFrameObject *self); + +static PyObject * +frame_back_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_back_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_trace_opcodes__doc__, +"Return True if opcode tracing is enabled, False otherwise."); +#if defined(frame_trace_opcodes_DOCSTR) +# undef frame_trace_opcodes_DOCSTR +#endif +#define frame_trace_opcodes_DOCSTR frame_trace_opcodes__doc__ + +#if !defined(frame_trace_opcodes_DOCSTR) +# define frame_trace_opcodes_DOCSTR NULL +#endif +#if defined(FRAME_TRACE_OPCODES_GETSETDEF) +# undef FRAME_TRACE_OPCODES_GETSETDEF +# define FRAME_TRACE_OPCODES_GETSETDEF {"f_trace_opcodes", (getter)frame_trace_opcodes_get, (setter)frame_trace_opcodes_set, frame_trace_opcodes_DOCSTR}, +#else +# define FRAME_TRACE_OPCODES_GETSETDEF {"f_trace_opcodes", (getter)frame_trace_opcodes_get, NULL, frame_trace_opcodes_DOCSTR}, +#endif + +static PyObject * +frame_trace_opcodes_get_impl(PyFrameObject *self); + +static PyObject * +frame_trace_opcodes_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_trace_opcodes_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if !defined(frame_trace_opcodes_DOCSTR) +# define frame_trace_opcodes_DOCSTR NULL +#endif +#if defined(FRAME_TRACE_OPCODES_GETSETDEF) +# undef FRAME_TRACE_OPCODES_GETSETDEF +# define FRAME_TRACE_OPCODES_GETSETDEF {"f_trace_opcodes", (getter)frame_trace_opcodes_get, (setter)frame_trace_opcodes_set, frame_trace_opcodes_DOCSTR}, +#else +# define FRAME_TRACE_OPCODES_GETSETDEF {"f_trace_opcodes", NULL, (setter)frame_trace_opcodes_set, NULL}, +#endif + +static int +frame_trace_opcodes_set_impl(PyFrameObject *self, PyObject *value); + +static int +frame_trace_opcodes_set(PyObject *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_trace_opcodes_set_impl((PyFrameObject *)self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if !defined(frame_lineno_DOCSTR) +# define frame_lineno_DOCSTR NULL +#endif +#if defined(FRAME_LINENO_GETSETDEF) +# undef FRAME_LINENO_GETSETDEF +# define FRAME_LINENO_GETSETDEF {"f_lineno", (getter)frame_lineno_get, (setter)frame_lineno_set, frame_lineno_DOCSTR}, +#else +# define FRAME_LINENO_GETSETDEF {"f_lineno", NULL, (setter)frame_lineno_set, NULL}, +#endif + +static int +frame_lineno_set_impl(PyFrameObject *self, PyObject *value); + +static int +frame_lineno_set(PyObject *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_lineno_set_impl((PyFrameObject *)self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_trace__doc__, +"Return the trace function for this frame, or None if no trace function is set."); +#if defined(frame_trace_DOCSTR) +# undef frame_trace_DOCSTR +#endif +#define frame_trace_DOCSTR frame_trace__doc__ + +#if !defined(frame_trace_DOCSTR) +# define frame_trace_DOCSTR NULL +#endif +#if defined(FRAME_TRACE_GETSETDEF) +# undef FRAME_TRACE_GETSETDEF +# define FRAME_TRACE_GETSETDEF {"f_trace", (getter)frame_trace_get, (setter)frame_trace_set, frame_trace_DOCSTR}, +#else +# define FRAME_TRACE_GETSETDEF {"f_trace", (getter)frame_trace_get, NULL, frame_trace_DOCSTR}, +#endif + +static PyObject * +frame_trace_get_impl(PyFrameObject *self); + +static PyObject * +frame_trace_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_trace_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if !defined(frame_trace_DOCSTR) +# define frame_trace_DOCSTR NULL +#endif +#if defined(FRAME_TRACE_GETSETDEF) +# undef FRAME_TRACE_GETSETDEF +# define FRAME_TRACE_GETSETDEF {"f_trace", (getter)frame_trace_get, (setter)frame_trace_set, frame_trace_DOCSTR}, +#else +# define FRAME_TRACE_GETSETDEF {"f_trace", NULL, (setter)frame_trace_set, NULL}, +#endif + +static int +frame_trace_set_impl(PyFrameObject *self, PyObject *value); + +static int +frame_trace_set(PyObject *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_trace_set_impl((PyFrameObject *)self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_generator__doc__, +"Return the generator or coroutine associated with this frame, or None."); +#if defined(frame_generator_DOCSTR) +# undef frame_generator_DOCSTR +#endif +#define frame_generator_DOCSTR frame_generator__doc__ + +#if !defined(frame_generator_DOCSTR) +# define frame_generator_DOCSTR NULL +#endif +#if defined(FRAME_GENERATOR_GETSETDEF) +# undef FRAME_GENERATOR_GETSETDEF +# define FRAME_GENERATOR_GETSETDEF {"f_generator", (getter)frame_generator_get, (setter)frame_generator_set, frame_generator_DOCSTR}, +#else +# define FRAME_GENERATOR_GETSETDEF {"f_generator", (getter)frame_generator_get, NULL, frame_generator_DOCSTR}, +#endif + +static PyObject * +frame_generator_get_impl(PyFrameObject *self); + +static PyObject * +frame_generator_get(PyObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_generator_get_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Clear all references held by the frame."); + +#define FRAME_CLEAR_METHODDEF \ + {"clear", (PyCFunction)frame_clear, METH_NOARGS, frame_clear__doc__}, + +static PyObject * +frame_clear_impl(PyFrameObject *self); + +static PyObject * +frame_clear(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame_clear_impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +PyDoc_STRVAR(frame___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Return the size of the frame in memory, in bytes."); + +#define FRAME___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)frame___sizeof__, METH_NOARGS, frame___sizeof____doc__}, + +static PyObject * +frame___sizeof___impl(PyFrameObject *self); + +static PyObject * +frame___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = frame___sizeof___impl((PyFrameObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} +/*[clinic end generated code: output=74abf652547c0c11 input=a9049054013a1b77]*/ diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 665199f7436ee8..88893467855ba2 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -19,6 +19,8 @@ #include "pycore_frame.h" #include "opcode.h" // EXTENDED_ARG +#include "clinic/frameobject.c.h" + #define PyFrameObject_CAST(op) \ (assert(PyObject_TypeCheck((op), &PyFrame_Type)), (PyFrameObject *)(op)) @@ -30,6 +32,11 @@ #define OFF(x) offsetof(PyFrameObject, x) +/*[clinic input] +class frame "PyFrameObject *" "&PyFrame_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2d1dbf2e06cf351f]*/ + // Returns new reference or NULL static PyObject * @@ -913,32 +920,36 @@ static PyMemberDef frame_memberlist[] = { {NULL} /* Sentinel */ }; +/*[clinic input] +@critical_section +@getter +frame.f_locals as frame_locals + +Return the mapping used by the frame to look up local variables. +[clinic start generated code]*/ + static PyObject * -frame_getlocals(PyObject *op, void *Py_UNUSED(closure)) +frame_locals_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=b4ace8bb4cae71f4 input=7bd444d0dc8ddf44]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - if (f == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - assert(!_PyFrame_IsIncomplete(f->f_frame)); + assert(!_PyFrame_IsIncomplete(self->f_frame)); - PyCodeObject *co = _PyFrame_GetCode(f->f_frame); + PyCodeObject *co = _PyFrame_GetCode(self->f_frame); - if (!(co->co_flags & CO_OPTIMIZED) && !_PyFrame_HasHiddenLocals(f->f_frame)) { - if (f->f_frame->f_locals == NULL) { + if (!(co->co_flags & CO_OPTIMIZED) && !_PyFrame_HasHiddenLocals(self->f_frame)) { + if (self->f_frame->f_locals == NULL) { // We found cases when f_locals is NULL for non-optimized code. // We fill the f_locals with an empty dict to avoid crash until // we find the root cause. - f->f_frame->f_locals = PyDict_New(); - if (f->f_frame->f_locals == NULL) { + self->f_frame->f_locals = PyDict_New(); + if (self->f_frame->f_locals == NULL) { return NULL; } } - return Py_NewRef(f->f_frame->f_locals); + return Py_NewRef(self->f_frame->f_locals); } - return _PyFrameLocalsProxy_New(f); + return _PyFrameLocalsProxy_New(self); } int @@ -961,99 +972,155 @@ PyFrame_GetLineNumber(PyFrameObject *f) return PyUnstable_InterpreterFrame_GetLine(f->f_frame); } +/*[clinic input] +@critical_section +@getter +frame.f_lineno as frame_lineno + +Return the current line number in the frame. +[clinic start generated code]*/ + static PyObject * -frame_getlineno(PyObject *op, void *Py_UNUSED(closure)) +frame_lineno_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=70f35de5ac7ad630 input=87b9ec648b742936]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - int lineno = PyFrame_GetLineNumber(f); + int lineno = PyFrame_GetLineNumber(self); if (lineno < 0) { Py_RETURN_NONE; } - else { - return PyLong_FromLong(lineno); - } + return PyLong_FromLong(lineno); } +/*[clinic input] +@critical_section +@getter +frame.f_lasti as frame_lasti + +Return the index of the last attempted instruction in the frame. +[clinic start generated code]*/ + static PyObject * -frame_getlasti(PyObject *op, void *Py_UNUSED(closure)) +frame_lasti_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=03275b4f0327d1a2 input=0225ed49cb1fbeeb]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - int lasti = _PyInterpreterFrame_LASTI(f->f_frame); + int lasti = _PyInterpreterFrame_LASTI(self->f_frame); if (lasti < 0) { return PyLong_FromLong(-1); } return PyLong_FromLong(lasti * sizeof(_Py_CODEUNIT)); } +/*[clinic input] +@critical_section +@getter +frame.f_globals as frame_globals + +Return the global variables in the frame. +[clinic start generated code]*/ + static PyObject * -frame_getglobals(PyObject *op, void *Py_UNUSED(closure)) +frame_globals_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=7758788c32885528 input=7fff7241357d314d]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyObject *globals = f->f_frame->f_globals; + PyObject *globals = self->f_frame->f_globals; if (globals == NULL) { globals = Py_None; } return Py_NewRef(globals); } +/*[clinic input] +@critical_section +@getter +frame.f_builtins as frame_builtins + +Return the built-in variables in the frame. +[clinic start generated code]*/ + static PyObject * -frame_getbuiltins(PyObject *op, void *Py_UNUSED(closure)) +frame_builtins_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=45362faa6d42c702 input=27c696d6ffcad2c7]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyObject *builtins = f->f_frame->f_builtins; + PyObject *builtins = self->f_frame->f_builtins; if (builtins == NULL) { builtins = Py_None; } return Py_NewRef(builtins); } +/*[clinic input] +@getter +frame.f_code as frame_code + +Return the code object being executed in this frame. +[clinic start generated code]*/ + static PyObject * -frame_getcode(PyObject *op, void *Py_UNUSED(closure)) +frame_code_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=a5ed6207395a8cef input=e127e7098c124816]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - if (PySys_Audit("object.__getattr__", "Os", f, "f_code") < 0) { + if (PySys_Audit("object.__getattr__", "Os", self, "f_code") < 0) { return NULL; } - return (PyObject *)PyFrame_GetCode(f); + return (PyObject *)PyFrame_GetCode(self); } +/*[clinic input] +@critical_section +@getter +frame.f_back as frame_back +[clinic start generated code]*/ + static PyObject * -frame_getback(PyObject *op, void *Py_UNUSED(closure)) +frame_back_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=3a84c22a55a63c79 input=9e528570d0e1f44a]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyObject *res = (PyObject *)PyFrame_GetBack(f); + PyObject *res = (PyObject *)PyFrame_GetBack(self); if (res == NULL) { Py_RETURN_NONE; } return res; } +/*[clinic input] +@critical_section +@getter +frame.f_trace_opcodes as frame_trace_opcodes + +Return True if opcode tracing is enabled, False otherwise. +[clinic start generated code]*/ + static PyObject * -frame_gettrace_opcodes(PyObject *op, void *Py_UNUSED(closure)) +frame_trace_opcodes_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=53ff41d09cc32e87 input=4eb91dc88e04677a]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyObject *result = f->f_trace_opcodes ? Py_True : Py_False; - return Py_NewRef(result); + return self->f_trace_opcodes ? Py_True : Py_False; } +/*[clinic input] +@critical_section +@setter +frame.f_trace_opcodes as frame_trace_opcodes +[clinic start generated code]*/ + static int -frame_settrace_opcodes(PyObject *op, PyObject* value, void *Py_UNUSED(closure)) +frame_trace_opcodes_set_impl(PyFrameObject *self, PyObject *value) +/*[clinic end generated code: output=92619da2bfccd449 input=7e286eea3c0333ff]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); if (!PyBool_Check(value)) { PyErr_SetString(PyExc_TypeError, "attribute value type must be bool"); return -1; } if (value == Py_True) { - f->f_trace_opcodes = 1; - if (f->f_trace) { - return _PyEval_SetOpcodeTrace(f, true); + self->f_trace_opcodes = 1; + if (self->f_trace) { + return _PyEval_SetOpcodeTrace(self, true); } } else { - f->f_trace_opcodes = 0; - return _PyEval_SetOpcodeTrace(f, false); + self->f_trace_opcodes = 0; + return _PyEval_SetOpcodeTrace(self, false); } return 0; } @@ -1530,23 +1597,29 @@ static bool frame_is_suspended(PyFrameObject *frame) * 'return' or 'exception' event since the eval loop has been exited at * that time. */ +/*[clinic input] +@critical_section +@setter +frame.f_lineno as frame_lineno +[clinic start generated code]*/ + static int -frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) +frame_lineno_set_impl(PyFrameObject *self, PyObject *value) +/*[clinic end generated code: output=e64c86ff6be64292 input=36ed3c896b27fb91]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyCodeObject *code = _PyFrame_GetCode(f->f_frame); - if (p_new_lineno == NULL) { + PyCodeObject *code = _PyFrame_GetCode(self->f_frame); + if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); return -1; } /* f_lineno must be an integer. */ - if (!PyLong_CheckExact(p_new_lineno)) { + if (!PyLong_CheckExact(value)) { PyErr_SetString(PyExc_ValueError, "lineno must be an integer"); return -1; } - bool is_suspended = frame_is_suspended(f); + bool is_suspended = frame_is_suspended(self); /* * This code preserves the historical restrictions on * setting the line number of a frame. @@ -1599,7 +1672,7 @@ frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) /* Fail if the line falls outside the code block and select first line with actual code. */ int overflow; - long l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow); + long l_new_lineno = PyLong_AsLongAndOverflow(value, &overflow); if (overflow #if SIZEOF_LONG > SIZEOF_INT || l_new_lineno > INT_MAX @@ -1644,7 +1717,7 @@ frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) int64_t best_stack = OVERFLOWED; int best_addr = -1; - int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(f->f_frame)]; + int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(self->f_frame)]; int err = -1; const char *msg = "cannot find bytecode for specified line"; for (int i = 0; i < len; i++) { @@ -1684,7 +1757,7 @@ frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) for (int i = 0; i < code->co_nlocalsplus; i++) { // Counting every unbound local is overly-cautious, but a full flow // analysis (like we do in the compiler) is probably too expensive: - unbound += PyStackRef_IsNull(f->f_frame->localsplus[i]); + unbound += PyStackRef_IsNull(self->f_frame->localsplus[i]); } if (unbound) { const char *e = "assigning None to %d unbound local%s"; @@ -1695,8 +1768,8 @@ frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) // Do this in a second pass to avoid writing a bunch of Nones when // warnings are being treated as errors and the previous bit raises: for (int i = 0; i < code->co_nlocalsplus; i++) { - if (PyStackRef_IsNull(f->f_frame->localsplus[i])) { - f->f_frame->localsplus[i] = PyStackRef_None; + if (PyStackRef_IsNull(self->f_frame->localsplus[i])) { + self->f_frame->localsplus[i] = PyStackRef_None; unbound--; } } @@ -1709,53 +1782,77 @@ frame_setlineno(PyObject *op, PyObject* p_new_lineno, void *Py_UNUSED(closure)) while (start_stack > best_stack) { if (top_of_stack(start_stack) == Except) { /* Pop exception stack as well as the evaluation stack */ - PyObject *exc = PyStackRef_AsPyObjectBorrow(_PyFrame_StackPop(f->f_frame)); + PyObject *exc = PyStackRef_AsPyObjectBorrow(_PyFrame_StackPop(self->f_frame)); assert(PyExceptionInstance_Check(exc) || exc == Py_None); PyThreadState *tstate = _PyThreadState_GET(); Py_XSETREF(tstate->exc_info->exc_value, exc == Py_None ? NULL : exc); } else { - PyStackRef_XCLOSE(_PyFrame_StackPop(f->f_frame)); + PyStackRef_XCLOSE(_PyFrame_StackPop(self->f_frame)); } start_stack = pop_value(start_stack); } /* Finally set the new lasti and return OK. */ - f->f_lineno = 0; - f->f_frame->instr_ptr = _PyFrame_GetBytecode(f->f_frame) + best_addr; + self->f_lineno = 0; + self->f_frame->instr_ptr = _PyFrame_GetBytecode(self->f_frame) + best_addr; return 0; } +/*[clinic input] +@critical_section +@getter +frame.f_trace as frame_trace + +Return the trace function for this frame, or None if no trace function is set. +[clinic start generated code]*/ + static PyObject * -frame_gettrace(PyObject *op, void *Py_UNUSED(closure)) +frame_trace_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=5475cbfce07826cd input=f382612525829773]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - PyObject* trace = f->f_trace; - if (trace == NULL) + PyObject* trace = self->f_trace; + if (trace == NULL) { trace = Py_None; + } return Py_NewRef(trace); } +/*[clinic input] +@critical_section +@setter +frame.f_trace as frame_trace +[clinic start generated code]*/ + static int -frame_settrace(PyObject *op, PyObject* v, void *Py_UNUSED(closure)) +frame_trace_set_impl(PyFrameObject *self, PyObject *value) +/*[clinic end generated code: output=d6fe08335cf76ae4 input=d96a18bda085707f]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - if (v == Py_None) { - v = NULL; + if (value == Py_None) { + value = NULL; } - if (v != f->f_trace) { - Py_XSETREF(f->f_trace, Py_XNewRef(v)); - if (v != NULL && f->f_trace_opcodes) { - return _PyEval_SetOpcodeTrace(f, true); + if (value != self->f_trace) { + Py_XSETREF(self->f_trace, Py_XNewRef(value)); + if (value != NULL && self->f_trace_opcodes) { + return _PyEval_SetOpcodeTrace(self, true); } } return 0; } +/*[clinic input] +@critical_section +@getter +frame.f_generator as frame_generator + +Return the generator or coroutine associated with this frame, or None. +[clinic start generated code]*/ + static PyObject * -frame_getgenerator(PyObject *op, void *Py_UNUSED(closure)) { - PyFrameObject *f = PyFrameObject_CAST(op); - if (f->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { - PyObject *gen = (PyObject *)_PyGen_GetGeneratorFromFrame(f->f_frame); +frame_generator_get_impl(PyFrameObject *self) +/*[clinic end generated code: output=97aeb2392562e55b input=00a2bd008b239ab0]*/ +{ + if (self->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyObject *gen = (PyObject *)_PyGen_GetGeneratorFromFrame(self->f_frame); return Py_NewRef(gen); } Py_RETURN_NONE; @@ -1763,16 +1860,16 @@ frame_getgenerator(PyObject *op, void *Py_UNUSED(closure)) { static PyGetSetDef frame_getsetlist[] = { - {"f_back", frame_getback, NULL, NULL}, - {"f_locals", frame_getlocals, NULL, NULL}, - {"f_lineno", frame_getlineno, frame_setlineno, NULL}, - {"f_trace", frame_gettrace, frame_settrace, NULL}, - {"f_lasti", frame_getlasti, NULL, NULL}, - {"f_globals", frame_getglobals, NULL, NULL}, - {"f_builtins", frame_getbuiltins, NULL, NULL}, - {"f_code", frame_getcode, NULL, NULL}, - {"f_trace_opcodes", frame_gettrace_opcodes, frame_settrace_opcodes, NULL}, - {"f_generator", frame_getgenerator, NULL, NULL}, + FRAME_BACK_GETSETDEF + FRAME_LOCALS_GETSETDEF + FRAME_LINENO_GETSETDEF + FRAME_TRACE_GETSETDEF + FRAME_LASTI_GETSETDEF + FRAME_GLOBALS_GETSETDEF + FRAME_BUILTINS_GETSETDEF + FRAME_CODE_GETSETDEF + FRAME_TRACE_OPCODES_GETSETDEF + FRAME_GENERATOR_GETSETDEF {0} }; @@ -1849,12 +1946,19 @@ frame_tp_clear(PyObject *op) return 0; } +/*[clinic input] +@critical_section +frame.clear + +Clear all references held by the frame. +[clinic start generated code]*/ + static PyObject * -frame_clear(PyObject *op, PyObject *Py_UNUSED(ignored)) +frame_clear_impl(PyFrameObject *self) +/*[clinic end generated code: output=864c662f16e9bfcc input=c358f9cff5f9b681]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); - if (f->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { - PyGenObject *gen = _PyGen_GetGeneratorFromFrame(f->f_frame); + if (self->f_frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyGenObject *gen = _PyGen_GetGeneratorFromFrame(self->f_frame); if (gen->gi_frame_state == FRAME_EXECUTING) { goto running; } @@ -1863,12 +1967,12 @@ frame_clear(PyObject *op, PyObject *Py_UNUSED(ignored)) } _PyGen_Finalize((PyObject *)gen); } - else if (f->f_frame->owner == FRAME_OWNED_BY_THREAD) { + else if (self->f_frame->owner == FRAME_OWNED_BY_THREAD) { goto running; } else { - assert(f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT); - (void)frame_tp_clear(op); + assert(self->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT); + (void)frame_tp_clear((PyObject *)self); } Py_RETURN_NONE; running: @@ -1881,23 +1985,24 @@ frame_clear(PyObject *op, PyObject *Py_UNUSED(ignored)) return NULL; } -PyDoc_STRVAR(clear__doc__, -"F.clear(): clear all references held by the frame"); +/*[clinic input] +@critical_section +frame.__sizeof__ + +Return the size of the frame in memory, in bytes. +[clinic start generated code]*/ static PyObject * -frame_sizeof(PyObject *op, PyObject *Py_UNUSED(ignored)) +frame___sizeof___impl(PyFrameObject *self) +/*[clinic end generated code: output=82948688e81078e2 input=908f90a83e73131d]*/ { - PyFrameObject *f = PyFrameObject_CAST(op); Py_ssize_t res; res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus); - PyCodeObject *code = _PyFrame_GetCode(f->f_frame); + PyCodeObject *code = _PyFrame_GetCode(self->f_frame); res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } -PyDoc_STRVAR(sizeof__doc__, -"F.__sizeof__() -> size of F in memory, in bytes"); - static PyObject * frame_repr(PyObject *op) { @@ -1910,8 +2015,8 @@ frame_repr(PyObject *op) } static PyMethodDef frame_methods[] = { - {"clear", frame_clear, METH_NOARGS, clear__doc__}, - {"__sizeof__", frame_sizeof, METH_NOARGS, sizeof__doc__}, + FRAME_CLEAR_METHODDEF + FRAME___SIZEOF___METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2230,10 +2335,12 @@ PyCodeObject * PyFrame_GetCode(PyFrameObject *frame) { assert(frame != NULL); + PyObject *code; + Py_BEGIN_CRITICAL_SECTION(frame); assert(!_PyFrame_IsIncomplete(frame->f_frame)); - PyCodeObject *code = _PyFrame_GetCode(frame->f_frame); - assert(code != NULL); - return (PyCodeObject*)Py_NewRef(code); + code = Py_NewRef(_PyFrame_GetCode(frame->f_frame)); + Py_END_CRITICAL_SECTION(); + return (PyCodeObject *)code; } @@ -2257,41 +2364,38 @@ PyObject* PyFrame_GetLocals(PyFrameObject *frame) { assert(!_PyFrame_IsIncomplete(frame->f_frame)); - return frame_getlocals((PyObject *)frame, NULL); + return frame_locals_get((PyObject *)frame, NULL); } PyObject* PyFrame_GetGlobals(PyFrameObject *frame) { assert(!_PyFrame_IsIncomplete(frame->f_frame)); - return frame_getglobals((PyObject *)frame, NULL); + return frame_globals_get((PyObject *)frame, NULL); } PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) { assert(!_PyFrame_IsIncomplete(frame->f_frame)); - return frame_getbuiltins((PyObject *)frame, NULL); + return frame_builtins_get((PyObject *)frame, NULL); } int PyFrame_GetLasti(PyFrameObject *frame) { + int ret; + Py_BEGIN_CRITICAL_SECTION(frame); assert(!_PyFrame_IsIncomplete(frame->f_frame)); int lasti = _PyInterpreterFrame_LASTI(frame->f_frame); - if (lasti < 0) { - return -1; - } - return lasti * sizeof(_Py_CODEUNIT); + ret = lasti < 0 ? -1 : lasti * (int)sizeof(_Py_CODEUNIT); + Py_END_CRITICAL_SECTION(); + return ret; } PyObject * PyFrame_GetGenerator(PyFrameObject *frame) { assert(!_PyFrame_IsIncomplete(frame->f_frame)); - if (frame->f_frame->owner != FRAME_OWNED_BY_GENERATOR) { - return NULL; - } - PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame->f_frame); - return Py_NewRef(gen); + return frame_generator_get((PyObject *)frame, NULL); } diff --git a/Python/frame.c b/Python/frame.c index 166ce07882126a..462202451f9f9d 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -49,6 +49,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame) static void take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) { + Py_BEGIN_CRITICAL_SECTION(f); assert(frame->owner < FRAME_OWNED_BY_INTERPRETER); assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); _PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)f->_f_frame_data; @@ -85,6 +86,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) { _PyObject_GC_TRACK((PyObject *)f); } + Py_END_CRITICAL_SECTION(); } void @@ -114,7 +116,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) if (frame->frame_obj) { PyFrameObject *f = frame->frame_obj; frame->frame_obj = NULL; - if (Py_REFCNT(f) > 1) { + if (!_PyObject_IsUniquelyReferenced((PyObject *)f)) { take_ownership(f, frame); Py_DECREF(f); return;