REALLOCATE_BITMAPSETS manual compile-time option
authorAlexander Korotkov
Wed, 27 Dec 2023 01:34:23 +0000 (03:34 +0200)
committerAlexander Korotkov
Wed, 27 Dec 2023 01:57:57 +0000 (03:57 +0200)
This option forces each bitmapset modification to reallocate bitmapset.  This
is useful for debugging hangling pointers to bitmapset's.

Discussion: https://postgr.es/m/CAMbWs4_wJthNtYBL%2BSsebpgF-5L2r5zFFk6xYbS0A78GKOTFHw%40mail.gmail.com
Reviewed-by: Richard Guo, Andres Freund, Ashutosh Bapat, Andrei Lepikhov
src/backend/nodes/bitmapset.c
src/include/pg_config_manual.h

index 1627922ef7ad1877f123d03d74d9b518ab2433e1..e13ecaa155df50e270eff28a6ccc2eec2b42745c 100644 (file)
@@ -263,6 +263,7 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b)
    /* Handle cases where either input is NULL */
    if (a == NULL || b == NULL)
        return NULL;
+
    /* Identify shorter and longer input; copy the shorter one */
    if (a->nwords <= b->nwords)
    {
@@ -798,8 +799,15 @@ bms_add_member(Bitmapset *a, int x)
    {
        int         oldnwords = a->nwords;
        int         i;
+#ifdef REALLOCATE_BITMAPSETS
+       Bitmapset  *tmp = a;
 
+       a = (Bitmapset *) palloc(BITMAPSET_SIZE(wordnum + 1));
+       memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+       pfree(tmp);
+#else
        a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(wordnum + 1));
+#endif
        a->nwords = wordnum + 1;
        /* zero out the enlarged portion */
        i = oldnwords;
@@ -808,6 +816,16 @@ bms_add_member(Bitmapset *a, int x)
            a->words[i] = 0;
        } while (++i < a->nwords);
    }
+#ifdef REALLOCATE_BITMAPSETS
+   else
+   {
+       Bitmapset  *tmp = a;
+
+       a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+       memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+       pfree(tmp);
+   }
+#endif
 
    a->words[wordnum] |= ((bitmapword) 1 << bitnum);
    return a;
@@ -825,6 +843,9 @@ bms_del_member(Bitmapset *a, int x)
 {
    int         wordnum,
                bitnum;
+#ifdef REALLOCATE_BITMAPSETS
+   Bitmapset  *tmp = a;
+#endif
 
    if (x < 0)
        elog(ERROR, "negative bitmapset member not allowed");
@@ -836,6 +857,12 @@ bms_del_member(Bitmapset *a, int x)
    wordnum = WORDNUM(x);
    bitnum = BITNUM(x);
 
+#ifdef REALLOCATE_BITMAPSETS
+   a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+   memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+   pfree(tmp);
+#endif
+
    /* member can't exist.  Return 'a' unmodified */
    if (unlikely(wordnum >= a->nwords))
        return a;
@@ -889,6 +916,13 @@ bms_add_members(Bitmapset *a, const Bitmapset *b)
    }
    else
    {
+#ifdef REALLOCATE_BITMAPSETS
+       Bitmapset  *tmp = a;
+
+       a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+       memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+       pfree(tmp);
+#endif
        result = a;
        other = b;
    }
@@ -941,9 +975,16 @@ bms_add_range(Bitmapset *a, int lower, int upper)
    {
        int         oldnwords = a->nwords;
        int         i;
+#ifdef REALLOCATE_BITMAPSETS
+       Bitmapset  *tmp = a;
 
+       a = (Bitmapset *) palloc(BITMAPSET_SIZE(uwordnum + 1));
+       memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+       pfree(tmp);
+#else
        /* ensure we have enough words to store the upper bit */
        a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
+#endif
        a->nwords = uwordnum + 1;
        /* zero out the enlarged portion */
        i = oldnwords;
@@ -992,6 +1033,12 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
    int         lastnonzero;
    int         shortlen;
    int         i;
+#ifdef REALLOCATE_BITMAPSETS
+   Bitmapset  *tmp = a;
+#endif
+
+   Assert(a == NULL || IsA(a, Bitmapset));
+   Assert(b == NULL || IsA(b, Bitmapset));
 
    Assert(a == NULL || IsA(a, Bitmapset));
    Assert(b == NULL || IsA(b, Bitmapset));
@@ -1004,6 +1051,13 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
        pfree(a);
        return NULL;
    }
+
+#ifdef REALLOCATE_BITMAPSETS
+   a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+   memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+   pfree(tmp);
+#endif
+
    /* Intersect b into a; we need never copy */
    shortlen = Min(a->nwords, b->nwords);
    lastnonzero = -1;
@@ -1035,6 +1089,9 @@ Bitmapset *
 bms_del_members(Bitmapset *a, const Bitmapset *b)
 {
    int         i;
+#ifdef REALLOCATE_BITMAPSETS
+   Bitmapset  *tmp = a;
+#endif
 
    Assert(a == NULL || (IsA(a, Bitmapset) && a->words[a->nwords - 1] != 0));
    Assert(b == NULL || (IsA(b, Bitmapset) && b->words[b->nwords - 1] != 0));
@@ -1044,6 +1101,13 @@ bms_del_members(Bitmapset *a, const Bitmapset *b)
        return NULL;
    if (b == NULL)
        return a;
+
+#ifdef REALLOCATE_BITMAPSETS
+   a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+   memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+   pfree(tmp);
+#endif
+
    /* Remove b's bits from a; we need never copy */
    if (a->nwords > b->nwords)
    {
@@ -1096,6 +1160,12 @@ bms_join(Bitmapset *a, Bitmapset *b)
    Bitmapset  *other;
    int         otherlen;
    int         i;
+#ifdef REALLOCATE_BITMAPSETS
+   Bitmapset  *tmp = a;
+#endif
+
+   Assert(a == NULL || IsA(a, Bitmapset));
+   Assert(b == NULL || IsA(b, Bitmapset));
 
    Assert(a == NULL || IsA(a, Bitmapset));
    Assert(b == NULL || IsA(b, Bitmapset));
@@ -1105,6 +1175,13 @@ bms_join(Bitmapset *a, Bitmapset *b)
        return b;
    if (b == NULL)
        return a;
+
+#ifdef REALLOCATE_BITMAPSETS
+   a = (Bitmapset *) palloc(BITMAPSET_SIZE(tmp->nwords));
+   memcpy(a, tmp, BITMAPSET_SIZE(tmp->nwords));
+   pfree(tmp);
+#endif
+
    /* Identify shorter and longer input; use longer one as result */
    if (a->nwords < b->nwords)
    {
index 8a6e67a445d39d94b555db8d90d1ad5b6480b4ad..16c383ba7f78335bf7208d0044828d7b27b763d3 100644 (file)
  */
 /* #define COPY_PARSE_PLAN_TREES */
 
+/*
+ * Define this to force Bitmapset reallocation on each modification.  Helps
+ * to find hangling pointers to Bitmapset's.
+ */
+/* #define REALLOCATE_BITMAPSETS */
+
 /*
  * Define this to force all parse and plan trees to be passed through
  * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in