summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-19 04:27:47 +0000
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-19 04:27:47 +0000
commitd0ff0cef60c58560dd92794651283428ad7d01ea (patch)
tree97012c25719e773eaf6b25c2608b5998e3c20cb7 /gcc
parent81859e4d1552229be7ea17d22d67550c37c3c8e3 (diff)
downloadgcc-d0ff0cef60c58560dd92794651283428ad7d01ea.tar.gz
* cp/search.c (grow_bfs_bases): New subroutine of bfs_walk.
(bfs_walk): Rewritten using circular queue of BINFO_BASETYPES vectors, for speed. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@63088 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/search.c138
2 files changed, 108 insertions, 36 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9071de04bf3..3006cfdd2a9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2003-02-18 Zack Weinberg <zack@codesourcery.com>
+
+ * cp/search.c (grow_bfs_bases): New subroutine of bfs_walk.
+ (bfs_walk): Rewritten using circular queue of BINFO_BASETYPES
+ vectors, for speed.
+
2003-02-18 Mark Mitchell <mark@codesourcery.com>
PR c++/9704
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index a87ba5f6029..395464e0ef9 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -102,6 +102,7 @@ static int look_for_overrides_r (tree, tree);
static struct search_level *push_search_level (struct stack_level *,
struct obstack *);
static struct search_level *pop_search_level (struct stack_level *);
+static void grow_bfs_bases (tree **, size_t *, size_t *);
static tree bfs_walk (tree, tree (*) (tree, void *),
tree (*) (tree, void *), void *);
static tree lookup_field_queue_p (tree, void *);
@@ -1620,6 +1621,43 @@ adjust_result_of_qualified_name_lookup (tree decl,
}
+/* Start with enough room for ten concurrent base classes. That
+ will be enough for most hierarchies. */
+#define BFS_WALK_INITIAL_QUEUE_SIZE 10
+
+/* Subroutine of bfs_walk; enlarges the buffer it uses for its
+ circular queue. */
+static void
+grow_bfs_bases (tree **basep, size_t *sizep, size_t *headp)
+{
+ tree *base;
+ size_t size = *sizep;
+ size_t head = *headp;
+
+ /* If the size is BFS_WALK_INITIAL_QUEUE_SIZE, the old array is on
+ the stack. */
+ if (size == BFS_WALK_INITIAL_QUEUE_SIZE)
+ {
+ base = xmalloc (size * 2 * sizeof(tree));
+ memcpy (base, *basep, size * sizeof(tree));
+ }
+ else
+ base = xrealloc (*basep, size * 2 * sizeof(tree));
+
+ *basep = base;
+ *sizep = size * 2;
+
+ /* Shift all the elements between head and the former end of the
+ array, opening up a gap between tail and head. If head==0 we
+ don't need to do anything to achieve this. */
+ if (head != 0)
+ {
+ memmove (&base[head + size], &base[head],
+ (size - head) * sizeof (tree));
+ *headp = head + size;
+ }
+}
+
/* Walk the class hierarchy dominated by TYPE. FN is called for each
type in the hierarchy, in a breadth-first preorder traversal.
If it ever returns a non-NULL value, that value is immediately
@@ -1629,61 +1667,89 @@ adjust_result_of_qualified_name_lookup (tree decl,
value returned is nonzero, the base-class is walked; otherwise it
is not. If QFN is NULL, it is treated as a function which always
returns 1. Both FN and QFN are passed the DATA whenever they are
- called. */
+ called.
+
+ Implementation notes: Uses a circular queue, which starts off on
+ the stack but gets moved to the malloc arena if it needs to be
+ enlarged. The underflow and overflow conditions are
+ indistinguishable except by context: if head == tail and we just
+ moved the head pointer, the queue is empty, but if we just moved
+ the tail pointer, the queue is full. Base class vectors are only
+ put on the queue if they are nonempty, which is why it's safe to
+ use do-while for the inner loop. */
static tree
bfs_walk (tree binfo, tree (*fn) (tree, void *),
tree (*qfn) (tree, void *), void *data)
{
- size_t head;
- size_t tail;
tree rval = NULL_TREE;
- /* An array of the base classes of BINFO. These will be built up in
- breadth-first order, except where QFN prunes the search. */
- varray_type bfs_bases;
- /* Start with enough room for ten base classes. That will be enough
- for most hierarchies. */
- VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
+ tree bfs_bases_initial[BFS_WALK_INITIAL_QUEUE_SIZE];
+ /* A circular queue of the base classes of BINFO. These will be
+ built up in breadth-first order, except where QFN prunes the
+ search. */
+ size_t head, tail;
+ size_t bfs_bases_size = BFS_WALK_INITIAL_QUEUE_SIZE;
+ tree *bfs_bases = bfs_bases_initial;
+
+ /* Is the first one what we're looking for? If so, we're done. */
+ rval = fn (binfo, data);
+ if (rval)
+ return rval;
+
+ /* If it has no base types, we are also done. */
+ if (BINFO_BASETYPES (binfo) == 0
+ || TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 0)
+ return 0;
+
+ /* Otherwise, initialize the queue with its basetypes vector
+ and proceed. */
- /* Put the first type into the stack. */
- VARRAY_TREE (bfs_bases, 0) = binfo;
- tail = 1;
+ head = tail = 0;
+ bfs_bases[tail++] = BINFO_BASETYPES (binfo);
- for (head = 0; head < tail; ++head)
+ do
{
- int i;
- int n_baselinks;
+ int i, n_baselinks;
tree binfos;
+
+ binfos = bfs_bases[head++];
+ if (head == bfs_bases_size)
+ head = 0;
- /* Pull the next type out of the queue. */
- binfo = VARRAY_TREE (bfs_bases, head);
-
- /* If this is the one we're looking for, we're done. */
- rval = (*fn) (binfo, data);
- if (rval)
- break;
-
- /* Queue up the base types. */
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
- for (i = 0; i < n_baselinks; i++)
+ i = 0;
+ n_baselinks = TREE_VEC_LENGTH (binfos);
+ do
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
+ binfo = TREE_VEC_ELT (binfos, i);
+ i++;
if (qfn)
- base_binfo = (*qfn) (base_binfo, data);
+ binfo = qfn (binfo, data);
+ if (!binfo)
+ continue;
- if (base_binfo)
- {
- if (tail == VARRAY_SIZE (bfs_bases))
- VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
- VARRAY_TREE (bfs_bases, tail) = base_binfo;
- ++tail;
- }
+ rval = fn (binfo, data);
+ if (rval)
+ goto done;
+
+ if (BINFO_BASETYPES (binfo) == 0
+ || TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 0)
+ continue;
+
+ bfs_bases[tail++] = BINFO_BASETYPES (binfo);
+ if (tail == bfs_bases_size)
+ tail = 0;
+ if (tail == head)
+ grow_bfs_bases (&bfs_bases, &bfs_bases_size, &head);
}
+ while (i < n_baselinks);
}
+ while (head != tail);
+ done:
+ if (bfs_bases != bfs_bases_initial)
+ free (bfs_bases);
return rval;
}