diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index 0717a1f956..bcadbaecc0 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -37,6 +37,8 @@ struct _Py_list_state { #define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item) +PyAPI_FUNC(int) +_PyList_AppendTakeRef(PyListObject *self, PyObject *newitem); #ifdef __cplusplus } diff --git a/Objects/listobject.c b/Objects/listobject.c index d50633d2b3..3463bcc18e 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -301,26 +301,34 @@ PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem) return ins1((PyListObject *)op, where, newitem); } -static int -app1(PyListObject *self, PyObject *v) +int +_PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) { - Py_ssize_t n = PyList_GET_SIZE(self); - - assert (v != NULL); - assert((size_t)n + 1 < PY_SSIZE_T_MAX); - if (list_resize(self, n+1) < 0) + assert(self != NULL && newitem != NULL); + assert(PyList_Check(self)); + Py_ssize_t len = PyList_GET_SIZE(self); + Py_ssize_t allocated = self->allocated; + assert((size_t)len + 1 < PY_SSIZE_T_MAX); + if (allocated > len) { + PyList_SET_ITEM(self, len, newitem); + Py_SET_SIZE(self, len + 1); + return 0; + } + if (list_resize(self, len + 1) < 0) { + Py_DECREF(newitem); return -1; - - Py_INCREF(v); - PyList_SET_ITEM(self, n, v); + } + PyList_SET_ITEM(self, len, newitem); return 0; } int PyList_Append(PyObject *op, PyObject *newitem) { - if (PyList_Check(op) && (newitem != NULL)) - return app1((PyListObject *)op, newitem); + if (PyList_Check(op) && (newitem != NULL)) { + Py_INCREF(newitem); + return _PyList_AppendTakeRef((PyListObject *)op, newitem); + } PyErr_BadInternalCall(); return -1; } @@ -844,7 +852,7 @@ static PyObject * list_append(PyListObject *self, PyObject *object) /*[clinic end generated code: output=7c096003a29c0eae input=43a3fe48a7066e91]*/ { - if (app1(self, object) == 0) + if (_PyList_AppendTakeRef(self, Py_NewRef(object)) == 0) Py_RETURN_NONE; return NULL; } @@ -963,9 +971,7 @@ list_extend(PyListObject *self, PyObject *iterable) Py_SET_SIZE(self, Py_SIZE(self) + 1); } else { - int status = app1(self, item); - Py_DECREF(item); /* append creates a new ref */ - if (status < 0) + if (_PyList_AppendTakeRef(self, item) < 0) goto error; } } diff --git a/Python/ceval.c b/Python/ceval.c index f751479664..7039a10c1a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2234,10 +2234,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(LIST_APPEND) { PyObject *v = POP(); PyObject *list = PEEK(oparg); - int err; - err = PyList_Append(list, v); - Py_DECREF(v); - if (err != 0) + if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto error; PREDICT(JUMP_ABSOLUTE); DISPATCH(); @@ -5070,14 +5067,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DEOPT_IF(!PyList_Check(list), PRECALL); STAT_INC(PRECALL, hit); SKIP_CALL(); - PyObject *arg = TOP(); - int err = PyList_Append(list, arg); - if (err) { + PyObject *arg = POP(); + if (_PyList_AppendTakeRef((PyListObject *)list, arg) < 0) { goto error; } - Py_DECREF(arg); Py_DECREF(list); - STACK_SHRINK(2); + STACK_SHRINK(1); Py_INCREF(Py_None); SET_TOP(Py_None); Py_DECREF(callable);