]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-115124: Use _PyObject_ASSERT() in gc.c (#115125)
authorVictor Stinner <vstinner@python.org>
Thu, 15 Feb 2024 14:29:42 +0000 (15:29 +0100)
committerGitHub <noreply@github.com>
Thu, 15 Feb 2024 14:29:42 +0000 (14:29 +0000)
Replace assert() with _PyObject_ASSERT() in gc.c to dump the object
when an assertion fails.

Python/gc.c

index 466467602915264c845998ba4e9e321c6fd0ef43..c6831f4c74bcac8f801788c350fb26c3fb7d8c03 100644 (file)
@@ -394,16 +394,17 @@ update_refs(PyGC_Head *containers)
 
     while (gc != containers) {
         next = GC_NEXT(gc);
+        PyObject *op = FROM_GC(gc);
         /* Move any object that might have become immortal to the
          * permanent generation as the reference count is not accurately
          * reflecting the actual number of live references to this object
          */
-        if (_Py_IsImmortal(FROM_GC(gc))) {
+        if (_Py_IsImmortal(op)) {
            gc_list_move(gc, &get_gc_state()->permanent_generation.head);
            gc = next;
            continue;
         }
-        gc_reset_refs(gc, Py_REFCNT(FROM_GC(gc)));
+        gc_reset_refs(gc, Py_REFCNT(op));
         /* Python's cyclic gc should never see an incoming refcount
          * of 0:  if something decref'ed to 0, it should have been
          * deallocated immediately at that time.
@@ -422,7 +423,7 @@ update_refs(PyGC_Head *containers)
          * so serious that maybe this should be a release-build
          * check instead of an assert?
          */
-        _PyObject_ASSERT(FROM_GC(gc), gc_get_refs(gc) != 0);
+        _PyObject_ASSERT(op, gc_get_refs(gc) != 0);
         gc = next;
     }
 }
@@ -488,7 +489,7 @@ visit_reachable(PyObject *op, void *arg)
     }
     // It would be a logic error elsewhere if the collecting flag were set on
     // an untracked object.
-    assert(gc->_gc_next != 0);
+    _PyObject_ASSERT(op, gc->_gc_next != 0);
 
     if (gc->_gc_next & NEXT_MASK_UNREACHABLE) {
         /* This had gc_refs = 0 when move_unreachable got
@@ -660,7 +661,9 @@ static void
 move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
 {
     PyGC_Head *gc, *next;
-    assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0);
+    _PyObject_ASSERT(
+        FROM_GC(unreachable),
+        (unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0);
 
     /* March over unreachable.  Move objects with finalizers into
      * `finalizers`.
@@ -683,10 +686,14 @@ static inline void
 clear_unreachable_mask(PyGC_Head *unreachable)
 {
     /* Check that the list head does not have the unreachable bit set */
-    assert(((uintptr_t)unreachable & NEXT_MASK_UNREACHABLE) == 0);
+    _PyObject_ASSERT(
+        FROM_GC(unreachable),
+        ((uintptr_t)unreachable & NEXT_MASK_UNREACHABLE) == 0);
+    _PyObject_ASSERT(
+        FROM_GC(unreachable),
+        (unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0);
 
     PyGC_Head *gc, *next;
-    assert((unreachable->_gc_next & NEXT_MASK_UNREACHABLE) == 0);
     for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) {
         _PyObject_ASSERT((PyObject*)FROM_GC(gc), gc->_gc_next & NEXT_MASK_UNREACHABLE);
         gc->_gc_next &= ~NEXT_MASK_UNREACHABLE;
@@ -840,7 +847,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
              */
             if (gc_is_collecting(AS_GC((PyObject *)wr))) {
                 /* it should already have been cleared above */
-                assert(wr->wr_object == Py_None);
+                _PyObject_ASSERT((PyObject*)wr, wr->wr_object == Py_None);
                 continue;
             }
 
@@ -851,9 +858,8 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
 
             /* Move wr to wrcb_to_call, for the next pass. */
             wrasgc = AS_GC((PyObject *)wr);
-            assert(wrasgc != next); /* wrasgc is reachable, but
-                                       next isn't, so they can't
-                                       be the same */
+            // wrasgc is reachable, but next isn't, so they can't be the same
+            _PyObject_ASSERT((PyObject *)wr, wrasgc != next);
             gc_list_move(wrasgc, &wrcb_to_call);
         }
     }
@@ -1773,13 +1779,14 @@ _Py_ScheduleGC(PyInterpreterState *interp)
 void
 _PyObject_GC_Link(PyObject *op)
 {
-    PyGC_Head *g = AS_GC(op);
-    assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0);  // g must be correctly aligned
+    PyGC_Head *gc = AS_GC(op);
+    // gc must be correctly aligned
+    _PyObject_ASSERT(op, ((uintptr_t)gc & (sizeof(uintptr_t)-1)) == 0);
 
     PyThreadState *tstate = _PyThreadState_GET();
     GCState *gcstate = &tstate->interp->gc;
-    g->_gc_next = 0;
-    g->_gc_prev = 0;
+    gc->_gc_next = 0;
+    gc->_gc_prev = 0;
     gcstate->generations[0].count++; /* number of allocated GC objects */
     if (gcstate->generations[0].count > gcstate->generations[0].threshold &&
         gcstate->enabled &&