diff options
-rw-r--r-- | Include/cpython/weakrefobject.h | 1 | ||||
-rw-r--r-- | Lib/test/test_sys.py | 4 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2022-01-23-06-56-33.bpo-46481.X_FfnB.rst | 2 | ||||
-rw-r--r-- | Objects/weakrefobject.c | 80 |
4 files changed, 35 insertions, 52 deletions
diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h index 9efcc41..3623071 100644 --- a/Include/cpython/weakrefobject.h +++ b/Include/cpython/weakrefobject.h @@ -29,6 +29,7 @@ struct _PyWeakReference { */ PyWeakReference *wr_prev; PyWeakReference *wr_next; + vectorcallfunc vectorcall; }; PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index accd35e..f6da57f 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -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 index 0000000..edab2eb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-23-06-56-33.bpo-46481.X_FfnB.rst @@ -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. diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 8922768..b992040 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -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, }; |