35
35
#define WORDS_PER_PAGE (n ) ((n) / BITS_PER_BITMAPWORD + 1)
36
36
37
37
/* number of offsets we can store in the header of a BlocktableEntry */
38
- #define NUM_FULL_OFFSETS ((sizeof(bitmapword ) - sizeof(uint16 )) / sizeof(OffsetNumber))
38
+ #define NUM_FULL_OFFSETS ((sizeof(uintptr_t ) - sizeof(uint8) - sizeof(int8 )) / sizeof(OffsetNumber))
39
39
40
40
/*
41
41
* This is named similarly to PagetableEntry in tidbitmap.c
42
42
* because the two have a similar function.
43
43
*/
44
44
typedef struct BlocktableEntry
45
45
{
46
- uint16 nwords ;
47
-
48
- /*
49
- * We can store a small number of offsets here to avoid wasting space with
50
- * a sparse bitmap.
51
- */
52
- OffsetNumber full_offsets [NUM_FULL_OFFSETS ];
46
+ union
47
+ {
48
+ struct
49
+ {
50
+ #ifndef WORDS_BIGENDIAN
51
+ /*
52
+ * We need to position this member so that the backing radix tree
53
+ * can use the lowest bit for a pointer tag. In particular, it
54
+ * must be placed within 'header' so that it corresponds to the
55
+ * lowest byte in 'ptr'. We position 'nwords' along with it to
56
+ * avoid struct padding.
57
+ */
58
+ uint8 flags ;
59
+
60
+ int8 nwords ;
61
+ #endif
62
+
63
+ /*
64
+ * We can store a small number of offsets here to avoid wasting
65
+ * space with a sparse bitmap.
66
+ */
67
+ OffsetNumber full_offsets [NUM_FULL_OFFSETS ];
68
+
69
+ #ifdef WORDS_BIGENDIAN
70
+ int8 nwords ;
71
+ uint8 flags ;
72
+ #endif
73
+ };
74
+ uintptr_t ptr ;
75
+ } header ;
53
76
54
77
bitmapword words [FLEXIBLE_ARRAY_MEMBER ];
55
78
} BlocktableEntry ;
79
+
80
+ /*
81
+ * The type of 'nwords' limits the max number of words in the 'words' array.
82
+ * This computes the max offset we can actually store in the bitmap. In
83
+ * practice, it's almost always the same as MaxOffsetNumber.
84
+ */
85
+ #define MAX_OFFSET_IN_BITMAP Min(BITS_PER_BITMAPWORD * PG_INT8_MAX - 1, MaxOffsetNumber)
86
+
56
87
#define MaxBlocktableEntrySize \
57
88
offsetof(BlocktableEntry, words) + \
58
- (sizeof(bitmapword) * WORDS_PER_PAGE(MaxOffsetNumber ))
89
+ (sizeof(bitmapword) * WORDS_PER_PAGE(MAX_OFFSET_IN_BITMAP ))
59
90
60
91
#define RT_PREFIX local_ts
61
92
#define RT_SCOPE static
@@ -64,7 +95,8 @@ typedef struct BlocktableEntry
64
95
#define RT_VALUE_TYPE BlocktableEntry
65
96
#define RT_VARLEN_VALUE_SIZE (page ) \
66
97
(offsetof(BlocktableEntry, words) + \
67
- sizeof(bitmapword) * (page)->nwords)
98
+ sizeof(bitmapword) * (page)->header.nwords)
99
+ #define RT_RUNTIME_EMBEDDABLE_VALUE
68
100
#include "lib/radixtree.h"
69
101
70
102
#define RT_PREFIX shared_ts
@@ -75,7 +107,8 @@ typedef struct BlocktableEntry
75
107
#define RT_VALUE_TYPE BlocktableEntry
76
108
#define RT_VARLEN_VALUE_SIZE (page ) \
77
109
(offsetof(BlocktableEntry, words) + \
78
- sizeof(bitmapword) * (page)->nwords)
110
+ sizeof(bitmapword) * (page)->header.nwords)
111
+ #define RT_RUNTIME_EMBEDDABLE_VALUE
79
112
#include "lib/radixtree.h"
80
113
81
114
/* Per-backend state for a TidStore */
@@ -350,13 +383,13 @@ TidStoreSetBlockOffsets(TidStore *ts, BlockNumber blkno, OffsetNumber *offsets,
350
383
OffsetNumber off = offsets [i ];
351
384
352
385
/* safety check to ensure we don't overrun bit array bounds */
353
- if (! OffsetNumberIsValid ( off ) )
386
+ if (off == InvalidOffsetNumber || off > MAX_OFFSET_IN_BITMAP )
354
387
elog (ERROR , "tuple offset out of range: %u" , off );
355
388
356
- page -> full_offsets [i ] = off ;
389
+ page -> header . full_offsets [i ] = off ;
357
390
}
358
391
359
- page -> nwords = 0 ;
392
+ page -> header . nwords = 0 ;
360
393
}
361
394
else
362
395
{
@@ -371,7 +404,7 @@ TidStoreSetBlockOffsets(TidStore *ts, BlockNumber blkno, OffsetNumber *offsets,
371
404
OffsetNumber off = offsets [idx ];
372
405
373
406
/* safety check to ensure we don't overrun bit array bounds */
374
- if (! OffsetNumberIsValid ( off ) )
407
+ if (off == InvalidOffsetNumber || off > MAX_OFFSET_IN_BITMAP )
375
408
elog (ERROR , "tuple offset out of range: %u" , off );
376
409
377
410
if (off >= next_word_threshold )
@@ -385,8 +418,8 @@ TidStoreSetBlockOffsets(TidStore *ts, BlockNumber blkno, OffsetNumber *offsets,
385
418
page -> words [wordnum ] = word ;
386
419
}
387
420
388
- page -> nwords = wordnum ;
389
- Assert (page -> nwords == WORDS_PER_PAGE (offsets [num_offsets - 1 ]));
421
+ page -> header . nwords = wordnum ;
422
+ Assert (page -> header . nwords == WORDS_PER_PAGE (offsets [num_offsets - 1 ]));
390
423
}
391
424
392
425
if (TidStoreIsShared (ts ))
@@ -414,12 +447,12 @@ TidStoreIsMember(TidStore *ts, ItemPointer tid)
414
447
if (page == NULL )
415
448
return false;
416
449
417
- if (page -> nwords == 0 )
450
+ if (page -> header . nwords == 0 )
418
451
{
419
452
/* we have offsets in the header */
420
453
for (int i = 0 ; i < NUM_FULL_OFFSETS ; i ++ )
421
454
{
422
- if (page -> full_offsets [i ] == off )
455
+ if (page -> header . full_offsets [i ] == off )
423
456
return true;
424
457
}
425
458
return false;
@@ -430,7 +463,7 @@ TidStoreIsMember(TidStore *ts, ItemPointer tid)
430
463
bitnum = BITNUM (off );
431
464
432
465
/* no bitmap for the off */
433
- if (wordnum >= page -> nwords )
466
+ if (wordnum >= page -> header . nwords )
434
467
return false;
435
468
436
469
return (page -> words [wordnum ] & ((bitmapword ) 1 << bitnum )) != 0 ;
@@ -554,18 +587,18 @@ tidstore_iter_extract_tids(TidStoreIter *iter, BlockNumber blkno,
554
587
result -> num_offsets = 0 ;
555
588
result -> blkno = blkno ;
556
589
557
- if (page -> nwords == 0 )
590
+ if (page -> header . nwords == 0 )
558
591
{
559
592
/* we have offsets in the header */
560
593
for (int i = 0 ; i < NUM_FULL_OFFSETS ; i ++ )
561
594
{
562
- if (page -> full_offsets [i ] != InvalidOffsetNumber )
563
- result -> offsets [result -> num_offsets ++ ] = page -> full_offsets [i ];
595
+ if (page -> header . full_offsets [i ] != InvalidOffsetNumber )
596
+ result -> offsets [result -> num_offsets ++ ] = page -> header . full_offsets [i ];
564
597
}
565
598
}
566
599
else
567
600
{
568
- for (wordnum = 0 ; wordnum < page -> nwords ; wordnum ++ )
601
+ for (wordnum = 0 ; wordnum < page -> header . nwords ; wordnum ++ )
569
602
{
570
603
bitmapword w = page -> words [wordnum ];
571
604
int off = wordnum * BITS_PER_BITMAPWORD ;
0 commit comments