| ... |
... |
@@ -101,7 +101,8 @@ static int openStatsFile ( |
|
101
|
101
|
char *filename, const char *FILENAME_FMT, FILE **file_ret);
|
|
102
|
102
|
|
|
103
|
103
|
static StgWord64 decodeSize (
|
|
104
|
|
- const char *flag, uint32_t offset, StgWord64 min, StgWord64 max);
|
|
|
104
|
+ const char *flag, uint32_t offset, StgWord64 min, StgWord64 max,
|
|
|
105
|
+ bool allow_zero);
|
|
105
|
106
|
|
|
106
|
107
|
static double parseDouble (
|
|
107
|
108
|
const char *arg, bool *error);
|
| ... |
... |
@@ -141,8 +142,8 @@ void initRtsFlagsDefaults(void) |
|
141
|
142
|
if (maxStkSize == 0)
|
|
142
|
143
|
maxStkSize = 8 * 1024 * 1024;
|
|
143
|
144
|
// GcFlags.maxStkSiz is 32-bit, so we need to cap to prevent overflow (#17019)
|
|
144
|
|
- else if (maxStkSize > UINT32_MAX * sizeof(W_))
|
|
145
|
|
- maxStkSize = UINT32_MAX * sizeof(W_);
|
|
|
145
|
+ else if (maxStkSize > (StgWord64) UINT32_MAX * sizeof(W_))
|
|
|
146
|
+ maxStkSize = (StgWord64) UINT32_MAX * sizeof(W_);
|
|
146
|
147
|
|
|
147
|
148
|
RtsFlags.GcFlags.statsFile = NULL;
|
|
148
|
149
|
RtsFlags.GcFlags.giveStats = NO_GC_STATS;
|
| ... |
... |
@@ -155,7 +156,7 @@ void initRtsFlagsDefaults(void) |
|
155
|
156
|
/* -A default. See #16499 for a discussion about the tradeoffs */
|
|
156
|
157
|
RtsFlags.GcFlags.minAllocAreaSize = (4 * 1024 * 1024) / BLOCK_SIZE;
|
|
157
|
158
|
RtsFlags.GcFlags.largeAllocLim = 0; /* defaults to minAllocAreasize */
|
|
158
|
|
- RtsFlags.GcFlags.nurseryChunkSize = 0;
|
|
|
159
|
+ RtsFlags.GcFlags.nurseryChunkSize = -1; /* -1: Nothing set by user, normalized to off by default, 0: off explicitly, <n>: explicit size*/
|
|
159
|
160
|
RtsFlags.GcFlags.minOldGenSize = (1024 * 1024) / BLOCK_SIZE; /* -O default */
|
|
160
|
161
|
RtsFlags.GcFlags.maxHeapSize = 0; /* off by default */
|
|
161
|
162
|
RtsFlags.GcFlags.heapLimitGrace = (1024 * 1024);
|
| ... |
... |
@@ -331,7 +332,7 @@ usage_text[] = { |
|
331
|
332
|
" --copying-gc",
|
|
332
|
333
|
" Selects the copying garbage collector to manage all generations.",
|
|
333
|
334
|
"",
|
|
334
|
|
-" -K<size> Sets the maximum stack size (default: 80% of the heap)",
|
|
|
335
|
+" -K<size> Sets the maximum stack size (0 = unlimited, default: 80% of the heap)",
|
|
335
|
336
|
" e.g.: -K32k -K512k -K8M",
|
|
336
|
337
|
" -ki<size> Sets the initial thread stack size (default 1k) e.g.: -ki4k -ki2m",
|
|
337
|
338
|
" -kc<size> Sets the stack chunk size (default 32k)",
|
| ... |
... |
@@ -349,9 +350,9 @@ usage_text[] = { |
|
349
|
350
|
" memory controlled by this factor (higher is slower). Setting the factor",
|
|
350
|
351
|
" to 0 means memory is not returned.",
|
|
351
|
352
|
" (default 4.0)",
|
|
352
|
|
-" -n<size> Allocation area chunk size (0 = disabled, default: 0)",
|
|
|
353
|
+" -n<size> Allocation area chunk size (0 = disabled, default: 0, 4m for -A >= 16m)",
|
|
353
|
354
|
" -O<size> Sets the minimum size of the old generation (default 1M)",
|
|
354
|
|
-" -M<size> Sets the maximum heap size (default unlimited) e.g.: -M256k -M1G",
|
|
|
355
|
+" -M<size> Sets the maximum heap size (0 = unlimited, default unlimited) e.g.: -M256k -M1G",
|
|
355
|
356
|
" -H<size> Sets the minimum heap size (default 0M) e.g.: -H24m -H1G",
|
|
356
|
357
|
" -xb<addr> Sets the address from which a suitable start for the heap memory",
|
|
357
|
358
|
" will be searched from. This is useful if the default address",
|
| ... |
... |
@@ -1239,19 +1240,19 @@ error = true; |
|
1239
|
1240
|
if (rts_argv[arg][2] == 'L') {
|
|
1240
|
1241
|
RtsFlags.GcFlags.largeAllocLim
|
|
1241
|
1242
|
= decodeSize(rts_argv[arg], 3, 2*BLOCK_SIZE,
|
|
1242
|
|
- HS_INT_MAX) / BLOCK_SIZE;
|
|
|
1243
|
+ (StgWord64) HS_WORD32_MAX * BLOCK_SIZE, true) / BLOCK_SIZE;
|
|
1243
|
1244
|
} else {
|
|
1244
|
1245
|
// minimum two blocks in the nursery, so that we have one
|
|
1245
|
1246
|
// to grab for allocate().
|
|
1246
|
1247
|
RtsFlags.GcFlags.minAllocAreaSize
|
|
1247
|
1248
|
= decodeSize(rts_argv[arg], 2, 2*BLOCK_SIZE,
|
|
1248
|
|
- HS_INT_MAX) / BLOCK_SIZE;
|
|
|
1249
|
+ (StgWord64) HS_WORD32_MAX * BLOCK_SIZE, false) / BLOCK_SIZE;
|
|
1249
|
1250
|
}
|
|
1250
|
1251
|
break;
|
|
1251
|
1252
|
case 'n':
|
|
1252
|
1253
|
OPTION_UNSAFE;
|
|
1253
|
1254
|
RtsFlags.GcFlags.nurseryChunkSize
|
|
1254
|
|
- = decodeSize(rts_argv[arg], 2, 2*BLOCK_SIZE, HS_INT_MAX)
|
|
|
1255
|
+ = decodeSize(rts_argv[arg], 2, 2*BLOCK_SIZE, ((StgWord64) HS_INT32_MAX) * BLOCK_SIZE, true)
|
|
1255
|
1256
|
/ BLOCK_SIZE;
|
|
1256
|
1257
|
break;
|
|
1257
|
1258
|
|
| ... |
... |
@@ -1301,9 +1302,14 @@ error = true; |
|
1301
|
1302
|
|
|
1302
|
1303
|
case 'K':
|
|
1303
|
1304
|
OPTION_UNSAFE;
|
|
1304
|
|
- RtsFlags.GcFlags.maxStkSize =
|
|
1305
|
|
- decodeSize(rts_argv[arg], 2, 0, UINT32_MAX)
|
|
1306
|
|
- / sizeof(W_);
|
|
|
1305
|
+ // -K and -K0 mean unlimited.
|
|
|
1306
|
+ if (rts_argv[arg][2] == '\0') {
|
|
|
1307
|
+ RtsFlags.GcFlags.maxStkSize = 0;
|
|
|
1308
|
+ } else {
|
|
|
1309
|
+ RtsFlags.GcFlags.maxStkSize =
|
|
|
1310
|
+ decodeSize(rts_argv[arg], 2, sizeof(W_), (StgWord64) UINT32_MAX * sizeof(W_), true)
|
|
|
1311
|
+ / sizeof(W_);
|
|
|
1312
|
+ }
|
|
1307
|
1313
|
break;
|
|
1308
|
1314
|
|
|
1309
|
1315
|
case 'k':
|
| ... |
... |
@@ -1311,22 +1317,22 @@ error = true; |
|
1311
|
1317
|
switch(rts_argv[arg][2]) {
|
|
1312
|
1318
|
case 'c':
|
|
1313
|
1319
|
RtsFlags.GcFlags.stkChunkSize =
|
|
1314
|
|
- decodeSize(rts_argv[arg], 3, sizeof(W_), HS_WORD_MAX)
|
|
|
1320
|
+ decodeSize(rts_argv[arg], 3, sizeof(W_), (StgWord64)HS_WORD32_MAX * sizeof(W_), false)
|
|
1315
|
1321
|
/ sizeof(W_);
|
|
1316
|
1322
|
break;
|
|
1317
|
1323
|
case 'b':
|
|
1318
|
1324
|
RtsFlags.GcFlags.stkChunkBufferSize =
|
|
1319
|
|
- decodeSize(rts_argv[arg], 3, sizeof(W_), HS_WORD_MAX)
|
|
|
1325
|
+ decodeSize(rts_argv[arg], 3, sizeof(W_), (StgWord64)HS_WORD32_MAX * sizeof(W_), false)
|
|
1320
|
1326
|
/ sizeof(W_);
|
|
1321
|
1327
|
break;
|
|
1322
|
1328
|
case 'i':
|
|
1323
|
1329
|
RtsFlags.GcFlags.initialStkSize =
|
|
1324
|
|
- decodeSize(rts_argv[arg], 3, sizeof(W_), HS_WORD_MAX)
|
|
|
1330
|
+ decodeSize(rts_argv[arg], 3, sizeof(W_), (StgWord64)HS_WORD32_MAX * sizeof(W_), false)
|
|
1325
|
1331
|
/ sizeof(W_);
|
|
1326
|
1332
|
break;
|
|
1327
|
1333
|
default:
|
|
1328
|
1334
|
RtsFlags.GcFlags.initialStkSize =
|
|
1329
|
|
- decodeSize(rts_argv[arg], 2, sizeof(W_), HS_WORD_MAX)
|
|
|
1335
|
+ decodeSize(rts_argv[arg], 2, sizeof(W_), (StgWord64)HS_WORD32_MAX * sizeof(W_), false)
|
|
1330
|
1336
|
/ sizeof(W_);
|
|
1331
|
1337
|
break;
|
|
1332
|
1338
|
}
|
| ... |
... |
@@ -1336,10 +1342,10 @@ error = true; |
|
1336
|
1342
|
OPTION_UNSAFE;
|
|
1337
|
1343
|
if (0 == strncmp("grace=", rts_argv[arg] + 2, 6)) {
|
|
1338
|
1344
|
RtsFlags.GcFlags.heapLimitGrace =
|
|
1339
|
|
- decodeSize(rts_argv[arg], 8, BLOCK_SIZE, HS_WORD_MAX);
|
|
|
1345
|
+ decodeSize(rts_argv[arg], 8, BLOCK_SIZE, HS_WORD_MAX, false);
|
|
1340
|
1346
|
} else {
|
|
1341
|
1347
|
RtsFlags.GcFlags.maxHeapSize =
|
|
1342
|
|
- decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX)
|
|
|
1348
|
+ decodeSize(rts_argv[arg], 2, BLOCK_SIZE, (StgWord64) HS_WORD32_MAX * BLOCK_SIZE, true)
|
|
1343
|
1349
|
/ BLOCK_SIZE;
|
|
1344
|
1350
|
// user give size in *bytes* but "maxHeapSize" is in
|
|
1345
|
1351
|
// *blocks*
|
| ... |
... |
@@ -1388,8 +1394,9 @@ error = true; |
|
1388
|
1394
|
#endif
|
|
1389
|
1395
|
case 'G':
|
|
1390
|
1396
|
OPTION_UNSAFE;
|
|
1391
|
|
- RtsFlags.GcFlags.generations =
|
|
1392
|
|
- decodeSize(rts_argv[arg], 2, 1, HS_INT_MAX);
|
|
|
1397
|
+ // Capped at 64 by hardcoded array size in non-threaded RTS.
|
|
|
1398
|
+ RtsFlags.GcFlags.generations = (uint32_t)
|
|
|
1399
|
+ decodeSize(rts_argv[arg], 2, 1, GC_MAX_GENERATIONS, false);
|
|
1393
|
1400
|
break;
|
|
1394
|
1401
|
|
|
1395
|
1402
|
case 'H':
|
| ... |
... |
@@ -1398,8 +1405,12 @@ error = true; |
|
1398
|
1405
|
RtsFlags.GcFlags.heapSizeSuggestionAuto = true;
|
|
1399
|
1406
|
} else {
|
|
1400
|
1407
|
RtsFlags.GcFlags.heapSizeSuggestion = (uint32_t)
|
|
1401
|
|
- (decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX)
|
|
|
1408
|
+ (decodeSize(rts_argv[arg], 2, BLOCK_SIZE, (StgWord64) HS_WORD32_MAX * BLOCK_SIZE, true)
|
|
1402
|
1409
|
/ BLOCK_SIZE);
|
|
|
1410
|
+ // -H0 resets to the default of no suggestion.
|
|
|
1411
|
+ if (RtsFlags.GcFlags.heapSizeSuggestion == 0) {
|
|
|
1412
|
+ RtsFlags.GcFlags.heapSizeSuggestionAuto = false;
|
|
|
1413
|
+ }
|
|
1403
|
1414
|
}
|
|
1404
|
1415
|
break;
|
|
1405
|
1416
|
|
| ... |
... |
@@ -1407,7 +1418,7 @@ error = true; |
|
1407
|
1418
|
OPTION_UNSAFE;
|
|
1408
|
1419
|
RtsFlags.GcFlags.minOldGenSize =
|
|
1409
|
1420
|
(uint32_t)(decodeSize(rts_argv[arg], 2, BLOCK_SIZE,
|
|
1410
|
|
- HS_WORD_MAX)
|
|
|
1421
|
+ (StgWord64) HS_WORD32_MAX * BLOCK_SIZE, false)
|
|
1411
|
1422
|
/ BLOCK_SIZE);
|
|
1412
|
1423
|
break;
|
|
1413
|
1424
|
|
| ... |
... |
@@ -1852,14 +1863,14 @@ error = true; |
|
1852
|
1863
|
case 'q':
|
|
1853
|
1864
|
OPTION_UNSAFE;
|
|
1854
|
1865
|
RtsFlags.GcFlags.allocLimitGrace
|
|
1855
|
|
- = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX)
|
|
|
1866
|
+ = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX, false)
|
|
1856
|
1867
|
/ BLOCK_SIZE;
|
|
1857
|
1868
|
break;
|
|
1858
|
1869
|
|
|
1859
|
1870
|
case 'r':
|
|
1860
|
1871
|
OPTION_UNSAFE;
|
|
1861
|
1872
|
RtsFlags.GcFlags.addressSpaceSize
|
|
1862
|
|
- = decodeSize(rts_argv[arg], 3, MBLOCK_SIZE, HS_WORD64_MAX);
|
|
|
1873
|
+ = decodeSize(rts_argv[arg], 3, MBLOCK_SIZE, HS_WORD64_MAX, false);
|
|
1863
|
1874
|
break;
|
|
1864
|
1875
|
|
|
1865
|
1876
|
default:
|
| ... |
... |
@@ -1994,9 +2005,25 @@ static void normaliseRtsOpts (void) |
|
1994
|
2005
|
RtsFlags.GcFlags.minAllocAreaSize = RtsFlags.GcFlags.maxHeapSize;
|
|
1995
|
2006
|
}
|
|
1996
|
2007
|
|
|
1997
|
|
- // If we have -A16m or larger, use -n4m.
|
|
1998
|
|
- if (RtsFlags.GcFlags.minAllocAreaSize >= (16*1024*1024) / BLOCK_SIZE) {
|
|
1999
|
|
- RtsFlags.GcFlags.nurseryChunkSize = (4*1024*1024) / BLOCK_SIZE;
|
|
|
2008
|
+ // If no explicit size was given, and we have -A16m or larger, use -n4m.
|
|
|
2009
|
+ if (RtsFlags.GcFlags.nurseryChunkSize == -1) {
|
|
|
2010
|
+ if (RtsFlags.GcFlags.minAllocAreaSize >= (16*1024*1024) / BLOCK_SIZE) {
|
|
|
2011
|
+ RtsFlags.GcFlags.nurseryChunkSize = (4*1024*1024) / BLOCK_SIZE;
|
|
|
2012
|
+ } else {
|
|
|
2013
|
+ RtsFlags.GcFlags.nurseryChunkSize = 0;
|
|
|
2014
|
+ }
|
|
|
2015
|
+ }
|
|
|
2016
|
+ else if ( RtsFlags.GcFlags.nurseryChunkSize > 0 && RtsFlags.GcFlags.nurseryChunkSize < 2) {
|
|
|
2017
|
+ errorBelch("nursery chunk size (-n) must be at least %" FMT_Word " large.", (W_)(2 * BLOCK_SIZE));
|
|
|
2018
|
+ errorBelch("Disabling nursery chunking");
|
|
|
2019
|
+ RtsFlags.GcFlags.nurseryChunkSize = 0;
|
|
|
2020
|
+ }
|
|
|
2021
|
+ // If the user gave a chunk size respect it, unless it's larger than
|
|
|
2022
|
+ // minimum allocation area.
|
|
|
2023
|
+ else if ( (StgWord64) RtsFlags.GcFlags.nurseryChunkSize > (StgWord64) RtsFlags.GcFlags.minAllocAreaSize) {
|
|
|
2024
|
+ errorBelch("warning: nursery chunk size (-n) is bigger than minimum alloc area size (-A), "
|
|
|
2025
|
+ "disabling nursery chunking");
|
|
|
2026
|
+ RtsFlags.GcFlags.nurseryChunkSize = 0;
|
|
2000
|
2027
|
}
|
|
2001
|
2028
|
|
|
2002
|
2029
|
if (RtsFlags.ParFlags.parGcLoadBalancingGen == ~0u) {
|
| ... |
... |
@@ -2144,10 +2171,14 @@ static void initStatsFile (FILE *f) |
|
2144
|
2171
|
|
|
2145
|
2172
|
/* -----------------------------------------------------------------------------
|
|
2146
|
2173
|
* decodeSize: parse a string containing a size, like 300K or 1.2M
|
|
|
2174
|
+ *
|
|
|
2175
|
+ * The result must lie within [min, max]. If allow_zero is set an explicitly
|
|
|
2176
|
+ * given zero (e.g. "-M0") is accepted as well.
|
|
2147
|
2177
|
-------------------------------------------------------------------------- */
|
|
2148
|
2178
|
|
|
2149
|
2179
|
static StgWord64
|
|
2150
|
|
-decodeSize(const char *flag, uint32_t offset, StgWord64 min, StgWord64 max)
|
|
|
2180
|
+decodeSize(const char *flag, uint32_t offset, StgWord64 min, StgWord64 max,
|
|
|
2181
|
+ bool allow_zero)
|
|
2151
|
2182
|
{
|
|
2152
|
2183
|
const char *s;
|
|
2153
|
2184
|
StgDouble m;
|
| ... |
... |
@@ -2206,10 +2237,14 @@ decodeSize(const char *flag, uint32_t offset, StgWord64 min, StgWord64 max) |
|
2206
|
2237
|
|
|
2207
|
2238
|
val = (StgWord64)m;
|
|
2208
|
2239
|
|
|
2209
|
|
- if (m < 0 || val < min || val > max) {
|
|
2210
|
|
- // printf doesn't like 64-bit format specs on Windows
|
|
2211
|
|
- // apparently, so fall back to unsigned long.
|
|
2212
|
|
- errorBelch("error in RTS option %s: size outside allowed range (%" FMT_Word " - %" FMT_Word ")", flag, (W_)min, (W_)max);
|
|
|
2240
|
+ // Only a explicit zero-digit is accepted for allow_zero.
|
|
|
2241
|
+ bool explicit_zero = allow_zero && *s != '\0' && m == 0;
|
|
|
2242
|
+ if (m < 0 || (val < min && !explicit_zero) || val > max) {
|
|
|
2243
|
+ if (allow_zero && min > 0) {
|
|
|
2244
|
+ errorBelch("error in RTS option %s: size outside allowed range (0 or %" FMT_Word64 " - %" FMT_Word64 ")", flag, (StgWord64)min, (StgWord64)max);
|
|
|
2245
|
+ } else {
|
|
|
2246
|
+ errorBelch("error in RTS option %s: size outside allowed range (%" FMT_Word64 " - %" FMT_Word64 ")", flag, (StgWord64)min, (StgWord64)max);
|
|
|
2247
|
+ }
|
|
2213
|
2248
|
stg_exit(EXIT_FAILURE);
|
|
2214
|
2249
|
}
|
|
2215
|
2250
|
|