summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/ggc-none.c9
-rw-r--r--gcc/ggc-page.c53
-rw-r--r--gcc/ggc-zone.c27
-rw-r--r--gcc/ggc.h2
-rw-r--r--gcc/toplev.c1
-rw-r--r--libcpp/ChangeLog8
-rw-r--r--libcpp/include/line-map.h8
-rw-r--r--libcpp/line-map.c39
9 files changed, 138 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 81caf547177..557916c82bc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,22 @@
2011-10-15 Tom Tromey <tromey@redhat.com>
Dodji Seketeli <dodji@redhat.com>
+ * ggc.h (ggc_round_alloc_size): Declare new public entry point.
+ * ggc-none.c (ggc_round_alloc_size): New public stub function.
+ * ggc-page.c (ggc_alloced_size_order_for_request): New static
+ function. Factorized from ggc_internal_alloc_stat.
+ (ggc_round_alloc_size): New public function. Uses
+ ggc_alloced_size_order_for_request.
+ (ggc_internal_alloc_stat): Use ggc_alloced_size_order_for_request.
+ * ggc-zone.c (ggc_round_alloc_size): New public function extracted
+ from ggc_internal_alloc_zone_stat.
+ (ggc_internal_alloc_zone_stat): Use ggc_round_alloc_size.
+ * toplev.c (general_init): Initialize
+ line_table->alloced_size_for_request.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
* input.c (ONE_K, ONE_M, SCALE, STAT_LABEL, FORMAT_AMOUNT): New
macros.
(num_expanded_macros_counter, num_macro_tokens_counter): Declare
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index 97d25b9b653..e57d61787df 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -39,6 +39,15 @@ ggc_alloc_typed_stat (enum gt_types_enum ARG_UNUSED (gte), size_t size
return xmalloc (size);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ return requested_size;
+}
+
void *
ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
{
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index a218f7696d7..beee851dd7f 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1054,6 +1054,47 @@ static unsigned char size_lookup[NUM_SIZE_LOOKUP] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
};
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated, as well as the size
+ order. */
+
+static void
+ggc_round_alloc_size_1 (size_t requested_size,
+ size_t *size_order,
+ size_t *alloced_size)
+{
+ size_t order, object_size;
+
+ if (requested_size < NUM_SIZE_LOOKUP)
+ {
+ order = size_lookup[requested_size];
+ object_size = OBJECT_SIZE (order);
+ }
+ else
+ {
+ order = 10;
+ while (requested_size > (object_size = OBJECT_SIZE (order)))
+ order++;
+ }
+
+ if (size_order)
+ *size_order = order;
+ if (alloced_size)
+ *alloced_size = object_size;
+}
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size = 0;
+
+ ggc_round_alloc_size_1 (requested_size, NULL, &size);
+ return size;
+}
+
/* Typed allocation function. Does nothing special in this collector. */
void *
@@ -1072,17 +1113,7 @@ ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
struct page_entry *entry;
void *result;
- if (size < NUM_SIZE_LOOKUP)
- {
- order = size_lookup[size];
- object_size = OBJECT_SIZE (order);
- }
- else
- {
- order = 10;
- while (size > (object_size = OBJECT_SIZE (order)))
- order++;
- }
+ ggc_round_alloc_size_1 (size, &order, &object_size);
/* If there are non-full pages for this size allocation, they are at
the head of the list. */
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index d0c1d79f53d..79c8c032966 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -1073,6 +1073,24 @@ free_chunk (char *ptr, size_t size, struct alloc_zone *zone)
fprintf (G.debug_file, "Deallocating object, chunk=%p\n", (void *)chunk);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size;
+
+ /* Make sure that zero-sized allocations get a unique and freeable
+ pointer. */
+ if (requested_size == 0)
+ size = MAX_ALIGNMENT;
+ else
+ size = (requested_size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+
+ return size;
+}
+
/* Allocate a chunk of memory of at least ORIG_SIZE bytes, in ZONE. */
void *
@@ -1084,14 +1102,7 @@ ggc_internal_alloc_zone_stat (size_t orig_size, struct alloc_zone *zone
struct small_page_entry *entry;
struct alloc_chunk *chunk, **pp;
void *result;
- size_t size = orig_size;
-
- /* Make sure that zero-sized allocations get a unique and freeable
- pointer. */
- if (size == 0)
- size = MAX_ALIGNMENT;
- else
- size = (size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+ size_t size = ggc_alloced_size_for_request (orig_size);
/* Try to allocate the object from several different sources. Each
of these cases is responsible for setting RESULT and SIZE to
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 30eca66c302..704237cc045 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -145,6 +145,8 @@ extern void gt_pch_save (FILE *f);
/* The internal primitive. */
extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL);
+extern size_t ggc_round_alloc_size (size_t requested_size);
+
#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
/* Allocate an object of the specified type and size. */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index f508196b3eb..86eed5d63a8 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1216,6 +1216,7 @@ general_init (const char *argv0)
line_table = ggc_alloc_line_maps ();
linemap_init (line_table);
line_table->reallocator = realloc_for_line_map;
+ line_table->round_alloc_size = ggc_round_alloc_size;
init_ttree ();
/* Initialize register usage now so switches may override. */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index fad0da65853..375072003af 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,6 +1,14 @@
2011-10-15 Tom Tromey <tromey@redhat.com>
Dodji Seketeli <dodji@redhat.com>
+ * include/line-map.h (struct line_maps::alloced_size_for_request):
+ New member.
+ * line-map.c (new_linemap): Use set->alloced_size_for_request to
+ get the actual allocated size of line maps.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
* line-map.h (struct linemap_stats): Declare new struct.
(linemap_get_statistics): Declare ...
* line-map.c (linemap_get_statistics): ... new function.
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 572e330a1bd..1e2a148e17b 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -53,6 +53,10 @@ typedef unsigned int source_location;
/* Memory allocation function typedef. Works like xrealloc. */
typedef void *(*line_map_realloc) (void *, size_t);
+/* Memory allocator function that returns the actual allocated size,
+ for a given requested allocation. */
+typedef size_t (*line_map_round_alloc_size_func) (size_t);
+
/* An ordinary line map encodes physical source locations. Those
physical source locations are called "spelling locations".
@@ -281,6 +285,10 @@ struct GTY(()) line_maps {
/* If non-null, the allocator to use when resizing 'maps'. If null,
xrealloc is used. */
line_map_realloc reallocator;
+
+ /* The allocators' function used to know the actual size it
+ allocated, for a certain allocation size requested. */
+ line_map_round_alloc_size_func round_alloc_size;
};
/* Returns the pointer to the memory region where information about
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 9086b3e3065..87b8bfe8a0f 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -92,16 +92,43 @@ new_linemap (struct line_maps *set,
if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
{
/* We ran out of allocated line maps. Let's allocate more. */
+ unsigned alloc_size;
line_map_realloc reallocator
= set->reallocator ? set->reallocator : xrealloc;
+ line_map_round_alloc_size_func round_alloc_size =
+ set->round_alloc_size;
+
+ /* We are going to execute some dance to try to reduce the
+ overhead of the memory allocator, in case we are using the
+ ggc-page.c one.
+
+ The actual size of memory we are going to get back from the
+ allocator is the smallest power of 2 that is greater than the
+ size we requested. So let's consider that size then. */
+
+ alloc_size =
+ (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256)
+ * sizeof (struct line_map);
+
+ /* Get the actual size of memory that is going to be allocated
+ by the allocator. */
+ alloc_size = round_alloc_size (alloc_size);
+
+ /* Now alloc_size contains the exact memory size we would get if
+ we have asked for the initial alloc_size amount of memory.
+ Let's get back to the number of macro map that amounts
+ to. */
LINEMAPS_ALLOCATED (set, macro_map_p) =
- 2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256;
- LINEMAPS_MAPS (set, macro_map_p)
- = (struct line_map *) (*reallocator) (LINEMAPS_MAPS (set, macro_map_p),
- LINEMAPS_ALLOCATED (set,
- macro_map_p)
- * sizeof (struct line_map));
+ alloc_size / (sizeof (struct line_map));
+
+ /* And now let's really do the re-allocation. */
+ LINEMAPS_MAPS (set, macro_map_p) =
+ (struct line_map *) (*reallocator)
+ (LINEMAPS_MAPS (set, macro_map_p),
+ (LINEMAPS_ALLOCATED (set, macro_map_p)
+ * sizeof (struct line_map)));
+
result =
&LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
memset (result, 0,