Skip to content

Commit 3e54b57

Browse files
authored
bpo-37340: remove free_list for bound method objects (GH-14232)
1 parent 76b6451 commit 3e54b57

File tree

5 files changed

+14
-101
lines changed

5 files changed

+14
-101
lines changed

Include/methodobject.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ typedef struct {
9999

100100
PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
101101

102-
#ifndef Py_LIMITED_API
103-
PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
104-
PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
105-
#endif
106-
107102
#ifdef __cplusplus
108103
}
109104
#endif
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Removed object cache (``free_list``) for bound method objects. Temporary
2+
bound method objects are less used than before thanks to the ``LOAD_METHOD``
3+
opcode and the ``_PyObject_VectorcallMethod`` C API.

Objects/classobject.c

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@
88

99
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
1010

11-
/* Free list for method objects to safe malloc/free overhead
12-
* The im_self element is used to chain the elements.
13-
*/
14-
static PyMethodObject *free_list;
15-
static int numfree = 0;
16-
#ifndef PyMethod_MAXFREELIST
17-
#define PyMethod_MAXFREELIST 256
18-
#endif
19-
2011
_Py_IDENTIFIER(__name__);
2112
_Py_IDENTIFIER(__qualname__);
2213

@@ -103,21 +94,13 @@ method_vectorcall(PyObject *method, PyObject *const *args,
10394
PyObject *
10495
PyMethod_New(PyObject *func, PyObject *self)
10596
{
106-
PyMethodObject *im;
10797
if (self == NULL) {
10898
PyErr_BadInternalCall();
10999
return NULL;
110100
}
111-
im = free_list;
112-
if (im != NULL) {
113-
free_list = (PyMethodObject *)(im->im_self);
114-
(void)PyObject_INIT(im, &PyMethod_Type);
115-
numfree--;
116-
}
117-
else {
118-
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
119-
if (im == NULL)
120-
return NULL;
101+
PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
102+
if (im == NULL) {
103+
return NULL;
121104
}
122105
im->im_weakreflist = NULL;
123106
Py_INCREF(func);
@@ -252,14 +235,7 @@ method_dealloc(PyMethodObject *im)
252235
PyObject_ClearWeakRefs((PyObject *)im);
253236
Py_DECREF(im->im_func);
254237
Py_XDECREF(im->im_self);
255-
if (numfree < PyMethod_MAXFREELIST) {
256-
im->im_self = (PyObject *)free_list;
257-
free_list = im;
258-
numfree++;
259-
}
260-
else {
261-
PyObject_GC_Del(im);
262-
}
238+
PyObject_GC_Del(im);
263239
}
264240

265241
static PyObject *
@@ -395,16 +371,7 @@ PyTypeObject PyMethod_Type = {
395371
int
396372
PyMethod_ClearFreeList(void)
397373
{
398-
int freelist_size = numfree;
399-
400-
while (free_list) {
401-
PyMethodObject *im = free_list;
402-
free_list = (PyMethodObject *)(im->im_self);
403-
PyObject_GC_Del(im);
404-
numfree--;
405-
}
406-
assert(numfree == 0);
407-
return freelist_size;
374+
return 0;
408375
}
409376

410377
void
@@ -413,15 +380,6 @@ PyMethod_Fini(void)
413380
(void)PyMethod_ClearFreeList();
414381
}
415382

416-
/* Print summary info about the state of the optimized allocator */
417-
void
418-
_PyMethod_DebugMallocStats(FILE *out)
419-
{
420-
_PyDebugAllocatorStats(out,
421-
"free PyMethodObject",
422-
numfree, sizeof(PyMethodObject));
423-
}
424-
425383
/* ------------------------------------------------------------------------
426384
* instance method
427385
*/

Objects/methodobject.c

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@
77
#include "pycore_pystate.h"
88
#include "structmember.h"
99

10-
/* Free list for method objects to safe malloc/free overhead
11-
* The m_self element is used to chain the objects.
12-
*/
13-
static PyCFunctionObject *free_list = NULL;
14-
static int numfree = 0;
15-
#ifndef PyCFunction_MAXFREELIST
16-
#define PyCFunction_MAXFREELIST 256
17-
#endif
18-
1910
/* undefine macro trampoline to PyCFunction_NewEx */
2011
#undef PyCFunction_New
2112

@@ -66,17 +57,10 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
6657
return NULL;
6758
}
6859

69-
PyCFunctionObject *op;
70-
op = free_list;
71-
if (op != NULL) {
72-
free_list = (PyCFunctionObject *)(op->m_self);
73-
(void)PyObject_INIT(op, &PyCFunction_Type);
74-
numfree--;
75-
}
76-
else {
77-
op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
78-
if (op == NULL)
79-
return NULL;
60+
PyCFunctionObject *op =
61+
PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
62+
if (op == NULL) {
63+
return NULL;
8064
}
8165
op->m_weakreflist = NULL;
8266
op->m_ml = ml;
@@ -130,14 +114,7 @@ meth_dealloc(PyCFunctionObject *m)
130114
}
131115
Py_XDECREF(m->m_self);
132116
Py_XDECREF(m->m_module);
133-
if (numfree < PyCFunction_MAXFREELIST) {
134-
m->m_self = (PyObject *)free_list;
135-
free_list = m;
136-
numfree++;
137-
}
138-
else {
139-
PyObject_GC_Del(m);
140-
}
117+
PyObject_GC_Del(m);
141118
}
142119

143120
static PyObject *
@@ -338,16 +315,7 @@ PyTypeObject PyCFunction_Type = {
338315
int
339316
PyCFunction_ClearFreeList(void)
340317
{
341-
int freelist_size = numfree;
342-
343-
while (free_list) {
344-
PyCFunctionObject *v = free_list;
345-
free_list = (PyCFunctionObject *)(v->m_self);
346-
PyObject_GC_Del(v);
347-
numfree--;
348-
}
349-
assert(numfree == 0);
350-
return freelist_size;
318+
return 0;
351319
}
352320

353321
void
@@ -356,15 +324,6 @@ PyCFunction_Fini(void)
356324
(void)PyCFunction_ClearFreeList();
357325
}
358326

359-
/* Print summary info about the state of the optimized allocator */
360-
void
361-
_PyCFunction_DebugMallocStats(FILE *out)
362-
{
363-
_PyDebugAllocatorStats(out,
364-
"free PyCFunctionObject",
365-
numfree, sizeof(PyCFunctionObject));
366-
}
367-
368327

369328
/* Vectorcall functions for each of the PyCFunction calling conventions,
370329
* except for METH_VARARGS (possibly combined with METH_KEYWORDS) which

Objects/object.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,12 +1959,10 @@ Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
19591959
void
19601960
_PyObject_DebugTypeStats(FILE *out)
19611961
{
1962-
_PyCFunction_DebugMallocStats(out);
19631962
_PyDict_DebugMallocStats(out);
19641963
_PyFloat_DebugMallocStats(out);
19651964
_PyFrame_DebugMallocStats(out);
19661965
_PyList_DebugMallocStats(out);
1967-
_PyMethod_DebugMallocStats(out);
19681966
_PyTuple_DebugMallocStats(out);
19691967
}
19701968

0 commit comments

Comments
 (0)