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]

Reply via email to