diff options
author | Tim Peters <tim.peters@gmail.com> | 2002-07-11 06:23:50 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2002-07-11 06:23:50 (GMT) |
commit | 3459251d5a2b9589e03e818effc357e5e60ee4a9 (patch) | |
tree | dd1a63fc9f5904fb0032b87adbfb5dfd684ce823 /Include/object.h | |
parent | dc1e70987f49aa23bf1d07f32c476edeba0cec30 (diff) | |
download | cpython-3459251d5a2b9589e03e818effc357e5e60ee4a9.zip cpython-3459251d5a2b9589e03e818effc357e5e60ee4a9.tar.gz cpython-3459251d5a2b9589e03e818effc357e5e60ee4a9.tar.bz2 |
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.
Diffstat (limited to 'Include/object.h')
-rw-r--r-- | Include/object.h | 100 |
1 files changed, 40 insertions, 60 deletions
diff --git a/Include/object.h b/Include/object.h index 1f9100e..736095a 100644 --- a/Include/object.h +++ b/Include/object.h @@ -51,35 +51,10 @@ A standard interface exists for objects that contain an array of items whose size is determined when the object is allocated. */ -#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. - */ +/* Py_DEBUG implies Py_TRACE_REFS. */ +#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) #define Py_TRACE_REFS -#endif /* Py_DEBUG */ +#endif /* Py_TRACE_REFS implies Py_REF_DEBUG. */ #if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) @@ -536,40 +511,45 @@ variable first, both of which are slower; and in a multi-threaded environment the global variable trick is not safe.) */ +/* 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 _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) \ +#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__, \ (PyObject *)(OP)); \ } #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 */; +#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 _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) , +#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 _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) +#define _Py_INC_TPALLOCS(OP) +#define _Py_INC_TPFREES(OP) +#define _Py_DEC_TPFREES(OP) +#define _Py_COUNT_ALLOCS_COMMA #endif /* COUNT_ALLOCS */ #ifdef Py_TRACE_REFS @@ -584,27 +564,27 @@ extern DL_IMPORT(void) _Py_ResetReferences(void); /* Without Py_TRACE_REFS, there's little enough to do that we expand code * inline. */ -#define _Py_NewReference(op) ( \ - _PyMAYBE_BUMP_COUNT_COMMA(op) \ - _PyMAYBE_BUMP_REFTOTAL_COMMA \ +#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) _PyMAYBE_BUMP_FREECOUNT(op) +#define _Py_ForgetReference(op) _Py_INC_TPFREES(op) #define _Py_Dealloc(op) ( \ - _PyMAYBE_BUMP_FREECOUNT_COMMA(op) \ + _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA \ (*(op)->ob_type->tp_dealloc)((PyObject *)(op))) #endif /* !Py_TRACE_REFS */ -#define Py_INCREF(op) ( \ - _PyMAYBE_BUMP_REFTOTAL_COMMA \ +#define Py_INCREF(op) ( \ + _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ (op)->ob_refcnt++) -#define Py_DECREF(op) \ - if (_PyMAYBE_DROP_REFTOTAL_COMMA \ - --(op)->ob_refcnt != 0) \ - _PyMAYBE_CHECK_REFCNT(op) \ - else \ +#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)) /* Macros to use in case the object pointer may be NULL: */ |