aboutsummaryrefslogtreecommitdiff
path: root/gcc/ggc-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ggc-page.c')
-rw-r--r--gcc/ggc-page.c220
1 files changed, 75 insertions, 145 deletions
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 1b643e6..048d130 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -27,7 +27,9 @@
#include "flags.h"
#include "ggc.h"
+#ifdef HAVE_MMAP
#include <sys/mman.h>
+#endif
/* Stategy:
@@ -111,10 +113,10 @@ char *empty_string;
significant PAGE_L2_BITS and PAGE_L1_BITS are the second and first
index values in the lookup table, respectively.
- The topmost leftover bits, if any, are ignored. For 32-bit
- architectures and the settings below, there are no leftover bits.
- For architectures with wider pointers, the lookup tree points to a
- list of pages, which must be scanned to find the correct one. */
+ For 32-bit architectures and the settings below, there are no
+ leftover bits. For architectures with wider pointers, the lookup
+ tree points to a list of pages, which must be scanned to find the
+ correct one. */
#define PAGE_L1_BITS (8)
#define PAGE_L2_BITS (32 - PAGE_L1_BITS - G.lg_pagesize)
@@ -178,8 +180,8 @@ typedef page_entry **page_table[PAGE_L1_SIZE];
#else
-/* On 64-bit hosts, we use two level page tables plus a linked list
- that disambiguates the top 32-bits. There will almost always be
+/* On 64-bit hosts, we use the same two level page tables plus a linked
+ list that disambiguates the top 32-bits. There will almost always be
exactly one entry in the list. */
typedef struct page_table_chain
{
@@ -221,7 +223,7 @@ static struct globals
unsigned char context_depth;
/* A file descriptor open to /dev/zero for reading. */
-#ifndef MAP_ANONYMOUS
+#if defined (HAVE_MMAP) && !defined(MAP_ANONYMOUS)
int dev_zero_fd;
#endif
@@ -258,16 +260,13 @@ static struct globals
#define GGC_MIN_LAST_ALLOCATED (4 * 1024 * 1024)
-static page_entry *** ggc_lookup_page_table PROTO ((void));
static int ggc_allocated_p PROTO ((const void *));
-static page_entry *lookup_page_table_entry PROTO ((void *));
+static page_entry *lookup_page_table_entry PROTO ((const void *));
static void set_page_table_entry PROTO ((void *, page_entry *));
static char *alloc_anon PROTO ((char *, size_t));
static struct page_entry * alloc_page PROTO ((unsigned));
static void free_page PROTO ((struct page_entry *));
static void release_pages PROTO ((void));
-static void *alloc_obj PROTO ((size_t, int));
-static int mark_obj PROTO ((void *));
static void clear_marks PROTO ((void));
static void sweep_pages PROTO ((void));
@@ -278,37 +277,31 @@ static void poison_pages PROTO ((void));
void debug_print_page_list PROTO ((int));
-/* Returns the lookup table appropriate for looking up P. */
+/* Returns non-zero if P was allocated in GC'able memory. */
-static inline page_entry ***
-ggc_lookup_page_table ()
+static inline int
+ggc_allocated_p (p)
+ const void *p;
{
page_entry ***base;
+ size_t L1, L2;
#if HOST_BITS_PER_PTR <= 32
base = &G.lookup[0];
#else
page_table table = G.lookup;
size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
- while (table->high_bits != high_bits)
- table = table->next;
+ while (1)
+ {
+ if (table == NULL)
+ return 0;
+ if (table->high_bits == high_bits)
+ break;
+ table = table->next;
+ }
base = &table->table[0];
#endif
- return base;
-}
-
-/* Returns non-zero if P was allocated in GC'able memory. */
-
-static inline int
-ggc_allocated_p (p)
- const void *p;
-{
- page_entry ***base;
- size_t L1, L2;
-
- base = ggc_lookup_page_table ();
-
/* Extract the level 1 and 2 indicies. */
L1 = LOOKUP_L1 (p);
L2 = LOOKUP_L2 (p);
@@ -321,12 +314,20 @@ ggc_allocated_p (p)
static inline page_entry *
lookup_page_table_entry(p)
- void *p;
+ const void *p;
{
page_entry ***base;
size_t L1, L2;
- base = ggc_lookup_page_table ();
+#if HOST_BITS_PER_PTR <= 32
+ base = &G.lookup[0];
+#else
+ page_table table = G.lookup;
+ size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
+ while (table->high_bits != high_bits)
+ table = table->next;
+ base = &table->table[0];
+#endif
/* Extract the level 1 and 2 indicies. */
L1 = LOOKUP_L1 (p);
@@ -407,11 +408,12 @@ poison (start, len)
(if non-null). */
static inline char *
alloc_anon (pref, size)
- char *pref;
+ char *pref ATTRIBUTE_UNUSED;
size_t size;
{
char *page;
+#ifdef HAVE_MMAP
#ifdef MAP_ANONYMOUS
page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -424,6 +426,16 @@ alloc_anon (pref, size)
fputs ("Virtual memory exhausted!\n", stderr);
exit(1);
}
+#else
+#ifdef HAVE_VALLOC
+ page = (char *) valloc (size);
+ if (!page)
+ {
+ fputs ("Virtual memory exhausted!\n", stderr);
+ exit(1);
+ }
+#endif /* HAVE_VALLOC */
+#endif /* HAVE_MMAP */
return page;
}
@@ -522,6 +534,7 @@ free_page (entry)
static inline void
release_pages ()
{
+#ifdef HAVE_MMAP
page_entry *p, *next;
char *start;
size_t len;
@@ -553,6 +566,19 @@ release_pages ()
}
munmap (start, len);
+#else
+#ifdef HAVE_VALLOC
+ page_entry *p, *next;
+
+ for (p = G.free_pages; p ; p = next)
+ {
+ next = p->next;
+ free (p->page);
+ free (p);
+ }
+#endif /* HAVE_VALLOC */
+#endif /* HAVE_MMAP */
+
G.free_pages = NULL;
}
@@ -582,8 +608,8 @@ static unsigned char const size_lookup[257] =
/* Allocate a chunk of memory of SIZE bytes. If ZERO is non-zero, the
memory is zeroed; otherwise, its contents are undefined. */
-static void *
-alloc_obj (size, zero)
+void *
+ggc_alloc_obj (size, zero)
size_t size;
int zero;
{
@@ -700,8 +726,8 @@ alloc_obj (size, zero)
/* If P is not marked, marks it and returns 0. Otherwise returns 1.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
-static int
-mark_obj (p)
+int
+ggc_set_mark (p)
void *p;
{
page_entry *entry;
@@ -738,6 +764,13 @@ mark_obj (p)
return 0;
}
+void
+ggc_mark_if_gcable (p)
+ void *p;
+{
+ if (p && ggc_allocated_p (p))
+ ggc_set_mark (p);
+}
/* Initialize the ggc-mmap allocator. */
void
@@ -746,7 +779,7 @@ init_ggc ()
G.pagesize = getpagesize();
G.lg_pagesize = exact_log2 (G.pagesize);
-#ifndef MAP_ANONYMOUS
+#if defined (HAVE_MMAP) && !defined(MAP_ANONYMOUS)
G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
if (G.dev_zero_fd == -1)
abort ();
@@ -812,64 +845,6 @@ ggc_pop_context ()
}
}
}
-
-
-struct rtx_def *
-ggc_alloc_rtx (nslots)
- int nslots;
-{
- return (struct rtx_def *)
- alloc_obj (sizeof (struct rtx_def) + (nslots - 1) * sizeof (rtunion), 1);
-}
-
-
-struct rtvec_def *
-ggc_alloc_rtvec (nelt)
- int nelt;
-{
- return (struct rtvec_def *)
- alloc_obj (sizeof (struct rtvec_def) + (nelt - 1) * sizeof (rtx), 1);
-}
-
-
-union tree_node *
-ggc_alloc_tree (length)
- int length;
-{
- return (union tree_node *) alloc_obj (length, 1);
-}
-
-
-char *
-ggc_alloc_string (contents, length)
- const char *contents;
- int length;
-{
- char *string;
-
- if (length < 0)
- {
- if (contents == NULL)
- return NULL;
- length = strlen (contents);
- }
-
- string = (char *) alloc_obj (length + 1, 0);
- if (contents != NULL)
- memcpy (string, contents, length);
- string[length] = 0;
-
- return string;
-}
-
-
-void *
-ggc_alloc (size)
- size_t size;
-{
- return alloc_obj (size, 0);
-}
-
static inline void
clear_marks ()
@@ -1072,54 +1047,9 @@ ggc_collect ()
time = get_run_time () - time;
gc_time += time;
- time = (time + 500) / 1000;
if (!quiet_flag)
- fprintf (stderr, "%luk in %d.%03d}",
- (unsigned long) G.allocated / 1024, time / 1000, time % 1000);
-}
-
-
-int
-ggc_set_mark_rtx (r)
- rtx r;
-{
- return mark_obj (r);
-}
-
-int
-ggc_set_mark_rtvec (v)
- rtvec v;
-{
- return mark_obj (v);
-}
-
-int
-ggc_set_mark_tree (t)
- tree t;
-{
- return mark_obj (t);
-}
-
-void
-ggc_mark_string (s)
- char *s;
-{
- if (s)
- mark_obj (s);
-}
-
-void
-ggc_mark_string_if_gcable (s)
- char *s;
-{
- if (s && ggc_allocated_p (s))
- mark_obj (s);
-}
-
-void
-ggc_mark (p)
- void *p;
-{
- if (p)
- mark_obj (p);
+ {
+ fprintf (stderr, "%luk in %.3f}",
+ (unsigned long) G.allocated / 1024, time * 1e-6);
+ }
}