Speed up Koenig lookup.

* decl.c (unqualified_namespace_lookup): Nonstatic.  Add spacep parm
	to return namespaces we've looked at.
	* decl2.c (lookup_using_namespace): Likewise.
	(add_function): Don't call ovl_member.
	(lookup_arg_dependent): Initialize k.namespaces to the list of
	namespaces seen in unqualified lookup.
	* call.c (equal_functions): Move here from tree.c.
	(joust): Use it to handle duplicate candidates.
	* tree.c (ovl_member): Use ==.

From-SVN: r28710
This commit is contained in:
Jason Merrill 1999-08-14 11:08:53 +00:00 committed by Jason Merrill
parent 9188c36364
commit 2c169babb6
7 changed files with 102 additions and 56 deletions

View File

@ -1,3 +1,16 @@
1999-08-14 Jason Merrill <jason@yorick.cygnus.com>
Speed up Koenig lookup.
* decl.c (unqualified_namespace_lookup): Nonstatic. Add spacep parm
to return namespaces we've looked at.
* decl2.c (lookup_using_namespace): Likewise.
(add_function): Don't call ovl_member.
(lookup_arg_dependent): Initialize k.namespaces to the list of
namespaces seen in unqualified lookup.
* call.c (equal_functions): Move here from tree.c.
(joust): Use it to handle duplicate candidates.
* tree.c (ovl_member): Use ==.
1999-08-13 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (DECL_STMT): Make it smaller.

View File

@ -44,6 +44,7 @@ static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
static tree build_field_call PROTO((tree, tree, tree, tree));
static struct z_candidate * tourney PROTO((struct z_candidate *));
static int equal_functions PROTO((tree, tree));
static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int));
@ -4768,6 +4769,20 @@ add_warning (winner, loser)
winner->warnings);
}
/* Returns true iff functions are equivalent. Equivalent functions are
not identical only if one is a function-local extern function.
This assumes that function-locals don't have TREE_PERMANENT. */
static inline int
equal_functions (fn1, fn2)
tree fn1;
tree fn2;
{
if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
return decls_match (fn1, fn2);
return fn1 == fn2;
}
/* Compare two candidates for overloading as described in
[over.match.best]. Return values:
@ -4963,6 +4978,12 @@ joust (cand1, cand2, warn)
}
}
/* If the two functions are the same (this can happen with declarations
in multiple scopes and arg-dependent lookup), arbitrarily choose one. */
if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& equal_functions (cand1->fn, cand2->fn))
return 1;
tweak:
/* Extension: If the worst conversion for one candidate is worse than the

View File

@ -2886,8 +2886,9 @@ extern tree lookup_name_namespace_only PROTO((tree));
extern void begin_only_namespace_names PROTO((void));
extern void end_only_namespace_names PROTO((void));
extern tree namespace_ancestor PROTO((tree, tree));
extern int lookup_using_namespace PROTO((tree,tree,tree,tree,int));
extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int));
extern tree unqualified_namespace_lookup PROTO((tree, int, tree *));
extern int lookup_using_namespace PROTO((tree, tree, tree, tree, int, tree *));
extern int qualified_lookup_using_namespace PROTO((tree, tree, tree, int));
extern tree auto_function PROTO((tree, tree, enum built_in_function));
extern void init_decl_processing PROTO((void));
extern int init_type_desc PROTO((void));

View File

@ -179,7 +179,6 @@ static void pop_binding PROTO((tree, tree));
static tree local_variable_p PROTO((tree));
static tree find_binding PROTO((tree, tree));
static tree select_decl PROTO((tree, int));
static tree unqualified_namespace_lookup PROTO((tree, int));
static int lookup_flags PROTO((int, int));
static tree qualify_lookup PROTO((tree, int));
static tree record_builtin_java_type PROTO((const char *, int));
@ -5557,13 +5556,15 @@ select_decl (binding, flags)
return val;
}
/* Unscoped lookup of a global, iterate over namespaces, considering
using namespace statements. */
/* Unscoped lookup of a global: iterate over current namespaces,
considering using-directives. If SPACESP is non-NULL, store a list
of the namespaces we've considered in it. */
static tree
unqualified_namespace_lookup (name, flags)
tree
unqualified_namespace_lookup (name, flags, spacesp)
tree name;
int flags;
tree *spacesp;
{
struct tree_binding _binding;
tree b = binding_init (&_binding);
@ -5573,8 +5574,13 @@ unqualified_namespace_lookup (name, flags)
struct binding_level *level;
tree val = NULL_TREE;
while (!val)
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
if (spacesp)
*spacesp = scratch_tree_cons (scope, NULL_TREE, *spacesp);
val = binding_for_name (name, scope);
/* Initialize binding for this context. */
@ -5586,7 +5592,7 @@ unqualified_namespace_lookup (name, flags)
!level->namespace_p;
level = level->level_chain)
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
scope, flags, spacesp))
/* Give up because of error. */
return error_mark_node;
@ -5596,7 +5602,7 @@ unqualified_namespace_lookup (name, flags)
while (1)
{
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
scope, flags, spacesp))
/* Give up because of error. */
return error_mark_node;
if (siter == scope) break;
@ -5606,7 +5612,6 @@ unqualified_namespace_lookup (name, flags)
val = select_decl (b, flags);
if (scope == global_namespace)
break;
scope = CP_DECL_CONTEXT (scope);
}
return val;
}
@ -5811,7 +5816,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
/* Now lookup in namespace scopes. */
if (!val || val_is_implicit_typename)
{
t = unqualified_namespace_lookup (name, flags);
t = unqualified_namespace_lookup (name, flags, 0);
if (t)
{
if (val_is_implicit_typename && !yylex)

View File

@ -4349,14 +4349,18 @@ ambiguous_decl (name, old, new, flags)
return old;
}
/* Add the bindings of name in used namespaces to val.
The using list is defined by usings, and the lookup goes to scope.
/* Subroutine of unualified_namespace_lookup:
Add the bindings of NAME in used namespaces to VAL.
We are currently looking for names in namespace SCOPE, so we
look through USINGS for using-directives of namespaces
which have SCOPE as a common ancestor with the current scope.
Returns zero on errors. */
int
lookup_using_namespace (name, val, usings, scope, flags)
lookup_using_namespace (name, val, usings, scope, flags, spacesp)
tree name, val, usings, scope;
int flags;
tree *spacesp;
{
tree iter;
tree val1;
@ -4365,6 +4369,9 @@ lookup_using_namespace (name, val, usings, scope, flags)
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
if (spacesp)
*spacesp = scratch_tree_cons (TREE_PURPOSE (iter), NULL_TREE,
*spacesp);
val1 = binding_for_name (name, TREE_PURPOSE (iter));
/* Resolve ambiguities. */
val = ambiguous_decl (name, val, val1, flags);
@ -4573,28 +4580,32 @@ add_function (k, fn)
struct arg_lookup *k;
tree fn;
{
if (ovl_member (fn, k->functions))
return 0;
/* We used to check here to see if the function was already in the list,
but that's O(n^2), which is just too expensive for function lookup.
Now we deal with the occasional duplicate in joust. In doing this, we
assume that the number of duplicates will be small compared to the
total number of functions being compared, which should usually be the
case. */
/* We must find only functions, or exactly one non-function. */
if (k->functions && is_overloaded_fn (k->functions)
&& is_overloaded_fn (fn))
k->functions = build_overload (fn, k->functions);
else
if(k->functions)
{
tree f1 = OVL_CURRENT (k->functions);
tree f2 = fn;
if (is_overloaded_fn (f1))
{
fn = f1; f1 = f2; f2 = fn;
}
cp_error_at ("`%D' is not a function,", f1);
cp_error_at (" conflict with `%D'", f2);
cp_error (" in call to `%D'", k->name);
return 1;
}
else
k->functions = fn;
else if (k->functions)
{
tree f1 = OVL_CURRENT (k->functions);
tree f2 = fn;
if (is_overloaded_fn (f1))
{
fn = f1; f1 = f2; f2 = fn;
}
cp_error_at ("`%D' is not a function,", f1);
cp_error_at (" conflict with `%D'", f2);
cp_error (" in call to `%D'", k->name);
return 1;
}
else
k->functions = fn;
return 0;
}
@ -4615,7 +4626,7 @@ arg_assoc_namespace (k, scope)
value = namespace_binding (k->name, scope);
if (!value)
return 0;
for (; value; value = OVL_NEXT (value))
if (add_function (k, OVL_CURRENT (value)))
return 1;
@ -4845,11 +4856,18 @@ lookup_arg_dependent (name, fns, args)
tree args;
{
struct arg_lookup k;
k.name = name;
k.functions = fns;
k.namespaces = NULL_TREE;
k.classes = NULL_TREE;
/* Note that we've already looked at some namespaces during normal
unqualified lookup, unless we found a decl in function scope. */
if (fns && ! TREE_PERMANENT (OVL_CURRENT (fns)))
k.namespaces = NULL_TREE;
else
unqualified_namespace_lookup (name, 0, &k.namespaces);
push_scratch_obstack ();
arg_assoc_args (&k, args);
pop_obstacks ();

View File

@ -3078,10 +3078,13 @@ do_identifier (token, parsing, args)
id = lastiddecl;
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead). */
expressions instead).
[basic.lookup.koenig]: If the ordinary unqualified lookup of the name
finds the declaration of a class member function, the associated
namespaces and classes are not considered. */
if (args && !current_template_parms && (!id || is_global (id)))
/* If we have arguments and we only found global names, do Koenig
lookup. */
id = lookup_arg_dependent (token, id, args);
/* Remember that this name has been used in the class definition, as per

View File

@ -37,7 +37,6 @@ static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree));
static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree));
static tree no_linkage_helper PROTO((tree));
static tree build_srcloc PROTO((char *, int));
@ -1411,20 +1410,6 @@ build_overload (decl, chain)
return ovl_cons (decl, chain);
}
/* Returns true iff functions are equivalent. Equivalent functions are
not identical only if one is a function-local extern function.
This assumes that function-locals don't have TREE_PERMANENT. */
static int
equal_functions (fn1, fn2)
tree fn1;
tree fn2;
{
if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
return decls_match (fn1, fn2);
return fn1 == fn2;
}
/* True if fn is in ovl. */
int
@ -1435,9 +1420,9 @@ ovl_member (fn, ovl)
if (ovl == NULL_TREE)
return 0;
if (TREE_CODE (ovl) != OVERLOAD)
return equal_functions (ovl, fn);
return ovl == fn;
for (; ovl; ovl = OVL_CHAIN (ovl))
if (equal_functions (OVL_FUNCTION (ovl), fn))
if (OVL_FUNCTION (ovl) == fn)
return 1;
return 0;
}