Skip to content

Commit 0dd6a4d

Browse files
authored
gh-87613: Use AC vectorcall for weakref.ref() (#159470)
1 parent 94d16d2 commit 0dd6a4d

4 files changed

Lines changed: 149 additions & 31 deletions

File tree

‎Lib/test/test_inspect/test_inspect.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6547,8 +6547,7 @@ def test_warnings_module_has_signatures(self):
65476547

65486548
def test_weakref_module_has_signatures(self):
65496549
import weakref
6550-
no_signature = {'ReferenceType', 'ref'}
6551-
self._test_module_has_signatures(weakref, no_signature)
6550+
self._test_module_has_signatures(weakref)
65526551

65536552
def test_python_function_override_signature(self):
65546553
def func(*args, **kwargs):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speed up creating :class:`weakref.ref` objects by adding a vectorcall implementation of the constructor generated by Argument Clinic. Patch by Pieter Eendebak.

‎Objects/clinic/weakrefobject.c.h‎

Lines changed: 106 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Objects/weakrefobject.c‎

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
99

1010
/*[clinic input]
11-
class weakref "PyWeakReference *" "&_PyWeakref_RefType"
11+
module weakref
12+
class weakref.ReferenceType "PyWeakReference *" "&_PyWeakref_RefType"
1213
[clinic start generated code]*/
13-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad66c8b0acee6ad9]*/
14+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=25211e4a7d687f3f]*/
1415

1516
#include "clinic/weakrefobject.c.h"
1617

@@ -195,12 +196,12 @@ weakref_vectorcall(PyObject *self, PyObject *const *args,
195196

196197
/*[clinic input]
197198
@critical_section
198-
weakref.__hash__
199+
weakref.ReferenceType.__hash__ as weakref_hash
199200
[clinic start generated code]*/
200201

201202
static Py_hash_t
202203
weakref_hash_impl(PyWeakReference *self)
203-
/*[clinic end generated code: output=4904eacaabf902c9 input=703596f4b120e47c]*/
204+
/*[clinic end generated code: output=4904eacaabf902c9 input=f248ec0b25c064e0]*/
204205
{
205206
if (self->hash != -1)
206207
return self->hash;
@@ -465,35 +466,45 @@ get_or_create_weakref(PyTypeObject *type, PyObject *obj, PyObject *callback)
465466
}
466467
}
467468

468-
static int
469-
parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
470-
PyObject **obp, PyObject **callbackp)
471-
{
472-
return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
473-
}
469+
/*[clinic input]
470+
@classmethod
471+
@vectorcall
472+
weakref.ReferenceType.__new__ as weakref_ref_new
473+
474+
object: object
475+
callback: object(c_default="NULL") = None
476+
/
477+
478+
Create a weak reference to object.
479+
480+
Calling the reference returns object, or None once it has been garbage
481+
collected. If callback is given, it is called with the reference as
482+
its only argument when object is about to be finalized.
483+
[clinic start generated code]*/
474484

475485
static PyObject *
476-
weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
486+
weakref_ref_new_impl(PyTypeObject *type, PyObject *object,
487+
PyObject *callback)
488+
/*[clinic end generated code: output=0b84aee8668f4c2f input=0cd09b468ebb6371]*/
477489
{
478-
PyObject *ob, *callback = NULL;
479-
if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
480-
return (PyObject *)get_or_create_weakref(type, ob, callback);
481-
}
482-
return NULL;
490+
return (PyObject *)get_or_create_weakref(type, object, callback);
483491
}
484492

485-
static int
486-
weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
487-
{
488-
PyObject *tmp;
493+
/*[clinic input]
494+
weakref.ReferenceType.__init__ as weakref_ref_init
489495
490-
if (!_PyArg_NoKeywords("ref", kwargs))
491-
return -1;
496+
object: object
497+
callback: object = None
498+
/
499+
[clinic start generated code]*/
492500

493-
if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
494-
return 0;
495-
else
496-
return -1;
501+
static int
502+
weakref_ref_init_impl(PyWeakReference *self, PyObject *object,
503+
PyObject *callback)
504+
/*[clinic end generated code: output=d36cfa9ccd36856e input=373a3e3f2841a4fa]*/
505+
{
506+
/* The arguments were already used by __new__; only validate them. */
507+
return 0;
497508
}
498509

499510

@@ -514,6 +525,7 @@ _PyWeakref_RefType = {
514525
PyVarObject_HEAD_INIT(&PyType_Type, 0)
515526
.tp_name = "weakref.ReferenceType",
516527
.tp_basicsize = sizeof(PyWeakReference),
528+
.tp_doc = weakref_ref_new__doc__,
517529
.tp_dealloc = weakref_dealloc,
518530
.tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
519531
.tp_call = PyVectorcall_Call,
@@ -526,10 +538,11 @@ _PyWeakref_RefType = {
526538
.tp_richcompare = weakref_richcompare,
527539
.tp_methods = weakref_methods,
528540
.tp_members = weakref_members,
529-
.tp_init = weakref___init__,
541+
.tp_init = weakref_ref_init,
530542
.tp_alloc = PyType_GenericAlloc,
531-
.tp_new = weakref___new__,
543+
.tp_new = weakref_ref_new,
532544
.tp_free = PyObject_GC_Del,
545+
.tp_vectorcall = weakref_ref_vectorcall,
533546
};
534547

535548

0 commit comments

Comments
 (0)