c++: Reduce memory consumption for large static arrays.
authorJason Merrill <jason@redhat.com>
Thu, 30 Jan 2020 23:49:29 +0000 (18:49 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 31 Jan 2020 23:19:31 +0000 (18:19 -0500)
PR14179 and the C counterpart PR12245 are about memory consumption of very
large file-scope arrays.  Recently, location wrappers increased memory
consumption significantly: in an array of integer constants, each one will
have a location wrapper, which added up to over 500MB in the 14179
testcase.  For this kind of testcase tracking these locations isn't worth
the cost, so this patch turns the wrappers off after 256 elements; any array
that size or larger isn't likely to be interested in the location of
individual integer constants.

PR c++/14179
* parser.c (cp_parser_initializer_list): Suppress location wrappers
after 256 elements.

gcc/cp/ChangeLog
gcc/cp/parser.c

index f260d5d5d809d5dcc679b3bac204f05f1713f464..f8140885dab408e680d8802cdddfc3fe84711aa0 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-31  Jason Merrill  <jason@redhat.com>
+
+       PR c++/14179
+       * parser.c (cp_parser_initializer_list): Suppress location wrappers
+       after 256 elements.
+
 2020-01-29  Jason Merrill  <jason@redhat.com>
 
        PR c++/82521
index bd8e524f0780c5b2774306c0de3025a9cf65e843..e0f72302e5e0f4b0033b71c000314327c16206d6 100644 (file)
@@ -23311,6 +23311,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
   /* Assume all of the expressions are constant.  */
   *non_constant_p = false;
 
+  unsigned nelts = 0;
+  int suppress = suppress_location_wrappers;
+
   /* Parse the rest of the list.  */
   while (true)
     {
@@ -23450,6 +23453,19 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
       if (token->type == CPP_CLOSE_BRACE)
        break;
 
+      /* Suppress location wrappers in a long initializer to save memory
+        (14179).  The cutoff is chosen arbitrarily.  */
+      const unsigned loc_max = 256;
+      unsigned incr = 1;
+      if (TREE_CODE (initializer) == CONSTRUCTOR)
+       /* Look one level down because it's easy.  Looking deeper would require
+          passing down a nelts pointer, and I don't think multi-level massive
+          initializers are common enough to justify this.  */
+       incr = CONSTRUCTOR_NELTS (initializer);
+      nelts += incr;
+      if (nelts >= loc_max && (nelts - incr) < loc_max)
+       ++suppress_location_wrappers;
+
       /* Consume the `,' token.  */
       cp_lexer_consume_token (parser->lexer);
     }
@@ -23479,6 +23495,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
          IDENTIFIER_MARKED (designator) = 0;
     }
 
+  suppress_location_wrappers = suppress;
+
   *designated = first_designator != NULL_TREE;
   return v;
 }