[Python-checkins] r53911 - in python/trunk: Include/dictobject.h Include/intobject.h Include/listobject.h Include/longobject.h Include/object.h Include/pyerrors.h Include/stringobject.h Include/tupleobject.h Include/unicodeobject.h Objects/dictobject.c Objects/exceptions.c Objects/intobject.c Objects/listobject.c Objects/longobject.c Objects/stringobject.c Objects/tupleobject.c Objects/typeobject.c Objects/unicodeobject.c

neal.norwitz python-checkins at python.org
Sun Feb 25 20:44:52 CET 2007


Author: neal.norwitz
Date: Sun Feb 25 20:44:48 2007
New Revision: 53911

Modified:
   python/trunk/Include/dictobject.h
   python/trunk/Include/intobject.h
   python/trunk/Include/listobject.h
   python/trunk/Include/longobject.h
   python/trunk/Include/object.h
   python/trunk/Include/pyerrors.h
   python/trunk/Include/stringobject.h
   python/trunk/Include/tupleobject.h
   python/trunk/Include/unicodeobject.h
   python/trunk/Objects/dictobject.c
   python/trunk/Objects/exceptions.c
   python/trunk/Objects/intobject.c
   python/trunk/Objects/listobject.c
   python/trunk/Objects/longobject.c
   python/trunk/Objects/stringobject.c
   python/trunk/Objects/tupleobject.c
   python/trunk/Objects/typeobject.c
   python/trunk/Objects/unicodeobject.c
Log:
Variation of patch # 1624059 to speed up checking if an object is a subclass
of some of the common builtin types.

Use a bit in tp_flags for each common builtin type.  Check the bit
to determine if any instance is a subclass of these common types.
The check avoids a function call and O(n) search of the base classes.
The check is done in the various Py*_Check macros rather than calling
PyType_IsSubtype().

All the bits are set in tp_flags when the type is declared 
in the Objects/*object.c files because PyType_Ready() is not called
for all the types.  Should PyType_Ready() be called for all types?
If so and the change is made, the changes to the Objects/*object.c files
can be reverted (remove setting the tp_flags).  Objects/typeobject.c
would also have to be modified to add conditions 
for Py*_CheckExact() in addition to each the PyType_IsSubtype check.


Modified: python/trunk/Include/dictobject.h
==============================================================================
--- python/trunk/Include/dictobject.h	(original)
+++ python/trunk/Include/dictobject.h	Sun Feb 25 20:44:48 2007
@@ -90,7 +90,8 @@
 
 PyAPI_DATA(PyTypeObject) PyDict_Type;
 
-#define PyDict_Check(op) PyObject_TypeCheck(op, &PyDict_Type)
+#define PyDict_Check(op) \
+                 PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_DICT_SUBCLASS)
 #define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type)
 
 PyAPI_FUNC(PyObject *) PyDict_New(void);

Modified: python/trunk/Include/intobject.h
==============================================================================
--- python/trunk/Include/intobject.h	(original)
+++ python/trunk/Include/intobject.h	Sun Feb 25 20:44:48 2007
@@ -27,7 +27,8 @@
 
 PyAPI_DATA(PyTypeObject) PyInt_Type;
 
-#define PyInt_Check(op) PyObject_TypeCheck(op, &PyInt_Type)
+#define PyInt_Check(op) \
+		 PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_INT_SUBCLASS)
 #define PyInt_CheckExact(op) ((op)->ob_type == &PyInt_Type)
 
 PyAPI_FUNC(PyObject *) PyInt_FromString(char*, char**, int);

Modified: python/trunk/Include/listobject.h
==============================================================================
--- python/trunk/Include/listobject.h	(original)
+++ python/trunk/Include/listobject.h	Sun Feb 25 20:44:48 2007
@@ -40,7 +40,8 @@
 
 PyAPI_DATA(PyTypeObject) PyList_Type;
 
-#define PyList_Check(op) PyObject_TypeCheck(op, &PyList_Type)
+#define PyList_Check(op) \
+		PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_LIST_SUBCLASS)
 #define PyList_CheckExact(op) ((op)->ob_type == &PyList_Type)
 
 PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size);

Modified: python/trunk/Include/longobject.h
==============================================================================
--- python/trunk/Include/longobject.h	(original)
+++ python/trunk/Include/longobject.h	Sun Feb 25 20:44:48 2007
@@ -11,7 +11,8 @@
 
 PyAPI_DATA(PyTypeObject) PyLong_Type;
 
-#define PyLong_Check(op) PyObject_TypeCheck(op, &PyLong_Type)
+#define PyLong_Check(op) \
+		PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_LONG_SUBCLASS)
 #define PyLong_CheckExact(op) ((op)->ob_type == &PyLong_Type)
 
 PyAPI_FUNC(PyObject *) PyLong_FromLong(long);

Modified: python/trunk/Include/object.h
==============================================================================
--- python/trunk/Include/object.h	(original)
+++ python/trunk/Include/object.h	Sun Feb 25 20:44:48 2007
@@ -376,7 +376,8 @@
 PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */
 PyAPI_DATA(PyTypeObject) PySuper_Type; /* built-in 'super' */
 
-#define PyType_Check(op) PyObject_TypeCheck(op, &PyType_Type)
+#define PyType_Check(op) \
+	PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_TYPE_SUBCLASS)
 #define PyType_CheckExact(op) ((op)->ob_type == &PyType_Type)
 
 PyAPI_FUNC(int) PyType_Ready(PyTypeObject *);
@@ -517,6 +518,17 @@
 /* Objects support nb_index in PyNumberMethods */
 #define Py_TPFLAGS_HAVE_INDEX (1L<<17)
 
+/* These flags are used to determine if a type is a subclass. */
+#define Py_TPFLAGS_INT_SUBCLASS		(1L<<23)
+#define Py_TPFLAGS_LONG_SUBCLASS	(1L<<24)
+#define Py_TPFLAGS_LIST_SUBCLASS	(1L<<25)
+#define Py_TPFLAGS_TUPLE_SUBCLASS	(1L<<26)
+#define Py_TPFLAGS_STRING_SUBCLASS	(1L<<27)
+#define Py_TPFLAGS_UNICODE_SUBCLASS	(1L<<28)
+#define Py_TPFLAGS_DICT_SUBCLASS	(1L<<29)
+#define Py_TPFLAGS_BASE_EXC_SUBCLASS	(1L<<30)
+#define Py_TPFLAGS_TYPE_SUBCLASS	(1L<<31)
+
 #define Py_TPFLAGS_DEFAULT  ( \
                              Py_TPFLAGS_HAVE_GETCHARBUFFER | \
                              Py_TPFLAGS_HAVE_SEQUENCE_IN | \
@@ -530,6 +542,7 @@
                             0)
 
 #define PyType_HasFeature(t,f)  (((t)->tp_flags & (f)) != 0)
+#define PyType_FastSubclass(t,f)  PyType_HasFeature(t,f)
 
 
 /*

Modified: python/trunk/Include/pyerrors.h
==============================================================================
--- python/trunk/Include/pyerrors.h	(original)
+++ python/trunk/Include/pyerrors.h	Sun Feb 25 20:44:48 2007
@@ -95,14 +95,12 @@
 /* */
 
 #define PyExceptionClass_Check(x)					\
-	(PyClass_Check((x))						\
-	 || (PyType_Check((x)) && PyType_IsSubtype(			\
-		     (PyTypeObject*)(x), (PyTypeObject*)PyExc_BaseException)))
-
+	(PyClass_Check((x)) || (PyType_Check((x)) &&			\
+	  PyType_FastSubclass((PyTypeObject*)(x), Py_TPFLAGS_BASE_EXC_SUBCLASS)))
 
 #define PyExceptionInstance_Check(x)			\
 	(PyInstance_Check((x)) ||			\
-	 (PyType_IsSubtype((x)->ob_type, (PyTypeObject*)PyExc_BaseException)))
+	 PyType_FastSubclass((x)->ob_type, Py_TPFLAGS_BASE_EXC_SUBCLASS))
 
 #define PyExceptionClass_Name(x)				   \
 	(PyClass_Check((x))					   \

Modified: python/trunk/Include/stringobject.h
==============================================================================
--- python/trunk/Include/stringobject.h	(original)
+++ python/trunk/Include/stringobject.h	Sun Feb 25 20:44:48 2007
@@ -55,7 +55,8 @@
 PyAPI_DATA(PyTypeObject) PyBaseString_Type;
 PyAPI_DATA(PyTypeObject) PyString_Type;
 
-#define PyString_Check(op) PyObject_TypeCheck(op, &PyString_Type)
+#define PyString_Check(op) \
+                 PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_STRING_SUBCLASS)
 #define PyString_CheckExact(op) ((op)->ob_type == &PyString_Type)
 
 PyAPI_FUNC(PyObject *) PyString_FromStringAndSize(const char *, Py_ssize_t);

Modified: python/trunk/Include/tupleobject.h
==============================================================================
--- python/trunk/Include/tupleobject.h	(original)
+++ python/trunk/Include/tupleobject.h	Sun Feb 25 20:44:48 2007
@@ -33,7 +33,8 @@
 
 PyAPI_DATA(PyTypeObject) PyTuple_Type;
 
-#define PyTuple_Check(op) PyObject_TypeCheck(op, &PyTuple_Type)
+#define PyTuple_Check(op) \
+                 PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_TUPLE_SUBCLASS)
 #define PyTuple_CheckExact(op) ((op)->ob_type == &PyTuple_Type)
 
 PyAPI_FUNC(PyObject *) PyTuple_New(Py_ssize_t size);

Modified: python/trunk/Include/unicodeobject.h
==============================================================================
--- python/trunk/Include/unicodeobject.h	(original)
+++ python/trunk/Include/unicodeobject.h	Sun Feb 25 20:44:48 2007
@@ -392,7 +392,8 @@
 
 PyAPI_DATA(PyTypeObject) PyUnicode_Type;
 
-#define PyUnicode_Check(op) PyObject_TypeCheck(op, &PyUnicode_Type)
+#define PyUnicode_Check(op) \
+                 PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_UNICODE_SUBCLASS)
 #define PyUnicode_CheckExact(op) ((op)->ob_type == &PyUnicode_Type)
 
 /* Fast access macros */

Modified: python/trunk/Objects/dictobject.c
==============================================================================
--- python/trunk/Objects/dictobject.c	(original)
+++ python/trunk/Objects/dictobject.c	Sun Feb 25 20:44:48 2007
@@ -2112,7 +2112,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS,	/* tp_flags */
 	dictionary_doc,				/* tp_doc */
 	dict_traverse,				/* tp_traverse */
 	dict_tp_clear,				/* tp_clear */

Modified: python/trunk/Objects/exceptions.c
==============================================================================
--- python/trunk/Objects/exceptions.c	(original)
+++ python/trunk/Objects/exceptions.c	Sun Feb 25 20:44:48 2007
@@ -300,7 +300,8 @@
     PyObject_GenericGetAttr,    /*tp_getattro*/
     PyObject_GenericSetAttr,    /*tp_setattro*/
     0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,  /*tp_flags*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+    	Py_TPFLAGS_BASE_EXC_SUBCLASS,  /*tp_flags*/
     PyDoc_STR("Common base class for all exceptions"), /* tp_doc */
     (traverseproc)BaseException_traverse, /* tp_traverse */
     (inquiry)BaseException_clear, /* tp_clear */

Modified: python/trunk/Objects/intobject.c
==============================================================================
--- python/trunk/Objects/intobject.c	(original)
+++ python/trunk/Objects/intobject.c	Sun Feb 25 20:44:48 2007
@@ -1138,7 +1138,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,	/* tp_flags */
 	int_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */

Modified: python/trunk/Objects/listobject.c
==============================================================================
--- python/trunk/Objects/listobject.c	(original)
+++ python/trunk/Objects/listobject.c	Sun Feb 25 20:44:48 2007
@@ -2672,7 +2672,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS,	/* tp_flags */
  	list_doc,				/* tp_doc */
  	(traverseproc)list_traverse,		/* tp_traverse */
  	(inquiry)list_clear,			/* tp_clear */

Modified: python/trunk/Objects/longobject.c
==============================================================================
--- python/trunk/Objects/longobject.c	(original)
+++ python/trunk/Objects/longobject.c	Sun Feb 25 20:44:48 2007
@@ -3418,7 +3418,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS,	/* tp_flags */
 	long_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */

Modified: python/trunk/Objects/stringobject.c
==============================================================================
--- python/trunk/Objects/stringobject.c	(original)
+++ python/trunk/Objects/stringobject.c	Sun Feb 25 20:44:48 2007
@@ -4017,7 +4017,7 @@
 	0,					/* tp_setattro */
 	&string_as_buffer,			/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_STRING_SUBCLASS,		/* tp_flags */
 	string_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */

Modified: python/trunk/Objects/tupleobject.c
==============================================================================
--- python/trunk/Objects/tupleobject.c	(original)
+++ python/trunk/Objects/tupleobject.c	Sun Feb 25 20:44:48 2007
@@ -669,7 +669,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, /* tp_flags */
 	tuple_doc,				/* tp_doc */
  	(traverseproc)tupletraverse,		/* tp_traverse */
 	0,					/* tp_clear */

Modified: python/trunk/Objects/typeobject.c
==============================================================================
--- python/trunk/Objects/typeobject.c	(original)
+++ python/trunk/Objects/typeobject.c	Sun Feb 25 20:44:48 2007
@@ -2288,7 +2288,7 @@
 	(setattrofunc)type_setattro,		/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS,	/* tp_flags */
 	type_doc,				/* tp_doc */
 	(traverseproc)type_traverse,		/* tp_traverse */
 	(inquiry)type_clear,			/* tp_clear */
@@ -2967,6 +2967,26 @@
 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
 		COPYVAL(tp_dictoffset);
 	}
+
+	/* Setup fast subclass flags */
+	if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException))
+		type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyType_Type))
+		type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyInt_Type))
+		type->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyLong_Type))
+		type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyString_Type))
+		type->tp_flags |= Py_TPFLAGS_STRING_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyUnicode_Type))
+		type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyTuple_Type))
+		type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyList_Type))
+		type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyDict_Type))
+		type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
 }
 
 static void

Modified: python/trunk/Objects/unicodeobject.c
==============================================================================
--- python/trunk/Objects/unicodeobject.c	(original)
+++ python/trunk/Objects/unicodeobject.c	Sun Feb 25 20:44:48 2007
@@ -7967,7 +7967,7 @@
     0,			 		/* tp_setattro */
     &unicode_as_buffer,			/* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
-	    Py_TPFLAGS_BASETYPE,	/* tp_flags */
+	    Py_TPFLAGS_BASETYPE | Py_TPFLAGS_UNICODE_SUBCLASS,	/* tp_flags */
     unicode_doc,			/* tp_doc */
     0,					/* tp_traverse */
     0,					/* tp_clear */


More information about the Python-checkins mailing list