bpo-40170: Add _PyIndex_Check() internal function (GH-19426)

Add _PyIndex_Check() function to the internal C API: fast inlined
verson of PyIndex_Check().

Add Include/internal/pycore_abstract.h header file.

Replace PyIndex_Check() with _PyIndex_Check() in C files of Objects
and Python subdirectories.
This commit is contained in:
Victor Stinner 2020-04-08 02:01:56 +02:00 committed by GitHub
parent 45ec5b99ae
commit a15e260b70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 72 additions and 30 deletions

View File

@ -0,0 +1,22 @@
#ifndef Py_INTERNAL_ABSTRACT_H
#define Py_INTERNAL_ABSTRACT_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
// Fast inlined version of PyIndex_Check()
static inline int
_PyIndex_Check(PyObject *obj)
{
PyNumberMethods *tp_as_number = Py_TYPE(obj)->tp_as_number;
return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
}
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_ABSTRACT_H */

View File

@ -1080,6 +1080,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/tupleobject.h \ $(srcdir)/Include/cpython/tupleobject.h \
$(srcdir)/Include/cpython/unicodeobject.h \ $(srcdir)/Include/cpython/unicodeobject.h \
\ \
$(srcdir)/Include/internal/pycore_abstract.h \
$(srcdir)/Include/internal/pycore_accu.h \ $(srcdir)/Include/internal/pycore_accu.h \
$(srcdir)/Include/internal/pycore_atomic.h \ $(srcdir)/Include/internal/pycore_atomic.h \
$(srcdir)/Include/internal/pycore_bytes_methods.h \ $(srcdir)/Include/internal/pycore_bytes_methods.h \

View File

@ -1,7 +1,8 @@
/* Abstract Object Interface (many thanks to Jim Fulton) */ /* Abstract Object Interface (many thanks to Jim Fulton) */
#include "Python.h" #include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "pycore_pyerrors.h" #include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include <ctype.h> #include <ctype.h>
@ -160,7 +161,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
ms = Py_TYPE(o)->tp_as_sequence; ms = Py_TYPE(o)->tp_as_sequence;
if (ms && ms->sq_item) { if (ms && ms->sq_item) {
if (PyIndex_Check(key)) { if (_PyIndex_Check(key)) {
Py_ssize_t key_value; Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError); key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred()) if (key_value == -1 && PyErr_Occurred())
@ -176,7 +177,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
if (PyType_Check(o)) { if (PyType_Check(o)) {
PyObject *meth, *result; PyObject *meth, *result;
_Py_IDENTIFIER(__class_getitem__); _Py_IDENTIFIER(__class_getitem__);
// Special case type[int], but disallow other types so str[int] fails // Special case type[int], but disallow other types so str[int] fails
if ((PyTypeObject*)o == &PyType_Type) { if ((PyTypeObject*)o == &PyType_Type) {
return Py_GenericAlias(o, key); return Py_GenericAlias(o, key);
@ -209,7 +210,7 @@ PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
return m->mp_ass_subscript(o, key, value); return m->mp_ass_subscript(o, key, value);
if (Py_TYPE(o)->tp_as_sequence) { if (Py_TYPE(o)->tp_as_sequence) {
if (PyIndex_Check(key)) { if (_PyIndex_Check(key)) {
Py_ssize_t key_value; Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError); key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred()) if (key_value == -1 && PyErr_Occurred())
@ -241,7 +242,7 @@ PyObject_DelItem(PyObject *o, PyObject *key)
return m->mp_ass_subscript(o, key, (PyObject*)NULL); return m->mp_ass_subscript(o, key, (PyObject*)NULL);
if (Py_TYPE(o)->tp_as_sequence) { if (Py_TYPE(o)->tp_as_sequence) {
if (PyIndex_Check(key)) { if (_PyIndex_Check(key)) {
Py_ssize_t key_value; Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError); key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred()) if (key_value == -1 && PyErr_Occurred())
@ -1030,7 +1031,7 @@ static PyObject *
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n) sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
{ {
Py_ssize_t count; Py_ssize_t count;
if (PyIndex_Check(n)) { if (_PyIndex_Check(n)) {
count = PyNumber_AsSsize_t(n, PyExc_OverflowError); count = PyNumber_AsSsize_t(n, PyExc_OverflowError);
if (count == -1 && PyErr_Occurred()) if (count == -1 && PyErr_Occurred())
return NULL; return NULL;
@ -1307,15 +1308,16 @@ PyNumber_Absolute(PyObject *o)
return type_error("bad operand type for abs(): '%.200s'", o); return type_error("bad operand type for abs(): '%.200s'", o);
} }
#undef PyIndex_Check #undef PyIndex_Check
int int
PyIndex_Check(PyObject *obj) PyIndex_Check(PyObject *obj)
{ {
return Py_TYPE(obj)->tp_as_number != NULL && return _PyIndex_Check(obj);
Py_TYPE(obj)->tp_as_number->nb_index != NULL;
} }
/* Return a Python int from the object item. /* Return a Python int from the object item.
Raise TypeError if the result is not an int Raise TypeError if the result is not an int
or if the object cannot be interpreted as an index. or if the object cannot be interpreted as an index.
@ -1332,7 +1334,7 @@ PyNumber_Index(PyObject *item)
Py_INCREF(item); Py_INCREF(item);
return item; return item;
} }
if (!PyIndex_Check(item)) { if (!_PyIndex_Check(item)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"'%.200s' object cannot be interpreted " "'%.200s' object cannot be interpreted "
"as an integer", Py_TYPE(item)->tp_name); "as an integer", Py_TYPE(item)->tp_name);

View File

@ -2,6 +2,7 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" #include "pycore_bytes_methods.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
@ -391,7 +392,7 @@ bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i)
static PyObject * static PyObject *
bytearray_subscript(PyByteArrayObject *self, PyObject *index) bytearray_subscript(PyByteArrayObject *self, PyObject *index)
{ {
if (PyIndex_Check(index)) { if (_PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
@ -610,7 +611,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu
char *buf, *bytes; char *buf, *bytes;
buf = PyByteArray_AS_STRING(self); buf = PyByteArray_AS_STRING(self);
if (PyIndex_Check(index)) { if (_PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
@ -809,7 +810,7 @@ bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
} }
/* Is it an int? */ /* Is it an int? */
if (PyIndex_Check(arg)) { if (_PyIndex_Check(arg)) {
count = PyNumber_AsSsize_t(arg, PyExc_OverflowError); count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (count == -1 && PyErr_Occurred()) { if (count == -1 && PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_TypeError)) if (!PyErr_ExceptionMatches(PyExc_TypeError))

View File

@ -1,5 +1,6 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" #include "pycore_bytes_methods.h"
PyDoc_STRVAR_shared(_Py_isspace__doc__, PyDoc_STRVAR_shared(_Py_isspace__doc__,
@ -466,7 +467,7 @@ parse_args_finds_byte(const char *function_name, PyObject *args,
return 1; return 1;
} }
if (!PyIndex_Check(tmp_subobj)) { if (!_PyIndex_Check(tmp_subobj)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"argument should be integer or bytes-like object, " "argument should be integer or bytes-like object, "
"not '%.200s'", "not '%.200s'",

View File

@ -3,6 +3,7 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" #include "pycore_bytes_methods.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
@ -1579,7 +1580,7 @@ bytes_hash(PyBytesObject *a)
static PyObject* static PyObject*
bytes_subscript(PyBytesObject* self, PyObject* item) bytes_subscript(PyBytesObject* self, PyObject* item)
{ {
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return NULL; return NULL;
@ -2536,7 +2537,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
/* Is it an integer? */ /* Is it an integer? */
if (PyIndex_Check(x)) { if (_PyIndex_Check(x)) {
size = PyNumber_AsSsize_t(x, PyExc_OverflowError); size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred()) { if (size == -1 && PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_TypeError)) if (!PyErr_ExceptionMatches(PyExc_TypeError))

View File

@ -1,7 +1,8 @@
/* InterpreterID object */ /* InterpreterID object */
#include "Python.h" #include "Python.h"
#include "internal/pycore_pystate.h" #include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_pystate.h"
#include "interpreteridobject.h" #include "interpreteridobject.h"
@ -42,7 +43,7 @@ interp_id_converter(PyObject *arg, void *ptr)
if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) { if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
id = ((interpid *)arg)->id; id = ((interpid *)arg)->id;
} }
else if (PyIndex_Check(arg)) { else if (_PyIndex_Check(arg)) {
id = PyLong_AsLongLong(arg); id = PyLong_AsLongLong(arg);
if (id == -1 && PyErr_Occurred()) { if (id == -1 && PyErr_Occurred()) {
return 0; return 0;

View File

@ -1,6 +1,7 @@
/* List object implementation */ /* List object implementation */
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "pycore_tupleobject.h" #include "pycore_tupleobject.h"
@ -2800,7 +2801,7 @@ static PySequenceMethods list_as_sequence = {
static PyObject * static PyObject *
list_subscript(PyListObject* self, PyObject* item) list_subscript(PyListObject* self, PyObject* item)
{ {
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
Py_ssize_t i; Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError); i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
@ -2855,7 +2856,7 @@ list_subscript(PyListObject* self, PyObject* item)
static int static int
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
{ {
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return -1; return -1;

View File

@ -11,6 +11,7 @@
*/ */
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
@ -2421,8 +2422,9 @@ is_multiindex(PyObject *key)
size = PyTuple_GET_SIZE(key); size = PyTuple_GET_SIZE(key);
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
PyObject *x = PyTuple_GET_ITEM(key, i); PyObject *x = PyTuple_GET_ITEM(key, i);
if (!PyIndex_Check(x)) if (!_PyIndex_Check(x)) {
return 0; return 0;
}
} }
return 1; return 1;
} }
@ -2459,7 +2461,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
} }
} }
if (PyIndex_Check(key)) { if (_PyIndex_Check(key)) {
Py_ssize_t index; Py_ssize_t index;
index = PyNumber_AsSsize_t(key, PyExc_IndexError); index = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (index == -1 && PyErr_Occurred()) if (index == -1 && PyErr_Occurred())
@ -2530,7 +2532,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
} }
} }
if (PyIndex_Check(key)) { if (_PyIndex_Check(key)) {
Py_ssize_t index; Py_ssize_t index;
if (1 < view->ndim) { if (1 < view->ndim) {
PyErr_SetString(PyExc_NotImplementedError, PyErr_SetString(PyExc_NotImplementedError,

View File

@ -1,8 +1,9 @@
/* Range object implementation */ /* Range object implementation */
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_tupleobject.h" #include "pycore_tupleobject.h"
#include "structmember.h"
/* Support objects whose length is > PY_SSIZE_T_MAX. /* Support objects whose length is > PY_SSIZE_T_MAX.
@ -631,7 +632,7 @@ range_reduce(rangeobject *r, PyObject *args)
static PyObject * static PyObject *
range_subscript(rangeobject* self, PyObject* item) range_subscript(rangeobject* self, PyObject* item)
{ {
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
PyObject *i, *result; PyObject *i, *result;
i = PyNumber_Index(item); i = PyNumber_Index(item);
if (!i) if (!i)

View File

@ -14,6 +14,7 @@ this type and there is exactly one in existence.
*/ */
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pymem.h" #include "pycore_pymem.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
@ -354,7 +355,7 @@ static PyMemberDef slice_members[] = {
static PyObject* static PyObject*
evaluate_slice_index(PyObject *v) evaluate_slice_index(PyObject *v)
{ {
if (PyIndex_Check(v)) { if (_PyIndex_Check(v)) {
return PyNumber_Index(v); return PyNumber_Index(v);
} }
else { else {

View File

@ -2,6 +2,7 @@
/* Tuple object implementation */ /* Tuple object implementation */
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "pycore_accu.h" #include "pycore_accu.h"
@ -763,7 +764,7 @@ static PySequenceMethods tuple_as_sequence = {
static PyObject* static PyObject*
tuplesubscript(PyTupleObject* self, PyObject* item) tuplesubscript(PyTupleObject* self, PyObject* item)
{ {
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return NULL; return NULL;

View File

@ -40,6 +40,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" #include "pycore_bytes_methods.h"
#include "pycore_fileutils.h" #include "pycore_fileutils.h"
#include "pycore_initconfig.h" #include "pycore_initconfig.h"
@ -14132,7 +14133,7 @@ unicode_subscript(PyObject* self, PyObject* item)
if (PyUnicode_READY(self) == -1) if (PyUnicode_READY(self) == -1)
return NULL; return NULL;
if (PyIndex_Check(item)) { if (_PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return NULL; return NULL;

View File

@ -161,6 +161,7 @@
<ClInclude Include="..\Include\graminit.h" /> <ClInclude Include="..\Include\graminit.h" />
<ClInclude Include="..\Include\grammar.h" /> <ClInclude Include="..\Include\grammar.h" />
<ClInclude Include="..\Include\import.h" /> <ClInclude Include="..\Include\import.h" />
<ClInclude Include="..\Include\internal\pycore_abstract.h" />
<ClInclude Include="..\Include\internal\pycore_accu.h" /> <ClInclude Include="..\Include\internal\pycore_accu.h" />
<ClInclude Include="..\Include\internal\pycore_atomic.h" /> <ClInclude Include="..\Include\internal\pycore_atomic.h" />
<ClInclude Include="..\Include\internal\pycore_bytes_methods.h" /> <ClInclude Include="..\Include\internal\pycore_bytes_methods.h" />

View File

@ -186,6 +186,9 @@
<ClInclude Include="..\Include\import.h"> <ClInclude Include="..\Include\import.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_abstract.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_accu.h"> <ClInclude Include="..\Include\internal\pycore_accu.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>

View File

@ -10,6 +10,7 @@
#define PY_LOCAL_AGGRESSIVE #define PY_LOCAL_AGGRESSIVE
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_call.h" #include "pycore_call.h"
#include "pycore_ceval.h" #include "pycore_ceval.h"
#include "pycore_code.h" #include "pycore_code.h"
@ -5089,7 +5090,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (v != Py_None) { if (v != Py_None) {
Py_ssize_t x; Py_ssize_t x;
if (PyIndex_Check(v)) { if (_PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL); x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && _PyErr_Occurred(tstate)) if (x == -1 && _PyErr_Occurred(tstate))
return 0; return 0;
@ -5110,7 +5111,7 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t x; Py_ssize_t x;
if (PyIndex_Check(v)) { if (_PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL); x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && _PyErr_Occurred(tstate)) if (x == -1 && _PyErr_Occurred(tstate))
return 0; return 0;

View File

@ -2,6 +2,7 @@
/* Module support implementation */ /* Module support implementation */
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#define FLAG_SIZE_T 1 #define FLAG_SIZE_T 1
typedef double va_double; typedef double va_double;
@ -20,7 +21,7 @@ _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
if (obj == Py_None) { if (obj == Py_None) {
return 1; return 1;
} }
else if (PyIndex_Check(obj)) { else if (_PyIndex_Check(obj)) {
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError); limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
if (limit == -1 && PyErr_Occurred()) { if (limit == -1 && PyErr_Occurred()) {
return 0; return 0;