]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46481: Implement vectorcall for weakref.ref.__call__ method. (GH-30820)
authorDong-hee Na <donghee.na@python.org>
Sun, 23 Jan 2022 15:39:45 +0000 (00:39 +0900)
committerGitHub <noreply@github.com>
Sun, 23 Jan 2022 15:39:45 +0000 (00:39 +0900)
Include/cpython/weakrefobject.h
Lib/test/test_sys.py
Misc/NEWS.d/next/Core and Builtins/2022-01-23-06-56-33.bpo-46481.X_FfnB.rst [new file with mode: 0644]
Objects/weakrefobject.c

index 9efcc412df9bed4a19defc2033ccf165de1663e5..3623071cdb04420a22ab6775fd80fe2af9f6f002 100644 (file)
@@ -29,6 +29,7 @@ struct _PyWeakReference {
      */
     PyWeakReference *wr_prev;
     PyWeakReference *wr_next;
+    vectorcallfunc vectorcall;
 };
 
 PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head);
index accd35e4ab2717578e39ed640b9a576f200746eb..f6da57f55f16178f3a225a59eab91275c2d994b6 100644 (file)
@@ -1538,11 +1538,11 @@ class SizeofTest(unittest.TestCase):
         # TODO: add check that forces layout of unicodefields
         # weakref
         import weakref
-        check(weakref.ref(int), size('2Pn2P'))
+        check(weakref.ref(int), size('2Pn3P'))
         # weakproxy
         # XXX
         # weakcallableproxy
-        check(weakref.proxy(int), size('2Pn2P'))
+        check(weakref.proxy(int), size('2Pn3P'))
 
     def check_slots(self, obj, base, extra):
         expected = sys.getsizeof(base) + struct.calcsize(extra)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-23-06-56-33.bpo-46481.X_FfnB.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-23-06-56-33.bpo-46481.X_FfnB.rst
new file mode 100644 (file)
index 0000000..edab2eb
--- /dev/null
@@ -0,0 +1,2 @@
+Speed up calls to :meth:`weakref.ref.__call__` by using the :pep:`590`
+``vectorcall`` calling convention. Patch by Dong-hee Na.
index 892276897522133662e739b342cb307fa714d44c..b9920404c5f9f0e4a392170cbf36c35abb6e3eaf 100644 (file)
@@ -19,6 +19,7 @@ _PyWeakref_GetWeakrefCount(PyWeakReference *head)
     return count;
 }
 
+static PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
 
 static void
 init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
@@ -27,8 +28,8 @@ init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
     self->wr_object = ob;
     self->wr_prev = NULL;
     self->wr_next = NULL;
-    Py_XINCREF(callback);
-    self->wr_callback = callback;
+    self->wr_callback = Py_XNewRef(callback);
+    self->vectorcall = (vectorcallfunc)weakref_vectorcall;
 }
 
 static PyWeakReference *
@@ -128,19 +129,19 @@ gc_clear(PyWeakReference *self)
 
 
 static PyObject *
-weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
+weakref_vectorcall(PyWeakReference *self, PyObject *const *args,
+                   size_t nargsf, PyObject *kwnames)
 {
-    static char *kwlist[] = {NULL};
-
-    if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
-        PyObject *object = PyWeakref_GET_OBJECT(self);
-        Py_INCREF(object);
-        return (object);
+    if (!_PyArg_NoKwnames("weakref", kwnames)) {
+        return NULL;
+    }
+    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+    if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) {
+        return NULL;
     }
-    return NULL;
+    return Py_NewRef(PyWeakref_GET_OBJECT(self));
 }
 
-
 static Py_hash_t
 weakref_hash(PyWeakReference *self)
 {
@@ -371,45 +372,24 @@ static PyMethodDef weakref_methods[] = {
 PyTypeObject
 _PyWeakref_RefType = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    "weakref",
-    sizeof(PyWeakReference),
-    0,
-    weakref_dealloc,            /*tp_dealloc*/
-    0,                          /*tp_vectorcall_offset*/
-    0,                          /*tp_getattr*/
-    0,                          /*tp_setattr*/
-    0,                          /*tp_as_async*/
-    (reprfunc)weakref_repr,     /*tp_repr*/
-    0,                          /*tp_as_number*/
-    0,                          /*tp_as_sequence*/
-    0,                          /*tp_as_mapping*/
-    (hashfunc)weakref_hash,     /*tp_hash*/
-    (ternaryfunc)weakref_call,  /*tp_call*/
-    0,                          /*tp_str*/
-    0,                          /*tp_getattro*/
-    0,                          /*tp_setattro*/
-    0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
-        | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
-    0,                          /*tp_doc*/
-    (traverseproc)gc_traverse,  /*tp_traverse*/
-    (inquiry)gc_clear,          /*tp_clear*/
-    (richcmpfunc)weakref_richcompare,   /*tp_richcompare*/
-    0,                          /*tp_weaklistoffset*/
-    0,                          /*tp_iter*/
-    0,                          /*tp_iternext*/
-    weakref_methods,            /*tp_methods*/
-    weakref_members,            /*tp_members*/
-    0,                          /*tp_getset*/
-    0,                          /*tp_base*/
-    0,                          /*tp_dict*/
-    0,                          /*tp_descr_get*/
-    0,                          /*tp_descr_set*/
-    0,                          /*tp_dictoffset*/
-    weakref___init__,           /*tp_init*/
-    PyType_GenericAlloc,        /*tp_alloc*/
-    weakref___new__,            /*tp_new*/
-    PyObject_GC_Del,            /*tp_free*/
+    .tp_name = "weakref",
+    .tp_basicsize = sizeof(PyWeakReference),
+    .tp_dealloc = weakref_dealloc,
+    .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
+    .tp_call = PyVectorcall_Call,
+    .tp_repr = (reprfunc)weakref_repr,
+    .tp_hash = (hashfunc)weakref_hash,
+    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+                Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE,
+    .tp_traverse = (traverseproc)gc_traverse,
+    .tp_clear = (inquiry)gc_clear,
+    .tp_richcompare = (richcmpfunc)weakref_richcompare,
+    .tp_methods = weakref_methods,
+    .tp_members = weakref_members,
+    .tp_init = weakref___init__,
+    .tp_alloc = PyType_GenericAlloc,
+    .tp_new = weakref___new__,
+    .tp_free = PyObject_GC_Del,
 };