Skip to content

Commit a962017

Browse files
committed
Use a tuple to store overwritten fast locals
1 parent fdb8a82 commit a962017

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

Include/internal/pycore_frame.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ struct _frame {
3232
PyEval_GetLocals requires a borrowed reference so the actual reference
3333
is stored here */
3434
PyObject *f_locals_cache;
35-
/* A list containing strong references to fast locals that were overwritten
35+
/* A tuple containing strong references to fast locals that were overwritten
3636
* via f_locals. Borrowed references to these locals may exist in frames
37-
* closer to the top of the stack. The references in this list act as
37+
* closer to the top of the stack. The references in this tuple act as
3838
* "support" for the borrowed references, ensuring that they remain valid.
3939
*/
4040
PyObject *f_overwritten_fast_locals;

Objects/frameobject.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,29 @@ framelocalsproxy_getitem(PyObject *self, PyObject *key)
206206
return NULL;
207207
}
208208

209+
static int
210+
add_overwritten_fast_local(PyFrameObject *frame, PyObject *obj)
211+
{
212+
Py_ssize_t new_size = 1;
213+
if (frame->f_overwritten_fast_locals != NULL) {
214+
new_size = PyTuple_Size(frame->f_overwritten_fast_locals);
215+
if (new_size == -1) {
216+
return -1;
217+
}
218+
}
219+
PyObject *new_tuple = PyTuple_New(new_size);
220+
if (new_tuple == NULL) {
221+
return -1;
222+
}
223+
for (Py_ssize_t i = 0; i < new_size - 1; i++) {
224+
PyObject *o = PyTuple_GET_ITEM(frame->f_overwritten_fast_locals, i);
225+
PyTuple_SET_ITEM(new_tuple, i, Py_NewRef(o));
226+
}
227+
PyTuple_SET_ITEM(new_tuple, new_size - 1, Py_NewRef(obj));
228+
Py_XSETREF(frame->f_overwritten_fast_locals, new_tuple);
229+
return 0;
230+
}
231+
209232
static int
210233
framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
211234
{
@@ -246,13 +269,7 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
246269
} else if (value != PyStackRef_AsPyObjectBorrow(oldvalue)) {
247270
PyObject *old_obj = PyStackRef_AsPyObjectBorrow(fast[i]);
248271
if (old_obj != NULL && !_Py_IsImmortal(old_obj)) {
249-
if (frame->f_overwritten_fast_locals == NULL) {
250-
frame->f_overwritten_fast_locals = PyList_New(0);
251-
if (frame->f_overwritten_fast_locals == NULL) {
252-
return -1;
253-
}
254-
}
255-
if (PyList_Append(frame->f_overwritten_fast_locals, old_obj) < 0) {
272+
if (add_overwritten_fast_local(frame, old_obj) < 0) {
256273
return -1;
257274
}
258275
PyStackRef_CLOSE(fast[i]);

0 commit comments

Comments
 (0)