search.c (grow_bfs_bases): New subroutine of bfs_walk.
* cp/search.c (grow_bfs_bases): New subroutine of bfs_walk. (bfs_walk): Rewritten using circular queue of BINFO_BASETYPES vectors, for speed. From-SVN: r63088
This commit is contained in:
parent
78bd5210e7
commit
860c9ea661
|
@ -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>
|
2003-02-18 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
PR c++/9704
|
PR c++/9704
|
||||||
|
|
136
gcc/cp/search.c
136
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 *,
|
static struct search_level *push_search_level (struct stack_level *,
|
||||||
struct obstack *);
|
struct obstack *);
|
||||||
static struct search_level *pop_search_level (struct stack_level *);
|
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 *),
|
static tree bfs_walk (tree, tree (*) (tree, void *),
|
||||||
tree (*) (tree, void *), void *);
|
tree (*) (tree, void *), void *);
|
||||||
static tree lookup_field_queue_p (tree, 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
|
/* Walk the class hierarchy dominated by TYPE. FN is called for each
|
||||||
type in the hierarchy, in a breadth-first preorder traversal.
|
type in the hierarchy, in a breadth-first preorder traversal.
|
||||||
If it ever returns a non-NULL value, that value is immediately
|
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
|
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
|
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
|
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
|
static tree
|
||||||
bfs_walk (tree binfo, tree (*fn) (tree, void *),
|
bfs_walk (tree binfo, tree (*fn) (tree, void *),
|
||||||
tree (*qfn) (tree, void *), void *data)
|
tree (*qfn) (tree, void *), void *data)
|
||||||
{
|
{
|
||||||
size_t head;
|
|
||||||
size_t tail;
|
|
||||||
tree rval = NULL_TREE;
|
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
|
tree bfs_bases_initial[BFS_WALK_INITIAL_QUEUE_SIZE];
|
||||||
for most hierarchies. */
|
/* A circular queue of the base classes of BINFO. These will be
|
||||||
VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
|
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;
|
||||||
|
|
||||||
/* Put the first type into the stack. */
|
/* Is the first one what we're looking for? If so, we're done. */
|
||||||
VARRAY_TREE (bfs_bases, 0) = binfo;
|
rval = fn (binfo, data);
|
||||||
tail = 1;
|
if (rval)
|
||||||
|
return rval;
|
||||||
|
|
||||||
for (head = 0; head < tail; ++head)
|
/* 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. */
|
||||||
|
|
||||||
|
head = tail = 0;
|
||||||
|
bfs_bases[tail++] = BINFO_BASETYPES (binfo);
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
int i;
|
int i, n_baselinks;
|
||||||
int n_baselinks;
|
|
||||||
tree binfos;
|
tree binfos;
|
||||||
|
|
||||||
/* Pull the next type out of the queue. */
|
binfos = bfs_bases[head++];
|
||||||
binfo = VARRAY_TREE (bfs_bases, head);
|
if (head == bfs_bases_size)
|
||||||
|
head = 0;
|
||||||
|
|
||||||
/* If this is the one we're looking for, we're done. */
|
i = 0;
|
||||||
rval = (*fn) (binfo, data);
|
n_baselinks = TREE_VEC_LENGTH (binfos);
|
||||||
if (rval)
|
do
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
binfo = TREE_VEC_ELT (binfos, i);
|
||||||
|
i++;
|
||||||
|
|
||||||
if (qfn)
|
if (qfn)
|
||||||
base_binfo = (*qfn) (base_binfo, data);
|
binfo = qfn (binfo, data);
|
||||||
|
if (!binfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (base_binfo)
|
rval = fn (binfo, data);
|
||||||
{
|
if (rval)
|
||||||
if (tail == VARRAY_SIZE (bfs_bases))
|
goto done;
|
||||||
VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
|
|
||||||
VARRAY_TREE (bfs_bases, tail) = base_binfo;
|
if (BINFO_BASETYPES (binfo) == 0
|
||||||
++tail;
|
|| 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;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue