Andreas Klebinger pushed to branch wip/apk/rts-flag-fixes at Glasgow Haskell Compiler / GHC

Commits:

10 changed files:

Changes:

  • changelog.d/T27830-rts-flag-bounds
    1
    +section: rts
    
    2
    +synopsis: Update RTS flag handling: It now respects user set -n values, allows resetting of more settings to defaults and gives more accurate bounds in errors.
    
    3
    +description:
    
    4
    +  Using 0 as argument to any of these flags now resets the flags setting to default:
    
    5
    +
    
    6
    +    - ``-n0`` disables nursery chunking.
    
    7
    +    - ``-K0`` (or a bare ``-K``) removes the stack size limit.
    
    8
    +    - ``-M0`` removes the heap size limit.
    
    9
    +    - ``-H0`` resets the suggested heap size, including the nursery scaling set by ``-H``.
    
    10
    +    - ``-AL0`` makes the large object allocation limit follow ``-A`` again.
    
    11
    +
    
    12
    +  A nursery chunk size (``-n``) larger than the allocation area (``-A``) now prints a
    
    13
    +  warning and disables nursery chunking. Previously every nursery was enlarged to the chunk size.
    
    14
    +
    
    15
    +  The number of generations (``-G``) is now limited to 64.
    
    16
    +issues: #27830 #27829
    
    17
    +mrs: !16713

  • docs/users_guide/runtime_control.rst
    ... ... @@ -493,7 +493,7 @@ performance.
    493 493
         Sets the limit on the total size of "large objects" (objects
    
    494 494
         larger than about 3KB) that can be allocated before a GC is
    
    495 495
         triggered. By default this limit is the same as the :rts-flag:`-A <-A
    
    496
    -    ⟨size⟩>` value.
    
    496
    +    ⟨size⟩>` value. ``-AL0`` restores the default.
    
    497 497
     
    
    498 498
         Large objects are not allocated from the normal allocation area
    
    499 499
         set by the ``-A`` flag, which is why there is a separate limit for
    
    ... ... @@ -635,10 +635,11 @@ performance.
    635 635
     
    
    636 636
         Set the number of generations used by the garbage
    
    637 637
         collector. The default of 2 seems to be good, but the garbage
    
    638
    -    collector can support any number of generations. Anything larger
    
    638
    +    collector can in theory support any number of generations. Anything larger
    
    639 639
         than about 4 is probably not a good idea unless your program runs
    
    640 640
         for a *long* time, because the oldest generation will hardly ever
    
    641
    -    get collected.
    
    641
    +    get collected. Currently the RTS hardcodes a limit of 64 generations which
    
    642
    +    seems plenty.
    
    642 643
     
    
    643 644
         Specifying 1 generation with ``+RTS -G1`` gives you a simple 2-space
    
    644 645
         collector, as you would expect. In a 2-space collector, the :rts-flag:`-A
    
    ... ... @@ -731,6 +732,9 @@ performance.
    731 732
         the default small ``-A`` value is suboptimal, as it can be in
    
    732 733
         programs that create large amounts of long-lived data.
    
    733 734
     
    
    735
    +    ``-H0`` resets both the size suggestion, and dynamic scaling enablied by a
    
    736
    +    bare ``-H``.
    
    737
    +
    
    734 738
     .. rts-flag:: -I ⟨seconds⟩
    
    735 739
     
    
    736 740
         :default: 0.3 seconds in the threaded runtime, 0 in the non-threaded runtime
    
    ... ... @@ -886,7 +890,7 @@ performance.
    886 890
         of the program. The only reason for having this option is to stop
    
    887 891
         the heap growing without bound and filling up all the available swap
    
    888 892
         space, which at the least will result in the program being summarily
    
    889
    -    killed by the operating system.
    
    893
    +    killed by the operating system. ``-M0`` resets any limit set by ``-M<size>``.
    
    890 894
     
    
    891 895
         The maximum heap size also affects other garbage collection
    
    892 896
         parameters: when the amount of live data in the heap exceeds a
    

  • rts/RtsFlags.c
    ... ... @@ -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
     
    

  • rts/include/rts/Flags.h
    ... ... @@ -45,7 +45,7 @@ typedef struct _GC_FLAGS {
    45 45
         uint32_t     maxHeapSize;        /* in *blocks* */
    
    46 46
         uint32_t     minAllocAreaSize;   /* in *blocks* */
    
    47 47
         uint32_t     largeAllocLim;      /* in *blocks* */
    
    48
    -    uint32_t     nurseryChunkSize;   /* in *blocks* */
    
    48
    +    int32_t      nurseryChunkSize;   /* in *blocks*, int to distinguish default off, vs explicit off */
    
    49 49
         uint32_t     minOldGenSize;      /* in *blocks* */
    
    50 50
         uint32_t     heapSizeSuggestion; /* in *blocks* */
    
    51 51
         bool heapSizeSuggestionAuto;
    
    ... ... @@ -80,7 +80,7 @@ typedef struct _GC_FLAGS {
    80 80
                                      * to handle the exception before we
    
    81 81
                                      * raise it again.
    
    82 82
                                      */
    
    83
    -    StgWord heapLimitGrace;     /* units: *blocks*
    
    83
    +    StgWord heapLimitGrace;     /* units: *bytes*
    
    84 84
                                      * After a HeapOverflow exception has
    
    85 85
                                      * been raised, how much extra space is
    
    86 86
                                      * given to the thread to handle the
    

  • rts/include/rts/storage/GC.h
    ... ... @@ -52,6 +52,8 @@
    52 52
     // ie. StgWord.  Note that we have had some tricky int overflows in a
    
    53 53
     // couple of cases caused by using ints rather than longs (e.g. #5086)
    
    54 54
     
    
    55
    +#define GC_MAX_GENERATIONS 64
    
    56
    +
    
    55 57
     typedef StgWord memcount;
    
    56 58
     
    
    57 59
     typedef struct nursery_ {
    

  • rts/sm/GC.c
    ... ... @@ -154,7 +154,7 @@ static Condition gc_exit_leave_now_cv;
    154 154
     
    
    155 155
     #else // THREADED_RTS
    
    156 156
     // Must match the alignment of gen_workspace.
    
    157
    -StgWord8 the_gc_thread[sizeof(gc_thread) + 64 * sizeof(gen_workspace)]
    
    157
    +StgWord8 the_gc_thread[sizeof(gc_thread) + GC_MAX_GENERATIONS * sizeof(gen_workspace)]
    
    158 158
         ATTRIBUTE_ALIGNED(GEN_WORKSPACE_ALIGNMENT);
    
    159 159
     #endif // THREADED_RTS
    
    160 160
     
    

  • rts/sm/Storage.c
    ... ... @@ -273,7 +273,7 @@ void storageAddCapabilities (uint32_t from, uint32_t to)
    273 273
         if (RtsFlags.GcFlags.nurseryChunkSize == 0) {
    
    274 274
             new_n_nurseries = to;
    
    275 275
         } else {
    
    276
    -        memcount total_alloc = to * RtsFlags.GcFlags.minAllocAreaSize;
    
    276
    +        memcount total_alloc = to * (size_t) RtsFlags.GcFlags.minAllocAreaSize;
    
    277 277
             new_n_nurseries =
    
    278 278
                 stg_max(to, total_alloc / RtsFlags.GcFlags.nurseryChunkSize);
    
    279 279
         }
    

  • testsuite/tests/rts/all.T
    ... ... @@ -171,7 +171,7 @@ test('T3424',
    171 171
     # Test for out-of-range heap size
    
    172 172
     test('rtsflags001', [ only_ways(['normal']),
    
    173 173
                           exit_code(1),
    
    174
    -                      extra_run_opts('+RTS -H0m -RTS'),
    
    174
    +                      extra_run_opts('+RTS -H1k -RTS'),
    
    175 175
                           js_skip # JS backend uses its own rts.
    
    176 176
                         ],
    
    177 177
                          compile_and_run, [''])
    

  • testsuite/tests/rts/rtsflags001.stderr-ws-32
    1
    -rtsflags001: error in RTS option -H0m: size outside allowed range (4096 - 4294967295)
    1
    +rtsflags001: error in RTS option -H1k: size outside allowed range (0 or 4096 - 17592186040320)

  • testsuite/tests/rts/rtsflags001.stderr-ws-64
    1
    -rtsflags001: error in RTS option -H0m: size outside allowed range (4096 - 18446744073709551615)
    1
    +rtsflags001: error in RTS option -H1k: size outside allowed range (0 or 4096 - 17592186040320)