From 2ef06d412531d1163dbc72877c88aedf3ed82a25 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sun, 19 Dec 2021 22:24:30 +0200 Subject: bpo-46131: add fastpath for PyFloat_Check() (#30200) --- Doc/c-api/typeobj.rst | 1 + Include/floatobject.h | 2 ++ Include/object.h | 1 + .../next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst | 2 ++ Objects/floatobject.c | 1 + Objects/typeobject.c | 3 +++ Tools/gdb/libpython.py | 13 +++++++++++++ 7 files changed, 23 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index cd8723e..eed2ac2 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1145,6 +1145,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. XXX Document more flags here? + .. data:: Py_TPFLAGS_FLOAT_SUBCLASS .. data:: Py_TPFLAGS_LONG_SUBCLASS .. data:: Py_TPFLAGS_LIST_SUBCLASS .. data:: Py_TPFLAGS_TUPLE_SUBCLASS diff --git a/Include/floatobject.h b/Include/floatobject.h index 3b6ca47..51be745 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -14,6 +14,8 @@ extern "C" { PyAPI_DATA(PyTypeObject) PyFloat_Type; #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) +#define PyFloat_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_FLOAT_SUBCLASS) #define PyFloat_CheckExact(op) Py_IS_TYPE(op, &PyFloat_Type) #ifdef Py_NAN diff --git a/Include/object.h b/Include/object.h index e5544e8..ee817a5 100644 --- a/Include/object.h +++ b/Include/object.h @@ -397,6 +397,7 @@ given type object has a specified feature. #define _Py_TPFLAGS_MATCH_SELF (1UL << 22) /* These flags are used to determine if a type is a subclass. */ +#define Py_TPFLAGS_FLOAT_SUBCLASS (1UL << 23) #define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24) #define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25) #define Py_TPFLAGS_TUPLE_SUBCLASS (1UL << 26) diff --git a/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst b/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst new file mode 100644 index 0000000..08768ca --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst @@ -0,0 +1,2 @@ +Add a fast path for ``PyFloat_Check`` via a ``Py_TPFLAGS_FLOAT_SUBCLASS`` +flag. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index f8620d6..37434f3 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1959,6 +1959,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_FLOAT_SUBCLASS | _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ float_new__doc__, /* tp_doc */ 0, /* tp_traverse */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index af35180..8bd9280 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5783,6 +5783,9 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) else if (PyType_IsSubtype(base, &PyDict_Type)) { type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; } + else if (PyType_IsSubtype(base, &PyFloat_Type)) { + type->tp_flags |= Py_TPFLAGS_FLOAT_SUBCLASS; + } if (PyType_HasFeature(base, _Py_TPFLAGS_MATCH_SELF)) { type->tp_flags |= _Py_TPFLAGS_MATCH_SELF; } diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index a0a95e3..41d1c3c 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -85,6 +85,7 @@ _is_pep393 = None Py_TPFLAGS_MANAGED_DICT = (1 << 4) Py_TPFLAGS_HEAPTYPE = (1 << 9) +Py_TPFLAGS_FLOAT_SUBCLASS = (1 << 23) Py_TPFLAGS_LONG_SUBCLASS = (1 << 24) Py_TPFLAGS_LIST_SUBCLASS = (1 << 25) Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26) @@ -379,6 +380,8 @@ class PyObjectPtr(object): if tp_flags & Py_TPFLAGS_HEAPTYPE: return HeapTypeObjectPtr + if tp_flags & Py_TPFLAGS_FLOAT_SUBCLASS: + return PyFloatObjectPtr if tp_flags & Py_TPFLAGS_LONG_SUBCLASS: return PyLongObjectPtr if tp_flags & Py_TPFLAGS_LIST_SUBCLASS: @@ -910,6 +913,16 @@ class PyNoneStructPtr(PyObjectPtr): def proxyval(self, visited): return None +class PyFloatObjectPtr(PyObjectPtr): + _typename = 'PyFloatObject' + + def proxyval(self, visited): + return self.field('ob_fval') + + def write_repr(self, out, visited): + proxy = self.proxyval(visited) + out.write("%s" % proxy) + class PyFrameObjectPtr(PyObjectPtr): _typename = 'PyFrameObject' -- cgit v0.12