[Python-checkins] python/dist/src/Include object.h,2.106,2.107

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Wed, 10 Jul 2002 23:23:52 -0700


Update of /cvsroot/python/python/dist/src/Include
In directory usw-pr-cvs1:/tmp/cvs-serv22768/python/Include

Modified Files:
	object.h 
Log Message:
object.h special-build macro minefield:  renamed all the new lexical
helper macros to something saner, and used them appropriately in other
files too, to reduce #ifdef blocks.

classobject.c, instance_dealloc():  One of my worst Python Memories is
trying to fix this routine a few years ago when COUNT_ALLOCS was defined
but Py_TRACE_REFS wasn't.  The special-build code here is way too
complicated.  Now it's much simpler.  Difference:  in a Py_TRACE_REFS
build, the instance is no longer in the doubly-linked list of live
objects while its __del__ method is executing, and that may be visible
via sys.getobjects() called from a __del__ method.  Tough -- the object
is presumed dead while its __del__ is executing anyway, and not calling
_Py_NewReference() at the start allows enormous code simplification.

typeobject.c, call_finalizer():  The special-build instance_dealloc()
pain apparently spread to here too via cut-'n-paste, and this is much
simpler now too.  In addition, I didn't understand why this routine
was calling _PyObject_GC_TRACK() after a resurrection, since there's no
plausible way _PyObject_GC_UNTRACK() could have been called on the
object by this point.  I suspect it was left over from pasting the
instance_delloc() code.  Instead asserted that the object is still
tracked.  Caution:  I suspect we don't have a test that actually
exercises the subtype_dealloc() __del__-resurrected-me code.


Index: object.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/object.h,v
retrieving revision 2.106
retrieving revision 2.107
diff -C2 -d -r2.106 -r2.107
*** object.h	10 Jul 2002 06:34:15 -0000	2.106
--- object.h	11 Jul 2002 06:23:49 -0000	2.107
***************
*** 52,84 ****
  */
  
! #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!
!  * Py_REF_DEBUG also checks after every decref to verify that the refcount
!  * hasn't gone negative, and causes an immediate fatal error if it has.
!  */
! #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. */
--- 52,59 ----
  */
  
! /* Py_DEBUG implies Py_TRACE_REFS. */
! #if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
  #define Py_TRACE_REFS
! #endif
  
  /* Py_TRACE_REFS implies Py_REF_DEBUG. */
***************
*** 537,549 ****
  */
  
  #ifdef Py_REF_DEBUG
  extern DL_IMPORT(long) _Py_RefTotal;
  extern DL_IMPORT(void) _Py_NegativeRefcount(const char *fname,
  					    int lineno, PyObject *op);
! #define _PyMAYBE_BUMP_REFTOTAL		_Py_RefTotal++
! #define _PyMAYBE_DROP_REFTOTAL		_Py_RefTotal--
! #define _PyMAYBE_BUMP_REFTOTAL_COMMA	_PyMAYBE_BUMP_REFTOTAL ,
! #define _PyMAYBE_DROP_REFTOTAL_COMMA	_PyMAYBE_DROP_REFTOTAL ,
! #define _PyMAYBE_CHECK_REFCNT(OP)				\
  {	if ((OP)->ob_refcnt < 0)				\
  		_Py_NegativeRefcount(__FILE__, __LINE__,	\
--- 512,532 ----
  */
  
+ /* First define a pile of simple helper macros, one set per special
+  * build symbol.  These either expand to the obvious things, or to
+  * nothing at all when the special mode isn't in effect.  The main
+  * macros can later be defined just once then, yet expand to different
+  * things depending on which special build options are and aren't in effect.
+  * Trust me <wink>:  while painful, this is 20x easier to understand than,
+  * e.g, defining _Py_NewReference five different times in a maze of nested
+  * #ifdefs (we used to do that -- it was impenetrable).
+  */
  #ifdef Py_REF_DEBUG
  extern DL_IMPORT(long) _Py_RefTotal;
  extern DL_IMPORT(void) _Py_NegativeRefcount(const char *fname,
  					    int lineno, PyObject *op);
! #define _Py_INC_REFTOTAL	_Py_RefTotal++
! #define _Py_DEC_REFTOTAL	_Py_RefTotal--
! #define _Py_REF_DEBUG_COMMA	,
! #define _Py_CHECK_REFCNT(OP)					\
  {	if ((OP)->ob_refcnt < 0)				\
  		_Py_NegativeRefcount(__FILE__, __LINE__,	\
***************
*** 551,574 ****
  }
  #else
! #define _PyMAYBE_BUMP_REFTOTAL
! #define _PyMAYBE_DROP_REFTOTAL
! #define _PyMAYBE_BUMP_REFTOTAL_COMMA
! #define _PyMAYBE_DROP_REFTOTAL_COMMA
! #define _PyMAYBE_CHECK_REFCNT(OP)	/* a semicolon */;
  #endif /* Py_REF_DEBUG */
  
  #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++
! #define _PyMAYBE_DROP_FREECOUNT(OP)	(OP)->ob_type->tp_frees--
! #define _PyMAYBE_BUMP_COUNT_COMMA(OP)	_PyMAYBE_BUMP_COUNT(OP) ,
! #define _PyMAYBE_BUMP_FREECOUNT_COMMA(OP) _PyMAYBE_BUMP_FREECOUNT(OP) ,
  #else
! #define _PyMAYBE_BUMP_COUNT(OP)
! #define _PyMAYBE_BUMP_FREECOUNT(OP)
! #define _PyMAYBE_DROP_FREECOUNT(OP)
! #define _PyMAYBE_BUMP_COUNT_COMMA(OP)
! #define _PyMAYBE_BUMP_FREECOUNT_COMMA(OP)
  #endif /* COUNT_ALLOCS */
  
--- 534,554 ----
  }
  #else
! #define _Py_INC_REFTOTAL
! #define _Py_DEC_REFTOTAL
! #define _Py_REF_DEBUG_COMMA
! #define _Py_CHECK_REFCNT(OP)	/* a semicolon */;
  #endif /* Py_REF_DEBUG */
  
  #ifdef COUNT_ALLOCS
  extern DL_IMPORT(void) inc_count(PyTypeObject *);
! #define _Py_INC_TPALLOCS(OP)	inc_count((OP)->ob_type)
! #define _Py_INC_TPFREES(OP)	(OP)->ob_type->tp_frees++
! #define _Py_DEC_TPFREES(OP)	(OP)->ob_type->tp_frees--
! #define _Py_COUNT_ALLOCS_COMMA	,
  #else
! #define _Py_INC_TPALLOCS(OP)
! #define _Py_INC_TPFREES(OP)
! #define _Py_DEC_TPFREES(OP)
! #define _Py_COUNT_ALLOCS_COMMA
  #endif /* COUNT_ALLOCS */
  
***************
*** 585,609 ****
   * inline.
   */
! #define _Py_NewReference(op) (		\
! 	_PyMAYBE_BUMP_COUNT_COMMA(op)	\
! 	_PyMAYBE_BUMP_REFTOTAL_COMMA	\
  	(op)->ob_refcnt = 1)
  
! #define _Py_ForgetReference(op) _PyMAYBE_BUMP_FREECOUNT(op)
  
  #define _Py_Dealloc(op) (				\
! 	_PyMAYBE_BUMP_FREECOUNT_COMMA(op)		\
  	(*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
  #endif /* !Py_TRACE_REFS */
  
! #define Py_INCREF(op) (			\
! 	_PyMAYBE_BUMP_REFTOTAL_COMMA	\
  	(op)->ob_refcnt++)
  
! #define Py_DECREF(op)				\
! 	if (_PyMAYBE_DROP_REFTOTAL_COMMA	\
! 	    --(op)->ob_refcnt != 0)		\
! 		_PyMAYBE_CHECK_REFCNT(op)	\
! 	else					\
  		_Py_Dealloc((PyObject *)(op))
  
--- 565,589 ----
   * inline.
   */
! #define _Py_NewReference(op) (				\
! 	_Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA	\
! 	_Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA		\
  	(op)->ob_refcnt = 1)
  
! #define _Py_ForgetReference(op) _Py_INC_TPFREES(op)
  
  #define _Py_Dealloc(op) (				\
! 	_Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA	\
  	(*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
  #endif /* !Py_TRACE_REFS */
  
! #define Py_INCREF(op) (				\
! 	_Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA	\
  	(op)->ob_refcnt++)
  
! #define Py_DECREF(op)					\
! 	if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA	\
! 	    --(op)->ob_refcnt != 0)			\
! 		_Py_CHECK_REFCNT(op)			\
! 	else						\
  		_Py_Dealloc((PyObject *)(op))