[Python-checkins] python/dist/src/Include object.h,2.103,2.104
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Sun, 07 Jul 2002 12:59:52 -0700
Update of /cvsroot/python/python/dist/src/Include
In directory usw-pr-cvs1:/tmp/cvs-serv7577/python/Include
Modified Files:
object.h
Log Message:
Rearranged and added comments to object.h, to clarify many things
that have taken me "too long" to reverse-engineer over the years.
Vastly reduced the nesting level and redundancy of #ifdef-ery.
Took a light stab at repairing comments that are no longer true.
sys_gettotalrefcount(): Changed to enable under Py_REF_DEBUG.
It was enabled under Py_TRACE_REFS, which was much heavier than
necessary. sys.gettotalrefcount() is now available in a
Py_REF_DEBUG-only build.
Index: object.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/object.h,v
retrieving revision 2.103
retrieving revision 2.104
diff -C2 -d -r2.103 -r2.104
*** object.h 7 Jul 2002 05:13:56 -0000 2.103
--- object.h 7 Jul 2002 19:59:50 -0000 2.104
***************
*** 14,18 ****
accessed through special macros and functions only. (Type objects are
exceptions to the first rule; the standard types are represented by
! statically initialized type objects.)
An object has a 'reference count' that is increased or decreased when a
--- 14,19 ----
accessed through special macros and functions only. (Type objects are
exceptions to the first rule; the standard types are represented by
! statically initialized type objects, although work on type/class unification
! for Python 2.2 made it possible to have heap-allocated type objects too).
An object has a 'reference count' that is increased or decreased when a
***************
*** 52,81 ****
#ifdef Py_DEBUG
! /* Turn on heavy reference debugging */
#define Py_TRACE_REFS
! /* Turn on reference counting */
#define Py_REF_DEBUG
!
! #endif /* Py_DEBUG */
#ifdef Py_TRACE_REFS
! #define PyObject_HEAD \
! struct _object *_ob_next, *_ob_prev; \
! int ob_refcnt; \
! struct _typeobject *ob_type;
! #define PyObject_HEAD_INIT(type) 0, 0, 1, type,
! #else /* !Py_TRACE_REFS */
! #define PyObject_HEAD \
! int ob_refcnt; \
struct _typeobject *ob_type;
- #define PyObject_HEAD_INIT(type) 1, type,
- #endif /* !Py_TRACE_REFS */
! #define PyObject_VAR_HEAD \
! PyObject_HEAD \
int ob_size; /* Number of items in variable part */
typedef struct _object {
PyObject_HEAD
--- 53,126 ----
#ifdef Py_DEBUG
+ /* Turn on aggregate reference counting. This arranges that extern
+ * _Py_RefTotal hold a count of all references, the sum of ob_refcnt
+ * across all objects. The value can be gotten programatically via
+ * sys.gettotalrefcount() (which exists only if Py_REF_DEBUG is enabled).
+ * In a debug-mode build, this is where the "8288" comes from in
+ *
+ * >>> 23
+ * 23
+ * [8288 refs]
+ * >>>
+ *
+ * Note that if this count increases when you're not storing away new objects,
+ * there's probably a leak. Remember, though, that in interactive mode the
+ * special name "_" holds a reference to the last result displayed!
+ */
+ #define Py_REF_DEBUG
! /* Turn on heavy reference debugging. This is major surgery. Every PyObject
! * grows two more pointers, to maintain a doubly-linked list of all live
! * heap-allocated objects (note that, e.g., most builtin type objects are
! * not in this list, as they're statically allocated). This list can be
! * materialized into a Python list via sys.getobjects() (which exists only
! * if Py_TRACE_REFS is enabled). Py_TRACE_REFS implies Py_REF_DEBUG.
! */
#define Py_TRACE_REFS
+ #endif /* Py_DEBUG */
! /* Py_TRACE_REFS implies Py_REF_DEBUG. */
! #if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
#define Py_REF_DEBUG
! #endif
#ifdef Py_TRACE_REFS
! /* Define pointers to support a doubly-linked list of all live heap objects. */
! #define _PyObject_HEAD_EXTRA \
! struct _object *_ob_next; \
! struct _object *_ob_prev;
!
! #define _PyObject_EXTRA_INIT 0, 0,
!
! #else
! #define _PyObject_HEAD_EXTRA
! #define _PyObject_EXTRA_INIT
! #endif
!
! /* PyObject_HEAD defines the initial segment of every PyObject. */
! #define PyObject_HEAD \
! _PyObject_HEAD_EXTRA \
! int ob_refcnt; \
struct _typeobject *ob_type;
! #define PyObject_HEAD_INIT(type) \
! _PyObject_EXTRA_INIT \
! 1, type,
!
! /* PyObject_VAR_HEAD defines the initial segment of all variable-size
! * container objects. These end with a declaration of an array with 1
! * element, but enough space is malloc'ed so that the array actually
! * has room for ob_size elements. Note that ob_size is an element count,
! * not necessarily a byte count.
! */
! #define PyObject_VAR_HEAD \
! PyObject_HEAD \
int ob_size; /* Number of items in variable part */
+ /* Nothing is actually declared to be a PyObject, but every pointer to
+ * a Python object can be cast to a PyObject*. This is inheritance built
+ * by hand. Similarly every pointer to a variable-size Python object can,
+ * in addition, be cast to PyVarObject*.
+ */
typedef struct _object {
PyObject_HEAD
***************
*** 89,99 ****
/*
Type objects contain a string containing the type name (to help somewhat
! in debugging), the allocation parameters (see newobj() and newvarobj()),
! and methods for accessing objects of the type. Methods are optional,a
nil pointer meaning that particular kind of access is not available for
this type. The Py_DECREF() macro uses the tp_dealloc method without
checking for a nil pointer; it should always be implemented except if
the implementation can guarantee that the reference count will never
! reach zero (e.g., for type objects).
NB: the methods for certain type groups are now contained in separate
--- 134,145 ----
/*
Type objects contain a string containing the type name (to help somewhat
! in debugging), the allocation parameters (see PyObject_New() and
! PyObject_NewVar()),
! and methods for accessing objects of the type. Methods are optional, a
nil pointer meaning that particular kind of access is not available for
this type. The Py_DECREF() macro uses the tp_dealloc method without
checking for a nil pointer; it should always be implemented except if
the implementation can guarantee that the reference count will never
! reach zero (e.g., for statically allocated type objects).
NB: the methods for certain type groups are now contained in separate
***************
*** 122,126 ****
/* For numbers without flag bit Py_TPFLAGS_CHECKTYPES set, all
arguments are guaranteed to be of the object's type (modulo
! coercion hacks that is -- i.e. if the type's coercion function
returns other types, then these are allowed as well). Numbers that
have the Py_TPFLAGS_CHECKTYPES flag bit set should check *both*
--- 168,172 ----
/* For numbers without flag bit Py_TPFLAGS_CHECKTYPES set, all
arguments are guaranteed to be of the object's type (modulo
! coercion hacks -- i.e. if the type's coercion function
returns other types, then these are allowed as well). Numbers that
have the Py_TPFLAGS_CHECKTYPES flag bit set should check *both*
***************
*** 379,384 ****
/*
!
! Type flags (tp_flags)
These flags are used to extend the type structure in a backwards-compatible
--- 425,429 ----
/*
! `Type flags (tp_flags)
These flags are used to extend the type structure in a backwards-compatible
***************
*** 398,402 ****
Code can use PyType_HasFeature(type_ob, flag_value) to test whether the
given type object has a specified feature.
-
*/
--- 443,446 ----
***************
*** 459,474 ****
/*
The macros Py_INCREF(op) and Py_DECREF(op) are used to increment or decrement
! reference counts. Py_DECREF calls the object's deallocator function; for
objects that don't contain references to other objects or heap memory
this can be the standard function free(). Both macros can be used
! wherever a void expression is allowed. The argument shouldn't be a
! NIL pointer. The macro _Py_NewReference(op) is used only to initialize
! reference counts to 1; it is defined here for convenience.
We assume that the reference count field can never overflow; this can
! be proven when the size of the field is the same as the pointer size
! but even with a 16-bit reference count field it is pretty unlikely so
! we ignore the possibility. (If you are paranoid, make it a long.)
Type objects should never be deallocated; the type pointer in an object
is not considered to be a reference to the type object, to save
--- 503,525 ----
/*
The macros Py_INCREF(op) and Py_DECREF(op) are used to increment or decrement
! reference counts. Py_DECREF calls the object's deallocator function when
! the refcount falls to 0; for
objects that don't contain references to other objects or heap memory
this can be the standard function free(). Both macros can be used
! wherever a void expression is allowed. The argument must not be a
! NIL pointer. If it may be NIL, use Py_XINCREF/Py_XDECREF instead.
! The macro _Py_NewReference(op) initialize reference counts to 1, and
! in special builds (Py_REF_DEBUG, Py_TRACE_REFS) performs additional
! bookkeeping appropriate to the special build.
We assume that the reference count field can never overflow; this can
! be proven when the size of the field is the same as the pointer size, so
! we ignore the possibility. Provided a C int is at least 32 bits (which
! is implicitly assumed in many parts of this code), that's enough for
! about 2**31 references to an object.
+ XXX The following became out of date in Python 2.2, but I'm not sure
+ XXX what the full truth is now. Certainly, heap-allocated type objects
+ XXX can and should be deallocated.
Type objects should never be deallocated; the type pointer in an object
is not considered to be a reference to the type object, to save
***************
*** 484,543 ****
*/
! #ifdef Py_TRACE_REFS
! #ifndef Py_REF_DEBUG
! #define Py_REF_DEBUG
#endif
#endif
#ifdef Py_TRACE_REFS
! extern DL_IMPORT(void) _Py_Dealloc(PyObject *);
extern DL_IMPORT(void) _Py_NewReference(PyObject *);
extern DL_IMPORT(void) _Py_ForgetReference(PyObject *);
extern DL_IMPORT(void) _Py_PrintReferences(FILE *);
extern DL_IMPORT(void) _Py_ResetReferences(void);
- #endif
-
- #ifndef Py_TRACE_REFS
- #ifdef COUNT_ALLOCS
- #define _Py_Dealloc(op) ((op)->ob_type->tp_frees++, (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
- #define _Py_ForgetReference(op) ((op)->ob_type->tp_frees++)
- #else /* !COUNT_ALLOCS */
- #define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op))
- #define _Py_ForgetReference(op) /*empty*/
- #endif /* !COUNT_ALLOCS */
- #endif /* !Py_TRACE_REFS */
! #ifdef COUNT_ALLOCS
! extern DL_IMPORT(void) inc_count(PyTypeObject *);
! #endif
! #ifdef Py_REF_DEBUG
! extern DL_IMPORT(long) _Py_RefTotal;
- #ifndef Py_TRACE_REFS
- #ifdef COUNT_ALLOCS
- #define _Py_NewReference(op) (inc_count((op)->ob_type), _Py_RefTotal++, (op)->ob_refcnt = 1)
- #else
- #define _Py_NewReference(op) (_Py_RefTotal++, (op)->ob_refcnt = 1)
- #endif
#endif /* !Py_TRACE_REFS */
! #define Py_INCREF(op) (_Py_RefTotal++, (op)->ob_refcnt++)
! /* under Py_REF_DEBUG: also log negative ref counts after Py_DECREF() !! */
#define Py_DECREF(op) \
if (--_Py_RefTotal, 0 < (--((op)->ob_refcnt))) ; \
else if (0 == (op)->ob_refcnt) _Py_Dealloc( (PyObject*)(op)); \
! else ((void)fprintf( stderr, "%s:%i negative ref count %i\n", \
__FILE__, __LINE__, (op)->ob_refcnt), abort())
- #else /* !Py_REF_DEBUG */
- #ifdef COUNT_ALLOCS
- #define _Py_NewReference(op) (inc_count((op)->ob_type), (op)->ob_refcnt = 1)
#else
- #define _Py_NewReference(op) ((op)->ob_refcnt = 1)
- #endif
-
- #define Py_INCREF(op) ((op)->ob_refcnt++)
#define Py_DECREF(op) \
if (--(op)->ob_refcnt != 0) \
--- 535,592 ----
*/
! #ifdef Py_REF_DEBUG
! extern DL_IMPORT(long) _Py_RefTotal;
! #define _PyMAYBE_BUMP_REFTOTAL _Py_RefTotal++
! #else
! #define _PyMAYBE_BUMP_REFTOTAL (void)0
#endif
+
+ #ifdef COUNT_ALLOCS
+ extern DL_IMPORT(void) inc_count(PyTypeObject *);
+ #define _PyMAYBE_BUMP_COUNT(OP) inc_count((OP)->ob_type)
+ #define _PyMAYBE_BUMP_FREECOUNT(OP) (OP)->ob_type->tp_frees++
+ #else
+ #define _PyMAYBE_BUMP_COUNT(OP) (void)0
+ #define _PyMAYBE_BUMP_FREECOUNT(OP) (void)0
#endif
#ifdef Py_TRACE_REFS
! /* Py_TRACE_REFS is such major surgery that we call external routines. */
extern DL_IMPORT(void) _Py_NewReference(PyObject *);
extern DL_IMPORT(void) _Py_ForgetReference(PyObject *);
+ extern DL_IMPORT(void) _Py_Dealloc(PyObject *);
extern DL_IMPORT(void) _Py_PrintReferences(FILE *);
extern DL_IMPORT(void) _Py_ResetReferences(void);
! #else
! /* Without Py_TRACE_REFS, there's little enough to do that we expand code
! * inline.
! */
! #define _Py_NewReference(op) ( \
! _PyMAYBE_BUMP_COUNT(op), \
! _PyMAYBE_BUMP_REFTOTAL, \
! (op)->ob_refcnt = 1)
! #define _Py_ForgetReference(op) (_PyMAYBE_BUMP_FREECOUNT(op))
! #define _Py_Dealloc(op) ( \
! _Py_ForgetReference(op), \
! (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
#endif /* !Py_TRACE_REFS */
! #define Py_INCREF(op) ( \
! _PyMAYBE_BUMP_REFTOTAL, \
! (op)->ob_refcnt++)
!
! #ifdef Py_REF_DEBUG
! /* under Py_REF_DEBUG: also log negative ref counts after Py_DECREF() !! */
#define Py_DECREF(op) \
if (--_Py_RefTotal, 0 < (--((op)->ob_refcnt))) ; \
else if (0 == (op)->ob_refcnt) _Py_Dealloc( (PyObject*)(op)); \
! else ((void)fprintf(stderr, "%s:%i negative ref count %i\n", \
__FILE__, __LINE__, (op)->ob_refcnt), abort())
#else
#define Py_DECREF(op) \
if (--(op)->ob_refcnt != 0) \
***************
*** 548,552 ****
/* Macros to use in case the object pointer may be NULL: */
-
#define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)
#define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)
--- 597,600 ----
***************
*** 558,564 ****
Don't forget to apply Py_INCREF() when returning this value!!!
*/
-
extern DL_IMPORT(PyObject) _Py_NoneStruct; /* Don't use this directly */
-
#define Py_None (&_Py_NoneStruct)
--- 606,610 ----
***************
*** 567,573 ****
not implemented for a given type combination.
*/
-
extern DL_IMPORT(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
-
#define Py_NotImplemented (&_Py_NotImplementedStruct)
--- 613,617 ----
***************
*** 625,629 ****
an integer return -1 (which could be a legal return value too!), and
other functions return 0 for success and -1 for failure.
! Callers should always check for errors before using the result.
Reference Counts
--- 669,675 ----
an integer return -1 (which could be a legal return value too!), and
other functions return 0 for success and -1 for failure.
! Callers should always check for errors before using the result. If
! an error was set, the caller must either explicitly clear it, or pass
! the error on to its caller.
Reference Counts