REALLOCATE_BITMAPSETS manual compile-time option

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
This commit is contained in:
Alexander Korotkov 2023-12-27 03:34:23 +02:00
parent 71a3e8c43b
commit 7d58f2342b
2 changed files with 83 additions and 0 deletions

View File

@ -263,6 +263,7 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b)
/* Handle cases where either input is NULL */ /* Handle cases where either input is NULL */
if (a == NULL || b == NULL) if (a == NULL || b == NULL)
return NULL; return NULL;
/* Identify shorter and longer input; copy the shorter one */ /* Identify shorter and longer input; copy the shorter one */
if (a->nwords <= b->nwords) if (a->nwords <= b->nwords)
{ {
@ -798,8 +799,15 @@ bms_add_member(Bitmapset *a, int x)
{ {
int oldnwords = a->nwords; int oldnwords = a->nwords;
int i; 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)); a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(wordnum + 1));
#endif
a->nwords = wordnum + 1; a->nwords = wordnum + 1;
/* zero out the enlarged portion */ /* zero out the enlarged portion */
i = oldnwords; i = oldnwords;
@ -808,6 +816,16 @@ bms_add_member(Bitmapset *a, int x)
a->words[i] = 0; a->words[i] = 0;
} while (++i < a->nwords); } 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); a->words[wordnum] |= ((bitmapword) 1 << bitnum);
return a; return a;
@ -825,6 +843,9 @@ bms_del_member(Bitmapset *a, int x)
{ {
int wordnum, int wordnum,
bitnum; bitnum;
#ifdef REALLOCATE_BITMAPSETS
Bitmapset *tmp = a;
#endif
if (x < 0) if (x < 0)
elog(ERROR, "negative bitmapset member not allowed"); elog(ERROR, "negative bitmapset member not allowed");
@ -836,6 +857,12 @@ bms_del_member(Bitmapset *a, int x)
wordnum = WORDNUM(x); wordnum = WORDNUM(x);
bitnum = BITNUM(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 */ /* member can't exist. Return 'a' unmodified */
if (unlikely(wordnum >= a->nwords)) if (unlikely(wordnum >= a->nwords))
return a; return a;
@ -889,6 +916,13 @@ bms_add_members(Bitmapset *a, const Bitmapset *b)
} }
else 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; result = a;
other = b; other = b;
} }
@ -941,9 +975,16 @@ bms_add_range(Bitmapset *a, int lower, int upper)
{ {
int oldnwords = a->nwords; int oldnwords = a->nwords;
int i; 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 */ /* ensure we have enough words to store the upper bit */
a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1)); a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
#endif
a->nwords = uwordnum + 1; a->nwords = uwordnum + 1;
/* zero out the enlarged portion */ /* zero out the enlarged portion */
i = oldnwords; i = oldnwords;
@ -992,6 +1033,12 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
int lastnonzero; int lastnonzero;
int shortlen; int shortlen;
int i; 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(a == NULL || IsA(a, Bitmapset));
Assert(b == NULL || IsA(b, Bitmapset)); Assert(b == NULL || IsA(b, Bitmapset));
@ -1004,6 +1051,13 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
pfree(a); pfree(a);
return NULL; 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 */ /* Intersect b into a; we need never copy */
shortlen = Min(a->nwords, b->nwords); shortlen = Min(a->nwords, b->nwords);
lastnonzero = -1; lastnonzero = -1;
@ -1035,6 +1089,9 @@ Bitmapset *
bms_del_members(Bitmapset *a, const Bitmapset *b) bms_del_members(Bitmapset *a, const Bitmapset *b)
{ {
int i; int i;
#ifdef REALLOCATE_BITMAPSETS
Bitmapset *tmp = a;
#endif
Assert(a == NULL || (IsA(a, Bitmapset) && a->words[a->nwords - 1] != 0)); Assert(a == NULL || (IsA(a, Bitmapset) && a->words[a->nwords - 1] != 0));
Assert(b == NULL || (IsA(b, Bitmapset) && b->words[b->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; return NULL;
if (b == NULL) if (b == NULL)
return a; 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 */ /* Remove b's bits from a; we need never copy */
if (a->nwords > b->nwords) if (a->nwords > b->nwords)
{ {
@ -1096,6 +1160,12 @@ bms_join(Bitmapset *a, Bitmapset *b)
Bitmapset *other; Bitmapset *other;
int otherlen; int otherlen;
int i; 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(a == NULL || IsA(a, Bitmapset));
Assert(b == NULL || IsA(b, Bitmapset)); Assert(b == NULL || IsA(b, Bitmapset));
@ -1105,6 +1175,13 @@ bms_join(Bitmapset *a, Bitmapset *b)
return b; return b;
if (b == NULL) if (b == NULL)
return a; 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 */ /* Identify shorter and longer input; use longer one as result */
if (a->nwords < b->nwords) if (a->nwords < b->nwords)
{ {

View File

@ -335,6 +335,12 @@
*/ */
/* #define COPY_PARSE_PLAN_TREES */ /* #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 * Define this to force all parse and plan trees to be passed through
* outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in