Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -710,11 +710,8 @@ extra checks are performed:

There may be additional checks not mentioned here.

Defining :c:macro:`Py_TRACE_REFS` enables reference tracing. When defined, a
circular doubly linked list of active objects is maintained by adding two extra
fields to every :c:type:`PyObject`. Total allocations are tracked as well. Upon
exit, all existing references are printed. (In interactive mode this happens
after every statement run by the interpreter.) Implied by :c:macro:`Py_DEBUG`.
Defining :c:macro:`Py_REF_DEBUG` enables reference tracing. When defined,
total allocations are tracked as well. Implied by :c:macro:`Py_DEBUG`.

Please refer to :file:`Misc/SpecialBuilds.txt` in the Python source distribution
for more detailed information.
Expand Down
17 changes: 0 additions & 17 deletions Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -493,23 +493,6 @@ metatype) initializes :c:member:`~PyTypeObject.tp_itemsize`, which means that it
type objects) *must* have the :attr:`ob_size` field.


.. c:member:: PyObject* PyObject._ob_next
PyObject* PyObject._ob_prev

These fields are only present when the macro ``Py_TRACE_REFS`` is defined.
Their initialization to *NULL* is taken care of by the ``PyObject_HEAD_INIT``
macro. For statically allocated objects, these fields always remain *NULL*.
For dynamically allocated objects, these two fields are used to link the object
into a doubly-linked list of *all* live objects on the heap. This could be used
for various debugging purposes; currently the only use is to print the objects
that are still alive at the end of a run when the environment variable
:envvar:`PYTHONDUMPREFS` is set.

**Inheritance:**

These fields are not inherited by subtypes.


.. c:member:: Py_ssize_t PyObject.ob_refcnt

This is the type object's reference count, initialized to ``1`` by the
Expand Down
5 changes: 0 additions & 5 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,3 @@ if Python was configured with the ``--with-pydebug`` build option.

If set, Python will print threading debug info.


.. envvar:: PYTHONDUMPREFS

If set, Python will dump objects and reference counts still alive after
shutting down the interpreter.
1 change: 0 additions & 1 deletion Include/cpython/coreconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ typedef struct {
int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */
int show_ref_count; /* -X showrefcount */
int show_alloc_count; /* -X showalloccount */
int dump_refs; /* PYTHONDUMPREFS */
int malloc_stats; /* PYTHONMALLOCSTATS */

/* Python filesystem encoding and error handler:
Expand Down
4 changes: 0 additions & 4 deletions Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *, PyObject *,
static inline void _Py_Dealloc_inline(PyObject *op)
{
destructor dealloc = Py_TYPE(op)->tp_dealloc;
#ifdef Py_TRACE_REFS
_Py_ForgetReference(op);
#else
_Py_INC_TPFREES(op);
#endif
(*dealloc)(op);
}
#define _Py_Dealloc(op) _Py_Dealloc_inline(op)
Expand Down
8 changes: 0 additions & 8 deletions Include/modsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,6 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def);
#define PYTHON_ABI_VERSION 3
#define PYTHON_ABI_STRING "3"

#ifdef Py_TRACE_REFS
/* When we are tracing reference counts, rename module creation functions so
modules compiled with incompatible settings will generate a
link-time error. */
#define PyModule_Create2 PyModule_Create2TraceRefs
#define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs
#endif

PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*,
int apiver);
#ifndef Py_LIMITED_API
Expand Down
47 changes: 5 additions & 42 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,40 +54,21 @@ A standard interface exists for objects that contain an array of items
whose size is determined when the object is allocated.
*/

/* 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. */
#if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
/* Py_DEBUG implies Py_REF_DEBUG. */
#if defined(Py_DEBUG) && !defined(Py_REF_DEBUG)
#define Py_REF_DEBUG
#endif

#if defined(Py_LIMITED_API) && defined(Py_REF_DEBUG)
#error Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG
#error Py_LIMITED_API is incompatible with Py_DEBUG and 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 ob_base;

#define PyObject_HEAD_INIT(type) \
{ _PyObject_EXTRA_INIT \
1, type },
{ 1, type },

#define PyVarObject_HEAD_INIT(type, size) \
{ PyObject_HEAD_INIT(type) size },
Expand All @@ -107,7 +88,6 @@ whose size is determined when the object is allocated.
* in addition, be cast to PyVarObject*.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
Expand Down Expand Up @@ -355,7 +335,7 @@ this can be the standard function free(). Both macros can be used
wherever a void expression is allowed. The argument must not be a
NULL pointer. If it may be NULL, 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
in special build (Py_REF_DEBUG) performs additional
bookkeeping appropriate to the special build.

We assume that the reference count field can never overflow; this can
Expand Down Expand Up @@ -418,16 +398,6 @@ PyAPI_FUNC(void) _Py_dec_count(struct _typeobject *);
when a memory block is reused from a free list. */
PyAPI_FUNC(int) _PyTraceMalloc_NewReference(PyObject *op);

#ifdef Py_TRACE_REFS
/* Py_TRACE_REFS is such major surgery that we call external routines. */
PyAPI_FUNC(void) _Py_NewReference(PyObject *);
PyAPI_FUNC(void) _Py_ForgetReference(PyObject *);
PyAPI_FUNC(void) _Py_PrintReferences(FILE *);
PyAPI_FUNC(void) _Py_PrintReferenceAddresses(FILE *);
PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
#else
/* Without Py_TRACE_REFS, there's little enough to do that we expand code
inline. */
static inline void _Py_NewReference(PyObject *op)
{
if (_Py_tracemalloc_config.tracing) {
Expand All @@ -438,13 +408,6 @@ static inline void _Py_NewReference(PyObject *op)
Py_REFCNT(op) = 1;
}

static inline void _Py_ForgetReference(PyObject *op)
{
_Py_INC_TPFREES(op);
}
#endif /* !Py_TRACE_REFS */


PyAPI_FUNC(void) _Py_Dealloc(PyObject *);

static inline void _Py_INCREF(PyObject *op)
Expand Down
3 changes: 0 additions & 3 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1637,9 +1637,6 @@ def python_is_optimized():

_header = 'nP'
_align = '0n'
if hasattr(sys, "gettotalrefcount"):
_header = '2P' + _header
_align = '0P'
_vheader = _header + 'n'

def calcobjsize(fmt):
Expand Down
1 change: 0 additions & 1 deletion Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'import_time': 0,
'show_ref_count': 0,
'show_alloc_count': 0,
'dump_refs': 0,
'malloc_stats': 0,

'filesystem_encoding': GET_DEFAULT_CONFIG,
Expand Down
47 changes: 1 addition & 46 deletions Misc/SpecialBuilds.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,6 @@ sys.gettotalrefcount()
Return current total of all refcounts.


Py_TRACE_REFS
-------------

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. Most built-in type objects are not in this list, as they're statically
allocated. Starting in Python 2.3, if COUNT_ALLOCS (see below) is also defined,
a static type object T does appear in this list if at least one object of type T
has been created.

Note that because the fundamental PyObject layout changes, Python modules
compiled with Py_TRACE_REFS are incompatible with modules compiled without it.

Py_TRACE_REFS implies Py_REF_DEBUG.

Special gimmicks:

sys.getobjects(max[, type])
Return list of the (no more than) max most-recently allocated objects, most
recently allocated first in the list, least-recently allocated last in the
list. max=0 means no limit on list length. If an optional type object is
passed, the list is also restricted to objects of that type. The return
list itself, and some temp objects created just to call sys.getobjects(),
are excluded from the return list. Note that the list returned is just
another object, though, so may appear in the return list the next time you
call getobjects(); note that every object in the list is kept alive too,
simply by virtue of being in the list.

envvar PYTHONDUMPREFS
If this envvar exists, Py_FinalizeEx() arranges to print a list of all
still-live heap objects. This is printed twice, in different formats,
before and after Py_FinalizeEx has cleaned up everything it can clean up. The
first output block produces the repr() of each object so is more
informative; however, a lot of stuff destined to die is still alive then.
The second output block is much harder to work with (repr() can't be invoked
anymore -- the interpreter has been torn down too far), but doesn't list any
objects that will die. The tool script combinerefs.py can be run over this
to combine the info from both output blocks. The second output block, and
combinerefs.py, were new in Python 2.3b1.


PYMALLOC_DEBUG
--------------

Expand Down Expand Up @@ -156,7 +115,7 @@ Py_DEBUG

This is what is generally meant by "a debug build" of Python.

Py_DEBUG implies LLTRACE, Py_REF_DEBUG, Py_TRACE_REFS, and PYMALLOC_DEBUG (if
Py_DEBUG implies LLTRACE, Py_REF_DEBUG, and PYMALLOC_DEBUG (if
WITH_PYMALLOC is enabled). In addition, C assert()s are enabled (via the C way:
by not defining NDEBUG), and some routines do additional sanity checks inside
"#ifdef Py_DEBUG" blocks.
Expand Down Expand Up @@ -192,10 +151,6 @@ this was fixed in 2.2.2. Use of COUNT_ALLOCS makes all heap-allocated type
objects immortal, except for those for which no object of that type is ever
allocated.

Starting with Python 2.3, If Py_TRACE_REFS is also defined, COUNT_ALLOCS
arranges to ensure that the type object for each allocated object appears in the
doubly-linked list of all objects maintained by Py_TRACE_REFS.

Special gimmicks:

sys.getcounts()
Expand Down
4 changes: 1 addition & 3 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3224,9 +3224,7 @@ slot_tp_del(PyObject *self)
/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
* we need to undo that. */
_Py_DEC_REFTOTAL;
/* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
* chain, so no more to do there.
* If COUNT_ALLOCS, the original decref bumped tp_frees, and
/* If COUNT_ALLOCS, the original decref bumped tp_frees, and
* _Py_NewReference bumped tp_allocs: both of those need to be
* undone.
*/
Expand Down
2 changes: 1 addition & 1 deletion Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3015,7 +3015,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
}
/* XXX UNREF/NEWREF interface should be more symmetrical */
_Py_DEC_REFTOTAL;
_Py_ForgetReference(v);
_Py_INC_TPFREES(op);
*pv = (PyObject *)
PyObject_REALLOC(v, PyBytesObject_SIZE + newsize);
if (*pv == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5721,7 +5721,7 @@ PyLong_Fini(void)
PyLongObject *v = small_ints;
for (i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++, v++) {
_Py_DEC_REFTOTAL;
_Py_ForgetReference((PyObject*)v);
_Py_INC_TPFREES((PyObject*)v);
}
#endif
}
Loading