aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInada Naoki <songofacandy@gmail.com>2019-07-26 15:05:50 +0900
committerGitHub <noreply@github.com>2019-07-26 15:05:50 +0900
commit3e54b575313c64f541e98216ed079fafed01ff5d (patch)
tree747f171a2d8d726cc97580c85ded8891a2bc41ae
parentbpo-29446: tkinter 'import *' only imports what it should (GH-14864) (diff)
downloadcpython-3e54b575313c64f541e98216ed079fafed01ff5d.tar.gz
cpython-3e54b575313c64f541e98216ed079fafed01ff5d.tar.bz2
cpython-3e54b575313c64f541e98216ed079fafed01ff5d.zip
bpo-37340: remove free_list for bound method objects (GH-14232)
-rw-r--r--Include/methodobject.h5
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2019-07-25-11-06-57.bpo-37340.5ktLEg.rst3
-rw-r--r--Objects/classobject.c52
-rw-r--r--Objects/methodobject.c53
-rw-r--r--Objects/object.c2
5 files changed, 14 insertions, 101 deletions
diff --git a/Include/methodobject.h b/Include/methodobject.h
index ab66b03f7a9..9f5f7c482c8 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -99,11 +99,6 @@ typedef struct {
PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
-PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-25-11-06-57.bpo-37340.5ktLEg.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-25-11-06-57.bpo-37340.5ktLEg.rst
new file mode 100644
index 00000000000..e61146b6f79
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-25-11-06-57.bpo-37340.5ktLEg.rst
@@ -0,0 +1,3 @@
+Removed object cache (``free_list``) for bound method objects. Temporary
+bound method objects are less used than before thanks to the ``LOAD_METHOD``
+opcode and the ``_PyObject_VectorcallMethod`` C API.
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 46525a737bc..40cbeaa9f2a 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -8,15 +8,6 @@
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
-/* Free list for method objects to safe malloc/free overhead
- * The im_self element is used to chain the elements.
- */
-static PyMethodObject *free_list;
-static int numfree = 0;
-#ifndef PyMethod_MAXFREELIST
-#define PyMethod_MAXFREELIST 256
-#endif
-
_Py_IDENTIFIER(__name__);
_Py_IDENTIFIER(__qualname__);
@@ -103,21 +94,13 @@ method_vectorcall(PyObject *method, PyObject *const *args,
PyObject *
PyMethod_New(PyObject *func, PyObject *self)
{
- PyMethodObject *im;
if (self == NULL) {
PyErr_BadInternalCall();
return NULL;
}
- im = free_list;
- if (im != NULL) {
- free_list = (PyMethodObject *)(im->im_self);
- (void)PyObject_INIT(im, &PyMethod_Type);
- numfree--;
- }
- else {
- im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
- if (im == NULL)
- return NULL;
+ PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
+ if (im == NULL) {
+ return NULL;
}
im->im_weakreflist = NULL;
Py_INCREF(func);
@@ -252,14 +235,7 @@ method_dealloc(PyMethodObject *im)
PyObject_ClearWeakRefs((PyObject *)im);
Py_DECREF(im->im_func);
Py_XDECREF(im->im_self);
- if (numfree < PyMethod_MAXFREELIST) {
- im->im_self = (PyObject *)free_list;
- free_list = im;
- numfree++;
- }
- else {
- PyObject_GC_Del(im);
- }
+ PyObject_GC_Del(im);
}
static PyObject *
@@ -395,16 +371,7 @@ PyTypeObject PyMethod_Type = {
int
PyMethod_ClearFreeList(void)
{
- int freelist_size = numfree;
-
- while (free_list) {
- PyMethodObject *im = free_list;
- free_list = (PyMethodObject *)(im->im_self);
- PyObject_GC_Del(im);
- numfree--;
- }
- assert(numfree == 0);
- return freelist_size;
+ return 0;
}
void
@@ -413,15 +380,6 @@ PyMethod_Fini(void)
(void)PyMethod_ClearFreeList();
}
-/* Print summary info about the state of the optimized allocator */
-void
-_PyMethod_DebugMallocStats(FILE *out)
-{
- _PyDebugAllocatorStats(out,
- "free PyMethodObject",
- numfree, sizeof(PyMethodObject));
-}
-
/* ------------------------------------------------------------------------
* instance method
*/
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 3494f11d80f..b9977467ac0 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -7,15 +7,6 @@
#include "pycore_pystate.h"
#include "structmember.h"
-/* Free list for method objects to safe malloc/free overhead
- * The m_self element is used to chain the objects.
- */
-static PyCFunctionObject *free_list = NULL;
-static int numfree = 0;
-#ifndef PyCFunction_MAXFREELIST
-#define PyCFunction_MAXFREELIST 256
-#endif
-
/* undefine macro trampoline to PyCFunction_NewEx */
#undef PyCFunction_New
@@ -66,17 +57,10 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
return NULL;
}
- PyCFunctionObject *op;
- op = free_list;
- if (op != NULL) {
- free_list = (PyCFunctionObject *)(op->m_self);
- (void)PyObject_INIT(op, &PyCFunction_Type);
- numfree--;
- }
- else {
- op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
- if (op == NULL)
- return NULL;
+ PyCFunctionObject *op =
+ PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+ if (op == NULL) {
+ return NULL;
}
op->m_weakreflist = NULL;
op->m_ml = ml;
@@ -130,14 +114,7 @@ meth_dealloc(PyCFunctionObject *m)
}
Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module);
- if (numfree < PyCFunction_MAXFREELIST) {
- m->m_self = (PyObject *)free_list;
- free_list = m;
- numfree++;
- }
- else {
- PyObject_GC_Del(m);
- }
+ PyObject_GC_Del(m);
}
static PyObject *
@@ -338,16 +315,7 @@ PyTypeObject PyCFunction_Type = {
int
PyCFunction_ClearFreeList(void)
{
- int freelist_size = numfree;
-
- while (free_list) {
- PyCFunctionObject *v = free_list;
- free_list = (PyCFunctionObject *)(v->m_self);
- PyObject_GC_Del(v);
- numfree--;
- }
- assert(numfree == 0);
- return freelist_size;
+ return 0;
}
void
@@ -356,15 +324,6 @@ PyCFunction_Fini(void)
(void)PyCFunction_ClearFreeList();
}
-/* Print summary info about the state of the optimized allocator */
-void
-_PyCFunction_DebugMallocStats(FILE *out)
-{
- _PyDebugAllocatorStats(out,
- "free PyCFunctionObject",
- numfree, sizeof(PyCFunctionObject));
-}
-
/* Vectorcall functions for each of the PyCFunction calling conventions,
* except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
diff --git a/Objects/object.c b/Objects/object.c
index 585a9748c84..ee2050656a0 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1959,12 +1959,10 @@ Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
void
_PyObject_DebugTypeStats(FILE *out)
{
- _PyCFunction_DebugMallocStats(out);
_PyDict_DebugMallocStats(out);
_PyFloat_DebugMallocStats(out);
_PyFrame_DebugMallocStats(out);
_PyList_DebugMallocStats(out);
- _PyMethod_DebugMallocStats(out);
_PyTuple_DebugMallocStats(out);
}