summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-29 02:28:23 +0200
committerGitHub <noreply@github.com>2020-04-29 02:28:23 +0200
commitcc0dc7e484c9626857e9a8b4c40eee37473702ed (patch)
tree7a43f0ada13a4e2f4427f3ef7684c6792fd39fbb
parentf7bbf58aa9299e9dd00b7a1bdd1113b4dcb6dfdf (diff)
downloadcpython-git-cc0dc7e484c9626857e9a8b4c40eee37473702ed.tar.gz
bpo-40429: Refactor super_init() (GH-19776)
Add super_init_without_args() sub-function. Hold a strong reference to the frame code object while calling super_init_without_args().
-rw-r--r--Objects/typeobject.c149
1 files changed, 85 insertions, 64 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 8f9ab5c0ba..7ba51e3961 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -8015,6 +8015,83 @@ super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
}
static int
+super_init_without_args(PyFrameObject *f, PyCodeObject *co,
+ PyTypeObject **type_p, PyObject **obj_p)
+{
+ if (co->co_argcount == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "super(): no arguments");
+ return -1;
+ }
+
+ PyObject *obj = f->f_localsplus[0];
+ Py_ssize_t i, n;
+ if (obj == NULL && co->co_cell2arg) {
+ /* The first argument might be a cell. */
+ n = PyTuple_GET_SIZE(co->co_cellvars);
+ for (i = 0; i < n; i++) {
+ if (co->co_cell2arg[i] == 0) {
+ PyObject *cell = f->f_localsplus[co->co_nlocals + i];
+ assert(PyCell_Check(cell));
+ obj = PyCell_GET(cell);
+ break;
+ }
+ }
+ }
+ if (obj == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "super(): arg[0] deleted");
+ return -1;
+ }
+
+ if (co->co_freevars == NULL) {
+ n = 0;
+ }
+ else {
+ assert(PyTuple_Check(co->co_freevars));
+ n = PyTuple_GET_SIZE(co->co_freevars);
+ }
+
+ PyTypeObject *type = NULL;
+ for (i = 0; i < n; i++) {
+ PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
+ assert(PyUnicode_Check(name));
+ if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) {
+ Py_ssize_t index = co->co_nlocals +
+ PyTuple_GET_SIZE(co->co_cellvars) + i;
+ PyObject *cell = f->f_localsplus[index];
+ if (cell == NULL || !PyCell_Check(cell)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "super(): bad __class__ cell");
+ return -1;
+ }
+ type = (PyTypeObject *) PyCell_GET(cell);
+ if (type == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "super(): empty __class__ cell");
+ return -1;
+ }
+ if (!PyType_Check(type)) {
+ PyErr_Format(PyExc_RuntimeError,
+ "super(): __class__ is not a type (%s)",
+ Py_TYPE(type)->tp_name);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (type == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "super(): __class__ cell not found");
+ return -1;
+ }
+
+ *type_p = type;
+ *obj_p = obj;
+ return 0;
+}
+
+static int
super_init(PyObject *self, PyObject *args, PyObject *kwds)
{
superobject *su = (superobject *)self;
@@ -8030,75 +8107,19 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
if (type == NULL) {
/* Call super(), without args -- fill in from __class__
and first local variable on the stack. */
- PyFrameObject *f;
- Py_ssize_t i, n;
- f = PyThreadState_GetFrame(_PyThreadState_GET());
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyFrameObject *f = PyThreadState_GetFrame(tstate);
if (f == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no current frame");
return -1;
}
- PyCodeObject *co = PyFrame_GetCode(f);
- Py_DECREF(co); // use a borrowed reference
- if (co->co_argcount == 0) {
- PyErr_SetString(PyExc_RuntimeError,
- "super(): no arguments");
- return -1;
- }
- obj = f->f_localsplus[0];
- if (obj == NULL && co->co_cell2arg) {
- /* The first argument might be a cell. */
- n = PyTuple_GET_SIZE(co->co_cellvars);
- for (i = 0; i < n; i++) {
- if (co->co_cell2arg[i] == 0) {
- PyObject *cell = f->f_localsplus[co->co_nlocals + i];
- assert(PyCell_Check(cell));
- obj = PyCell_GET(cell);
- break;
- }
- }
- }
- if (obj == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "super(): arg[0] deleted");
- return -1;
- }
- if (co->co_freevars == NULL)
- n = 0;
- else {
- assert(PyTuple_Check(co->co_freevars));
- n = PyTuple_GET_SIZE(co->co_freevars);
- }
- for (i = 0; i < n; i++) {
- PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
- assert(PyUnicode_Check(name));
- if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) {
- Py_ssize_t index = co->co_nlocals +
- PyTuple_GET_SIZE(co->co_cellvars) + i;
- PyObject *cell = f->f_localsplus[index];
- if (cell == NULL || !PyCell_Check(cell)) {
- PyErr_SetString(PyExc_RuntimeError,
- "super(): bad __class__ cell");
- return -1;
- }
- type = (PyTypeObject *) PyCell_GET(cell);
- if (type == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "super(): empty __class__ cell");
- return -1;
- }
- if (!PyType_Check(type)) {
- PyErr_Format(PyExc_RuntimeError,
- "super(): __class__ is not a type (%s)",
- Py_TYPE(type)->tp_name);
- return -1;
- }
- break;
- }
- }
- if (type == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "super(): __class__ cell not found");
+
+ PyCodeObject *code = PyFrame_GetCode(f);
+ int res = super_init_without_args(f, code, &type, &obj);
+ Py_DECREF(code);
+
+ if (res < 0) {
return -1;
}
}