Skip to content

Commit 899dcc9

Browse files
eendebakptclaude
andcommitted
Use a managed weakref list for the _io types
Replace the explicit weakreflist field of the _io types with Py_TPFLAGS_MANAGED_WEAKREF, inherited from _IOBase, so the weakref list lives in the pre-header like the managed dict. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 4a9f0fa commit 899dcc9

8 files changed

Lines changed: 15 additions & 39 deletions

File tree

‎Lib/test/test_io/test_memoryio.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,12 +1038,12 @@ def test_setstate(self):
10381038
@support.cpython_only
10391039
def test_sizeof(self):
10401040
if support.Py_GIL_DISABLED:
1041-
basesize = support.calcobjsize('P2nPni')
1041+
basesize = support.calcobjsize('P2nni')
10421042
else:
1043-
basesize = support.calcobjsize('P2nPn')
1043+
basesize = support.calcobjsize('P2nn')
10441044
check = self.check_sizeof
10451045
self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
1046-
# sys.getsizeof() includes the managed dict pre-header
1046+
# sys.getsizeof() includes the managed dict and weakref pre-header
10471047
basesize += 2 * struct.calcsize('P')
10481048
check(io.BytesIO(), basesize )
10491049
n = 1000 # use a variable to prevent constant folding

‎Modules/_io/bufferedio.c‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99

1010
#include "Python.h"
1111
#include "pycore_call.h" // _PyObject_CallNoArgs()
12+
#include "pycore_critical_section.h" // _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()
1213
#include "pycore_fileutils.h" // _PyFile_Flush
1314
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
1415
#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
1516
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
16-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
1717

1818
#include "_iomodule.h"
1919

@@ -260,7 +260,6 @@ typedef struct {
260260
Py_ssize_t buffer_size;
261261
Py_ssize_t buffer_mask;
262262

263-
PyObject *weakreflist;
264263
} buffered;
265264

266265
#define buffered_CAST(op) ((buffered *)(op))
@@ -430,7 +429,7 @@ buffered_dealloc(PyObject *op)
430429
return;
431430
_PyObject_GC_UNTRACK(self);
432431
self->ok = 0;
433-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
432+
PyObject_ClearWeakRefs(op);
434433
if (self->buffer) {
435434
PyMem_Free(self->buffer);
436435
self->buffer = NULL;
@@ -2248,7 +2247,6 @@ typedef struct {
22482247
PyObject_HEAD
22492248
buffered *reader;
22502249
buffered *writer;
2251-
PyObject *weakreflist;
22522250
} rwpair;
22532251

22542252
#define rwpair_CAST(op) ((rwpair *)(op))
@@ -2327,7 +2325,7 @@ bufferedrwpair_dealloc(PyObject *op)
23272325
rwpair *self = rwpair_CAST(op);
23282326
PyTypeObject *tp = Py_TYPE(self);
23292327
_PyObject_GC_UNTRACK(self);
2330-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
2328+
PyObject_ClearWeakRefs(op);
23312329
(void)bufferedrwpair_clear(op);
23322330
tp->tp_free(self);
23332331
Py_DECREF(tp);
@@ -2634,7 +2632,6 @@ static PyMethodDef bufferedreader_methods[] = {
26342632
static PyMemberDef bufferedreader_members[] = {
26352633
{"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
26362634
{"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2637-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
26382635
{NULL}
26392636
};
26402637

@@ -2692,7 +2689,6 @@ static PyMethodDef bufferedwriter_methods[] = {
26922689
static PyMemberDef bufferedwriter_members[] = {
26932690
{"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
26942691
{"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2695-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
26962692
{NULL}
26972693
};
26982694

@@ -2745,7 +2741,6 @@ static PyMethodDef bufferedrwpair_methods[] = {
27452741
};
27462742

27472743
static PyMemberDef bufferedrwpair_members[] = {
2748-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(rwpair, weakreflist), Py_READONLY},
27492744
{NULL}
27502745
};
27512746

@@ -2807,7 +2802,6 @@ static PyMethodDef bufferedrandom_methods[] = {
28072802
static PyMemberDef bufferedrandom_members[] = {
28082803
{"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
28092804
{"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2810-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
28112805
{NULL}
28122806
};
28132807

‎Modules/_io/bytesio.c‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "pycore_object.h"
66
#include "pycore_pyatomic_ft_wrappers.h"
77
#include "pycore_sysmodule.h" // _PySys_GetSizeOf()
8-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
98

109
#include <stddef.h> // offsetof()
1110
#include "_iomodule.h"
@@ -21,7 +20,6 @@ typedef struct {
2120
PyObject *buf;
2221
Py_ssize_t pos;
2322
Py_ssize_t string_size;
24-
PyObject *weakreflist;
2523
Py_ssize_t exports;
2624
#ifdef Py_GIL_DISABLED
2725
int buf_shared;
@@ -1094,7 +1092,7 @@ bytesio_dealloc(PyObject *op)
10941092
}
10951093
Py_CLEAR(self->buf);
10961094
PyObject_ClearManagedDict(op);
1097-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
1095+
PyObject_ClearWeakRefs(op);
10981096
tp->tp_free(self);
10991097
Py_DECREF(tp);
11001098
}
@@ -1242,7 +1240,6 @@ static struct PyMethodDef bytesio_methods[] = {
12421240
};
12431241

12441242
static PyMemberDef bytesio_members[] = {
1245-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(bytesio, weakreflist), Py_READONLY},
12461243
{NULL}
12471244
};
12481245

‎Modules/_io/fileio.c‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
55
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
66
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
7-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
87

98
#include <stdbool.h> // bool
109
#ifdef HAVE_UNISTD_H
@@ -80,7 +79,6 @@ typedef struct {
8079
modified outside of the fileio object / Python (ex. gh-90102, GH-121941,
8180
gh-109523). */
8281
struct _Py_stat_struct *stat_atopen;
83-
PyObject *weakreflist;
8482
} fileio;
8583

8684
#define PyFileIO_Check(state, op) (PyObject_TypeCheck((op), state->PyFileIO_Type))
@@ -219,7 +217,6 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
219217
self->truncate = 0;
220218
self->stat_atopen = NULL;
221219
self->closefd = 1;
222-
self->weakreflist = NULL;
223220
return (PyObject *) self;
224221
}
225222

@@ -581,7 +578,7 @@ fileio_dealloc(PyObject *op)
581578
PyMem_Free(self->stat_atopen);
582579
self->stat_atopen = NULL;
583580
}
584-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
581+
PyObject_ClearWeakRefs(op);
585582
(void)fileio_clear(op);
586583

587584
PyTypeObject *tp = Py_TYPE(op);
@@ -1363,7 +1360,6 @@ static PyGetSetDef fileio_getsetlist[] = {
13631360

13641361
static PyMemberDef fileio_members[] = {
13651362
{"_finalizing", Py_T_BOOL, offsetof(fileio, finalizing), 0},
1366-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(fileio, weakreflist), Py_READONLY},
13671363
{NULL}
13681364
};
13691365

‎Modules/_io/iobase.c‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "pycore_long.h" // _PyLong_GetOne()
1515
#include "pycore_object.h" // _PyType_HasFeature()
1616
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
17-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
1817

1918
#include <stddef.h> // offsetof()
2019
#include "_iomodule.h"
@@ -33,7 +32,6 @@ class _io._RawIOBase "PyObject *" "clinic_state()->PyRawIOBase_Type"
3332
typedef struct {
3433
PyObject_HEAD
3534

36-
PyObject *weakreflist;
3735
} iobase;
3836

3937
#define iobase_CAST(op) ((iobase *)(op))
@@ -413,7 +411,7 @@ iobase_dealloc(PyObject *op)
413411
}
414412
PyTypeObject *tp = Py_TYPE(self);
415413
_PyObject_GC_UNTRACK(self);
416-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
414+
PyObject_ClearWeakRefs(op);
417415
PyObject_ClearManagedDict(op);
418416
tp->tp_free(self);
419417
Py_DECREF(tp);
@@ -905,7 +903,6 @@ static PyGetSetDef iobase_getset[] = {
905903
};
906904

907905
static struct PyMemberDef iobase_members[] = {
908-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(iobase, weakreflist), Py_READONLY},
909906
{NULL},
910907
};
911908

@@ -928,7 +925,8 @@ PyType_Spec _Py_iobase_spec = {
928925
.name = "_io._IOBase",
929926
.basicsize = sizeof(iobase),
930927
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
931-
Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT),
928+
Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
929+
Py_TPFLAGS_MANAGED_WEAKREF),
932930
.slots = iobase_slots,
933931
};
934932

‎Modules/_io/stringio.c‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include "Python.h"
22
#include <stddef.h> // offsetof()
3+
#include "pycore_critical_section.h" // _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()
34
#include "pycore_object.h"
45
#include "pycore_unicodeobject.h" // _PyUnicode_ResizeCompact()
5-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
66
#include "_iomodule.h"
77

88
/* Implementation note: the buffer is always at least one character longer
@@ -42,7 +42,6 @@ typedef struct {
4242
PyObject *readnl;
4343
PyObject *writenl;
4444

45-
PyObject *weakreflist;
4645
_PyIO_State *module_state;
4746
} stringio;
4847

@@ -701,7 +700,7 @@ stringio_dealloc(PyObject *op)
701700
}
702701
PyUnicodeWriter_Discard(self->writer);
703702
(void)stringio_clear(op);
704-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
703+
PyObject_ClearWeakRefs(op);
705704
tp->tp_free(self);
706705
Py_DECREF(tp);
707706
}
@@ -1144,7 +1143,6 @@ static PyGetSetDef stringio_getset[] = {
11441143
};
11451144

11461145
static struct PyMemberDef stringio_members[] = {
1147-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(stringio, weakreflist), Py_READONLY},
11481146
{NULL},
11491147
};
11501148

‎Modules/_io/textio.c‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
1717
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1818
#include "pycore_unicodeobject.h" // _PyUnicode_AsASCIIString()
19-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
2019

2120
#include "_iomodule.h"
2221

@@ -731,7 +730,6 @@ struct textio
731730
/* Cache raw object if it's a FileIO object */
732731
PyObject *raw;
733732

734-
PyObject *weakreflist;
735733

736734
_PyIO_State *state;
737735
};
@@ -1555,7 +1553,7 @@ textiowrapper_dealloc(PyObject *op)
15551553
return;
15561554
self->ok = 0;
15571555
_PyObject_GC_UNTRACK(self);
1558-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
1556+
PyObject_ClearWeakRefs(op);
15591557
(void)textiowrapper_clear(op);
15601558
tp->tp_free(self);
15611559
Py_DECREF(tp);
@@ -3536,7 +3534,6 @@ static PyMemberDef textiowrapper_members[] = {
35363534
{"line_buffering", Py_T_BOOL, offsetof(textio, line_buffering), Py_READONLY},
35373535
{"write_through", Py_T_BOOL, offsetof(textio, write_through), Py_READONLY},
35383536
{"_finalizing", Py_T_BOOL, offsetof(textio, finalizing), 0},
3539-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(textio, weakreflist), Py_READONLY},
35403537
{NULL}
35413538
};
35423539

‎Modules/_io/winconsoleio.c‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
1111
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
1212
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
13-
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
1413

1514
#ifdef HAVE_WINDOWS_CONSOLE_IO
1615

@@ -216,7 +215,6 @@ typedef struct {
216215
unsigned int closefd : 1;
217216
char finalizing;
218217
unsigned int blksize;
219-
PyObject *weakreflist;
220218
char buf[SMALLBUF];
221219
wchar_t wbuf;
222220
} winconsoleio;
@@ -299,7 +297,6 @@ winconsoleio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
299297
self->writable = 0;
300298
self->closefd = 0;
301299
self->blksize = 0;
302-
self->weakreflist = NULL;
303300
}
304301

305302
return (PyObject *) self;
@@ -516,7 +513,7 @@ winconsoleio_dealloc(PyObject *op)
516513
if (_PyIOBase_finalize(op) < 0)
517514
return;
518515
_PyObject_GC_UNTRACK(self);
519-
FT_CLEAR_WEAKREFS(op, self->weakreflist);
516+
PyObject_ClearWeakRefs(op);
520517
PyObject_ClearManagedDict(op);
521518
tp->tp_free(self);
522519
Py_DECREF(tp);
@@ -1255,7 +1252,6 @@ static PyGetSetDef winconsoleio_getsetlist[] = {
12551252
static PyMemberDef winconsoleio_members[] = {
12561253
{"_blksize", Py_T_UINT, offsetof(winconsoleio, blksize), 0},
12571254
{"_finalizing", Py_T_BOOL, offsetof(winconsoleio, finalizing), 0},
1258-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(winconsoleio, weakreflist), Py_READONLY},
12591255
{NULL}
12601256
};
12611257

0 commit comments

Comments
 (0)