@@ -211,8 +211,8 @@ struct Tuplesortstate
211
211
* tuples to return? */
212
212
bool boundUsed ; /* true if we made use of a bounded heap */
213
213
int bound ; /* if bounded, the maximum number of tuples */
214
- long availMem ; /* remaining memory available, in bytes */
215
- long allowedMem ; /* total memory allowed, in bytes */
214
+ Size availMem ; /* remaining memory available, in bytes */
215
+ Size allowedMem ; /* total memory allowed, in bytes */
216
216
int maxTapes ; /* number of tapes (Knuth's T) */
217
217
int tapeRange ; /* maxTapes-1 (Knuth's P) */
218
218
MemoryContext sortcontext ; /* memory context holding all sort data */
@@ -308,7 +308,7 @@ struct Tuplesortstate
308
308
int * mergenext ; /* first preread tuple for each source */
309
309
int * mergelast ; /* last preread tuple for each source */
310
310
int * mergeavailslots ; /* slots left for prereading each tape */
311
- long * mergeavailmem ; /* availMem for prereading each tape */
311
+ Size * mergeavailmem ; /* availMem for prereading each tape */
312
312
int mergefreelist ; /* head of freelist of recycled slots */
313
313
int mergefirstfree ; /* first slot never used in this merge */
314
314
@@ -961,25 +961,26 @@ tuplesort_end(Tuplesortstate *state)
961
961
}
962
962
963
963
/*
964
- * Grow the memtuples[] array, if possible within our memory constraint.
965
- * Return TRUE if we were able to enlarge the array, FALSE if not.
964
+ * Grow the memtuples[] array, if possible within our memory constraint. We
965
+ * must not exceed INT_MAX tuples in memory or the caller-provided memory
966
+ * limit. Return TRUE if we were able to enlarge the array, FALSE if not.
966
967
*
967
- * Normally, at each increment we double the size of the array. When we no
968
- * longer have enough memory to do that , we attempt one last, smaller increase
969
- * (and then clear the growmemtuples flag so we don't try any more). That
970
- * allows us to use allowedMem as fully as possible ; sticking to the pure
971
- * doubling rule could result in almost half of allowedMem going unused.
972
- * Because availMem moves around with tuple addition/removal, we need some
973
- * rule to prevent making repeated small increases in memtupsize, which would
974
- * just be useless thrashing. The growmemtuples flag accomplishes that and
975
- * also prevents useless recalculations in this function.
968
+ * Normally, at each increment we double the size of the array. When doing
969
+ * that would exceed a limit , we attempt one last, smaller increase (and then
970
+ * clear the growmemtuples flag so we don't try any more). That allows us to
971
+ * use memory as fully as permitted ; sticking to the pure doubling rule could
972
+ * result in almost half going unused. Because availMem moves around with
973
+ * tuple addition/removal, we need some rule to prevent making repeated small
974
+ * increases in memtupsize, which would just be useless thrashing. The
975
+ * growmemtuples flag accomplishes that and also prevents useless
976
+ * recalculations in this function.
976
977
*/
977
978
static bool
978
979
grow_memtuples (Tuplesortstate * state )
979
980
{
980
981
int newmemtupsize ;
981
982
int memtupsize = state -> memtupsize ;
982
- long memNowUsed = state -> allowedMem - state -> availMem ;
983
+ Size memNowUsed = state -> allowedMem - state -> availMem ;
983
984
984
985
/* Forget it if we've already maxed out memtuples, per comment above */
985
986
if (!state -> growmemtuples )
@@ -989,14 +990,16 @@ grow_memtuples(Tuplesortstate *state)
989
990
if (memNowUsed <= state -> availMem )
990
991
{
991
992
/*
992
- * It is surely safe to double memtupsize if we've used no more than
993
- * half of allowedMem.
994
- *
995
- * Note: it might seem that we need to worry about memtupsize * 2
996
- * overflowing an int, but the MaxAllocSize clamp applied below
997
- * ensures the existing memtupsize can't be large enough for that.
993
+ * We've used no more than half of allowedMem; double our usage,
994
+ * clamping at INT_MAX.
998
995
*/
999
- newmemtupsize = memtupsize * 2 ;
996
+ if (memtupsize < INT_MAX / 2 )
997
+ newmemtupsize = memtupsize * 2 ;
998
+ else
999
+ {
1000
+ newmemtupsize = INT_MAX ;
1001
+ state -> growmemtuples = false;
1002
+ }
1000
1003
}
1001
1004
else
1002
1005
{
@@ -1012,24 +1015,27 @@ grow_memtuples(Tuplesortstate *state)
1012
1015
* we've already seen, and thus we can extrapolate from the space
1013
1016
* consumption so far to estimate an appropriate new size for the
1014
1017
* memtuples array. The optimal value might be higher or lower than
1015
- * this estimate, but it's hard to know that in advance.
1018
+ * this estimate, but it's hard to know that in advance. We again
1019
+ * clamp at INT_MAX tuples.
1016
1020
*
1017
1021
* This calculation is safe against enlarging the array so much that
1018
1022
* LACKMEM becomes true, because the memory currently used includes
1019
1023
* the present array; thus, there would be enough allowedMem for the
1020
1024
* new array elements even if no other memory were currently used.
1021
1025
*
1022
1026
* We do the arithmetic in float8, because otherwise the product of
1023
- * memtupsize and allowedMem could overflow. (A little algebra shows
1024
- * that grow_ratio must be less than 2 here, so we are not risking
1025
- * integer overflow this way.) Any inaccuracy in the result should be
1026
- * insignificant; but even if we computed a completely insane result,
1027
- * the checks below will prevent anything really bad from happening.
1027
+ * memtupsize and allowedMem could overflow. Any inaccuracy in the
1028
+ * result should be insignificant; but even if we computed a
1029
+ * completely insane result, the checks below will prevent anything
1030
+ * really bad from happening.
1028
1031
*/
1029
1032
double grow_ratio ;
1030
1033
1031
1034
grow_ratio = (double ) state -> allowedMem / (double ) memNowUsed ;
1032
- newmemtupsize = (int ) (memtupsize * grow_ratio );
1035
+ if (memtupsize * grow_ratio < INT_MAX )
1036
+ newmemtupsize = (int ) (memtupsize * grow_ratio );
1037
+ else
1038
+ newmemtupsize = INT_MAX ;
1033
1039
1034
1040
/* We won't make any further enlargement attempts */
1035
1041
state -> growmemtuples = false;
@@ -1040,12 +1046,13 @@ grow_memtuples(Tuplesortstate *state)
1040
1046
goto noalloc ;
1041
1047
1042
1048
/*
1043
- * On a 64-bit machine, allowedMem could be more than MaxAllocSize. Clamp
1044
- * to ensure our request won't be rejected by palloc.
1049
+ * On a 32-bit machine, allowedMem could exceed MaxAllocHugeSize. Clamp
1050
+ * to ensure our request won't be rejected. Note that we can easily
1051
+ * exhaust address space before facing this outcome.
1045
1052
*/
1046
- if ((Size ) newmemtupsize >= MaxAllocSize / sizeof (SortTuple ))
1053
+ if ((Size ) newmemtupsize >= MaxAllocHugeSize / sizeof (SortTuple ))
1047
1054
{
1048
- newmemtupsize = (int ) (MaxAllocSize / sizeof (SortTuple ));
1055
+ newmemtupsize = (int ) (MaxAllocHugeSize / sizeof (SortTuple ));
1049
1056
state -> growmemtuples = false; /* can't grow any more */
1050
1057
}
1051
1058
@@ -1060,15 +1067,15 @@ grow_memtuples(Tuplesortstate *state)
1060
1067
* palloc would be treating both old and new arrays as separate chunks.
1061
1068
* But we'll check LACKMEM explicitly below just in case.)
1062
1069
*/
1063
- if (state -> availMem < (long ) ((newmemtupsize - memtupsize ) * sizeof (SortTuple )))
1070
+ if (state -> availMem < (Size ) ((newmemtupsize - memtupsize ) * sizeof (SortTuple )))
1064
1071
goto noalloc ;
1065
1072
1066
1073
/* OK, do it */
1067
1074
FREEMEM (state , GetMemoryChunkSpace (state -> memtuples ));
1068
1075
state -> memtupsize = newmemtupsize ;
1069
1076
state -> memtuples = (SortTuple * )
1070
- repalloc (state -> memtuples ,
1071
- state -> memtupsize * sizeof (SortTuple ));
1077
+ repalloc_huge (state -> memtuples ,
1078
+ state -> memtupsize * sizeof (SortTuple ));
1072
1079
USEMEM (state , GetMemoryChunkSpace (state -> memtuples ));
1073
1080
if (LACKMEM (state ))
1074
1081
elog (ERROR , "unexpected out-of-memory situation during sort" );
@@ -1715,7 +1722,7 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
1715
1722
* This is exported for use by the planner. allowedMem is in bytes.
1716
1723
*/
1717
1724
int
1718
- tuplesort_merge_order (long allowedMem )
1725
+ tuplesort_merge_order (Size allowedMem )
1719
1726
{
1720
1727
int mOrder ;
1721
1728
@@ -1749,7 +1756,7 @@ inittapes(Tuplesortstate *state)
1749
1756
int maxTapes ,
1750
1757
ntuples ,
1751
1758
j ;
1752
- long tapeSpace ;
1759
+ Size tapeSpace ;
1753
1760
1754
1761
/* Compute number of tapes to use: merge order plus 1 */
1755
1762
maxTapes = tuplesort_merge_order (state -> allowedMem ) + 1 ;
@@ -1798,7 +1805,7 @@ inittapes(Tuplesortstate *state)
1798
1805
state -> mergenext = (int * ) palloc0 (maxTapes * sizeof (int ));
1799
1806
state -> mergelast = (int * ) palloc0 (maxTapes * sizeof (int ));
1800
1807
state -> mergeavailslots = (int * ) palloc0 (maxTapes * sizeof (int ));
1801
- state -> mergeavailmem = (long * ) palloc0 (maxTapes * sizeof (long ));
1808
+ state -> mergeavailmem = (Size * ) palloc0 (maxTapes * sizeof (Size ));
1802
1809
state -> tp_fib = (int * ) palloc0 (maxTapes * sizeof (int ));
1803
1810
state -> tp_runs = (int * ) palloc0 (maxTapes * sizeof (int ));
1804
1811
state -> tp_dummy = (int * ) palloc0 (maxTapes * sizeof (int ));
@@ -2026,7 +2033,7 @@ mergeonerun(Tuplesortstate *state)
2026
2033
int srcTape ;
2027
2034
int tupIndex ;
2028
2035
SortTuple * tup ;
2029
- long priorAvail ,
2036
+ Size priorAvail ,
2030
2037
spaceFreed ;
2031
2038
2032
2039
/*
@@ -2100,7 +2107,7 @@ beginmerge(Tuplesortstate *state)
2100
2107
int tapenum ;
2101
2108
int srcTape ;
2102
2109
int slotsPerTape ;
2103
- long spacePerTape ;
2110
+ Size spacePerTape ;
2104
2111
2105
2112
/* Heap should be empty here */
2106
2113
Assert (state -> memtupcount == 0 );
@@ -2221,7 +2228,7 @@ mergeprereadone(Tuplesortstate *state, int srcTape)
2221
2228
unsigned int tuplen ;
2222
2229
SortTuple stup ;
2223
2230
int tupIndex ;
2224
- long priorAvail ,
2231
+ Size priorAvail ,
2225
2232
spaceUsed ;
2226
2233
2227
2234
if (!state -> mergeactive [srcTape ])
0 commit comments