+/* Mark function for strings. */
+
+void
+gt_ggc_m_S (const void *p)
+{
+ page_entry *entry;
+ unsigned long offset;
+
+ if (!p)
+ return;
+
+ /* Look up the page on which the object is alloced. . */
+ entry = lookup_page_table_if_allocated (p);
+ if (! entry)
+ return;
+
+ if (entry->pch_p)
+ {
+ size_t alloc_word, alloc_bit, t;
+ t = ((const char *) p - pch_zone.page) / BYTES_PER_ALLOC_BIT;
+ alloc_word = t / (8 * sizeof (alloc_type));
+ alloc_bit = t % (8 * sizeof (alloc_type));
+ offset = zone_find_object_offset (pch_zone.alloc_bits, alloc_word,
+ alloc_bit);
+ }
+ else if (entry->large_p)
+ {
+ struct large_page_entry *le = (struct large_page_entry *) entry;
+ offset = ((const char *) p) - entry->page;
+ gcc_assert (offset < le->bytes);
+ }
+ else
+ {
+ struct small_page_entry *se = (struct small_page_entry *) entry;
+ unsigned int start_word = zone_get_object_alloc_word (p);
+ unsigned int start_bit = zone_get_object_alloc_bit (p);
+ offset = zone_find_object_offset (se->alloc_bits, start_word, start_bit);
+
+ /* On some platforms a char* will not necessarily line up on an
+ allocation boundary, so we have to update the offset to
+ account for the leftover bytes. */
+ offset += (size_t) p % BYTES_PER_ALLOC_BIT;
+ }
+
+ 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 (CONST_CAST(void *, p));
+ return;
+ }
+
+ /* Inefficient, but also unlikely to matter. */
+ ggc_set_mark (p);
+}
+