From 0c88daa55ac82b2ecf61c1c8248e27d8e7dac513 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 4 Mar 2024 08:24:38 +0300 Subject: [PATCH] Assume argument of GC_set_fl_marks is non-null (refactoring) * alloc.c (GC_set_fl_marks): Remove comment; assume the argument is not null (add assertion); use "ifdef MARK_BIT_PER_OBJ" instead of IF_PER_OBJ(). * alloc.c (GC_set_fl_marks, GC_clear_fl_marks): Use EXPECT(FALSE) for h!=last_h. * alloc.c (GC_clear_fl_marks): Refine comment. * alloc.c (GC_finish_collection): Move size and q local variables to the nested scope. * include/private/gc_priv.h (IF_PER_OBJ): Remove. * include/private/gc_priv.h (GC_set_fl_marks): Remove argument name. --- alloc.c | 67 +++++++++++++++++++++------------------ include/private/gc_priv.h | 4 +-- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/alloc.c b/alloc.c index 579f4e317..9d1023d43 100644 --- a/alloc.c +++ b/alloc.c @@ -978,32 +978,35 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) return TRUE; } -/* Set all mark bits for the free list whose first entry is q */ GC_INNER void GC_set_fl_marks(ptr_t q) { - if (q /* != NULL */) { /* CPPCHECK */ -# ifdef GC_ASSERTIONS +# ifdef GC_ASSERTIONS ptr_t q2; -# endif - struct hblk *h = HBLKPTR(q); - struct hblk *last_h = h; - hdr *hhdr = HDR(h); - IF_PER_OBJ(word sz = hhdr->hb_sz;) +# endif + struct hblk *h = HBLKPTR(q); + struct hblk *last_h = h; + hdr *hhdr; +# ifdef MARK_BIT_PER_OBJ + word sz; +# endif -# ifdef GC_ASSERTIONS + GC_ASSERT(q != NULL); + hhdr = HDR(h); +# ifdef MARK_BIT_PER_OBJ + sz = hhdr -> hb_sz; +# endif +# ifdef GC_ASSERTIONS q2 = (ptr_t)obj_link(q); -# endif - for (;;) { +# endif + for (;;) { word bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); if (!mark_bit_from_hdr(hhdr, bit_no)) { set_mark_bit_from_hdr(hhdr, bit_no); INCR_MARKS(hhdr); } - q = (ptr_t)obj_link(q); - if (q == NULL) - break; + if (NULL == q) break; # ifdef GC_ASSERTIONS /* Detect a cycle in the freelist. The algorithm is to */ /* have a second "twice faster" iterator over the list - */ @@ -1020,12 +1023,14 @@ GC_INNER void GC_set_fl_marks(ptr_t q) # endif h = HBLKPTR(q); - if (h != last_h) { + if (EXPECT(h != last_h, FALSE)) { last_h = h; + /* Update hhdr and sz. */ hhdr = HDR(h); - IF_PER_OBJ(sz = hhdr->hb_sz;) +# ifdef MARK_BIT_PER_OBJ + sz = hhdr -> hb_sz; +# endif } - } } } @@ -1074,14 +1079,14 @@ GC_INNER void GC_set_fl_marks(ptr_t q) } #endif /* GC_ASSERTIONS && THREAD_LOCAL_ALLOC */ -/* Clear all mark bits for the free list whose first entry is q */ -/* Decrement GC_bytes_found by number of bytes on free list. */ +/* Clear all mark bits for the free list (specified by the first */ +/* entry). Decrement GC_bytes_found by number of bytes on free list. */ STATIC void GC_clear_fl_marks(ptr_t q) { struct hblk *h = HBLKPTR(q); struct hblk *last_h = h; hdr *hhdr = HDR(h); - word sz = hhdr->hb_sz; /* Normally set only once. */ + word sz = hhdr -> hb_sz; /* Normally set only once. */ for (;;) { word bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); @@ -1104,14 +1109,14 @@ STATIC void GC_clear_fl_marks(ptr_t q) GC_bytes_found -= (signed_word)sz; q = (ptr_t)obj_link(q); - if (q == NULL) - break; + if (NULL == q) break; h = HBLKPTR(q); - if (h != last_h) { + if (EXPECT(h != last_h, FALSE)) { last_h = h; + /* Update hhdr and sz. */ hhdr = HDR(h); - sz = hhdr->hb_sz; + sz = hhdr -> hb_sz; } } } @@ -1181,13 +1186,14 @@ STATIC void GC_finish_collection(void) if (GC_find_leak) { /* Mark all objects on the free list. All objects should be */ /* marked when we're done. */ - word size; /* current object size */ unsigned kind; - ptr_t q; for (kind = 0; kind < GC_n_kinds; kind++) { + word size; /* current object size */ + for (size = 1; size <= MAXOBJGRANULES; size++) { - q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size]; + ptr_t q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size]; + if (q != NULL) GC_set_fl_marks(q); } @@ -1220,13 +1226,14 @@ STATIC void GC_finish_collection(void) /* Thus accidentally marking a free list is not a problem; only */ /* objects on the list itself will be marked, and that's fixed here. */ { - word size; /* current object size */ - ptr_t q; /* pointer to current object */ unsigned kind; for (kind = 0; kind < GC_n_kinds; kind++) { + word size; /* current object size */ + for (size = 1; size <= MAXOBJGRANULES; size++) { - q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size]; + ptr_t q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size]; + if (q != NULL) GC_clear_fl_marks(q); } diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 416601b3b..af41c657b 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1920,13 +1920,11 @@ struct GC_traced_stack_sect_s { /* offset and size (in bytes). */ # define MARK_BIT_OFFSET(sz) 1 /* Spacing between useful mark bits. */ -# define IF_PER_OBJ(x) x # define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES? 1 : HBLK_OBJS(sz)) /* Position of final, always set, mark bit. */ #else # define MARK_BIT_NO(offset, sz) BYTES_TO_GRANULES((word)(offset)) # define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz) -# define IF_PER_OBJ(x) # define FINAL_MARK_BIT(sz) \ ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \ : BYTES_TO_GRANULES((sz) * HBLK_OBJS(sz))) @@ -2168,7 +2166,7 @@ GC_INNER void GC_clear_hdr_marks(hdr * hhdr); /* Clear the mark bits in a header */ GC_INNER void GC_set_hdr_marks(hdr * hhdr); /* Set the mark bits in a header */ -GC_INNER void GC_set_fl_marks(ptr_t p); +GC_INNER void GC_set_fl_marks(ptr_t); /* Set all mark bits associated with */ /* a free list. */ #if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)