https://github.com/python/cpython/commit/07db3e96d8eb179890c71638ea3331c553f4e35c
commit: 07db3e96d8eb179890c71638ea3331c553f4e35c
branch: main
author: Pieter Eendebak <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-10-31T11:58:33Z
summary:
gh-87613: Use AC vectorcall for slice() (#159471)
]
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-10-15-12-40-00.gh-issue-87613.Sl1ceV.rst
A Objects/clinic/sliceobject.c.h
M Objects/sliceobject.c
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-15-12-40-00.gh-issue-87613.Sl1ceV.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-15-12-40-00.gh-issue-87613.Sl1ceV.rst
new file mode 100644
index 000000000000000..bd96edc0b9f1770
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-15-12-40-00.gh-issue-87613.Sl1ceV.rst
@@ -0,0 +1 @@
+Speed up calling :class:`slice` by adding a vectorcall implementation of the
constructor generated by Argument Clinic. Patch by Pieter Eendebak.
diff --git a/Objects/clinic/sliceobject.c.h b/Objects/clinic/sliceobject.c.h
new file mode 100644
index 000000000000000..39fff4b06eb6a35
--- /dev/null
+++ b/Objects/clinic/sliceobject.c.h
@@ -0,0 +1,78 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+#include "pycore_modsupport.h" // _PyArg_CheckPositional()
+
+static PyObject *
+slice_new_impl(PyTypeObject *type, PyObject *start, PyObject *stop,
+ PyObject *step);
+
+static PyObject *
+slice_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = &PySlice_Type;
+ PyObject *start;
+ PyObject *stop = NULL;
+ PyObject *step = NULL;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("slice", kwargs)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("slice", PyTuple_GET_SIZE(args), 1, 3)) {
+ goto exit;
+ }
+ start = PyTuple_GET_ITEM(args, 0);
+ if (PyTuple_GET_SIZE(args) < 2) {
+ goto skip_optional;
+ }
+ stop = PyTuple_GET_ITEM(args, 1);
+ if (PyTuple_GET_SIZE(args) < 3) {
+ goto skip_optional;
+ }
+ step = PyTuple_GET_ITEM(args, 2);
+skip_optional:
+ return_value = slice_new_impl(type, start, stop, step);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+slice_vectorcall(PyObject *type, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+ PyObject *start;
+ PyObject *stop = NULL;
+ PyObject *step = NULL;
+
+ assert(Py_Is(_PyType_CAST(type), &PySlice_Type));
+ /* Make sure the type object is immutable: the generated
+ * vectorcall doesn't deal e.g. with users reassigning __init__. */
+ assert(PyType_HasFeature(_PyType_CAST(type), Py_TPFLAGS_IMMUTABLETYPE));
+ if (!_PyArg_NoKwnames("slice", kwnames)) {
+ goto exit;
+ }
+ if (!_PyArg_CheckPositional("slice", nargs, 1, 3)) {
+ goto exit;
+ }
+ start = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ stop = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ step = args[2];
+skip_optional:
+ return_value = slice_new_impl(_PyType_CAST(type), start, stop, step);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=3547c23a3ee3cd86 input=a9049054013a1b77]*/
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index 91d1753b822fc13..5ab7e42d9e7b76e 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -21,6 +21,13 @@ this type and there is exactly one in existence.
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs
+#include "clinic/sliceobject.c.h"
+
+/*[clinic input]
+class slice "PySliceObject *" "&PySlice_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=857b514967456ef4]*/
+
#define _PySlice_CAST(op) _Py_CAST(PySliceObject*, (op))
@@ -308,19 +315,22 @@ PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
return 0;
}
-static PyObject *
-slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- PyObject *start, *stop, *step;
+/*[clinic input]
+@classmethod
+@vectorcall
+slice.__new__ as slice_new
- start = stop = step = NULL;
-
- if (!_PyArg_NoKeywords("slice", kw))
- return NULL;
-
- if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
- return NULL;
+ start: object
+ stop: object(c_default="NULL") = None
+ step: object(c_default="NULL") = None
+ /
+[clinic start generated code]*/
+static PyObject *
+slice_new_impl(PyTypeObject *type, PyObject *start, PyObject *stop,
+ PyObject *step)
+/*[clinic end generated code: output=35a6e86397efb677 input=cf5c572a0d2caa22]*/
+{
/* This swapping of stop and start is to maintain similarity with
range(). */
if (stop == NULL) {
@@ -702,4 +712,5 @@ PyTypeObject PySlice_Type = {
0, /* tp_init */
0, /* tp_alloc */
slice_new, /* tp_new */
+ .tp_vectorcall = slice_vectorcall,
};
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]