summaryrefslogtreecommitdiff
path: root/gcc/ggc-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ggc-page.c')
-rw-r--r--gcc/ggc-page.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index ea637b1b63c..f22ddf6e826 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1,5 +1,5 @@
/* "Bag-of-pages" garbage collector for the GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
@@ -1256,6 +1256,57 @@ ggc_alloc_stat (size_t size MEM_STAT_DECL)
return result;
}
+/* Mark function for strings. */
+
+void
+gt_ggc_m_S (const void *p)
+{
+ page_entry *entry;
+ unsigned bit, word;
+ unsigned long mask;
+ unsigned long offset;
+
+ if (!p || !ggc_allocated_p (p))
+ return;
+
+ /* Look up the page on which the object is alloced. . */
+ entry = lookup_page_table_entry (p);
+ gcc_assert (entry);
+
+ /* Calculate the index of the object on the page; this is its bit
+ position in the in_use_p bitmap. Note that because a char* might
+ point to the middle of an object, we need special code here to
+ make sure P points to the start of an object. */
+ offset = ((const char *) p - entry->page) % object_size_table[entry->order];
+ if (offset)
+ {
+ /* Here we've seen a char* which does not point to the beginning
+ of an allocated object. We assume it points to the middle of
+ a STRING_CST. */
+ gcc_assert (offset == offsetof (struct tree_string, str));
+ p = ((const char *) p) - offset;
+ gt_ggc_mx_lang_tree_node ((void *) p);
+ return;
+ }
+
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
+ word = bit / HOST_BITS_PER_LONG;
+ mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
+
+ /* If the bit was previously set, skip it. */
+ if (entry->in_use_p[word] & mask)
+ return;
+
+ /* Otherwise set it, and decrement the free object count. */
+ entry->in_use_p[word] |= mask;
+ entry->num_free_objects -= 1;
+
+ if (GGC_DEBUG_LEVEL >= 4)
+ fprintf (G.debug_file, "Marking %p\n", p);
+
+ return;
+}
+
/* If P is not marked, marks it and return false. Otherwise return true.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */